@koda-sl/baker-cli 0.122.0-dev.3a1b48e85 → 0.122.0-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 -24
- package/dist/{chunk-MWFJ5NOP.js → chunk-SH6L4BCQ.js} +335 -73
- package/dist/chunk-SH6L4BCQ.js.map +1 -0
- package/dist/cli.js +1391 -1114
- 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-MWFJ5NOP.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
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
|
+
ulid,
|
|
15
21
|
validateCanvasDeep
|
|
16
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-SH6L4BCQ.js";
|
|
17
23
|
import {
|
|
18
24
|
csvOrJson,
|
|
19
25
|
daysAgoIso,
|
|
@@ -49,7 +55,7 @@ import {
|
|
|
49
55
|
import "./chunk-5WRI5ZAA.js";
|
|
50
56
|
|
|
51
57
|
// src/cli.ts
|
|
52
|
-
import { defineCommand as
|
|
58
|
+
import { defineCommand as defineCommand160, runMain } from "citty";
|
|
53
59
|
|
|
54
60
|
// src/commands/actions/index.ts
|
|
55
61
|
import { defineCommand as defineCommand18 } from "citty";
|
|
@@ -848,6 +854,7 @@ var LINKEDIN_LIMITS = {
|
|
|
848
854
|
choiceOptionsMax: 30,
|
|
849
855
|
choiceOptionTextMax: 100,
|
|
850
856
|
thankYouMessageMax: 300,
|
|
857
|
+
privacyPolicyTextMax: 2e3,
|
|
851
858
|
legalDisclaimerMax: 2e3,
|
|
852
859
|
consentsMax: 5,
|
|
853
860
|
// Campaign Manager caps disclosure checkboxes at 5
|
|
@@ -1442,6 +1449,7 @@ var leadFormFields = {
|
|
|
1442
1449
|
/** Form language, e.g. { country: "US", language: "en" }. Defaults to the account locale on LinkedIn. */
|
|
1443
1450
|
locale: z2.object({ country: z2.string().length(2), language: z2.string().length(2) }).optional(),
|
|
1444
1451
|
privacyPolicyUrl: httpsUrlSchema,
|
|
1452
|
+
privacyPolicyText: z2.string().max(LEAD.privacyPolicyTextMax).optional(),
|
|
1445
1453
|
questions: z2.array(leadFormQuestionSchema).min(1).max(LEAD.questionsMax),
|
|
1446
1454
|
consents: z2.array(leadFormConsentSchema).max(LEAD.consentsMax).optional(),
|
|
1447
1455
|
hiddenFields: z2.array(leadFormHiddenFieldSchema).max(LEAD.hiddenFieldsMax).optional(),
|
|
@@ -1916,241 +1924,142 @@ var imagesIngestResponseSchema = z4.object({
|
|
|
1916
1924
|
contentHash: z4.string()
|
|
1917
1925
|
});
|
|
1918
1926
|
|
|
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 tagDraftOpKindSchema = z5.enum(["create", "update", "delete"]);
|
|
1943
|
-
var tagDraftOpViewSchema = z5.object({
|
|
1944
|
-
/** `tag_temp_*` for staged creates; the real tag id for update/delete ops. */
|
|
1945
|
-
ref: z5.string(),
|
|
1946
|
-
kind: tagDraftOpKindSchema,
|
|
1947
|
-
type: tagTypeSchema,
|
|
1948
|
-
/** Present on update/delete ops — the real tag this op targets. */
|
|
1949
|
-
tagId: z5.string().optional(),
|
|
1950
|
-
/** Non-secret config (create: full; update: the staged patch). Secrets are structurally absent. */
|
|
1951
|
-
config: z5.record(z5.string(), z5.string()),
|
|
1952
|
-
/** Update only — fields the op explicitly clears. */
|
|
1953
|
-
clearFields: z5.array(z5.string()).optional(),
|
|
1954
|
-
/** Names of secret fields already provided via the dashboard secure form. Never values. */
|
|
1955
|
-
secretsSet: z5.array(z5.string()),
|
|
1956
|
-
/** Names of secret fields still awaiting user input. */
|
|
1957
|
-
secretsPending: z5.array(z5.string()),
|
|
1958
|
-
summary: z5.string(),
|
|
1959
|
-
stagedAt: z5.number()
|
|
1960
|
-
});
|
|
1961
|
-
var tagsEffectiveEntrySchema = z5.object({
|
|
1962
|
-
/** Real tag id, or `tag_temp_*` for staged creates. Use as flow side-effect `tagIds` value. */
|
|
1963
|
-
ref: z5.string(),
|
|
1964
|
-
tagId: z5.string().optional(),
|
|
1965
|
-
type: tagTypeSchema,
|
|
1966
|
-
/** Value of the type's identifying field, when set. */
|
|
1967
|
-
identifier: z5.string().optional(),
|
|
1968
|
-
/** Redacted config; for staged updates, production config with the patch merged. */
|
|
1969
|
-
config: z5.record(z5.string(), z5.string()),
|
|
1970
|
-
/** Absent = live production tag with no staged changes in this chat. */
|
|
1971
|
-
staged: tagDraftOpKindSchema.optional(),
|
|
1972
|
-
secretsSet: z5.array(z5.string()),
|
|
1973
|
-
secretsPending: z5.array(z5.string())
|
|
1974
|
-
});
|
|
1975
|
-
var tagsListRequestSchema = z5.object({ chatId: z5.string() });
|
|
1976
|
-
var tagsListResponseSchema = z5.object({ tags: z5.array(tagsEffectiveEntrySchema) });
|
|
1977
|
-
var tagsDraftListRequestSchema = z5.object({ chatId: z5.string() });
|
|
1978
|
-
var tagsDraftListResponseSchema = z5.object({
|
|
1979
|
-
status: z5.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
1980
|
-
ops: z5.array(tagDraftOpViewSchema)
|
|
1981
|
-
});
|
|
1982
|
-
var tagInputRequestSchema = z5.object({
|
|
1983
|
-
// Every tag change is a tab in the approval form: create/edit show the full
|
|
1984
|
-
// body; delete shows a confirm. No tag change bypasses this approval.
|
|
1985
|
-
mode: z5.enum(["create", "edit", "delete"]),
|
|
1986
|
-
tagType: tagTypeSchema,
|
|
1987
|
-
/** Edit/delete mode — the real tag id or `tag_temp_*` ref being changed. */
|
|
1988
|
-
ref: z5.string().optional(),
|
|
1989
|
-
/** Non-secret values the agent proposes to prefill. Secret keys are stripped at every boundary. */
|
|
1990
|
-
prefilledConfig: z5.record(z5.string(), z5.string()).optional(),
|
|
1991
|
-
/** Secret field names the agent asks the user to provide. */
|
|
1992
|
-
requestedSecretFields: z5.array(z5.string()).optional(),
|
|
1993
|
-
/** Short message shown above the form explaining why the input is needed. */
|
|
1994
|
-
message: z5.string().optional()
|
|
1995
|
-
});
|
|
1996
|
-
var tagChangeToolInputSchema = z5.object({
|
|
1997
|
-
changes: z5.array(tagInputRequestSchema).min(1).max(8)
|
|
1998
|
-
});
|
|
1999
|
-
var tagInputResultSchema = z5.discriminatedUnion("status", [
|
|
2000
|
-
z5.object({
|
|
2001
|
-
status: z5.literal("submitted"),
|
|
2002
|
-
ref: z5.string(),
|
|
2003
|
-
type: tagTypeSchema,
|
|
2004
|
-
/** Identifying field name → value (non-secret), when the type has one. */
|
|
2005
|
-
identifier: z5.record(z5.string(), z5.string()).optional(),
|
|
2006
|
-
secretFieldsSet: z5.array(z5.string()),
|
|
2007
|
-
note: z5.string().optional()
|
|
2008
|
-
}),
|
|
2009
|
-
z5.object({
|
|
2010
|
-
status: z5.literal("declined"),
|
|
2011
|
-
reason: z5.string().optional()
|
|
2012
|
-
})
|
|
2013
|
-
]);
|
|
2014
|
-
var tagChangeToolResultSchema = z5.object({
|
|
2015
|
-
results: z5.array(tagInputResultSchema)
|
|
2016
|
-
});
|
|
2017
|
-
|
|
2018
1927
|
// ../api/src/testimonials.ts
|
|
2019
|
-
import { z as
|
|
2020
|
-
var testimonialSourceTypeSchema =
|
|
2021
|
-
var testimonialStatusSchema =
|
|
2022
|
-
var testimonialSentimentSchema =
|
|
2023
|
-
var testimonialDocSchema =
|
|
2024
|
-
_id:
|
|
2025
|
-
_creationTime:
|
|
2026
|
-
companyId:
|
|
2027
|
-
sourceId:
|
|
1928
|
+
import { z as z5 } from "zod";
|
|
1929
|
+
var testimonialSourceTypeSchema = z5.enum(["google", "trustpilot"]);
|
|
1930
|
+
var testimonialStatusSchema = z5.enum(["pending", "processing", "ready", "error"]);
|
|
1931
|
+
var testimonialSentimentSchema = z5.enum(["positive", "neutral", "negative"]);
|
|
1932
|
+
var testimonialDocSchema = z5.object({
|
|
1933
|
+
_id: z5.string(),
|
|
1934
|
+
_creationTime: z5.number(),
|
|
1935
|
+
companyId: z5.string(),
|
|
1936
|
+
sourceId: z5.string(),
|
|
2028
1937
|
sourceType: testimonialSourceTypeSchema,
|
|
2029
|
-
reviewText:
|
|
2030
|
-
reviewTitle:
|
|
2031
|
-
searchText:
|
|
2032
|
-
reviewerName:
|
|
2033
|
-
reviewerImageUrl:
|
|
2034
|
-
reviewerImageId:
|
|
2035
|
-
reviewerLocation:
|
|
2036
|
-
rating:
|
|
2037
|
-
reviewDate:
|
|
2038
|
-
ownerAnswer:
|
|
2039
|
-
mediaUrls:
|
|
2040
|
-
imageIds:
|
|
2041
|
-
videoIds:
|
|
2042
|
-
sourceUrl:
|
|
2043
|
-
rawData:
|
|
2044
|
-
tags:
|
|
2045
|
-
highlight:
|
|
2046
|
-
language:
|
|
2047
|
-
summary:
|
|
1938
|
+
reviewText: z5.string(),
|
|
1939
|
+
reviewTitle: z5.string().optional(),
|
|
1940
|
+
searchText: z5.string().optional(),
|
|
1941
|
+
reviewerName: z5.string().optional(),
|
|
1942
|
+
reviewerImageUrl: z5.string().optional(),
|
|
1943
|
+
reviewerImageId: z5.string().optional(),
|
|
1944
|
+
reviewerLocation: z5.string().optional(),
|
|
1945
|
+
rating: z5.number().optional(),
|
|
1946
|
+
reviewDate: z5.number().optional(),
|
|
1947
|
+
ownerAnswer: z5.string().optional(),
|
|
1948
|
+
mediaUrls: z5.array(z5.string()).optional(),
|
|
1949
|
+
imageIds: z5.array(z5.string()).optional(),
|
|
1950
|
+
videoIds: z5.array(z5.string()).optional(),
|
|
1951
|
+
sourceUrl: z5.string().optional(),
|
|
1952
|
+
rawData: z5.unknown().optional(),
|
|
1953
|
+
tags: z5.array(z5.string()),
|
|
1954
|
+
highlight: z5.string().optional(),
|
|
1955
|
+
language: z5.string().optional(),
|
|
1956
|
+
summary: z5.string().optional(),
|
|
2048
1957
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2049
|
-
textEmbedding:
|
|
2050
|
-
externalId:
|
|
2051
|
-
contentHash:
|
|
1958
|
+
textEmbedding: z5.array(z5.number()).optional(),
|
|
1959
|
+
externalId: z5.string().optional(),
|
|
1960
|
+
contentHash: z5.string().optional(),
|
|
2052
1961
|
status: testimonialStatusSchema,
|
|
2053
|
-
errorMessage:
|
|
2054
|
-
createdAt:
|
|
2055
|
-
updatedAt:
|
|
1962
|
+
errorMessage: z5.string().optional(),
|
|
1963
|
+
createdAt: z5.number(),
|
|
1964
|
+
updatedAt: z5.number()
|
|
2056
1965
|
});
|
|
2057
|
-
var testimonialsListRequestSchema =
|
|
1966
|
+
var testimonialsListRequestSchema = z5.object({
|
|
2058
1967
|
source: testimonialSourceTypeSchema.optional(),
|
|
2059
|
-
rating_min:
|
|
2060
|
-
rating_max:
|
|
2061
|
-
tags:
|
|
1968
|
+
rating_min: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1969
|
+
rating_max: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1970
|
+
tags: z5.string().transform((s) => s.split(",").filter(Boolean)).optional(),
|
|
2062
1971
|
status: testimonialStatusSchema.optional(),
|
|
2063
1972
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2064
|
-
language:
|
|
2065
|
-
limit:
|
|
2066
|
-
});
|
|
2067
|
-
var testimonialsListResponseSchema =
|
|
2068
|
-
var testimonialsGetRequestSchema =
|
|
2069
|
-
var testimonialsSearchRequestSchema =
|
|
2070
|
-
query:
|
|
2071
|
-
limit:
|
|
1973
|
+
language: z5.string().min(2).max(5).optional(),
|
|
1974
|
+
limit: z5.coerce.number().int().positive().max(200).optional()
|
|
1975
|
+
});
|
|
1976
|
+
var testimonialsListResponseSchema = z5.array(testimonialDocSchema);
|
|
1977
|
+
var testimonialsGetRequestSchema = z5.object({ id: z5.string().min(1, "Missing id parameter") });
|
|
1978
|
+
var testimonialsSearchRequestSchema = z5.object({
|
|
1979
|
+
query: z5.string().min(1),
|
|
1980
|
+
limit: z5.coerce.number().int().positive().max(100).optional(),
|
|
2072
1981
|
source: testimonialSourceTypeSchema.optional(),
|
|
2073
|
-
rating_min:
|
|
2074
|
-
rating_max:
|
|
2075
|
-
tags:
|
|
1982
|
+
rating_min: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1983
|
+
rating_max: z5.coerce.number().int().min(1).max(5).optional(),
|
|
1984
|
+
tags: z5.array(z5.string()).optional(),
|
|
2076
1985
|
status: testimonialStatusSchema.optional(),
|
|
2077
1986
|
sentiment: testimonialSentimentSchema.optional(),
|
|
2078
|
-
language:
|
|
1987
|
+
language: z5.string().min(2).max(5).optional()
|
|
2079
1988
|
}).refine(
|
|
2080
1989
|
(data) => data.rating_min === void 0 || data.rating_max === void 0 || data.rating_min <= data.rating_max,
|
|
2081
1990
|
{ message: "rating_min must be less than or equal to rating_max" }
|
|
2082
1991
|
);
|
|
2083
|
-
var testimonialsSearchResponseSchema =
|
|
2084
|
-
var testimonialsOutscraperWebhookResponseSchema =
|
|
2085
|
-
ok:
|
|
2086
|
-
note:
|
|
1992
|
+
var testimonialsSearchResponseSchema = z5.array(testimonialDocSchema);
|
|
1993
|
+
var testimonialsOutscraperWebhookResponseSchema = z5.object({
|
|
1994
|
+
ok: z5.literal(true),
|
|
1995
|
+
note: z5.string().optional()
|
|
2087
1996
|
});
|
|
2088
1997
|
|
|
2089
1998
|
// ../api/src/videos.ts
|
|
2090
|
-
import { z as
|
|
2091
|
-
var videoStatusSchema =
|
|
2092
|
-
var videoTranscriptSegmentSchema =
|
|
2093
|
-
text:
|
|
2094
|
-
startSecond:
|
|
2095
|
-
endSecond:
|
|
2096
|
-
});
|
|
2097
|
-
var videoSceneSchema =
|
|
2098
|
-
title:
|
|
2099
|
-
description:
|
|
2100
|
-
startSecond:
|
|
2101
|
-
endSecond:
|
|
2102
|
-
thumbnailTime:
|
|
2103
|
-
});
|
|
2104
|
-
var videoDocSchema =
|
|
2105
|
-
_id:
|
|
2106
|
-
_creationTime:
|
|
2107
|
-
companyId:
|
|
2108
|
-
muxAssetId:
|
|
2109
|
-
muxPlaybackId:
|
|
2110
|
-
muxUploadId:
|
|
2111
|
-
name:
|
|
2112
|
-
description:
|
|
2113
|
-
tags:
|
|
2114
|
-
source:
|
|
2115
|
-
externalId:
|
|
2116
|
-
sourceId:
|
|
2117
|
-
width:
|
|
2118
|
-
height:
|
|
2119
|
-
aspectRatio:
|
|
2120
|
-
duration:
|
|
2121
|
-
transcript:
|
|
2122
|
-
transcriptSegments:
|
|
2123
|
-
scenes:
|
|
2124
|
-
descriptionEmbedding:
|
|
2125
|
-
searchText:
|
|
1999
|
+
import { z as z6 } from "zod";
|
|
2000
|
+
var videoStatusSchema = z6.enum(["uploading", "uploaded", "processing", "ready", "error"]);
|
|
2001
|
+
var videoTranscriptSegmentSchema = z6.object({
|
|
2002
|
+
text: z6.string(),
|
|
2003
|
+
startSecond: z6.number(),
|
|
2004
|
+
endSecond: z6.number()
|
|
2005
|
+
});
|
|
2006
|
+
var videoSceneSchema = z6.object({
|
|
2007
|
+
title: z6.string(),
|
|
2008
|
+
description: z6.string(),
|
|
2009
|
+
startSecond: z6.number(),
|
|
2010
|
+
endSecond: z6.number(),
|
|
2011
|
+
thumbnailTime: z6.number()
|
|
2012
|
+
});
|
|
2013
|
+
var videoDocSchema = z6.object({
|
|
2014
|
+
_id: z6.string(),
|
|
2015
|
+
_creationTime: z6.number(),
|
|
2016
|
+
companyId: z6.string(),
|
|
2017
|
+
muxAssetId: z6.string(),
|
|
2018
|
+
muxPlaybackId: z6.string(),
|
|
2019
|
+
muxUploadId: z6.string(),
|
|
2020
|
+
name: z6.string(),
|
|
2021
|
+
description: z6.string(),
|
|
2022
|
+
tags: z6.array(z6.string()),
|
|
2023
|
+
source: z6.string(),
|
|
2024
|
+
externalId: z6.string().optional(),
|
|
2025
|
+
sourceId: z6.string().optional(),
|
|
2026
|
+
width: z6.number().optional(),
|
|
2027
|
+
height: z6.number().optional(),
|
|
2028
|
+
aspectRatio: z6.number().optional(),
|
|
2029
|
+
duration: z6.number().optional(),
|
|
2030
|
+
transcript: z6.string().optional(),
|
|
2031
|
+
transcriptSegments: z6.array(videoTranscriptSegmentSchema).optional(),
|
|
2032
|
+
scenes: z6.array(videoSceneSchema).optional(),
|
|
2033
|
+
descriptionEmbedding: z6.array(z6.number()).optional(),
|
|
2034
|
+
searchText: z6.string().optional(),
|
|
2126
2035
|
status: videoStatusSchema,
|
|
2127
|
-
errorMessage:
|
|
2128
|
-
createdAt:
|
|
2129
|
-
updatedAt:
|
|
2130
|
-
thumbnailUrl:
|
|
2131
|
-
});
|
|
2132
|
-
var videosWebhookResponseSchema =
|
|
2133
|
-
var videosGetRequestSchema =
|
|
2134
|
-
var videosSearchRequestSchema =
|
|
2135
|
-
query:
|
|
2136
|
-
limit:
|
|
2137
|
-
tags:
|
|
2138
|
-
});
|
|
2139
|
-
var videoSearchResultSchema =
|
|
2140
|
-
_id:
|
|
2141
|
-
thumbnailUrl:
|
|
2142
|
-
name:
|
|
2143
|
-
description:
|
|
2144
|
-
tags:
|
|
2145
|
-
status:
|
|
2146
|
-
duration:
|
|
2147
|
-
muxPlaybackId:
|
|
2148
|
-
createdAt:
|
|
2149
|
-
});
|
|
2150
|
-
var videosSearchResponseSchema =
|
|
2151
|
-
var videosUploadResponseSchema =
|
|
2152
|
-
var videosDeleteRequestSchema =
|
|
2153
|
-
var videosDeleteResponseSchema =
|
|
2036
|
+
errorMessage: z6.string().optional(),
|
|
2037
|
+
createdAt: z6.number(),
|
|
2038
|
+
updatedAt: z6.number(),
|
|
2039
|
+
thumbnailUrl: z6.string()
|
|
2040
|
+
});
|
|
2041
|
+
var videosWebhookResponseSchema = z6.object({ ok: z6.literal(true) });
|
|
2042
|
+
var videosGetRequestSchema = z6.object({ id: z6.string().min(1, "Missing id parameter") });
|
|
2043
|
+
var videosSearchRequestSchema = z6.object({
|
|
2044
|
+
query: z6.string().min(1),
|
|
2045
|
+
limit: z6.coerce.number().int().positive().max(100).optional(),
|
|
2046
|
+
tags: z6.array(z6.string()).optional()
|
|
2047
|
+
});
|
|
2048
|
+
var videoSearchResultSchema = z6.object({
|
|
2049
|
+
_id: z6.string(),
|
|
2050
|
+
thumbnailUrl: z6.string(),
|
|
2051
|
+
name: z6.string(),
|
|
2052
|
+
description: z6.string(),
|
|
2053
|
+
tags: z6.array(z6.string()),
|
|
2054
|
+
status: z6.string(),
|
|
2055
|
+
duration: z6.number().optional(),
|
|
2056
|
+
muxPlaybackId: z6.string(),
|
|
2057
|
+
createdAt: z6.number()
|
|
2058
|
+
});
|
|
2059
|
+
var videosSearchResponseSchema = z6.array(videoSearchResultSchema);
|
|
2060
|
+
var videosUploadResponseSchema = z6.object({ uploadUrl: z6.string(), videoId: z6.string() });
|
|
2061
|
+
var videosDeleteRequestSchema = z6.object({ id: z6.string().min(1, "Missing video ID") });
|
|
2062
|
+
var videosDeleteResponseSchema = z6.object({ ok: z6.literal(true) });
|
|
2154
2063
|
|
|
2155
2064
|
// src/commands/actions/complete.ts
|
|
2156
2065
|
import { defineCommand as defineCommand2 } from "citty";
|
|
@@ -3963,37 +3872,37 @@ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
|
|
|
3963
3872
|
var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
|
|
3964
3873
|
|
|
3965
3874
|
// ../api/src/ads-google/ops.ts
|
|
3966
|
-
import { z as
|
|
3967
|
-
var tempRefSchema2 =
|
|
3968
|
-
var refSchema =
|
|
3969
|
-
|
|
3970
|
-
|
|
3875
|
+
import { z as z7 } from "zod";
|
|
3876
|
+
var tempRefSchema2 = z7.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
|
|
3877
|
+
var refSchema = z7.union([
|
|
3878
|
+
z7.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
|
|
3879
|
+
z7.string().regex(NUMERIC_ID_REGEX2, "expected a numeric id"),
|
|
3971
3880
|
tempRefSchema2
|
|
3972
3881
|
]);
|
|
3973
3882
|
var targetRefSchema = refSchema;
|
|
3974
|
-
var microsSchema =
|
|
3975
|
-
var httpsUrlSchema2 =
|
|
3976
|
-
var customerIdSchema =
|
|
3977
|
-
var stageableStatusSchema2 =
|
|
3978
|
-
var matchTypeSchema =
|
|
3979
|
-
var keywordTextSchema =
|
|
3980
|
-
var budgetCreateSchema =
|
|
3981
|
-
name:
|
|
3883
|
+
var microsSchema = z7.number().int().positive("expected a positive micros amount");
|
|
3884
|
+
var httpsUrlSchema2 = z7.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
|
|
3885
|
+
var customerIdSchema = z7.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
|
|
3886
|
+
var stageableStatusSchema2 = z7.enum(STAGEABLE_CREATE_STATUSES2);
|
|
3887
|
+
var matchTypeSchema = z7.enum(KEYWORD_MATCH_TYPES);
|
|
3888
|
+
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");
|
|
3889
|
+
var budgetCreateSchema = z7.object({
|
|
3890
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax),
|
|
3982
3891
|
amountMicros: microsSchema,
|
|
3983
|
-
deliveryMethod:
|
|
3984
|
-
explicitlyShared:
|
|
3892
|
+
deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
|
|
3893
|
+
explicitlyShared: z7.boolean().default(false)
|
|
3985
3894
|
});
|
|
3986
|
-
var budgetUpdateSchema =
|
|
3987
|
-
name:
|
|
3895
|
+
var budgetUpdateSchema = z7.object({
|
|
3896
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
|
|
3988
3897
|
amountMicros: microsSchema.optional(),
|
|
3989
|
-
deliveryMethod:
|
|
3898
|
+
deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).optional()
|
|
3990
3899
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
3991
|
-
var biddingConfigSchema =
|
|
3992
|
-
type:
|
|
3900
|
+
var biddingConfigSchema = z7.object({
|
|
3901
|
+
type: z7.enum(BIDDING_STRATEGY_TYPES),
|
|
3993
3902
|
targetCpaMicros: microsSchema.optional(),
|
|
3994
|
-
targetRoas:
|
|
3903
|
+
targetRoas: z7.number().positive().optional(),
|
|
3995
3904
|
cpcBidCeilingMicros: microsSchema.optional(),
|
|
3996
|
-
enhancedCpcEnabled:
|
|
3905
|
+
enhancedCpcEnabled: z7.boolean().optional()
|
|
3997
3906
|
}).superRefine((p, ctx) => {
|
|
3998
3907
|
if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
|
|
3999
3908
|
ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
|
|
@@ -4002,17 +3911,17 @@ var biddingConfigSchema = z8.object({
|
|
|
4002
3911
|
ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
|
|
4003
3912
|
}
|
|
4004
3913
|
});
|
|
4005
|
-
var networkSettingsSchema =
|
|
4006
|
-
targetGoogleSearch:
|
|
4007
|
-
targetSearchNetwork:
|
|
4008
|
-
targetContentNetwork:
|
|
4009
|
-
targetPartnerSearchNetwork:
|
|
3914
|
+
var networkSettingsSchema = z7.object({
|
|
3915
|
+
targetGoogleSearch: z7.boolean().optional(),
|
|
3916
|
+
targetSearchNetwork: z7.boolean().optional(),
|
|
3917
|
+
targetContentNetwork: z7.boolean().optional(),
|
|
3918
|
+
targetPartnerSearchNetwork: z7.boolean().optional()
|
|
4010
3919
|
});
|
|
4011
|
-
var dateSchema =
|
|
4012
|
-
var campaignCreateSchema2 =
|
|
4013
|
-
name:
|
|
4014
|
-
channelType:
|
|
4015
|
-
channelSubType:
|
|
3920
|
+
var dateSchema = z7.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
|
|
3921
|
+
var campaignCreateSchema2 = z7.object({
|
|
3922
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
|
|
3923
|
+
channelType: z7.enum(ADVERTISING_CHANNEL_TYPES),
|
|
3924
|
+
channelSubType: z7.enum(ADVERTISING_CHANNEL_SUB_TYPES).optional(),
|
|
4016
3925
|
budget: refSchema,
|
|
4017
3926
|
/** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
|
|
4018
3927
|
bidding: biddingConfigSchema.optional(),
|
|
@@ -4021,7 +3930,7 @@ var campaignCreateSchema2 = z8.object({
|
|
|
4021
3930
|
startDate: dateSchema.optional(),
|
|
4022
3931
|
endDate: dateSchema.optional(),
|
|
4023
3932
|
/** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
|
|
4024
|
-
objective:
|
|
3933
|
+
objective: z7.enum(CAMPAIGN_OBJECTIVES).optional(),
|
|
4025
3934
|
status: stageableStatusSchema2.default("PAUSED")
|
|
4026
3935
|
}).superRefine((p, ctx) => {
|
|
4027
3936
|
if (!p.bidding && !p.biddingStrategy) {
|
|
@@ -4045,129 +3954,129 @@ var campaignCreateSchema2 = z8.object({
|
|
|
4045
3954
|
ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
|
|
4046
3955
|
}
|
|
4047
3956
|
});
|
|
4048
|
-
var campaignUpdateSchema2 =
|
|
4049
|
-
name:
|
|
3957
|
+
var campaignUpdateSchema2 = z7.object({
|
|
3958
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
|
|
4050
3959
|
budget: refSchema.optional(),
|
|
4051
3960
|
bidding: biddingConfigSchema.optional(),
|
|
4052
3961
|
networkSettings: networkSettingsSchema.optional(),
|
|
4053
3962
|
startDate: dateSchema.optional(),
|
|
4054
3963
|
endDate: dateSchema.optional(),
|
|
4055
|
-
status:
|
|
3964
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4056
3965
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4057
|
-
var adGroupCreateSchema =
|
|
4058
|
-
name:
|
|
3966
|
+
var adGroupCreateSchema = z7.object({
|
|
3967
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
|
|
4059
3968
|
campaign: refSchema,
|
|
4060
|
-
type:
|
|
3969
|
+
type: z7.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
|
|
4061
3970
|
cpcBidMicros: microsSchema.optional(),
|
|
4062
3971
|
status: stageableStatusSchema2.default("PAUSED")
|
|
4063
3972
|
});
|
|
4064
|
-
var adGroupUpdateSchema =
|
|
4065
|
-
name:
|
|
3973
|
+
var adGroupUpdateSchema = z7.object({
|
|
3974
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
|
|
4066
3975
|
cpcBidMicros: microsSchema.optional(),
|
|
4067
|
-
status:
|
|
3976
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4068
3977
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4069
|
-
var keywordAddSchema =
|
|
3978
|
+
var keywordAddSchema = z7.object({
|
|
4070
3979
|
adGroup: refSchema,
|
|
4071
3980
|
text: keywordTextSchema,
|
|
4072
3981
|
matchType: matchTypeSchema,
|
|
4073
3982
|
cpcBidMicros: microsSchema.optional(),
|
|
4074
|
-
finalUrls:
|
|
3983
|
+
finalUrls: z7.array(httpsUrlSchema2).optional(),
|
|
4075
3984
|
status: stageableStatusSchema2.default("ENABLED")
|
|
4076
3985
|
});
|
|
4077
|
-
var keywordUpdateSchema =
|
|
3986
|
+
var keywordUpdateSchema = z7.object({
|
|
4078
3987
|
cpcBidMicros: microsSchema.optional(),
|
|
4079
|
-
finalUrls:
|
|
4080
|
-
status:
|
|
3988
|
+
finalUrls: z7.array(httpsUrlSchema2).optional(),
|
|
3989
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4081
3990
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4082
|
-
var negativeKeywordAddSchema =
|
|
4083
|
-
level:
|
|
3991
|
+
var negativeKeywordAddSchema = z7.object({
|
|
3992
|
+
level: z7.enum(["adGroup", "campaign"]),
|
|
4084
3993
|
parent: refSchema,
|
|
4085
3994
|
text: keywordTextSchema,
|
|
4086
3995
|
matchType: matchTypeSchema
|
|
4087
3996
|
});
|
|
4088
|
-
var sharedSetCreateSchema =
|
|
4089
|
-
name:
|
|
4090
|
-
type:
|
|
3997
|
+
var sharedSetCreateSchema = z7.object({
|
|
3998
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
|
|
3999
|
+
type: z7.enum(SHARED_SET_TYPES).default("NEGATIVE_KEYWORDS")
|
|
4091
4000
|
});
|
|
4092
|
-
var sharedSetMemberAddSchema =
|
|
4001
|
+
var sharedSetMemberAddSchema = z7.object({
|
|
4093
4002
|
sharedSet: refSchema,
|
|
4094
4003
|
text: keywordTextSchema,
|
|
4095
4004
|
matchType: matchTypeSchema
|
|
4096
4005
|
});
|
|
4097
|
-
var campaignSharedSetAttachSchema =
|
|
4006
|
+
var campaignSharedSetAttachSchema = z7.object({
|
|
4098
4007
|
campaign: refSchema,
|
|
4099
4008
|
sharedSet: refSchema
|
|
4100
4009
|
});
|
|
4101
|
-
var adTextAssetSchema =
|
|
4102
|
-
text:
|
|
4103
|
-
pinnedField:
|
|
4010
|
+
var adTextAssetSchema = z7.object({
|
|
4011
|
+
text: z7.string().min(1),
|
|
4012
|
+
pinnedField: z7.enum(PINNED_FIELDS).optional()
|
|
4104
4013
|
});
|
|
4105
|
-
var responsiveSearchAdSchema =
|
|
4106
|
-
format:
|
|
4107
|
-
headlines:
|
|
4014
|
+
var responsiveSearchAdSchema = z7.object({
|
|
4015
|
+
format: z7.literal("responsiveSearch"),
|
|
4016
|
+
headlines: z7.array(
|
|
4108
4017
|
adTextAssetSchema.refine(
|
|
4109
4018
|
(a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
|
|
4110
4019
|
"headline exceeds 30 chars"
|
|
4111
4020
|
)
|
|
4112
4021
|
).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
|
|
4113
|
-
descriptions:
|
|
4022
|
+
descriptions: z7.array(
|
|
4114
4023
|
adTextAssetSchema.refine(
|
|
4115
4024
|
(a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
|
|
4116
4025
|
"description exceeds 90 chars"
|
|
4117
4026
|
)
|
|
4118
4027
|
).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
|
|
4119
|
-
path1:
|
|
4120
|
-
path2:
|
|
4121
|
-
finalUrls:
|
|
4122
|
-
});
|
|
4123
|
-
var responsiveDisplayAdSchema =
|
|
4124
|
-
format:
|
|
4125
|
-
headlines:
|
|
4126
|
-
longHeadline:
|
|
4127
|
-
descriptions:
|
|
4128
|
-
businessName:
|
|
4028
|
+
path1: z7.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
|
|
4029
|
+
path2: z7.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
|
|
4030
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4031
|
+
});
|
|
4032
|
+
var responsiveDisplayAdSchema = z7.object({
|
|
4033
|
+
format: z7.literal("responsiveDisplay"),
|
|
4034
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
|
|
4035
|
+
longHeadline: z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
|
|
4036
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
|
|
4037
|
+
businessName: z7.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.businessNameMax),
|
|
4129
4038
|
// A Responsive Display Ad's images are fields on the ad's own content (never campaign-level
|
|
4130
4039
|
// asset links). Google requires ≥1 landscape marketing image (1.91:1) AND ≥1 square marketing
|
|
4131
4040
|
// image (1:1) to serve; the logo images are optional.
|
|
4132
|
-
marketingImageAssets:
|
|
4133
|
-
squareMarketingImageAssets:
|
|
4134
|
-
logoImageAssets:
|
|
4135
|
-
finalUrls:
|
|
4136
|
-
});
|
|
4137
|
-
var callAdSchema =
|
|
4138
|
-
format:
|
|
4139
|
-
countryCode:
|
|
4140
|
-
phoneNumber:
|
|
4141
|
-
headline1:
|
|
4142
|
-
headline2:
|
|
4143
|
-
description1:
|
|
4144
|
-
description2:
|
|
4145
|
-
businessName:
|
|
4146
|
-
finalUrls:
|
|
4147
|
-
});
|
|
4148
|
-
var appAdSchema =
|
|
4149
|
-
format:
|
|
4150
|
-
headlines:
|
|
4151
|
-
descriptions:
|
|
4152
|
-
});
|
|
4153
|
-
var videoAdSchema =
|
|
4154
|
-
format:
|
|
4041
|
+
marketingImageAssets: z7.array(refSchema).optional(),
|
|
4042
|
+
squareMarketingImageAssets: z7.array(refSchema).optional(),
|
|
4043
|
+
logoImageAssets: z7.array(refSchema).optional(),
|
|
4044
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4045
|
+
});
|
|
4046
|
+
var callAdSchema = z7.object({
|
|
4047
|
+
format: z7.literal("call"),
|
|
4048
|
+
countryCode: z7.string().length(2),
|
|
4049
|
+
phoneNumber: z7.string().min(3),
|
|
4050
|
+
headline1: z7.string().min(1).max(30),
|
|
4051
|
+
headline2: z7.string().min(1).max(30),
|
|
4052
|
+
description1: z7.string().min(1).max(90),
|
|
4053
|
+
description2: z7.string().min(1).max(90),
|
|
4054
|
+
businessName: z7.string().min(1).max(25),
|
|
4055
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4056
|
+
});
|
|
4057
|
+
var appAdSchema = z7.object({
|
|
4058
|
+
format: z7.literal("app"),
|
|
4059
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(30) })).min(1),
|
|
4060
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(90) })).min(1)
|
|
4061
|
+
});
|
|
4062
|
+
var videoAdSchema = z7.object({
|
|
4063
|
+
format: z7.literal("video"),
|
|
4155
4064
|
// A raw YouTube id is not a publishable Google Ads reference — the video must be staged as
|
|
4156
4065
|
// its own `google.asset.create` (type: youtubeVideo) first, then referenced here by asset ref.
|
|
4157
|
-
videoAssets:
|
|
4158
|
-
finalUrls:
|
|
4159
|
-
});
|
|
4160
|
-
var demandGenAdSchema =
|
|
4161
|
-
format:
|
|
4162
|
-
headlines:
|
|
4163
|
-
descriptions:
|
|
4164
|
-
businessName:
|
|
4165
|
-
finalUrls:
|
|
4166
|
-
imageAssets:
|
|
4167
|
-
squareImageAssets:
|
|
4168
|
-
logoImageAssets:
|
|
4169
|
-
});
|
|
4170
|
-
var adContentSchema =
|
|
4066
|
+
videoAssets: z7.array(refSchema).min(1),
|
|
4067
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4068
|
+
});
|
|
4069
|
+
var demandGenAdSchema = z7.object({
|
|
4070
|
+
format: z7.literal("demandGen"),
|
|
4071
|
+
headlines: z7.array(z7.object({ text: z7.string().min(1).max(40) })).min(1).max(5),
|
|
4072
|
+
descriptions: z7.array(z7.object({ text: z7.string().min(1).max(90) })).min(1).max(5),
|
|
4073
|
+
businessName: z7.string().min(1).max(25),
|
|
4074
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1),
|
|
4075
|
+
imageAssets: z7.array(refSchema).optional(),
|
|
4076
|
+
squareImageAssets: z7.array(refSchema).optional(),
|
|
4077
|
+
logoImageAssets: z7.array(refSchema).optional()
|
|
4078
|
+
});
|
|
4079
|
+
var adContentSchema = z7.discriminatedUnion("format", [
|
|
4171
4080
|
responsiveSearchAdSchema,
|
|
4172
4081
|
responsiveDisplayAdSchema,
|
|
4173
4082
|
callAdSchema,
|
|
@@ -4175,45 +4084,45 @@ var adContentSchema = z8.discriminatedUnion("format", [
|
|
|
4175
4084
|
videoAdSchema,
|
|
4176
4085
|
demandGenAdSchema
|
|
4177
4086
|
]);
|
|
4178
|
-
var adCreateSchema =
|
|
4087
|
+
var adCreateSchema = z7.object({
|
|
4179
4088
|
adGroup: refSchema,
|
|
4180
4089
|
status: stageableStatusSchema2.default("PAUSED"),
|
|
4181
4090
|
content: adContentSchema
|
|
4182
4091
|
});
|
|
4183
|
-
var adUpdateSchema =
|
|
4184
|
-
status:
|
|
4092
|
+
var adUpdateSchema = z7.object({
|
|
4093
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
|
|
4185
4094
|
/** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
|
|
4186
|
-
content:
|
|
4095
|
+
content: z7.record(z7.string(), z7.unknown()).optional()
|
|
4187
4096
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4188
|
-
var textAssetSchema =
|
|
4189
|
-
var imageAssetSchema =
|
|
4190
|
-
type:
|
|
4191
|
-
imageId:
|
|
4192
|
-
name:
|
|
4193
|
-
});
|
|
4194
|
-
var youtubeVideoAssetSchema =
|
|
4195
|
-
type:
|
|
4196
|
-
youtubeVideoId:
|
|
4197
|
-
name:
|
|
4198
|
-
});
|
|
4199
|
-
var sitelinkAssetSchema =
|
|
4200
|
-
type:
|
|
4201
|
-
linkText:
|
|
4202
|
-
description1:
|
|
4203
|
-
description2:
|
|
4204
|
-
finalUrls:
|
|
4205
|
-
});
|
|
4206
|
-
var calloutAssetSchema =
|
|
4207
|
-
type:
|
|
4208
|
-
calloutText:
|
|
4209
|
-
});
|
|
4210
|
-
var structuredSnippetAssetSchema =
|
|
4211
|
-
type:
|
|
4212
|
-
header:
|
|
4213
|
-
values:
|
|
4214
|
-
});
|
|
4215
|
-
var callToActionAssetSchema =
|
|
4216
|
-
var assetCreateSchema =
|
|
4097
|
+
var textAssetSchema = z7.object({ type: z7.literal("text"), text: z7.string().min(1) });
|
|
4098
|
+
var imageAssetSchema = z7.object({
|
|
4099
|
+
type: z7.literal("image"),
|
|
4100
|
+
imageId: z7.string().min(1),
|
|
4101
|
+
name: z7.string().optional()
|
|
4102
|
+
});
|
|
4103
|
+
var youtubeVideoAssetSchema = z7.object({
|
|
4104
|
+
type: z7.literal("youtubeVideo"),
|
|
4105
|
+
youtubeVideoId: z7.string().min(1),
|
|
4106
|
+
name: z7.string().optional()
|
|
4107
|
+
});
|
|
4108
|
+
var sitelinkAssetSchema = z7.object({
|
|
4109
|
+
type: z7.literal("sitelink"),
|
|
4110
|
+
linkText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
|
|
4111
|
+
description1: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4112
|
+
description2: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4113
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1)
|
|
4114
|
+
});
|
|
4115
|
+
var calloutAssetSchema = z7.object({
|
|
4116
|
+
type: z7.literal("callout"),
|
|
4117
|
+
calloutText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
|
|
4118
|
+
});
|
|
4119
|
+
var structuredSnippetAssetSchema = z7.object({
|
|
4120
|
+
type: z7.literal("structuredSnippet"),
|
|
4121
|
+
header: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
|
|
4122
|
+
values: z7.array(z7.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
|
|
4123
|
+
});
|
|
4124
|
+
var callToActionAssetSchema = z7.object({ type: z7.literal("callToAction"), callToAction: z7.string().min(1) });
|
|
4125
|
+
var assetCreateSchema = z7.discriminatedUnion("type", [
|
|
4217
4126
|
textAssetSchema,
|
|
4218
4127
|
imageAssetSchema,
|
|
4219
4128
|
youtubeVideoAssetSchema,
|
|
@@ -4222,136 +4131,136 @@ var assetCreateSchema = z8.discriminatedUnion("type", [
|
|
|
4222
4131
|
structuredSnippetAssetSchema,
|
|
4223
4132
|
callToActionAssetSchema
|
|
4224
4133
|
]);
|
|
4225
|
-
var assetUpdateSchema =
|
|
4226
|
-
name:
|
|
4227
|
-
linkText:
|
|
4228
|
-
description1:
|
|
4229
|
-
description2:
|
|
4230
|
-
finalUrls:
|
|
4231
|
-
calloutText:
|
|
4232
|
-
header:
|
|
4233
|
-
values:
|
|
4234
|
-
callToAction:
|
|
4235
|
-
text:
|
|
4134
|
+
var assetUpdateSchema = z7.object({
|
|
4135
|
+
name: z7.string().min(1).optional(),
|
|
4136
|
+
linkText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax).optional(),
|
|
4137
|
+
description1: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4138
|
+
description2: z7.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
|
|
4139
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1).optional(),
|
|
4140
|
+
calloutText: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax).optional(),
|
|
4141
|
+
header: z7.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax).optional(),
|
|
4142
|
+
values: z7.array(z7.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
|
|
4143
|
+
callToAction: z7.string().min(1).optional(),
|
|
4144
|
+
text: z7.string().min(1).optional()
|
|
4236
4145
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4237
|
-
var assetLinkAttachSchema =
|
|
4238
|
-
level:
|
|
4146
|
+
var assetLinkAttachSchema = z7.object({
|
|
4147
|
+
level: z7.enum(["campaign", "adGroup", "customer"]),
|
|
4239
4148
|
parent: refSchema.optional(),
|
|
4240
4149
|
asset: refSchema,
|
|
4241
|
-
fieldType:
|
|
4150
|
+
fieldType: z7.enum(ASSET_FIELD_TYPES)
|
|
4242
4151
|
}).superRefine((value, ctx) => {
|
|
4243
4152
|
if (value.level !== "customer" && !value.parent) {
|
|
4244
4153
|
ctx.addIssue({
|
|
4245
|
-
code:
|
|
4154
|
+
code: z7.ZodIssueCode.custom,
|
|
4246
4155
|
path: ["parent"],
|
|
4247
4156
|
message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
|
|
4248
4157
|
});
|
|
4249
4158
|
}
|
|
4250
4159
|
});
|
|
4251
|
-
var assetGroupCreateSchema =
|
|
4160
|
+
var assetGroupCreateSchema = z7.object({
|
|
4252
4161
|
campaign: refSchema,
|
|
4253
|
-
name:
|
|
4254
|
-
finalUrls:
|
|
4255
|
-
headlines:
|
|
4256
|
-
longHeadlines:
|
|
4257
|
-
descriptions:
|
|
4258
|
-
businessName:
|
|
4259
|
-
imageAssets:
|
|
4260
|
-
squareImageAssets:
|
|
4261
|
-
logoAssets:
|
|
4262
|
-
status:
|
|
4263
|
-
});
|
|
4264
|
-
var assetGroupUpdateSchema =
|
|
4265
|
-
name:
|
|
4266
|
-
finalUrls:
|
|
4267
|
-
status:
|
|
4162
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax),
|
|
4163
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1),
|
|
4164
|
+
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),
|
|
4165
|
+
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),
|
|
4166
|
+
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),
|
|
4167
|
+
businessName: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.businessNameMax),
|
|
4168
|
+
imageAssets: z7.array(refSchema).optional(),
|
|
4169
|
+
squareImageAssets: z7.array(refSchema).optional(),
|
|
4170
|
+
logoAssets: z7.array(refSchema).optional(),
|
|
4171
|
+
status: z7.enum(["ENABLED", "PAUSED"]).default("PAUSED")
|
|
4172
|
+
});
|
|
4173
|
+
var assetGroupUpdateSchema = z7.object({
|
|
4174
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax).optional(),
|
|
4175
|
+
finalUrls: z7.array(httpsUrlSchema2).min(1).optional(),
|
|
4176
|
+
status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
|
|
4268
4177
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4269
|
-
var audienceCreateSchema2 =
|
|
4270
|
-
name:
|
|
4271
|
-
type:
|
|
4272
|
-
description:
|
|
4178
|
+
var audienceCreateSchema2 = z7.object({
|
|
4179
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
|
|
4180
|
+
type: z7.enum(USER_LIST_TYPES).default("BASIC"),
|
|
4181
|
+
description: z7.string().optional(),
|
|
4273
4182
|
/** Customer-match members (crm-based) — file-first for large lists. */
|
|
4274
|
-
members:
|
|
4275
|
-
sourceFileRef:
|
|
4183
|
+
members: z7.array(z7.record(z7.string(), z7.string())).optional(),
|
|
4184
|
+
sourceFileRef: z7.string().optional()
|
|
4276
4185
|
});
|
|
4277
|
-
var audienceCriterionAttachSchema =
|
|
4278
|
-
level:
|
|
4186
|
+
var audienceCriterionAttachSchema = z7.object({
|
|
4187
|
+
level: z7.enum(["campaign", "adGroup"]),
|
|
4279
4188
|
parent: refSchema,
|
|
4280
4189
|
userList: refSchema,
|
|
4281
|
-
negative:
|
|
4190
|
+
negative: z7.boolean().default(false)
|
|
4282
4191
|
});
|
|
4283
|
-
var conversionActionCreateSchema =
|
|
4284
|
-
name:
|
|
4285
|
-
type:
|
|
4286
|
-
category:
|
|
4287
|
-
countingType:
|
|
4192
|
+
var conversionActionCreateSchema = z7.object({
|
|
4193
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
|
|
4194
|
+
type: z7.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
|
|
4195
|
+
category: z7.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
|
|
4196
|
+
countingType: z7.enum(CONVERSION_COUNTING_TYPES).default("ONE_PER_CLICK"),
|
|
4288
4197
|
defaultValueMicros: microsSchema.optional(),
|
|
4289
|
-
defaultCurrencyCode:
|
|
4290
|
-
clickThroughLookbackWindowDays:
|
|
4291
|
-
viewThroughLookbackWindowDays:
|
|
4292
|
-
status:
|
|
4293
|
-
});
|
|
4294
|
-
var conversionActionUpdateSchema =
|
|
4295
|
-
name:
|
|
4296
|
-
category:
|
|
4297
|
-
countingType:
|
|
4198
|
+
defaultCurrencyCode: z7.string().length(3).optional(),
|
|
4199
|
+
clickThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4200
|
+
viewThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4201
|
+
status: z7.enum(["ENABLED", "PAUSED"]).default("ENABLED")
|
|
4202
|
+
});
|
|
4203
|
+
var conversionActionUpdateSchema = z7.object({
|
|
4204
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
|
|
4205
|
+
category: z7.enum(CONVERSION_ACTION_CATEGORIES).optional(),
|
|
4206
|
+
countingType: z7.enum(CONVERSION_COUNTING_TYPES).optional(),
|
|
4298
4207
|
defaultValueMicros: microsSchema.optional(),
|
|
4299
|
-
defaultCurrencyCode:
|
|
4300
|
-
clickThroughLookbackWindowDays:
|
|
4301
|
-
viewThroughLookbackWindowDays:
|
|
4302
|
-
status:
|
|
4208
|
+
defaultCurrencyCode: z7.string().length(3).optional(),
|
|
4209
|
+
clickThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4210
|
+
viewThroughLookbackWindowDays: z7.number().int().positive().optional(),
|
|
4211
|
+
status: z7.enum(["ENABLED", "REMOVED", "HIDDEN"]).optional()
|
|
4303
4212
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4304
|
-
var biddingStrategyCreateSchema =
|
|
4305
|
-
name:
|
|
4213
|
+
var biddingStrategyCreateSchema = z7.object({
|
|
4214
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
|
|
4306
4215
|
config: biddingConfigSchema
|
|
4307
4216
|
}).superRefine((p, ctx) => {
|
|
4308
4217
|
if (p.config.type === "MANUAL_CPC") {
|
|
4309
4218
|
ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
|
|
4310
4219
|
}
|
|
4311
4220
|
});
|
|
4312
|
-
var biddingStrategyUpdateSchema =
|
|
4313
|
-
name:
|
|
4221
|
+
var biddingStrategyUpdateSchema = z7.object({
|
|
4222
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
|
|
4314
4223
|
config: biddingConfigSchema.optional()
|
|
4315
4224
|
}).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
|
|
4316
|
-
var labelCreateSchema =
|
|
4317
|
-
name:
|
|
4318
|
-
backgroundColor:
|
|
4319
|
-
description:
|
|
4225
|
+
var labelCreateSchema = z7.object({
|
|
4226
|
+
name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
|
|
4227
|
+
backgroundColor: z7.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
|
|
4228
|
+
description: z7.string().optional()
|
|
4320
4229
|
});
|
|
4321
|
-
var labelAttachSchema =
|
|
4322
|
-
level:
|
|
4230
|
+
var labelAttachSchema = z7.object({
|
|
4231
|
+
level: z7.enum(["campaign", "adGroup", "ad"]),
|
|
4323
4232
|
parent: refSchema,
|
|
4324
4233
|
label: refSchema
|
|
4325
4234
|
});
|
|
4326
|
-
var locationCriterionSchema =
|
|
4327
|
-
criterionType:
|
|
4328
|
-
geoTargetConstant:
|
|
4329
|
-
});
|
|
4330
|
-
var languageCriterionSchema =
|
|
4331
|
-
criterionType:
|
|
4332
|
-
languageConstant:
|
|
4333
|
-
});
|
|
4334
|
-
var adScheduleCriterionSchema =
|
|
4335
|
-
criterionType:
|
|
4336
|
-
dayOfWeek:
|
|
4337
|
-
startHour:
|
|
4338
|
-
startMinute:
|
|
4339
|
-
endHour:
|
|
4340
|
-
endMinute:
|
|
4341
|
-
});
|
|
4342
|
-
var deviceCriterionSchema =
|
|
4343
|
-
criterionType:
|
|
4344
|
-
device:
|
|
4235
|
+
var locationCriterionSchema = z7.object({
|
|
4236
|
+
criterionType: z7.literal("location"),
|
|
4237
|
+
geoTargetConstant: z7.union([z7.string().regex(GEO_TARGET_CONSTANT_REGEX), z7.string().regex(NUMERIC_ID_REGEX2)])
|
|
4238
|
+
});
|
|
4239
|
+
var languageCriterionSchema = z7.object({
|
|
4240
|
+
criterionType: z7.literal("language"),
|
|
4241
|
+
languageConstant: z7.union([z7.string().regex(LANGUAGE_CONSTANT_REGEX), z7.string().regex(NUMERIC_ID_REGEX2)])
|
|
4242
|
+
});
|
|
4243
|
+
var adScheduleCriterionSchema = z7.object({
|
|
4244
|
+
criterionType: z7.literal("adSchedule"),
|
|
4245
|
+
dayOfWeek: z7.enum(DAYS_OF_WEEK),
|
|
4246
|
+
startHour: z7.number().int().min(0).max(23),
|
|
4247
|
+
startMinute: z7.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
|
|
4248
|
+
endHour: z7.number().int().min(0).max(24),
|
|
4249
|
+
endMinute: z7.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
|
|
4250
|
+
});
|
|
4251
|
+
var deviceCriterionSchema = z7.object({
|
|
4252
|
+
criterionType: z7.literal("device"),
|
|
4253
|
+
device: z7.enum(DEVICE_TYPES),
|
|
4345
4254
|
// Google's `CampaignCriterion.bid_modifier`: "The modifier must be in the range 0.1 - 10.0. Use 0
|
|
4346
4255
|
// 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.
|
|
4347
|
-
bidModifier:
|
|
4256
|
+
bidModifier: z7.number().min(0).max(10).optional().refine((v) => v === void 0 || v === 0 || v >= 0.1, {
|
|
4348
4257
|
message: "bid modifier must be 0 (exclude the device) or between 0.1 and 10.0"
|
|
4349
4258
|
})
|
|
4350
4259
|
});
|
|
4351
|
-
var campaignCriterionAddSchema =
|
|
4260
|
+
var campaignCriterionAddSchema = z7.object({
|
|
4352
4261
|
campaign: refSchema,
|
|
4353
|
-
negative:
|
|
4354
|
-
criterion:
|
|
4262
|
+
negative: z7.boolean().default(false),
|
|
4263
|
+
criterion: z7.discriminatedUnion("criterionType", [
|
|
4355
4264
|
locationCriterionSchema,
|
|
4356
4265
|
languageCriterionSchema,
|
|
4357
4266
|
adScheduleCriterionSchema,
|
|
@@ -4361,7 +4270,7 @@ var campaignCriterionAddSchema = z8.object({
|
|
|
4361
4270
|
const c = val.criterion;
|
|
4362
4271
|
if (c.criterionType === "adSchedule" && c.endHour === 24 && c.endMinute !== "ZERO") {
|
|
4363
4272
|
ctx.addIssue({
|
|
4364
|
-
code:
|
|
4273
|
+
code: z7.ZodIssueCode.custom,
|
|
4365
4274
|
message: "endHour 24 (midnight) cannot have a non-zero endMinute",
|
|
4366
4275
|
path: ["criterion", "endMinute"]
|
|
4367
4276
|
});
|
|
@@ -4413,17 +4322,17 @@ var GOOGLE_DRAFT_OP_KINDS = [
|
|
|
4413
4322
|
"google.campaignCriterion.add",
|
|
4414
4323
|
"google.campaignCriterion.remove"
|
|
4415
4324
|
];
|
|
4416
|
-
var googleDraftOpKindSchema =
|
|
4325
|
+
var googleDraftOpKindSchema = z7.enum(GOOGLE_DRAFT_OP_KINDS);
|
|
4417
4326
|
function createOp2(kind, payload) {
|
|
4418
|
-
return
|
|
4327
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, payload });
|
|
4419
4328
|
}
|
|
4420
4329
|
function updateOp2(kind, payload) {
|
|
4421
|
-
return
|
|
4330
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
|
|
4422
4331
|
}
|
|
4423
4332
|
function targetOp(kind) {
|
|
4424
|
-
return
|
|
4333
|
+
return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
|
|
4425
4334
|
}
|
|
4426
|
-
var googleDraftOpInputSchema =
|
|
4335
|
+
var googleDraftOpInputSchema = z7.discriminatedUnion("kind", [
|
|
4427
4336
|
createOp2("google.budget.create", budgetCreateSchema),
|
|
4428
4337
|
updateOp2("google.budget.update", budgetUpdateSchema),
|
|
4429
4338
|
createOp2("google.campaign.create", campaignCreateSchema2),
|
|
@@ -4471,132 +4380,132 @@ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
|
|
|
4471
4380
|
]);
|
|
4472
4381
|
|
|
4473
4382
|
// ../api/src/ads-google/wire.ts
|
|
4474
|
-
import { z as
|
|
4475
|
-
var googleWriteModeSchema =
|
|
4476
|
-
var googleDraftOpResultSchema =
|
|
4477
|
-
status:
|
|
4478
|
-
resourceName:
|
|
4479
|
-
error:
|
|
4480
|
-
skippedBecause:
|
|
4481
|
-
executedAt:
|
|
4482
|
-
});
|
|
4483
|
-
var googleDraftStageRequestSchema =
|
|
4484
|
-
chatId:
|
|
4383
|
+
import { z as z8 } from "zod";
|
|
4384
|
+
var googleWriteModeSchema = z8.enum(["live", "simulated"]);
|
|
4385
|
+
var googleDraftOpResultSchema = z8.object({
|
|
4386
|
+
status: z8.enum(["applied", "simulated", "failed", "skipped"]),
|
|
4387
|
+
resourceName: z8.string().optional(),
|
|
4388
|
+
error: z8.string().optional(),
|
|
4389
|
+
skippedBecause: z8.string().optional(),
|
|
4390
|
+
executedAt: z8.number().optional()
|
|
4391
|
+
});
|
|
4392
|
+
var googleDraftStageRequestSchema = z8.object({
|
|
4393
|
+
chatId: z8.string(),
|
|
4485
4394
|
op: googleDraftOpInputSchema
|
|
4486
4395
|
});
|
|
4487
|
-
var googleDraftStageResponseSchema =
|
|
4488
|
-
staged:
|
|
4489
|
-
ref:
|
|
4396
|
+
var googleDraftStageResponseSchema = z8.object({
|
|
4397
|
+
staged: z8.literal(true),
|
|
4398
|
+
ref: z8.string(),
|
|
4490
4399
|
kind: googleDraftOpKindSchema,
|
|
4491
4400
|
mode: googleWriteModeSchema,
|
|
4492
|
-
dependsOn:
|
|
4493
|
-
summary:
|
|
4494
|
-
warnings:
|
|
4401
|
+
dependsOn: z8.array(z8.string()),
|
|
4402
|
+
summary: z8.string(),
|
|
4403
|
+
warnings: z8.array(z8.string()),
|
|
4495
4404
|
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
4496
|
-
amended:
|
|
4405
|
+
amended: z8.boolean().optional()
|
|
4497
4406
|
});
|
|
4498
|
-
var googleDraftAmendRequestSchema =
|
|
4499
|
-
chatId:
|
|
4500
|
-
ref:
|
|
4501
|
-
patch:
|
|
4407
|
+
var googleDraftAmendRequestSchema = z8.object({
|
|
4408
|
+
chatId: z8.string(),
|
|
4409
|
+
ref: z8.string(),
|
|
4410
|
+
patch: z8.record(z8.string(), z8.unknown())
|
|
4502
4411
|
});
|
|
4503
|
-
var googleDraftShowRequestSchema =
|
|
4504
|
-
chatId:
|
|
4505
|
-
ref:
|
|
4412
|
+
var googleDraftShowRequestSchema = z8.object({
|
|
4413
|
+
chatId: z8.string(),
|
|
4414
|
+
ref: z8.string()
|
|
4506
4415
|
});
|
|
4507
4416
|
var GOOGLE_DRAFT_BATCH_MAX = 500;
|
|
4508
|
-
var googleDraftStageBatchRequestSchema =
|
|
4509
|
-
chatId:
|
|
4510
|
-
ops:
|
|
4417
|
+
var googleDraftStageBatchRequestSchema = z8.object({
|
|
4418
|
+
chatId: z8.string(),
|
|
4419
|
+
ops: z8.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
|
|
4511
4420
|
});
|
|
4512
|
-
var googleDraftStageBatchResponseSchema =
|
|
4513
|
-
staged:
|
|
4421
|
+
var googleDraftStageBatchResponseSchema = z8.object({
|
|
4422
|
+
staged: z8.literal(true),
|
|
4514
4423
|
mode: googleWriteModeSchema,
|
|
4515
|
-
count:
|
|
4516
|
-
ops:
|
|
4517
|
-
|
|
4518
|
-
ref:
|
|
4424
|
+
count: z8.number(),
|
|
4425
|
+
ops: z8.array(
|
|
4426
|
+
z8.object({
|
|
4427
|
+
ref: z8.string(),
|
|
4519
4428
|
kind: googleDraftOpKindSchema,
|
|
4520
|
-
dependsOn:
|
|
4521
|
-
summary:
|
|
4522
|
-
warnings:
|
|
4429
|
+
dependsOn: z8.array(z8.string()),
|
|
4430
|
+
summary: z8.string(),
|
|
4431
|
+
warnings: z8.array(z8.string())
|
|
4523
4432
|
})
|
|
4524
4433
|
)
|
|
4525
4434
|
});
|
|
4526
|
-
var googleDraftOpViewSchema =
|
|
4527
|
-
ref:
|
|
4435
|
+
var googleDraftOpViewSchema = z8.object({
|
|
4436
|
+
ref: z8.string(),
|
|
4528
4437
|
kind: googleDraftOpKindSchema,
|
|
4529
|
-
customerId:
|
|
4530
|
-
target:
|
|
4531
|
-
dependsOn:
|
|
4532
|
-
summary:
|
|
4533
|
-
stagedAt:
|
|
4438
|
+
customerId: z8.string(),
|
|
4439
|
+
target: z8.string().optional(),
|
|
4440
|
+
dependsOn: z8.array(z8.string()),
|
|
4441
|
+
summary: z8.string(),
|
|
4442
|
+
stagedAt: z8.number(),
|
|
4534
4443
|
result: googleDraftOpResultSchema.optional()
|
|
4535
4444
|
});
|
|
4536
|
-
var googleDraftShowResponseSchema =
|
|
4445
|
+
var googleDraftShowResponseSchema = z8.object({
|
|
4537
4446
|
op: googleDraftOpViewSchema.extend({
|
|
4538
|
-
payload:
|
|
4539
|
-
warnings:
|
|
4540
|
-
annotations:
|
|
4447
|
+
payload: z8.unknown().optional(),
|
|
4448
|
+
warnings: z8.array(z8.string()).optional(),
|
|
4449
|
+
annotations: z8.unknown().optional()
|
|
4541
4450
|
})
|
|
4542
4451
|
});
|
|
4543
|
-
var googleDraftListRequestSchema =
|
|
4544
|
-
chatId:
|
|
4452
|
+
var googleDraftListRequestSchema = z8.object({
|
|
4453
|
+
chatId: z8.string()
|
|
4545
4454
|
});
|
|
4546
|
-
var googleDraftAdvisorySchema =
|
|
4547
|
-
scope:
|
|
4548
|
-
message:
|
|
4455
|
+
var googleDraftAdvisorySchema = z8.object({
|
|
4456
|
+
scope: z8.enum(["campaign", "adGroup"]),
|
|
4457
|
+
message: z8.string()
|
|
4549
4458
|
});
|
|
4550
|
-
var googleDraftStatusCollectionSchema =
|
|
4551
|
-
label:
|
|
4552
|
-
added:
|
|
4553
|
-
removed:
|
|
4554
|
-
existing:
|
|
4459
|
+
var googleDraftStatusCollectionSchema = z8.object({
|
|
4460
|
+
label: z8.string(),
|
|
4461
|
+
added: z8.number(),
|
|
4462
|
+
removed: z8.number(),
|
|
4463
|
+
existing: z8.number()
|
|
4555
4464
|
});
|
|
4556
|
-
var googleDraftChangeOperationSchema =
|
|
4557
|
-
var googleDraftStatusNodeSchema =
|
|
4558
|
-
() =>
|
|
4559
|
-
entity:
|
|
4560
|
-
name:
|
|
4465
|
+
var googleDraftChangeOperationSchema = z8.enum(["create", "update", "pause", "resume", "remove"]);
|
|
4466
|
+
var googleDraftStatusNodeSchema = z8.lazy(
|
|
4467
|
+
() => z8.object({
|
|
4468
|
+
entity: z8.string(),
|
|
4469
|
+
name: z8.string(),
|
|
4561
4470
|
operation: googleDraftChangeOperationSchema.optional(),
|
|
4562
|
-
existing:
|
|
4563
|
-
collections:
|
|
4564
|
-
children:
|
|
4565
|
-
warnings:
|
|
4471
|
+
existing: z8.boolean(),
|
|
4472
|
+
collections: z8.array(googleDraftStatusCollectionSchema),
|
|
4473
|
+
children: z8.array(googleDraftStatusNodeSchema),
|
|
4474
|
+
warnings: z8.array(z8.string()).optional()
|
|
4566
4475
|
})
|
|
4567
4476
|
);
|
|
4568
|
-
var googleDraftListResponseSchema =
|
|
4569
|
-
status:
|
|
4477
|
+
var googleDraftListResponseSchema = z8.object({
|
|
4478
|
+
status: z8.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
4570
4479
|
mode: googleWriteModeSchema,
|
|
4571
|
-
count:
|
|
4572
|
-
ops:
|
|
4480
|
+
count: z8.number(),
|
|
4481
|
+
ops: z8.array(googleDraftOpViewSchema),
|
|
4573
4482
|
/** Grouped campaign ▸ ad group ▸ ad tree for the readable CLI status view. */
|
|
4574
|
-
tree:
|
|
4483
|
+
tree: z8.array(googleDraftStatusNodeSchema).optional(),
|
|
4575
4484
|
/** Non-blocking completeness advisories for the whole draft. */
|
|
4576
|
-
advisories:
|
|
4485
|
+
advisories: z8.array(googleDraftAdvisorySchema).optional()
|
|
4577
4486
|
});
|
|
4578
|
-
var googleDraftRemoveRequestSchema =
|
|
4579
|
-
chatId:
|
|
4580
|
-
ref:
|
|
4487
|
+
var googleDraftRemoveRequestSchema = z8.object({
|
|
4488
|
+
chatId: z8.string(),
|
|
4489
|
+
ref: z8.string()
|
|
4581
4490
|
});
|
|
4582
|
-
var googleDraftRemoveResponseSchema =
|
|
4491
|
+
var googleDraftRemoveResponseSchema = z8.object({
|
|
4583
4492
|
/** The requested ref plus any dependents removed by cascade. */
|
|
4584
|
-
removed:
|
|
4493
|
+
removed: z8.array(z8.string())
|
|
4585
4494
|
});
|
|
4586
|
-
var googleDraftClearRequestSchema =
|
|
4587
|
-
chatId:
|
|
4495
|
+
var googleDraftClearRequestSchema = z8.object({
|
|
4496
|
+
chatId: z8.string()
|
|
4588
4497
|
});
|
|
4589
|
-
var googleDraftClearResponseSchema =
|
|
4590
|
-
cleared:
|
|
4498
|
+
var googleDraftClearResponseSchema = z8.object({
|
|
4499
|
+
cleared: z8.number()
|
|
4591
4500
|
});
|
|
4592
|
-
var googleFieldErrorSchema =
|
|
4593
|
-
path:
|
|
4594
|
-
message:
|
|
4501
|
+
var googleFieldErrorSchema = z8.object({
|
|
4502
|
+
path: z8.string(),
|
|
4503
|
+
message: z8.string()
|
|
4595
4504
|
});
|
|
4596
|
-
var googleDraftErrorResponseSchema =
|
|
4597
|
-
code:
|
|
4598
|
-
error:
|
|
4599
|
-
fields:
|
|
4505
|
+
var googleDraftErrorResponseSchema = z8.object({
|
|
4506
|
+
code: z8.string(),
|
|
4507
|
+
error: z8.string(),
|
|
4508
|
+
fields: z8.array(googleFieldErrorSchema).optional()
|
|
4600
4509
|
});
|
|
4601
4510
|
|
|
4602
4511
|
// src/commands/ads/google/draft-status.ts
|
|
@@ -4761,11 +4670,11 @@ function rawTextEntries(value) {
|
|
|
4761
4670
|
const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
|
|
4762
4671
|
return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
4763
4672
|
}
|
|
4764
|
-
function rawFileEntries(
|
|
4765
|
-
if (typeof
|
|
4673
|
+
function rawFileEntries(path14) {
|
|
4674
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
4766
4675
|
return [];
|
|
4767
4676
|
}
|
|
4768
|
-
return readFileSync2(
|
|
4677
|
+
return readFileSync2(path14, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
4769
4678
|
}
|
|
4770
4679
|
function keywordEntries(args) {
|
|
4771
4680
|
const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
|
|
@@ -4788,19 +4697,19 @@ function keywordEntries(args) {
|
|
|
4788
4697
|
}
|
|
4789
4698
|
return entries;
|
|
4790
4699
|
}
|
|
4791
|
-
function loadJsonFileArg(
|
|
4792
|
-
if (typeof
|
|
4700
|
+
function loadJsonFileArg(path14) {
|
|
4701
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
4793
4702
|
return {};
|
|
4794
4703
|
}
|
|
4795
4704
|
try {
|
|
4796
|
-
const parsed = JSON.parse(readFileSync2(
|
|
4705
|
+
const parsed = JSON.parse(readFileSync2(path14, "utf8"));
|
|
4797
4706
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4798
|
-
failWriteValidation(`${
|
|
4707
|
+
failWriteValidation(`${path14} must contain a JSON object`);
|
|
4799
4708
|
}
|
|
4800
4709
|
return parsed;
|
|
4801
4710
|
} catch (err) {
|
|
4802
4711
|
if (err instanceof SyntaxError) {
|
|
4803
|
-
failWriteValidation(`${
|
|
4712
|
+
failWriteValidation(`${path14} is not valid JSON: ${err.message}`);
|
|
4804
4713
|
}
|
|
4805
4714
|
throw err;
|
|
4806
4715
|
}
|
|
@@ -4911,10 +4820,10 @@ async function stageUpdate(kind, customerId, target, payload) {
|
|
|
4911
4820
|
async function stageTarget(kind, customerId, target) {
|
|
4912
4821
|
await stageGoogleOp({ kind, customerId, target });
|
|
4913
4822
|
}
|
|
4914
|
-
async function draftAction(
|
|
4823
|
+
async function draftAction(path14, body) {
|
|
4915
4824
|
try {
|
|
4916
4825
|
const chatId = requireChatId();
|
|
4917
|
-
const response = await apiPost(
|
|
4826
|
+
const response = await apiPost(path14, { chatId, ...body });
|
|
4918
4827
|
writeJsonEnvelope(response);
|
|
4919
4828
|
} catch (err) {
|
|
4920
4829
|
handleGoogleError(err);
|
|
@@ -8669,19 +8578,19 @@ function failWriteValidation2(message) {
|
|
|
8669
8578
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
8670
8579
|
process.exit(1);
|
|
8671
8580
|
}
|
|
8672
|
-
function loadJsonFileArg2(
|
|
8673
|
-
if (typeof
|
|
8581
|
+
function loadJsonFileArg2(path14) {
|
|
8582
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8674
8583
|
return {};
|
|
8675
8584
|
}
|
|
8676
8585
|
try {
|
|
8677
|
-
const parsed = JSON.parse(readFileSync6(
|
|
8586
|
+
const parsed = JSON.parse(readFileSync6(path14, "utf8"));
|
|
8678
8587
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
8679
|
-
failWriteValidation2(`${
|
|
8588
|
+
failWriteValidation2(`${path14} must contain a JSON object`);
|
|
8680
8589
|
}
|
|
8681
8590
|
return parsed;
|
|
8682
8591
|
} catch (err) {
|
|
8683
8592
|
if (err instanceof SyntaxError) {
|
|
8684
|
-
failWriteValidation2(`${
|
|
8593
|
+
failWriteValidation2(`${path14} is not valid JSON: ${err.message}`);
|
|
8685
8594
|
}
|
|
8686
8595
|
throw err;
|
|
8687
8596
|
}
|
|
@@ -8766,15 +8675,15 @@ function parseLocaleFlag(value) {
|
|
|
8766
8675
|
}
|
|
8767
8676
|
return { language: match[1], country: match[2].toUpperCase() };
|
|
8768
8677
|
}
|
|
8769
|
-
function loadTargetingFileArg(
|
|
8770
|
-
if (typeof
|
|
8678
|
+
function loadTargetingFileArg(path14) {
|
|
8679
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8771
8680
|
return void 0;
|
|
8772
8681
|
}
|
|
8773
|
-
const parsed = loadJsonFileArg2(
|
|
8682
|
+
const parsed = loadJsonFileArg2(path14);
|
|
8774
8683
|
const criteria = parsed.targetingCriteria ?? parsed;
|
|
8775
8684
|
if (!criteria.include) {
|
|
8776
8685
|
failWriteValidation2(
|
|
8777
|
-
`${
|
|
8686
|
+
`${path14} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
|
|
8778
8687
|
);
|
|
8779
8688
|
}
|
|
8780
8689
|
return criteria;
|
|
@@ -8809,14 +8718,14 @@ function parseCsvLine(line) {
|
|
|
8809
8718
|
cells.push(current);
|
|
8810
8719
|
return cells.map((cell) => cell.trim());
|
|
8811
8720
|
}
|
|
8812
|
-
function parseListFileArg(
|
|
8813
|
-
if (typeof
|
|
8721
|
+
function parseListFileArg(path14, maxRows) {
|
|
8722
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
8814
8723
|
return void 0;
|
|
8815
8724
|
}
|
|
8816
|
-
const raw = readFileSync6(
|
|
8725
|
+
const raw = readFileSync6(path14, "utf8");
|
|
8817
8726
|
const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
8818
8727
|
if (lines.length < 2) {
|
|
8819
|
-
failWriteValidation2(`${
|
|
8728
|
+
failWriteValidation2(`${path14} needs a header row and at least one data row`);
|
|
8820
8729
|
}
|
|
8821
8730
|
const columns = parseCsvLine(lines[0]).map((column) => column.trim());
|
|
8822
8731
|
const rows = [];
|
|
@@ -8835,7 +8744,7 @@ function parseListFileArg(path12, maxRows) {
|
|
|
8835
8744
|
}
|
|
8836
8745
|
}
|
|
8837
8746
|
if (rows.length > maxRows) {
|
|
8838
|
-
failWriteValidation2(`${
|
|
8747
|
+
failWriteValidation2(`${path14} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
|
|
8839
8748
|
}
|
|
8840
8749
|
return { columns, rows };
|
|
8841
8750
|
}
|
|
@@ -9480,7 +9389,7 @@ var leadFormsCreateCommand = defineCommand38({
|
|
|
9480
9389
|
Required: name, headline (\u226460), privacyPolicyUrl, questions[] (\u226412; playbook: \u22644 for completion).
|
|
9481
9390
|
Each question is a predefined profile field ({ name, predefinedField: "EMAIL" }) or a custom question ({ name, questionType: "MULTIPLE_CHOICE", options: [...] }; \u22643 custom).
|
|
9482
9391
|
Best-practice fields the preview will nudge for if missing: 1-3 qualifying questions, consents[] (disclosure checkboxes), thankYou.message + thankYou.landingUrl|appointmentUrl.
|
|
9483
|
-
Also supported: locale, formImageId|formImageUrn, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
|
|
9392
|
+
Also supported: locale, formImageId|formImageUrn, privacyPolicyText, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
|
|
9484
9393
|
},
|
|
9485
9394
|
args: {
|
|
9486
9395
|
...accountArgs,
|
|
@@ -10904,72 +10813,72 @@ var NUMERIC_ID_REGEX3 = /^\d+$/;
|
|
|
10904
10813
|
var IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;
|
|
10905
10814
|
|
|
10906
10815
|
// ../api/src/ads-meta/ops.ts
|
|
10907
|
-
import { z as
|
|
10908
|
-
var tempRefSchema3 =
|
|
10909
|
-
var parentRefSchema2 =
|
|
10910
|
-
var moneySchema2 =
|
|
10911
|
-
amount:
|
|
10912
|
-
currencyCode:
|
|
10913
|
-
});
|
|
10914
|
-
var httpsUrlSchema3 =
|
|
10915
|
-
var bakerMediaIdSchema2 =
|
|
10916
|
-
var stageableStatusSchema3 =
|
|
10917
|
-
var updateStatusSchema =
|
|
10816
|
+
import { z as z9 } from "zod";
|
|
10817
|
+
var tempRefSchema3 = z9.string().regex(TEMP_REF_REGEX3, "expected a meta_temp_* reference");
|
|
10818
|
+
var parentRefSchema2 = z9.union([z9.string().regex(NUMERIC_ID_REGEX3, "expected a numeric id"), tempRefSchema3]);
|
|
10819
|
+
var moneySchema2 = z9.object({
|
|
10820
|
+
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"),
|
|
10821
|
+
currencyCode: z9.string().length(3).optional()
|
|
10822
|
+
});
|
|
10823
|
+
var httpsUrlSchema3 = z9.string().url().refine((u) => u.startsWith("https://"), "destination URLs must be https");
|
|
10824
|
+
var bakerMediaIdSchema2 = z9.string().min(1);
|
|
10825
|
+
var stageableStatusSchema3 = z9.enum(STAGEABLE_CREATE_STATUSES3);
|
|
10826
|
+
var updateStatusSchema = z9.enum(UPDATE_STATUSES);
|
|
10918
10827
|
function currencyMinimums2(currencyCode) {
|
|
10919
10828
|
return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
|
|
10920
10829
|
}
|
|
10921
|
-
function validateDailyBudgetFloor(money, ctx,
|
|
10830
|
+
function validateDailyBudgetFloor(money, ctx, path14) {
|
|
10922
10831
|
if (money?.currencyCode) {
|
|
10923
10832
|
const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
|
|
10924
10833
|
if (Number(money.amount) < min) {
|
|
10925
|
-
ctx.addIssue({ code: "custom", path:
|
|
10834
|
+
ctx.addIssue({ code: "custom", path: path14, message: `below the ${min} ${money.currencyCode} daily minimum` });
|
|
10926
10835
|
}
|
|
10927
10836
|
}
|
|
10928
10837
|
}
|
|
10929
|
-
var geoLocationsSchema =
|
|
10930
|
-
countries:
|
|
10931
|
-
regions:
|
|
10932
|
-
cities:
|
|
10933
|
-
zips:
|
|
10934
|
-
location_types:
|
|
10935
|
-
}).catchall(
|
|
10936
|
-
var idNameSchema =
|
|
10937
|
-
var metaTargetingSchema =
|
|
10838
|
+
var geoLocationsSchema = z9.object({
|
|
10839
|
+
countries: z9.array(z9.string().length(2)).optional(),
|
|
10840
|
+
regions: z9.array(z9.object({ key: z9.string() })).optional(),
|
|
10841
|
+
cities: z9.array(z9.object({ key: z9.string(), radius: z9.number().optional(), distance_unit: z9.string().optional() })).optional(),
|
|
10842
|
+
zips: z9.array(z9.object({ key: z9.string() })).optional(),
|
|
10843
|
+
location_types: z9.array(z9.string()).optional()
|
|
10844
|
+
}).catchall(z9.unknown());
|
|
10845
|
+
var idNameSchema = z9.object({ id: z9.string(), name: z9.string().optional() });
|
|
10846
|
+
var metaTargetingSchema = z9.object({
|
|
10938
10847
|
geo_locations: geoLocationsSchema.optional(),
|
|
10939
10848
|
excluded_geo_locations: geoLocationsSchema.optional(),
|
|
10940
|
-
age_min:
|
|
10941
|
-
age_max:
|
|
10942
|
-
genders:
|
|
10943
|
-
locales:
|
|
10944
|
-
interests:
|
|
10945
|
-
behaviors:
|
|
10946
|
-
custom_audiences:
|
|
10947
|
-
excluded_custom_audiences:
|
|
10948
|
-
flexible_spec:
|
|
10949
|
-
exclusions:
|
|
10950
|
-
publisher_platforms:
|
|
10951
|
-
facebook_positions:
|
|
10952
|
-
instagram_positions:
|
|
10953
|
-
audience_network_positions:
|
|
10954
|
-
messenger_positions:
|
|
10955
|
-
device_platforms:
|
|
10956
|
-
targeting_automation:
|
|
10957
|
-
}).catchall(
|
|
10958
|
-
var specialAdCategoriesSchema =
|
|
10959
|
-
var campaignCreateSchema3 =
|
|
10960
|
-
name:
|
|
10961
|
-
objective:
|
|
10849
|
+
age_min: z9.number().int().min(13).max(65).optional(),
|
|
10850
|
+
age_max: z9.number().int().min(13).max(65).optional(),
|
|
10851
|
+
genders: z9.array(z9.union([z9.literal(1), z9.literal(2)])).optional(),
|
|
10852
|
+
locales: z9.array(z9.number().int()).optional(),
|
|
10853
|
+
interests: z9.array(idNameSchema).optional(),
|
|
10854
|
+
behaviors: z9.array(idNameSchema).optional(),
|
|
10855
|
+
custom_audiences: z9.array(z9.object({ id: parentRefSchema2 })).optional(),
|
|
10856
|
+
excluded_custom_audiences: z9.array(z9.object({ id: parentRefSchema2 })).optional(),
|
|
10857
|
+
flexible_spec: z9.array(z9.record(z9.string(), z9.unknown())).optional(),
|
|
10858
|
+
exclusions: z9.record(z9.string(), z9.unknown()).optional(),
|
|
10859
|
+
publisher_platforms: z9.array(z9.string()).optional(),
|
|
10860
|
+
facebook_positions: z9.array(z9.string()).optional(),
|
|
10861
|
+
instagram_positions: z9.array(z9.string()).optional(),
|
|
10862
|
+
audience_network_positions: z9.array(z9.string()).optional(),
|
|
10863
|
+
messenger_positions: z9.array(z9.string()).optional(),
|
|
10864
|
+
device_platforms: z9.array(z9.string()).optional(),
|
|
10865
|
+
targeting_automation: z9.object({ advantage_audience: z9.union([z9.literal(0), z9.literal(1)]) }).partial().optional()
|
|
10866
|
+
}).catchall(z9.unknown());
|
|
10867
|
+
var specialAdCategoriesSchema = z9.array(z9.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
|
|
10868
|
+
var campaignCreateSchema3 = z9.object({
|
|
10869
|
+
name: z9.string().min(1).max(META_LIMITS.campaign.nameMax),
|
|
10870
|
+
objective: z9.enum(OBJECTIVES),
|
|
10962
10871
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
10963
10872
|
special_ad_categories: specialAdCategoriesSchema,
|
|
10964
|
-
special_ad_category_country:
|
|
10965
|
-
buying_type:
|
|
10966
|
-
bid_strategy:
|
|
10873
|
+
special_ad_category_country: z9.array(z9.string().length(2)).optional(),
|
|
10874
|
+
buying_type: z9.enum(BUYING_TYPES).default("AUCTION"),
|
|
10875
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10967
10876
|
/** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */
|
|
10968
10877
|
dailyBudget: moneySchema2.optional(),
|
|
10969
10878
|
lifetimeBudget: moneySchema2.optional(),
|
|
10970
10879
|
spendCap: moneySchema2.optional(),
|
|
10971
|
-
start_time:
|
|
10972
|
-
stop_time:
|
|
10880
|
+
start_time: z9.number().int().positive().optional(),
|
|
10881
|
+
stop_time: z9.number().int().positive().optional()
|
|
10973
10882
|
}).superRefine((p, ctx) => {
|
|
10974
10883
|
if (p.dailyBudget && p.lifetimeBudget) {
|
|
10975
10884
|
ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
|
|
@@ -10979,15 +10888,15 @@ var campaignCreateSchema3 = z10.object({
|
|
|
10979
10888
|
ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
|
|
10980
10889
|
}
|
|
10981
10890
|
});
|
|
10982
|
-
var campaignUpdateSchema3 =
|
|
10983
|
-
name:
|
|
10891
|
+
var campaignUpdateSchema3 = z9.object({
|
|
10892
|
+
name: z9.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
|
|
10984
10893
|
status: updateStatusSchema.optional(),
|
|
10985
|
-
bid_strategy:
|
|
10894
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10986
10895
|
dailyBudget: moneySchema2.optional(),
|
|
10987
10896
|
lifetimeBudget: moneySchema2.optional(),
|
|
10988
10897
|
spendCap: moneySchema2.optional(),
|
|
10989
|
-
start_time:
|
|
10990
|
-
stop_time:
|
|
10898
|
+
start_time: z9.number().int().positive().optional(),
|
|
10899
|
+
stop_time: z9.number().int().positive().optional()
|
|
10991
10900
|
}).superRefine((p, ctx) => {
|
|
10992
10901
|
if (!Object.values(p).some((val) => val !== void 0)) {
|
|
10993
10902
|
ctx.addIssue({ code: "custom", message: "update needs at least one field" });
|
|
@@ -10997,38 +10906,38 @@ var campaignUpdateSchema3 = z10.object({
|
|
|
10997
10906
|
}
|
|
10998
10907
|
validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
|
|
10999
10908
|
});
|
|
11000
|
-
var promotedObjectSchema =
|
|
10909
|
+
var promotedObjectSchema = z9.object({
|
|
11001
10910
|
page_id: parentRefSchema2.optional(),
|
|
11002
|
-
pixel_id:
|
|
11003
|
-
custom_event_type:
|
|
11004
|
-
application_id:
|
|
11005
|
-
object_store_url:
|
|
11006
|
-
product_catalog_id:
|
|
11007
|
-
product_set_id:
|
|
11008
|
-
whatsapp_phone_number:
|
|
11009
|
-
offline_conversion_data_set_id:
|
|
10911
|
+
pixel_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10912
|
+
custom_event_type: z9.enum(CUSTOM_EVENT_TYPES).optional(),
|
|
10913
|
+
application_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10914
|
+
object_store_url: z9.string().url().optional(),
|
|
10915
|
+
product_catalog_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10916
|
+
product_set_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
10917
|
+
whatsapp_phone_number: z9.string().optional(),
|
|
10918
|
+
offline_conversion_data_set_id: z9.string().regex(NUMERIC_ID_REGEX3).optional()
|
|
11010
10919
|
}).partial();
|
|
11011
|
-
var attributionSpecSchema =
|
|
11012
|
-
|
|
11013
|
-
event_type:
|
|
11014
|
-
window_days:
|
|
10920
|
+
var attributionSpecSchema = z9.array(
|
|
10921
|
+
z9.object({
|
|
10922
|
+
event_type: z9.enum(ATTRIBUTION_EVENT_TYPES),
|
|
10923
|
+
window_days: z9.union([z9.literal(1), z9.literal(7), z9.literal(28)])
|
|
11015
10924
|
})
|
|
11016
10925
|
);
|
|
11017
10926
|
var adSetFields = {
|
|
11018
|
-
name:
|
|
10927
|
+
name: z9.string().min(1).max(META_LIMITS.adSet.nameMax),
|
|
11019
10928
|
campaign_id: parentRefSchema2,
|
|
11020
10929
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
11021
10930
|
dailyBudget: moneySchema2.optional(),
|
|
11022
10931
|
lifetimeBudget: moneySchema2.optional(),
|
|
11023
10932
|
bidAmount: moneySchema2.optional(),
|
|
11024
|
-
bid_strategy:
|
|
11025
|
-
billing_event:
|
|
11026
|
-
optimization_goal:
|
|
11027
|
-
destination_type:
|
|
10933
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10934
|
+
billing_event: z9.enum(BILLING_EVENTS),
|
|
10935
|
+
optimization_goal: z9.enum(OPTIMIZATION_GOALS),
|
|
10936
|
+
destination_type: z9.enum(DESTINATION_TYPES).optional(),
|
|
11028
10937
|
promoted_object: promotedObjectSchema.optional(),
|
|
11029
10938
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11030
|
-
start_time:
|
|
11031
|
-
end_time:
|
|
10939
|
+
start_time: z9.number().int().positive().optional(),
|
|
10940
|
+
end_time: z9.number().int().positive().optional(),
|
|
11032
10941
|
targeting: metaTargetingSchema
|
|
11033
10942
|
};
|
|
11034
10943
|
function validateAdSetBudgetAndBid(p, ctx) {
|
|
@@ -11046,22 +10955,22 @@ function validateAdSetBudgetAndBid(p, ctx) {
|
|
|
11046
10955
|
ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
|
|
11047
10956
|
}
|
|
11048
10957
|
}
|
|
11049
|
-
var adSetCreateSchema =
|
|
10958
|
+
var adSetCreateSchema = z9.object(adSetFields).superRefine((p, ctx) => {
|
|
11050
10959
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11051
10960
|
});
|
|
11052
|
-
var adSetUpdateSchema =
|
|
10961
|
+
var adSetUpdateSchema = z9.object({
|
|
11053
10962
|
name: adSetFields.name.optional(),
|
|
11054
10963
|
status: updateStatusSchema.optional(),
|
|
11055
10964
|
dailyBudget: moneySchema2.optional(),
|
|
11056
10965
|
lifetimeBudget: moneySchema2.optional(),
|
|
11057
10966
|
bidAmount: moneySchema2.optional(),
|
|
11058
|
-
bid_strategy:
|
|
11059
|
-
optimization_goal:
|
|
11060
|
-
destination_type:
|
|
10967
|
+
bid_strategy: z9.enum(BID_STRATEGIES).optional(),
|
|
10968
|
+
optimization_goal: z9.enum(OPTIMIZATION_GOALS).optional(),
|
|
10969
|
+
destination_type: z9.enum(DESTINATION_TYPES).optional(),
|
|
11061
10970
|
promoted_object: promotedObjectSchema.optional(),
|
|
11062
10971
|
attribution_spec: attributionSpecSchema.optional(),
|
|
11063
|
-
start_time:
|
|
11064
|
-
end_time:
|
|
10972
|
+
start_time: z9.number().int().positive().optional(),
|
|
10973
|
+
end_time: z9.number().int().positive().optional(),
|
|
11065
10974
|
targeting: metaTargetingSchema.optional()
|
|
11066
10975
|
}).superRefine((p, ctx) => {
|
|
11067
10976
|
if (!Object.values(p).some((val) => val !== void 0)) {
|
|
@@ -11069,38 +10978,38 @@ var adSetUpdateSchema = z10.object({
|
|
|
11069
10978
|
}
|
|
11070
10979
|
validateAdSetBudgetAndBid(p, ctx);
|
|
11071
10980
|
});
|
|
11072
|
-
var messageSchema =
|
|
11073
|
-
var headlineSchema2 =
|
|
11074
|
-
var descriptionSchema =
|
|
11075
|
-
var callToActionSchema =
|
|
11076
|
-
type:
|
|
10981
|
+
var messageSchema = z9.string().min(1).max(META_LIMITS.creative.messageHardMax);
|
|
10982
|
+
var headlineSchema2 = z9.string().min(1).max(META_LIMITS.creative.headlineMax);
|
|
10983
|
+
var descriptionSchema = z9.string().min(1).max(META_LIMITS.creative.descriptionMax);
|
|
10984
|
+
var callToActionSchema = z9.object({
|
|
10985
|
+
type: z9.enum(CTA_TYPES2),
|
|
11077
10986
|
/** Overrides the base link for the CTA button; defaults to the ad's link. */
|
|
11078
10987
|
link: httpsUrlSchema3.optional()
|
|
11079
10988
|
});
|
|
11080
|
-
var creativeEnhancementsSchema =
|
|
11081
|
-
standardEnhancements:
|
|
11082
|
-
features:
|
|
10989
|
+
var creativeEnhancementsSchema = z9.object({
|
|
10990
|
+
standardEnhancements: z9.enum(ENROLL_STATUSES).optional(),
|
|
10991
|
+
features: z9.record(z9.string(), z9.enum(ENROLL_STATUSES)).optional()
|
|
11083
10992
|
});
|
|
11084
10993
|
var creativeSharedFields = {
|
|
11085
|
-
name:
|
|
10994
|
+
name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
|
|
11086
10995
|
/** Facebook Page id backing the ad's identity. */
|
|
11087
10996
|
page_id: parentRefSchema2,
|
|
11088
10997
|
/** Instagram account id for IG placements (aka instagram_actor_id on read). */
|
|
11089
|
-
instagram_user_id:
|
|
10998
|
+
instagram_user_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
11090
10999
|
/** URL tracking parameters appended to the destination, e.g. "utm_source=fb&utm_campaign=x". */
|
|
11091
|
-
url_tags:
|
|
11000
|
+
url_tags: z9.string().max(1e3).optional(),
|
|
11092
11001
|
enhancements: creativeEnhancementsSchema.optional()
|
|
11093
11002
|
};
|
|
11094
11003
|
var imageMediaFields = {
|
|
11095
|
-
imageHash:
|
|
11004
|
+
imageHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
|
|
11096
11005
|
imageRef: tempRefSchema3.optional()
|
|
11097
11006
|
};
|
|
11098
11007
|
var videoMediaFields = {
|
|
11099
|
-
videoId:
|
|
11008
|
+
videoId: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
|
|
11100
11009
|
videoRef: tempRefSchema3.optional(),
|
|
11101
11010
|
/** Thumbnail for a video creative — image hash, ref, or public url. */
|
|
11102
|
-
thumbnailHash:
|
|
11103
|
-
imageUrl:
|
|
11011
|
+
thumbnailHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
|
|
11012
|
+
imageUrl: z9.string().url().optional()
|
|
11104
11013
|
};
|
|
11105
11014
|
function countImageRefs(p) {
|
|
11106
11015
|
return [p.imageHash, p.imageRef].filter(Boolean).length;
|
|
@@ -11108,8 +11017,8 @@ function countImageRefs(p) {
|
|
|
11108
11017
|
function countVideoRefs(p) {
|
|
11109
11018
|
return [p.videoId, p.videoRef].filter(Boolean).length;
|
|
11110
11019
|
}
|
|
11111
|
-
var singleCreativeSchema =
|
|
11112
|
-
creativeType:
|
|
11020
|
+
var singleCreativeSchema = z9.object({
|
|
11021
|
+
creativeType: z9.literal("single"),
|
|
11113
11022
|
...creativeSharedFields,
|
|
11114
11023
|
/** Primary text. */
|
|
11115
11024
|
message: messageSchema,
|
|
@@ -11118,7 +11027,7 @@ var singleCreativeSchema = z10.object({
|
|
|
11118
11027
|
headline: headlineSchema2.optional(),
|
|
11119
11028
|
description: descriptionSchema.optional(),
|
|
11120
11029
|
/** Display URL / caption shown under the headline. */
|
|
11121
|
-
caption:
|
|
11030
|
+
caption: z9.string().max(255).optional(),
|
|
11122
11031
|
call_to_action: callToActionSchema.optional(),
|
|
11123
11032
|
...imageMediaFields,
|
|
11124
11033
|
...videoMediaFields
|
|
@@ -11142,10 +11051,10 @@ var singleCreativeSchema = z10.object({
|
|
|
11142
11051
|
});
|
|
11143
11052
|
}
|
|
11144
11053
|
});
|
|
11145
|
-
var carouselCardSchema =
|
|
11054
|
+
var carouselCardSchema = z9.object({
|
|
11146
11055
|
link: httpsUrlSchema3,
|
|
11147
|
-
headline:
|
|
11148
|
-
description:
|
|
11056
|
+
headline: z9.string().max(META_LIMITS.creative.headlineMax).optional(),
|
|
11057
|
+
description: z9.string().max(META_LIMITS.creative.descriptionMax).optional(),
|
|
11149
11058
|
call_to_action: callToActionSchema.optional(),
|
|
11150
11059
|
...imageMediaFields,
|
|
11151
11060
|
...videoMediaFields
|
|
@@ -11165,35 +11074,35 @@ var carouselCardSchema = z10.object({
|
|
|
11165
11074
|
ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
|
|
11166
11075
|
}
|
|
11167
11076
|
});
|
|
11168
|
-
var carouselCreativeSchema2 =
|
|
11169
|
-
creativeType:
|
|
11077
|
+
var carouselCreativeSchema2 = z9.object({
|
|
11078
|
+
creativeType: z9.literal("carousel"),
|
|
11170
11079
|
...creativeSharedFields,
|
|
11171
11080
|
message: messageSchema,
|
|
11172
11081
|
/** Optional "see more" card destination applied when a card has no own link. */
|
|
11173
11082
|
link: httpsUrlSchema3.optional(),
|
|
11174
11083
|
call_to_action: callToActionSchema.optional(),
|
|
11175
|
-
cards:
|
|
11084
|
+
cards: z9.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax)
|
|
11176
11085
|
});
|
|
11177
|
-
var dynamicImageSchema =
|
|
11178
|
-
var dynamicVideoSchema =
|
|
11086
|
+
var dynamicImageSchema = z9.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
|
|
11087
|
+
var dynamicVideoSchema = z9.object({
|
|
11179
11088
|
videoId: videoMediaFields.videoId,
|
|
11180
11089
|
videoRef: videoMediaFields.videoRef,
|
|
11181
11090
|
thumbnailHash: videoMediaFields.thumbnailHash
|
|
11182
11091
|
}).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
|
|
11183
11092
|
var DYN = META_LIMITS.creative;
|
|
11184
|
-
var dynamicCreativeSchema =
|
|
11185
|
-
creativeType:
|
|
11093
|
+
var dynamicCreativeSchema = z9.object({
|
|
11094
|
+
creativeType: z9.literal("dynamic"),
|
|
11186
11095
|
...creativeSharedFields,
|
|
11187
|
-
bodies:
|
|
11188
|
-
titles:
|
|
11189
|
-
descriptions:
|
|
11190
|
-
images:
|
|
11191
|
-
videos:
|
|
11192
|
-
ad_formats:
|
|
11193
|
-
call_to_action_types:
|
|
11194
|
-
link_urls:
|
|
11096
|
+
bodies: z9.array(z9.object({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
|
|
11097
|
+
titles: z9.array(z9.object({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
|
|
11098
|
+
descriptions: z9.array(z9.object({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
|
|
11099
|
+
images: z9.array(dynamicImageSchema).optional(),
|
|
11100
|
+
videos: z9.array(dynamicVideoSchema).optional(),
|
|
11101
|
+
ad_formats: z9.array(z9.enum(AD_FORMATS2)).min(1),
|
|
11102
|
+
call_to_action_types: z9.array(z9.enum(CTA_TYPES2)).optional(),
|
|
11103
|
+
link_urls: z9.array(z9.object({ website_url: httpsUrlSchema3, display_url: z9.string().optional() })).min(1),
|
|
11195
11104
|
/** Multi-language / placement customization — structural passthrough for v1. */
|
|
11196
|
-
asset_customization_rules:
|
|
11105
|
+
asset_customization_rules: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11197
11106
|
}).superRefine((p, ctx) => {
|
|
11198
11107
|
if (!(p.images?.length || p.videos?.length)) {
|
|
11199
11108
|
ctx.addIssue({
|
|
@@ -11203,57 +11112,57 @@ var dynamicCreativeSchema = z10.object({
|
|
|
11203
11112
|
});
|
|
11204
11113
|
}
|
|
11205
11114
|
});
|
|
11206
|
-
var existingPostCreativeSchema =
|
|
11207
|
-
creativeType:
|
|
11115
|
+
var existingPostCreativeSchema = z9.object({
|
|
11116
|
+
creativeType: z9.literal("existing_post"),
|
|
11208
11117
|
name: creativeSharedFields.name,
|
|
11209
11118
|
/** "<page_id>_<post_id>" object story id of the post to promote. */
|
|
11210
|
-
object_story_id:
|
|
11119
|
+
object_story_id: z9.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
|
|
11211
11120
|
instagram_user_id: creativeSharedFields.instagram_user_id,
|
|
11212
11121
|
url_tags: creativeSharedFields.url_tags,
|
|
11213
11122
|
enhancements: creativeSharedFields.enhancements
|
|
11214
11123
|
});
|
|
11215
|
-
var creativeContentSchema2 =
|
|
11124
|
+
var creativeContentSchema2 = z9.discriminatedUnion("creativeType", [
|
|
11216
11125
|
singleCreativeSchema,
|
|
11217
11126
|
carouselCreativeSchema2,
|
|
11218
11127
|
dynamicCreativeSchema,
|
|
11219
11128
|
existingPostCreativeSchema
|
|
11220
11129
|
]);
|
|
11221
11130
|
var adCreativeCreateSchema = creativeContentSchema2;
|
|
11222
|
-
var adCreativeUpdateSchema =
|
|
11223
|
-
name:
|
|
11131
|
+
var adCreativeUpdateSchema = z9.object({
|
|
11132
|
+
name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
|
|
11224
11133
|
status: updateStatusSchema.optional(),
|
|
11225
11134
|
/** Content patch — only honored when the target is a staged meta_temp_* creative. */
|
|
11226
|
-
content:
|
|
11135
|
+
content: z9.record(z9.string(), z9.unknown()).optional()
|
|
11227
11136
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11228
|
-
var adCreateSchema2 =
|
|
11229
|
-
name:
|
|
11137
|
+
var adCreateSchema2 = z9.object({
|
|
11138
|
+
name: z9.string().min(1).max(META_LIMITS.ad.nameMax),
|
|
11230
11139
|
adset_id: parentRefSchema2,
|
|
11231
11140
|
status: stageableStatusSchema3.default("PAUSED"),
|
|
11232
|
-
creative:
|
|
11141
|
+
creative: z9.object({ creative_id: parentRefSchema2 }),
|
|
11233
11142
|
/** Conversion pixel / offline event set / view tags — structural passthrough. */
|
|
11234
|
-
tracking_specs:
|
|
11143
|
+
tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11235
11144
|
});
|
|
11236
|
-
var adUpdateSchema2 =
|
|
11237
|
-
name:
|
|
11145
|
+
var adUpdateSchema2 = z9.object({
|
|
11146
|
+
name: z9.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
|
|
11238
11147
|
status: updateStatusSchema.optional(),
|
|
11239
11148
|
/** Swapping the creative is the Meta way to "edit" an ad's creative. */
|
|
11240
|
-
creative:
|
|
11241
|
-
tracking_specs:
|
|
11149
|
+
creative: z9.object({ creative_id: parentRefSchema2 }).optional(),
|
|
11150
|
+
tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
|
|
11242
11151
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11243
|
-
var lookalikeSpecSchema =
|
|
11244
|
-
origin:
|
|
11245
|
-
ratio:
|
|
11246
|
-
country:
|
|
11247
|
-
});
|
|
11248
|
-
var customAudienceCreateSchema =
|
|
11249
|
-
name:
|
|
11250
|
-
subtype:
|
|
11251
|
-
description:
|
|
11252
|
-
customer_file_source:
|
|
11253
|
-
retention_days:
|
|
11152
|
+
var lookalikeSpecSchema = z9.object({
|
|
11153
|
+
origin: z9.array(z9.object({ id: parentRefSchema2 })).min(1),
|
|
11154
|
+
ratio: z9.number().min(0.01).max(0.2).optional(),
|
|
11155
|
+
country: z9.string().length(2).optional()
|
|
11156
|
+
});
|
|
11157
|
+
var customAudienceCreateSchema = z9.object({
|
|
11158
|
+
name: z9.string().min(1).max(META_LIMITS.audience.nameMax),
|
|
11159
|
+
subtype: z9.enum(CUSTOM_AUDIENCE_SUBTYPES),
|
|
11160
|
+
description: z9.string().max(500).optional(),
|
|
11161
|
+
customer_file_source: z9.string().optional(),
|
|
11162
|
+
retention_days: z9.number().int().min(1).max(META_LIMITS.audience.retentionDaysMax).optional(),
|
|
11254
11163
|
lookalike_spec: lookalikeSpecSchema.optional(),
|
|
11255
11164
|
/** Website/engagement rule — structural passthrough validated by Meta. */
|
|
11256
|
-
rule:
|
|
11165
|
+
rule: z9.record(z9.string(), z9.unknown()).optional()
|
|
11257
11166
|
}).superRefine((p, ctx) => {
|
|
11258
11167
|
if (p.subtype === "LOOKALIKE" && !p.lookalike_spec) {
|
|
11259
11168
|
ctx.addIssue({ code: "custom", path: ["lookalike_spec"], message: "LOOKALIKE audiences need a lookalike_spec" });
|
|
@@ -11262,16 +11171,16 @@ var customAudienceCreateSchema = z10.object({
|
|
|
11262
11171
|
ctx.addIssue({ code: "custom", path: ["rule"], message: `${p.subtype} audiences need a rule (use --file)` });
|
|
11263
11172
|
}
|
|
11264
11173
|
});
|
|
11265
|
-
var customAudienceUpdateSchema =
|
|
11266
|
-
name:
|
|
11267
|
-
description:
|
|
11174
|
+
var customAudienceUpdateSchema = z9.object({
|
|
11175
|
+
name: z9.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
|
|
11176
|
+
description: z9.string().max(500).optional()
|
|
11268
11177
|
}).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
|
|
11269
|
-
var mediaUploadSchema =
|
|
11270
|
-
kind:
|
|
11178
|
+
var mediaUploadSchema = z9.object({
|
|
11179
|
+
kind: z9.enum(MEDIA_KINDS),
|
|
11271
11180
|
bakerImageId: bakerMediaIdSchema2.optional(),
|
|
11272
11181
|
bakerVideoId: bakerMediaIdSchema2.optional(),
|
|
11273
11182
|
/** Optional display name / filename hint. */
|
|
11274
|
-
name:
|
|
11183
|
+
name: z9.string().max(255).optional()
|
|
11275
11184
|
}).superRefine((p, ctx) => {
|
|
11276
11185
|
if (p.kind === "image" && !p.bakerImageId) {
|
|
11277
11186
|
ctx.addIssue({ code: "custom", path: ["bakerImageId"], message: "image uploads need a bakerImageId" });
|
|
@@ -11293,16 +11202,16 @@ var META_DRAFT_OP_KINDS = [
|
|
|
11293
11202
|
"customAudience.update",
|
|
11294
11203
|
"media.upload"
|
|
11295
11204
|
];
|
|
11296
|
-
var metaDraftOpKindSchema =
|
|
11297
|
-
var accountIdSchema2 =
|
|
11298
|
-
var updateTargetSchema2 =
|
|
11205
|
+
var metaDraftOpKindSchema = z9.enum(META_DRAFT_OP_KINDS);
|
|
11206
|
+
var accountIdSchema2 = z9.string().regex(NUMERIC_ID_REGEX3, "accountId must be the bare numeric ad account id");
|
|
11207
|
+
var updateTargetSchema2 = z9.union([z9.string().regex(NUMERIC_ID_REGEX3), tempRefSchema3]);
|
|
11299
11208
|
function createOp3(kind, payload) {
|
|
11300
|
-
return
|
|
11209
|
+
return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, payload });
|
|
11301
11210
|
}
|
|
11302
11211
|
function updateOp3(kind, payload) {
|
|
11303
|
-
return
|
|
11212
|
+
return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, target: updateTargetSchema2, payload });
|
|
11304
11213
|
}
|
|
11305
|
-
var metaDraftOpInputSchema =
|
|
11214
|
+
var metaDraftOpInputSchema = z9.discriminatedUnion("kind", [
|
|
11306
11215
|
createOp3("campaign.create", campaignCreateSchema3),
|
|
11307
11216
|
updateOp3("campaign.update", campaignUpdateSchema3),
|
|
11308
11217
|
createOp3("adSet.create", adSetCreateSchema),
|
|
@@ -11317,89 +11226,89 @@ var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
|
|
|
11317
11226
|
]);
|
|
11318
11227
|
|
|
11319
11228
|
// ../api/src/ads-meta/wire.ts
|
|
11320
|
-
import { z as
|
|
11321
|
-
var metaWriteModeSchema =
|
|
11322
|
-
var metaDraftOpResultSchema =
|
|
11323
|
-
status:
|
|
11229
|
+
import { z as z10 } from "zod";
|
|
11230
|
+
var metaWriteModeSchema = z10.enum(["live", "simulated"]);
|
|
11231
|
+
var metaDraftOpResultSchema = z10.object({
|
|
11232
|
+
status: z10.enum(["applied", "simulated", "failed", "skipped"]),
|
|
11324
11233
|
/** The resulting Meta node id (campaign/adset/creative/ad/audience) or simulated id. */
|
|
11325
|
-
id:
|
|
11234
|
+
id: z10.string().optional(),
|
|
11326
11235
|
/** For media.upload ops: the resulting image hash. */
|
|
11327
|
-
hash:
|
|
11328
|
-
error:
|
|
11329
|
-
skippedBecause:
|
|
11330
|
-
executedAt:
|
|
11236
|
+
hash: z10.string().optional(),
|
|
11237
|
+
error: z10.string().optional(),
|
|
11238
|
+
skippedBecause: z10.string().optional(),
|
|
11239
|
+
executedAt: z10.number().optional()
|
|
11331
11240
|
});
|
|
11332
|
-
var metaDraftStageRequestSchema =
|
|
11333
|
-
chatId:
|
|
11241
|
+
var metaDraftStageRequestSchema = z10.object({
|
|
11242
|
+
chatId: z10.string(),
|
|
11334
11243
|
op: metaDraftOpInputSchema
|
|
11335
11244
|
});
|
|
11336
|
-
var metaDraftStageResponseSchema =
|
|
11337
|
-
staged:
|
|
11338
|
-
ref:
|
|
11245
|
+
var metaDraftStageResponseSchema = z10.object({
|
|
11246
|
+
staged: z10.literal(true),
|
|
11247
|
+
ref: z10.string(),
|
|
11339
11248
|
kind: metaDraftOpKindSchema,
|
|
11340
11249
|
mode: metaWriteModeSchema,
|
|
11341
|
-
dependsOn:
|
|
11342
|
-
summary:
|
|
11343
|
-
warnings:
|
|
11250
|
+
dependsOn: z10.array(z10.string()),
|
|
11251
|
+
summary: z10.string(),
|
|
11252
|
+
warnings: z10.array(z10.string()),
|
|
11344
11253
|
/** True when the op amended an already-staged op in place instead of appending a new one. */
|
|
11345
|
-
amended:
|
|
11346
|
-
});
|
|
11347
|
-
var metaDraftDuplicateRequestSchema =
|
|
11348
|
-
chatId:
|
|
11349
|
-
accountId:
|
|
11350
|
-
entity:
|
|
11351
|
-
sourceId:
|
|
11352
|
-
overrides:
|
|
11254
|
+
amended: z10.boolean().optional()
|
|
11255
|
+
});
|
|
11256
|
+
var metaDraftDuplicateRequestSchema = z10.object({
|
|
11257
|
+
chatId: z10.string(),
|
|
11258
|
+
accountId: z10.string(),
|
|
11259
|
+
entity: z10.enum(["campaign", "adSet", "ad"]),
|
|
11260
|
+
sourceId: z10.string(),
|
|
11261
|
+
overrides: z10.record(z10.string(), z10.unknown()).optional(),
|
|
11353
11262
|
/** Pause the original after the copy publishes. */
|
|
11354
|
-
replace:
|
|
11263
|
+
replace: z10.boolean().optional()
|
|
11355
11264
|
});
|
|
11356
|
-
var metaDraftOpViewSchema =
|
|
11357
|
-
ref:
|
|
11265
|
+
var metaDraftOpViewSchema = z10.object({
|
|
11266
|
+
ref: z10.string(),
|
|
11358
11267
|
kind: metaDraftOpKindSchema,
|
|
11359
|
-
accountId:
|
|
11360
|
-
target:
|
|
11361
|
-
dependsOn:
|
|
11362
|
-
summary:
|
|
11363
|
-
stagedAt:
|
|
11268
|
+
accountId: z10.string(),
|
|
11269
|
+
target: z10.string().optional(),
|
|
11270
|
+
dependsOn: z10.array(z10.string()),
|
|
11271
|
+
summary: z10.string(),
|
|
11272
|
+
stagedAt: z10.number(),
|
|
11364
11273
|
result: metaDraftOpResultSchema.optional()
|
|
11365
11274
|
});
|
|
11366
|
-
var metaDraftListRequestSchema =
|
|
11367
|
-
chatId:
|
|
11275
|
+
var metaDraftListRequestSchema = z10.object({
|
|
11276
|
+
chatId: z10.string()
|
|
11368
11277
|
});
|
|
11369
|
-
var metaDraftAdvisorySchema =
|
|
11370
|
-
ref:
|
|
11371
|
-
message:
|
|
11278
|
+
var metaDraftAdvisorySchema = z10.object({
|
|
11279
|
+
ref: z10.string(),
|
|
11280
|
+
message: z10.string()
|
|
11372
11281
|
});
|
|
11373
|
-
var metaDraftListResponseSchema =
|
|
11374
|
-
status:
|
|
11282
|
+
var metaDraftListResponseSchema = z10.object({
|
|
11283
|
+
status: z10.enum(["active", "publishing", "applied", "discarded", "none"]),
|
|
11375
11284
|
mode: metaWriteModeSchema,
|
|
11376
|
-
count:
|
|
11377
|
-
ops:
|
|
11285
|
+
count: z10.number(),
|
|
11286
|
+
ops: z10.array(metaDraftOpViewSchema),
|
|
11378
11287
|
/** Non-blocking cross-op quality advisories — "good campaign, not just valid". */
|
|
11379
|
-
advisories:
|
|
11288
|
+
advisories: z10.array(metaDraftAdvisorySchema)
|
|
11380
11289
|
});
|
|
11381
|
-
var metaDraftRemoveRequestSchema =
|
|
11382
|
-
chatId:
|
|
11383
|
-
ref:
|
|
11290
|
+
var metaDraftRemoveRequestSchema = z10.object({
|
|
11291
|
+
chatId: z10.string(),
|
|
11292
|
+
ref: z10.string()
|
|
11384
11293
|
});
|
|
11385
|
-
var metaDraftRemoveResponseSchema =
|
|
11294
|
+
var metaDraftRemoveResponseSchema = z10.object({
|
|
11386
11295
|
/** The requested ref plus any dependents removed by cascade. */
|
|
11387
|
-
removed:
|
|
11296
|
+
removed: z10.array(z10.string())
|
|
11388
11297
|
});
|
|
11389
|
-
var metaDraftClearRequestSchema =
|
|
11390
|
-
chatId:
|
|
11298
|
+
var metaDraftClearRequestSchema = z10.object({
|
|
11299
|
+
chatId: z10.string()
|
|
11391
11300
|
});
|
|
11392
|
-
var metaDraftClearResponseSchema =
|
|
11393
|
-
cleared:
|
|
11301
|
+
var metaDraftClearResponseSchema = z10.object({
|
|
11302
|
+
cleared: z10.number()
|
|
11394
11303
|
});
|
|
11395
|
-
var metaFieldErrorSchema =
|
|
11396
|
-
path:
|
|
11397
|
-
message:
|
|
11304
|
+
var metaFieldErrorSchema = z10.object({
|
|
11305
|
+
path: z10.string(),
|
|
11306
|
+
message: z10.string()
|
|
11398
11307
|
});
|
|
11399
|
-
var metaDraftErrorResponseSchema =
|
|
11400
|
-
code:
|
|
11401
|
-
error:
|
|
11402
|
-
fields:
|
|
11308
|
+
var metaDraftErrorResponseSchema = z10.object({
|
|
11309
|
+
code: z10.string(),
|
|
11310
|
+
error: z10.string(),
|
|
11311
|
+
fields: z10.array(metaFieldErrorSchema).optional()
|
|
11403
11312
|
});
|
|
11404
11313
|
|
|
11405
11314
|
// src/commands/ads/meta/write-shared.ts
|
|
@@ -11410,19 +11319,19 @@ function failWriteValidation3(message) {
|
|
|
11410
11319
|
writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
|
|
11411
11320
|
process.exit(1);
|
|
11412
11321
|
}
|
|
11413
|
-
function loadJsonFileArg3(
|
|
11414
|
-
if (typeof
|
|
11322
|
+
function loadJsonFileArg3(path14) {
|
|
11323
|
+
if (typeof path14 !== "string" || path14.length === 0) {
|
|
11415
11324
|
return {};
|
|
11416
11325
|
}
|
|
11417
11326
|
try {
|
|
11418
|
-
const parsed = JSON.parse(readFileSync8(
|
|
11327
|
+
const parsed = JSON.parse(readFileSync8(path14, "utf8"));
|
|
11419
11328
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11420
|
-
failWriteValidation3(`${
|
|
11329
|
+
failWriteValidation3(`${path14} must contain a JSON object`);
|
|
11421
11330
|
}
|
|
11422
11331
|
return parsed;
|
|
11423
11332
|
} catch (err) {
|
|
11424
11333
|
if (err instanceof SyntaxError) {
|
|
11425
|
-
failWriteValidation3(`${
|
|
11334
|
+
failWriteValidation3(`${path14} is not valid JSON: ${err.message}`);
|
|
11426
11335
|
}
|
|
11427
11336
|
throw err;
|
|
11428
11337
|
}
|
|
@@ -14485,7 +14394,7 @@ async function probeDuration(filePath) {
|
|
|
14485
14394
|
|
|
14486
14395
|
// src/commands/canvas/run.ts
|
|
14487
14396
|
import { readFile as readFile2 } from "fs/promises";
|
|
14488
|
-
import
|
|
14397
|
+
import path5 from "path";
|
|
14489
14398
|
import { defineCommand as defineCommand88 } from "citty";
|
|
14490
14399
|
|
|
14491
14400
|
// src/commands/canvas/placeholders.ts
|
|
@@ -14529,9 +14438,260 @@ function isResolvableRelative(value) {
|
|
|
14529
14438
|
return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
|
|
14530
14439
|
}
|
|
14531
14440
|
|
|
14441
|
+
// src/commands/canvas/run-record.ts
|
|
14442
|
+
import path3 from "path";
|
|
14443
|
+
var MAX_RUN_NODES = 200;
|
|
14444
|
+
var MAX_OUTPUTS_PER_NODE = 10;
|
|
14445
|
+
var MAX_FINAL_OUTPUTS = 10;
|
|
14446
|
+
var MAX_PARAMS_PREVIEW_LENGTH = 1e3;
|
|
14447
|
+
function paramsPreviewFromParams(params) {
|
|
14448
|
+
if (params === void 0 || params === null) return void 0;
|
|
14449
|
+
const prompt = params.prompt;
|
|
14450
|
+
const text = typeof prompt === "string" && prompt.trim() ? prompt.trim() : 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 compactJson(params) {
|
|
14455
|
+
try {
|
|
14456
|
+
const json = JSON.stringify(params);
|
|
14457
|
+
return json && json !== "{}" ? json : void 0;
|
|
14458
|
+
} catch {
|
|
14459
|
+
return void 0;
|
|
14460
|
+
}
|
|
14461
|
+
}
|
|
14462
|
+
var MAX_CREATIVE_SLUG_LENGTH = 100;
|
|
14463
|
+
function creativeSlugFromCanvasPath(filePath) {
|
|
14464
|
+
const normalized = filePath.split(path3.sep).join("/");
|
|
14465
|
+
const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
|
|
14466
|
+
const slug = match?.[1] ?? null;
|
|
14467
|
+
return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
|
|
14468
|
+
}
|
|
14469
|
+
var OUTPUT_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
|
|
14470
|
+
function toRecordOutput(slot, value) {
|
|
14471
|
+
const refs = collectAssetRefLikes(value);
|
|
14472
|
+
const ref = refs.length === 1 ? refs[0] : null;
|
|
14473
|
+
if (!ref || !isPersistedAssetRef(ref)) return null;
|
|
14474
|
+
const kind = typeof ref.kind === "string" && OUTPUT_KINDS.has(ref.kind) ? ref.kind : null;
|
|
14475
|
+
if (!kind) return null;
|
|
14476
|
+
return {
|
|
14477
|
+
slot,
|
|
14478
|
+
kind,
|
|
14479
|
+
sha256: ref.sha256,
|
|
14480
|
+
url: ref.url,
|
|
14481
|
+
mime: ref.mime,
|
|
14482
|
+
width: typeof ref.width === "number" ? ref.width : void 0,
|
|
14483
|
+
height: typeof ref.height === "number" ? ref.height : void 0,
|
|
14484
|
+
durationMs: typeof ref.duration_ms === "number" ? ref.duration_ms : void 0
|
|
14485
|
+
};
|
|
14486
|
+
}
|
|
14487
|
+
function nodeOutputsToRecord(nodeOutputs) {
|
|
14488
|
+
const out = [];
|
|
14489
|
+
for (const [slot, value] of Object.entries(nodeOutputs)) {
|
|
14490
|
+
if (Array.isArray(value)) {
|
|
14491
|
+
value.forEach((item, i) => {
|
|
14492
|
+
const rec = toRecordOutput(`${slot}#${i}`, item);
|
|
14493
|
+
if (rec) out.push(rec);
|
|
14494
|
+
});
|
|
14495
|
+
} else {
|
|
14496
|
+
const rec = toRecordOutput(slot, value);
|
|
14497
|
+
if (rec) out.push(rec);
|
|
14498
|
+
}
|
|
14499
|
+
}
|
|
14500
|
+
return out.slice(0, MAX_OUTPUTS_PER_NODE);
|
|
14501
|
+
}
|
|
14502
|
+
function finalOutputsToRecord(output) {
|
|
14503
|
+
if (Array.isArray(output)) {
|
|
14504
|
+
return output.map((item, i) => toRecordOutput(`final#${i}`, item)).filter((rec2) => rec2 !== null).slice(0, MAX_FINAL_OUTPUTS);
|
|
14505
|
+
}
|
|
14506
|
+
const rec = toRecordOutput("final", output);
|
|
14507
|
+
return rec ? [rec] : [];
|
|
14508
|
+
}
|
|
14509
|
+
function buildRunRecord(result, meta, plan) {
|
|
14510
|
+
const nodes = result.node_runs.slice(0, MAX_RUN_NODES).map((run) => {
|
|
14511
|
+
const planned = plan?.get(run.node_id);
|
|
14512
|
+
return {
|
|
14513
|
+
nodeId: run.node_id,
|
|
14514
|
+
nodeType: run.node_type,
|
|
14515
|
+
cached: run.cached,
|
|
14516
|
+
credits: run.credits,
|
|
14517
|
+
durationMs: run.duration_ms,
|
|
14518
|
+
outputs: nodeOutputsToRecord(result.outputs_by_node[run.node_id] ?? {}),
|
|
14519
|
+
deps: planned?.deps,
|
|
14520
|
+
status: plan ? "completed" : void 0,
|
|
14521
|
+
paramsPreview: planned?.paramsPreview
|
|
14522
|
+
};
|
|
14523
|
+
});
|
|
14524
|
+
const finalOutputs = finalOutputsToRecord(result.output);
|
|
14525
|
+
return {
|
|
14526
|
+
runId: result.run_id,
|
|
14527
|
+
creativeSlug: meta.creativeSlug,
|
|
14528
|
+
canvasPath: meta.canvasPath,
|
|
14529
|
+
canvasSha: meta.canvasSha,
|
|
14530
|
+
chatId: meta.chatId,
|
|
14531
|
+
status: "completed",
|
|
14532
|
+
stats: {
|
|
14533
|
+
totalNodes: result.stats.total_nodes,
|
|
14534
|
+
cachedNodes: result.stats.cached_nodes,
|
|
14535
|
+
totalCredits: result.stats.total_credits,
|
|
14536
|
+
durationMs: result.stats.duration_ms
|
|
14537
|
+
},
|
|
14538
|
+
nodes,
|
|
14539
|
+
finalOutputs: finalOutputs.length > 0 ? finalOutputs : void 0
|
|
14540
|
+
};
|
|
14541
|
+
}
|
|
14542
|
+
function buildFailedRunRecord(runId, errorMessage, meta) {
|
|
14543
|
+
return {
|
|
14544
|
+
runId,
|
|
14545
|
+
creativeSlug: meta.creativeSlug,
|
|
14546
|
+
canvasPath: meta.canvasPath,
|
|
14547
|
+
canvasSha: meta.canvasSha,
|
|
14548
|
+
chatId: meta.chatId,
|
|
14549
|
+
status: "failed",
|
|
14550
|
+
errorMessage: errorMessage.slice(0, 2e3),
|
|
14551
|
+
stats: { totalNodes: 0, cachedNodes: 0, totalCredits: 0, durationMs: 0 },
|
|
14552
|
+
nodes: []
|
|
14553
|
+
};
|
|
14554
|
+
}
|
|
14555
|
+
|
|
14556
|
+
// src/commands/canvas/run-progress.ts
|
|
14557
|
+
var RunProgressTracker = class {
|
|
14558
|
+
runId;
|
|
14559
|
+
meta;
|
|
14560
|
+
startedAt;
|
|
14561
|
+
nodes = /* @__PURE__ */ new Map();
|
|
14562
|
+
planned = false;
|
|
14563
|
+
constructor(runId, meta) {
|
|
14564
|
+
this.runId = runId;
|
|
14565
|
+
this.meta = meta;
|
|
14566
|
+
this.startedAt = Date.now();
|
|
14567
|
+
}
|
|
14568
|
+
apply(event) {
|
|
14569
|
+
if (event.kind === "plan") {
|
|
14570
|
+
for (const node of event.nodes) {
|
|
14571
|
+
this.nodes.set(node.node_id, {
|
|
14572
|
+
nodeId: node.node_id,
|
|
14573
|
+
nodeType: node.node_type,
|
|
14574
|
+
cached: false,
|
|
14575
|
+
credits: 0,
|
|
14576
|
+
durationMs: 0,
|
|
14577
|
+
outputs: [],
|
|
14578
|
+
deps: node.deps,
|
|
14579
|
+
status: "pending",
|
|
14580
|
+
paramsPreview: paramsPreviewFromParams(node.params)
|
|
14581
|
+
});
|
|
14582
|
+
}
|
|
14583
|
+
this.planned = true;
|
|
14584
|
+
return;
|
|
14585
|
+
}
|
|
14586
|
+
if (event.kind === "node_start") {
|
|
14587
|
+
this.patchNode(event.node_id, { status: "running" });
|
|
14588
|
+
return;
|
|
14589
|
+
}
|
|
14590
|
+
if (event.kind === "node_settled") {
|
|
14591
|
+
this.patchNode(event.run.node_id, {
|
|
14592
|
+
status: "completed",
|
|
14593
|
+
cached: event.run.cached,
|
|
14594
|
+
credits: event.run.credits,
|
|
14595
|
+
durationMs: event.run.duration_ms,
|
|
14596
|
+
outputs: nodeOutputsToRecord(event.outputs)
|
|
14597
|
+
});
|
|
14598
|
+
return;
|
|
14599
|
+
}
|
|
14600
|
+
this.patchNode(event.node_id, { status: "failed" });
|
|
14601
|
+
}
|
|
14602
|
+
/** True once the plan event landed — before that there is nothing worth posting. */
|
|
14603
|
+
hasPlan() {
|
|
14604
|
+
return this.planned;
|
|
14605
|
+
}
|
|
14606
|
+
/** Plan facts (deps + params preview) for stamping the terminal record's nodes. */
|
|
14607
|
+
planInfo() {
|
|
14608
|
+
const info = /* @__PURE__ */ new Map();
|
|
14609
|
+
for (const node of this.nodes.values()) {
|
|
14610
|
+
info.set(node.nodeId, { deps: node.deps ?? [], paramsPreview: node.paramsPreview });
|
|
14611
|
+
}
|
|
14612
|
+
return info;
|
|
14613
|
+
}
|
|
14614
|
+
/** The current in-flight state as a postable full record. */
|
|
14615
|
+
snapshot() {
|
|
14616
|
+
const nodes = [...this.nodes.values()];
|
|
14617
|
+
return {
|
|
14618
|
+
runId: this.runId,
|
|
14619
|
+
...this.meta,
|
|
14620
|
+
status: "running",
|
|
14621
|
+
stats: {
|
|
14622
|
+
totalNodes: nodes.length,
|
|
14623
|
+
cachedNodes: nodes.filter((n) => n.cached).length,
|
|
14624
|
+
totalCredits: nodes.reduce((sum, n) => sum + n.credits, 0),
|
|
14625
|
+
durationMs: Date.now() - this.startedAt
|
|
14626
|
+
},
|
|
14627
|
+
nodes
|
|
14628
|
+
};
|
|
14629
|
+
}
|
|
14630
|
+
/**
|
|
14631
|
+
* Terminal record for a failed run, preserving what each node got to —
|
|
14632
|
+
* completed nodes keep their outputs so the graph shows exactly where the
|
|
14633
|
+
* run died instead of an empty husk.
|
|
14634
|
+
*/
|
|
14635
|
+
failedSnapshot(errorMessage) {
|
|
14636
|
+
const snapshot = this.snapshot();
|
|
14637
|
+
return {
|
|
14638
|
+
...snapshot,
|
|
14639
|
+
status: "failed",
|
|
14640
|
+
errorMessage: errorMessage.slice(0, 2e3),
|
|
14641
|
+
stats: { ...snapshot.stats, durationMs: Date.now() - this.startedAt }
|
|
14642
|
+
};
|
|
14643
|
+
}
|
|
14644
|
+
patchNode(nodeId, patch) {
|
|
14645
|
+
const existing = this.nodes.get(nodeId);
|
|
14646
|
+
if (!existing) return;
|
|
14647
|
+
this.nodes.set(nodeId, { ...existing, ...patch, status: patch.status ?? existing.status });
|
|
14648
|
+
}
|
|
14649
|
+
};
|
|
14650
|
+
var RunRecordPoster = class {
|
|
14651
|
+
post;
|
|
14652
|
+
latest = null;
|
|
14653
|
+
inflight = null;
|
|
14654
|
+
warned = false;
|
|
14655
|
+
constructor(post) {
|
|
14656
|
+
this.post = post;
|
|
14657
|
+
}
|
|
14658
|
+
/** Queue a progress snapshot; returns immediately. */
|
|
14659
|
+
enqueue(payload) {
|
|
14660
|
+
this.latest = payload;
|
|
14661
|
+
if (!this.inflight) this.inflight = this.pump();
|
|
14662
|
+
}
|
|
14663
|
+
/**
|
|
14664
|
+
* Post the terminal record (awaited, errors surfaced to the caller). Any
|
|
14665
|
+
* queued progress snapshot is superseded — the terminal record is the full
|
|
14666
|
+
* state — but an in-flight POST is awaited first so it can't land after.
|
|
14667
|
+
*/
|
|
14668
|
+
async flush(terminal) {
|
|
14669
|
+
this.latest = null;
|
|
14670
|
+
if (this.inflight) await this.inflight;
|
|
14671
|
+
await this.post(terminal);
|
|
14672
|
+
}
|
|
14673
|
+
async pump() {
|
|
14674
|
+
while (this.latest) {
|
|
14675
|
+
const payload = this.latest;
|
|
14676
|
+
this.latest = null;
|
|
14677
|
+
try {
|
|
14678
|
+
await this.post(payload);
|
|
14679
|
+
} catch (e) {
|
|
14680
|
+
if (!this.warned) {
|
|
14681
|
+
this.warned = true;
|
|
14682
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14683
|
+
process.stderr.write(`[warn] live run progress not streaming (${msg})
|
|
14684
|
+
`);
|
|
14685
|
+
}
|
|
14686
|
+
}
|
|
14687
|
+
}
|
|
14688
|
+
this.inflight = null;
|
|
14689
|
+
}
|
|
14690
|
+
};
|
|
14691
|
+
|
|
14532
14692
|
// src/commands/canvas/run-retention.ts
|
|
14533
14693
|
import { rm } from "fs/promises";
|
|
14534
|
-
import
|
|
14694
|
+
import path4 from "path";
|
|
14535
14695
|
function runDirsToPrune(entries, keep, currentRunId) {
|
|
14536
14696
|
const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
|
|
14537
14697
|
if (keep <= 0) return runs;
|
|
@@ -14548,7 +14708,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
|
|
|
14548
14708
|
const toPrune = runDirsToPrune(entries, keep, currentRunId);
|
|
14549
14709
|
if (toPrune.length === 0) return;
|
|
14550
14710
|
for (const dir of toPrune) {
|
|
14551
|
-
await rm(
|
|
14711
|
+
await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
|
|
14552
14712
|
(e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
|
|
14553
14713
|
);
|
|
14554
14714
|
}
|
|
@@ -14575,10 +14735,22 @@ var runCommand = defineCommand88({
|
|
|
14575
14735
|
"keep-runs": {
|
|
14576
14736
|
type: "string",
|
|
14577
14737
|
description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
|
|
14738
|
+
},
|
|
14739
|
+
"remote-cache": {
|
|
14740
|
+
type: "string",
|
|
14741
|
+
description: "on | off \u2014 company-scoped remote cache + durable asset persistence (default on; env BAKER_CANVAS_REMOTE_CACHE)"
|
|
14742
|
+
},
|
|
14743
|
+
// citty consumes any `--no-<flag>` as a negation of `<flag>`, so the
|
|
14744
|
+
// opt-out spelling `--no-record` requires the flag to be named `record`
|
|
14745
|
+
// (a literal "no-record" arg would never receive a value).
|
|
14746
|
+
record: {
|
|
14747
|
+
type: "boolean",
|
|
14748
|
+
default: true,
|
|
14749
|
+
description: "Post the durable run-history record to Baker (disable with --no-record)"
|
|
14578
14750
|
}
|
|
14579
14751
|
},
|
|
14580
14752
|
async run({ args }) {
|
|
14581
|
-
const filePath =
|
|
14753
|
+
const filePath = path5.resolve(String(args.file));
|
|
14582
14754
|
const raw = await readFile2(filePath, "utf8");
|
|
14583
14755
|
let parsed;
|
|
14584
14756
|
try {
|
|
@@ -14589,7 +14761,7 @@ var runCommand = defineCommand88({
|
|
|
14589
14761
|
`);
|
|
14590
14762
|
process.exit(2);
|
|
14591
14763
|
}
|
|
14592
|
-
parsed = resolveRelativeCanvasPaths(parsed,
|
|
14764
|
+
parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
|
|
14593
14765
|
const pending = unsuppliedPlaceholderAssets(parsed);
|
|
14594
14766
|
if (pending.length > 0) {
|
|
14595
14767
|
process.stderr.write(
|
|
@@ -14609,26 +14781,43 @@ var runCommand = defineCommand88({
|
|
|
14609
14781
|
);
|
|
14610
14782
|
process.exit(2);
|
|
14611
14783
|
}
|
|
14784
|
+
const remoteCache = args["remote-cache"] !== void 0 ? String(args["remote-cache"]) !== "off" : void 0;
|
|
14612
14785
|
const engine = createEngineFromEnv({
|
|
14613
14786
|
cacheDir: args["cache-dir"] ? String(args["cache-dir"]) : void 0,
|
|
14614
14787
|
outputsDir: args["outputs-dir"] ? String(args["outputs-dir"]) : void 0,
|
|
14615
14788
|
log: (line) => process.stdout.write(`${line}
|
|
14616
|
-
`)
|
|
14789
|
+
`),
|
|
14790
|
+
remoteCache
|
|
14617
14791
|
});
|
|
14792
|
+
const runId = args["run-id"] ? String(args["run-id"]) : `r_${ulid()}`;
|
|
14793
|
+
const recordMeta = {
|
|
14794
|
+
creativeSlug: creativeSlugFromCanvasPath(filePath) ?? void 0,
|
|
14795
|
+
canvasPath: path5.relative(process.cwd(), filePath) || void 0,
|
|
14796
|
+
canvasSha: sha256Hex(Buffer.from(raw)),
|
|
14797
|
+
chatId: getEnv().BAKER_CHAT_ID || void 0
|
|
14798
|
+
};
|
|
14799
|
+
const record = args.record === false ? null : buildRecorder();
|
|
14800
|
+
const progress = record ? new RunProgressTracker(runId, recordMeta) : null;
|
|
14801
|
+
const poster = record ? new RunRecordPoster(record) : null;
|
|
14618
14802
|
try {
|
|
14619
14803
|
const policy = args["cache-policy"] ?? "read_write";
|
|
14620
14804
|
const result = await engine.run(parsed, {
|
|
14621
|
-
run_id:
|
|
14805
|
+
run_id: runId,
|
|
14622
14806
|
cache_policy: policy,
|
|
14623
14807
|
concurrency: resolveConcurrency(
|
|
14624
14808
|
// --concurrency wins; --parallel is the discoverable alias for the same bound.
|
|
14625
14809
|
(args.concurrency ?? args.parallel) !== void 0 ? String(args.concurrency ?? args.parallel) : void 0,
|
|
14626
14810
|
process.env.BAKER_CANVAS_CONCURRENCY
|
|
14627
|
-
)
|
|
14811
|
+
),
|
|
14812
|
+
onProgress: progress && poster ? (event) => {
|
|
14813
|
+
progress.apply(event);
|
|
14814
|
+
if (progress.hasPlan()) poster.enqueue(progress.snapshot());
|
|
14815
|
+
} : void 0
|
|
14628
14816
|
});
|
|
14817
|
+
if (poster) await poster.flush(buildRunRecord(result, recordMeta, progress?.planInfo()));
|
|
14629
14818
|
const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
|
|
14630
14819
|
if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
|
|
14631
|
-
const outputsDir = args["outputs-dir"] ?
|
|
14820
|
+
const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
|
|
14632
14821
|
await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
|
|
14633
14822
|
`));
|
|
14634
14823
|
}
|
|
@@ -14654,8 +14843,10 @@ var runCommand = defineCommand88({
|
|
|
14654
14843
|
);
|
|
14655
14844
|
process.exit(2);
|
|
14656
14845
|
}
|
|
14846
|
+
const failedPayload = (message) => progress?.hasPlan() ? progress.failedSnapshot(message) : buildFailedRunRecord(runId, message, recordMeta);
|
|
14657
14847
|
if (e instanceof LayerExecutionError) {
|
|
14658
14848
|
const failures = e.failures.map((f) => ({ node_id: f.nodeId, message: describeFailureReason(f.reason) }));
|
|
14849
|
+
if (poster) await poster.flush(failedPayload(e.message));
|
|
14659
14850
|
process.stderr.write(
|
|
14660
14851
|
`${JSON.stringify({ ok: false, error: { code: "runtime", message: e.message, failures } }, null, 2)}
|
|
14661
14852
|
`
|
|
@@ -14663,40 +14854,54 @@ var runCommand = defineCommand88({
|
|
|
14663
14854
|
process.exit(1);
|
|
14664
14855
|
}
|
|
14665
14856
|
const msg = e instanceof Error ? e.message : String(e);
|
|
14857
|
+
if (poster) await poster.flush(failedPayload(msg));
|
|
14666
14858
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "runtime", message: msg } }, null, 2)}
|
|
14667
14859
|
`);
|
|
14668
14860
|
process.exit(1);
|
|
14669
14861
|
}
|
|
14670
14862
|
}
|
|
14671
14863
|
});
|
|
14864
|
+
function buildRecorder() {
|
|
14865
|
+
return async (payload) => {
|
|
14866
|
+
try {
|
|
14867
|
+
const creds = requireCredentialsFromEnv();
|
|
14868
|
+
const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
|
|
14869
|
+
await client.recordRun(payload);
|
|
14870
|
+
} catch (e) {
|
|
14871
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14872
|
+
process.stderr.write(`[warn] run record not persisted (${msg})
|
|
14873
|
+
`);
|
|
14874
|
+
}
|
|
14875
|
+
};
|
|
14876
|
+
}
|
|
14672
14877
|
|
|
14673
14878
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
14674
|
-
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
14675
|
-
import
|
|
14879
|
+
import { access, cp, mkdir, readFile as readFile3, writeFile } from "fs/promises";
|
|
14880
|
+
import path8 from "path";
|
|
14676
14881
|
import { defineCommand as defineCommand89 } from "citty";
|
|
14677
14882
|
|
|
14678
14883
|
// src/engine/scaffold/staticAd.ts
|
|
14679
|
-
import { z as
|
|
14884
|
+
import { z as z11 } from "zod";
|
|
14680
14885
|
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"]);
|
|
14681
14886
|
var DEFAULT_ASPECT_RATIO = "9:16";
|
|
14682
|
-
var Blueprint =
|
|
14683
|
-
meta:
|
|
14684
|
-
text_content:
|
|
14887
|
+
var Blueprint = z11.object({
|
|
14888
|
+
meta: z11.object({ estimated_aspect_ratio: z11.string().optional() }).loose().optional(),
|
|
14889
|
+
text_content: z11.array(z11.object({ text: z11.string().optional() }).loose()).optional()
|
|
14685
14890
|
}).loose();
|
|
14686
|
-
var ElementLocator =
|
|
14687
|
-
collection:
|
|
14688
|
-
index:
|
|
14891
|
+
var ElementLocator = z11.object({
|
|
14892
|
+
collection: z11.enum(["subjects", "people", "brands_logos"]),
|
|
14893
|
+
index: z11.number().int().nonnegative()
|
|
14689
14894
|
}).loose();
|
|
14690
|
-
var MainElement =
|
|
14895
|
+
var MainElement = z11.object({
|
|
14691
14896
|
// logo | product | person | animal | badge | other
|
|
14692
|
-
type:
|
|
14693
|
-
label:
|
|
14694
|
-
description:
|
|
14695
|
-
expression:
|
|
14696
|
-
reason:
|
|
14897
|
+
type: z11.string(),
|
|
14898
|
+
label: z11.string().optional(),
|
|
14899
|
+
description: z11.string().optional(),
|
|
14900
|
+
expression: z11.string().nullable().optional(),
|
|
14901
|
+
reason: z11.string().optional(),
|
|
14697
14902
|
locator: ElementLocator.optional()
|
|
14698
14903
|
}).loose();
|
|
14699
|
-
var MainElements =
|
|
14904
|
+
var MainElements = z11.array(MainElement);
|
|
14700
14905
|
function sanitizeId(raw, fallback) {
|
|
14701
14906
|
const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
14702
14907
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
@@ -14858,18 +15063,106 @@ function staticAdReport(input, elementsInput, opts) {
|
|
|
14858
15063
|
};
|
|
14859
15064
|
}
|
|
14860
15065
|
|
|
15066
|
+
// src/commands/canvas/creative-definition.ts
|
|
15067
|
+
import path6 from "path";
|
|
15068
|
+
var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
|
|
15069
|
+
var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
|
|
15070
|
+
function titleFromSlug(slug) {
|
|
15071
|
+
const title = slug.split("-").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
15072
|
+
return title || slug;
|
|
15073
|
+
}
|
|
15074
|
+
function resolvePlatform(platform) {
|
|
15075
|
+
const value = platform?.trim();
|
|
15076
|
+
return value && PLATFORM_VALUES.includes(value) ? value : "meta";
|
|
15077
|
+
}
|
|
15078
|
+
function resolveFormats(aspect) {
|
|
15079
|
+
const value = aspect?.trim();
|
|
15080
|
+
return value && FORMAT_VALUES.includes(value) ? [value] : ["4:5"];
|
|
15081
|
+
}
|
|
15082
|
+
function referenceRelativePath(kind, ext) {
|
|
15083
|
+
const name = kind === "video" ? "source" : "original";
|
|
15084
|
+
return `references/${name}${ext}`;
|
|
15085
|
+
}
|
|
15086
|
+
function sourceExtension(source, isUrl, kind) {
|
|
15087
|
+
const raw = isUrl ? urlPathname(source) : source;
|
|
15088
|
+
const ext = path6.extname(raw).toLowerCase();
|
|
15089
|
+
if (/^\.[a-z0-9]{1,5}$/.test(ext)) return ext;
|
|
15090
|
+
return kind === "video" ? ".mp4" : ".jpg";
|
|
15091
|
+
}
|
|
15092
|
+
function urlPathname(source) {
|
|
15093
|
+
try {
|
|
15094
|
+
return new URL(source).pathname;
|
|
15095
|
+
} catch {
|
|
15096
|
+
return source;
|
|
15097
|
+
}
|
|
15098
|
+
}
|
|
15099
|
+
function describeBlueprintIntent(blueprint) {
|
|
15100
|
+
const intent = blueprint?.ad_intent;
|
|
15101
|
+
if (typeof intent === "string" && intent.trim()) return intent.trim();
|
|
15102
|
+
if (intent && typeof intent === "object") {
|
|
15103
|
+
const summary = intent.summary ?? intent.feeling;
|
|
15104
|
+
if (typeof summary === "string" && summary.trim()) return summary.trim();
|
|
15105
|
+
}
|
|
15106
|
+
return void 0;
|
|
15107
|
+
}
|
|
15108
|
+
function yamlScalar(value) {
|
|
15109
|
+
return JSON.stringify(value);
|
|
15110
|
+
}
|
|
15111
|
+
function buildCreativeDefinition(input) {
|
|
15112
|
+
const lines = ["---", `title: ${yamlScalar(input.title)}`, `kind: ${input.kind}`, `platform: ${input.platform}`];
|
|
15113
|
+
lines.push(`formats: [${input.formats.map(yamlScalar).join(", ")}]`);
|
|
15114
|
+
lines.push(`status: ${input.status ?? "draft"}`);
|
|
15115
|
+
if (input.sourceReferenceUrl) lines.push(`sourceReferenceUrl: ${yamlScalar(input.sourceReferenceUrl)}`);
|
|
15116
|
+
if (input.sourceAdvertiser) lines.push(`sourceAdvertiser: ${yamlScalar(input.sourceAdvertiser)}`);
|
|
15117
|
+
if (input.sourceKind) lines.push(`sourceKind: ${input.sourceKind}`);
|
|
15118
|
+
if (input.sourcePath) lines.push(`sourcePath: ${yamlScalar(input.sourcePath)}`);
|
|
15119
|
+
lines.push("---", "");
|
|
15120
|
+
lines.push(input.description?.trim() || `${input.title} \u2014 canvas-built ${input.kind} ad for ${input.platform}.`);
|
|
15121
|
+
lines.push("");
|
|
15122
|
+
return lines.join("\n");
|
|
15123
|
+
}
|
|
15124
|
+
|
|
14861
15125
|
// src/commands/canvas/scaffold-static-ad-paths.ts
|
|
14862
|
-
import
|
|
14863
|
-
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd()) {
|
|
15126
|
+
import path7 from "path";
|
|
15127
|
+
function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
|
|
14864
15128
|
const file = rawFile.trim();
|
|
14865
15129
|
const imageIsUrl = /^https?:\/\//i.test(file);
|
|
14866
|
-
const imageSource = imageIsUrl ? file :
|
|
14867
|
-
const outPath = out ?
|
|
14868
|
-
const blueprintPath =
|
|
14869
|
-
|
|
15130
|
+
const imageSource = imageIsUrl ? file : path7.resolve(cwd, file);
|
|
15131
|
+
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");
|
|
15132
|
+
const blueprintPath = path7.join(path7.dirname(outPath), "prompt.json");
|
|
15133
|
+
const creativeDir = slug ? path7.dirname(outPath) : null;
|
|
15134
|
+
const definitionPath = creativeDir ? path7.join(creativeDir, "_definition.md") : null;
|
|
15135
|
+
const referencesDir = creativeDir ? path7.join(creativeDir, "references") : null;
|
|
15136
|
+
return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
|
|
15137
|
+
}
|
|
15138
|
+
var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
15139
|
+
var SCAFFOLD_SLUG_MAX_LENGTH = 100;
|
|
15140
|
+
function isValidScaffoldSlug(slug) {
|
|
15141
|
+
return slug.length <= SCAFFOLD_SLUG_MAX_LENGTH && SCAFFOLD_SLUG_PATTERN.test(slug);
|
|
14870
15142
|
}
|
|
14871
15143
|
|
|
14872
15144
|
// src/commands/canvas/scaffold-static-ad.ts
|
|
15145
|
+
async function fileExists(target) {
|
|
15146
|
+
try {
|
|
15147
|
+
await access(target);
|
|
15148
|
+
return true;
|
|
15149
|
+
} catch {
|
|
15150
|
+
return false;
|
|
15151
|
+
}
|
|
15152
|
+
}
|
|
15153
|
+
async function copySourceIntoReferences(source, isUrl, referencesDir) {
|
|
15154
|
+
await mkdir(referencesDir, { recursive: true });
|
|
15155
|
+
const relPath = referenceRelativePath("image", sourceExtension(source, isUrl, "image"));
|
|
15156
|
+
const dest = path8.join(referencesDir, path8.basename(relPath));
|
|
15157
|
+
if (isUrl) {
|
|
15158
|
+
const res = await fetch(source);
|
|
15159
|
+
if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
|
|
15160
|
+
await writeFile(dest, Buffer.from(await res.arrayBuffer()));
|
|
15161
|
+
} else {
|
|
15162
|
+
await cp(source, dest);
|
|
15163
|
+
}
|
|
15164
|
+
return relPath;
|
|
15165
|
+
}
|
|
14873
15166
|
function resolveModel(kind, preferred) {
|
|
14874
15167
|
const ids = Object.keys(MODEL_REGISTRY[kind]);
|
|
14875
15168
|
return ids.includes(preferred) ? preferred : ids[0] ?? preferred;
|
|
@@ -15029,6 +15322,16 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15029
15322
|
file: { type: "positional", required: true, description: "Path or http(s) URL to the source/inspiration image" },
|
|
15030
15323
|
context: { type: "string", description: "Known provenance (advertiser, category, market) to ground the describe" },
|
|
15031
15324
|
out: { type: "string", description: "Output canvas path (default <image-dir>/static-ad.canvas.json)" },
|
|
15325
|
+
slug: {
|
|
15326
|
+
type: "string",
|
|
15327
|
+
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
15328
|
+
},
|
|
15329
|
+
title: { type: "string", description: "Creative title for _definition.md (default: title-cased slug)" },
|
|
15330
|
+
platform: {
|
|
15331
|
+
type: "string",
|
|
15332
|
+
description: "Ad platform for _definition.md (meta|google|linkedin|tiktok|youtube|x|other; default meta)"
|
|
15333
|
+
},
|
|
15334
|
+
advertiser: { type: "string", description: "Source advertiser recorded in _definition.md" },
|
|
15032
15335
|
"describe-model": { type: "string", description: "Override the image_describe model id" },
|
|
15033
15336
|
"select-model": { type: "string", description: "Override the text_generate model id for element selection" },
|
|
15034
15337
|
"layout-model": { type: "string", description: "Override the text_generate model id for the layout pass" },
|
|
@@ -15037,10 +15340,21 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15037
15340
|
"skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
|
|
15038
15341
|
},
|
|
15039
15342
|
async run({ args }) {
|
|
15040
|
-
const
|
|
15343
|
+
const slug = args.slug ? String(args.slug) : void 0;
|
|
15344
|
+
if (slug && !isValidScaffoldSlug(slug)) {
|
|
15345
|
+
process.stderr.write(
|
|
15346
|
+
`${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
|
|
15347
|
+
`
|
|
15348
|
+
);
|
|
15349
|
+
process.exit(2);
|
|
15350
|
+
}
|
|
15351
|
+
const { imageIsUrl, imageSource, outPath, blueprintPath, definitionPath, referencesDir } = resolveScaffoldStaticAdPaths(
|
|
15041
15352
|
String(args.file),
|
|
15042
|
-
args.out ? String(args.out) : void 0
|
|
15353
|
+
args.out ? String(args.out) : void 0,
|
|
15354
|
+
process.cwd(),
|
|
15355
|
+
slug
|
|
15043
15356
|
);
|
|
15357
|
+
await mkdir(path8.dirname(outPath), { recursive: true });
|
|
15044
15358
|
const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
|
|
15045
15359
|
const describeCanvas = buildDescribeCanvas(
|
|
15046
15360
|
imageSource,
|
|
@@ -15057,11 +15371,21 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15057
15371
|
}
|
|
15058
15372
|
await writeFile(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
15059
15373
|
`, "utf8");
|
|
15374
|
+
let canvasImagePath = imageSource;
|
|
15375
|
+
let canvasImageIsUrl = imageIsUrl;
|
|
15376
|
+
let canvasBlueprintPath = blueprintPath;
|
|
15377
|
+
let sourceRelPath;
|
|
15378
|
+
if (referencesDir) {
|
|
15379
|
+
sourceRelPath = await copySourceIntoReferences(imageSource, imageIsUrl, referencesDir);
|
|
15380
|
+
canvasImagePath = sourceRelPath;
|
|
15381
|
+
canvasImageIsUrl = false;
|
|
15382
|
+
canvasBlueprintPath = "./prompt.json";
|
|
15383
|
+
}
|
|
15060
15384
|
const opts = {
|
|
15061
15385
|
genModel,
|
|
15062
|
-
imagePath:
|
|
15063
|
-
imageIsUrl,
|
|
15064
|
-
blueprintPath,
|
|
15386
|
+
imagePath: canvasImagePath,
|
|
15387
|
+
imageIsUrl: canvasImageIsUrl,
|
|
15388
|
+
blueprintPath: canvasBlueprintPath,
|
|
15065
15389
|
aspectRatio: args.aspect ? String(args.aspect) : void 0,
|
|
15066
15390
|
includeFont: !args["skip-font"]
|
|
15067
15391
|
};
|
|
@@ -15083,12 +15407,31 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15083
15407
|
}
|
|
15084
15408
|
await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
15085
15409
|
`, "utf8");
|
|
15410
|
+
if (definitionPath && !await fileExists(definitionPath)) {
|
|
15411
|
+
await writeFile(
|
|
15412
|
+
definitionPath,
|
|
15413
|
+
buildCreativeDefinition({
|
|
15414
|
+
title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
|
|
15415
|
+
kind: "static",
|
|
15416
|
+
platform: resolvePlatform(args.platform ? String(args.platform) : void 0),
|
|
15417
|
+
formats: resolveFormats(args.aspect ? String(args.aspect) : report.aspect_ratio),
|
|
15418
|
+
sourceReferenceUrl: imageIsUrl ? imageSource : void 0,
|
|
15419
|
+
sourceAdvertiser: args.advertiser ? String(args.advertiser) : args.context ? String(args.context) : void 0,
|
|
15420
|
+
sourceKind: "image",
|
|
15421
|
+
sourcePath: sourceRelPath,
|
|
15422
|
+
description: describeBlueprintIntent(blueprint)
|
|
15423
|
+
}),
|
|
15424
|
+
"utf8"
|
|
15425
|
+
);
|
|
15426
|
+
}
|
|
15086
15427
|
process.stdout.write(
|
|
15087
15428
|
`${JSON.stringify(
|
|
15088
15429
|
{
|
|
15089
15430
|
ok: true,
|
|
15090
15431
|
canvas_path: outPath,
|
|
15091
15432
|
prompt_path: blueprintPath,
|
|
15433
|
+
definition_path: definitionPath ?? void 0,
|
|
15434
|
+
source_reference: sourceRelPath ?? void 0,
|
|
15092
15435
|
output: canvas.output,
|
|
15093
15436
|
models: { describe: describeModel, select: selectModel, layout: layoutModel, gen: opts.genModel },
|
|
15094
15437
|
aspect_ratio: report.aspect_ratio,
|
|
@@ -15099,7 +15442,7 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15099
15442
|
run_estimated_credits: validation.estimatedCredits
|
|
15100
15443
|
},
|
|
15101
15444
|
checklist: {
|
|
15102
|
-
edit_prompt: `Edit ${
|
|
15445
|
+
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.`,
|
|
15103
15446
|
assets_to_supply: report.elements,
|
|
15104
15447
|
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)",
|
|
15105
15448
|
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."
|
|
@@ -15114,8 +15457,8 @@ var scaffoldStaticAdCommand = defineCommand89({
|
|
|
15114
15457
|
});
|
|
15115
15458
|
|
|
15116
15459
|
// src/commands/canvas/scaffold-video.ts
|
|
15117
|
-
import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
15118
|
-
import
|
|
15460
|
+
import { cp as cp2, mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
|
|
15461
|
+
import path11 from "path";
|
|
15119
15462
|
import { defineCommand as defineCommand90 } from "citty";
|
|
15120
15463
|
|
|
15121
15464
|
// src/engine/nodes/local/lib/sceneDetect.ts
|
|
@@ -15232,7 +15575,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
|
|
|
15232
15575
|
import { toCardinal as nwNl } from "n2words/nl-NL";
|
|
15233
15576
|
import { toCardinal as nwPl } from "n2words/pl-PL";
|
|
15234
15577
|
import { toCardinal as nwPt } from "n2words/pt-PT";
|
|
15235
|
-
import { z as
|
|
15578
|
+
import { z as z12 } from "zod";
|
|
15236
15579
|
|
|
15237
15580
|
// src/engine/scaffold/lib/shoot-modes.ts
|
|
15238
15581
|
var SHOOT_MODES = [
|
|
@@ -15545,71 +15888,71 @@ function trimArgs(durationS, offsetS = 0, dims) {
|
|
|
15545
15888
|
"{{out.video}}"
|
|
15546
15889
|
];
|
|
15547
15890
|
}
|
|
15548
|
-
var FrameAsset =
|
|
15549
|
-
var DialogueLine =
|
|
15550
|
-
speaker:
|
|
15551
|
-
line:
|
|
15891
|
+
var FrameAsset = z12.object({ url: z12.string().optional() }).loose().optional();
|
|
15892
|
+
var DialogueLine = z12.object({
|
|
15893
|
+
speaker: z12.string().optional(),
|
|
15894
|
+
line: z12.string().optional(),
|
|
15552
15895
|
// Absolute seconds on the source timeline (the deconstruct emits both).
|
|
15553
|
-
start_s:
|
|
15554
|
-
end_s:
|
|
15555
|
-
delivery:
|
|
15556
|
-
voice_description:
|
|
15896
|
+
start_s: z12.number().optional(),
|
|
15897
|
+
end_s: z12.number().optional(),
|
|
15898
|
+
delivery: z12.string().optional(),
|
|
15899
|
+
voice_description: z12.string().optional(),
|
|
15557
15900
|
// DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element
|
|
15558
15901
|
// presence alone can't answer that — a founder pictured in a polaroid close-up is
|
|
15559
15902
|
// "present" yet the line is voiceover, and treating it as on-camera produced a
|
|
15560
15903
|
// native Seedance lip-sync clip of a still photograph. `false` pins the line to
|
|
15561
15904
|
// the VO path; absent keeps the presence-based decision (old blueprints).
|
|
15562
|
-
on_camera:
|
|
15905
|
+
on_camera: z12.boolean().optional()
|
|
15563
15906
|
}).loose();
|
|
15564
|
-
var Sfx =
|
|
15565
|
-
at_s:
|
|
15566
|
-
duration_s:
|
|
15567
|
-
sound_effect_prompt:
|
|
15568
|
-
description:
|
|
15907
|
+
var Sfx = z12.object({
|
|
15908
|
+
at_s: z12.number().optional(),
|
|
15909
|
+
duration_s: z12.number().optional(),
|
|
15910
|
+
sound_effect_prompt: z12.string().optional(),
|
|
15911
|
+
description: z12.string().optional()
|
|
15569
15912
|
}).loose();
|
|
15570
|
-
var CompositionRegion =
|
|
15913
|
+
var CompositionRegion = z12.object({
|
|
15571
15914
|
// full | top | bottom | left | right | inset
|
|
15572
|
-
panel:
|
|
15915
|
+
panel: z12.string().optional(),
|
|
15573
15916
|
// 9-grid anchor for an `inset` presenter box.
|
|
15574
|
-
position:
|
|
15575
|
-
is_presenter:
|
|
15917
|
+
position: z12.string().optional(),
|
|
15918
|
+
is_presenter: z12.boolean().optional(),
|
|
15576
15919
|
// The cast id shown/speaking in this region (routes lip-sync + element refs).
|
|
15577
|
-
cast_ref:
|
|
15920
|
+
cast_ref: z12.string().optional(),
|
|
15578
15921
|
// What the region's content IS: camera | screen_capture | static_graphic |
|
|
15579
15922
|
// generated. Authoritative for routing when present (regex-over-prose fallback
|
|
15580
15923
|
// otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the
|
|
15581
15924
|
// overlay layer, never AI-generated.
|
|
15582
|
-
kind:
|
|
15925
|
+
kind: z12.string().optional(),
|
|
15583
15926
|
// Opaque id naming the SPECIFIC on-screen document/note/app-state this
|
|
15584
15927
|
// screen_capture region shows. Two scenes share it only when they show the SAME
|
|
15585
15928
|
// recording continuing (scrolling/typing/waiting within it) — a genuinely
|
|
15586
15929
|
// DIFFERENT document/note/recording (a source video splicing two screen captures)
|
|
15587
15930
|
// gets a different id. Breaks a persistent-layout run into separate surface stubs
|
|
15588
15931
|
// instead of asking the operator for one screenshot that can't cover both.
|
|
15589
|
-
surface_id:
|
|
15932
|
+
surface_id: z12.string().optional(),
|
|
15590
15933
|
// Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style
|
|
15591
15934
|
// presenter bubble inside a screen recording) — video-in-video the reproduction
|
|
15592
15935
|
// must re-composite, not paint into the surface.
|
|
15593
|
-
nested:
|
|
15594
|
-
summary:
|
|
15595
|
-
frame_prompt:
|
|
15596
|
-
motion_prompt:
|
|
15936
|
+
nested: z12.array(z12.object({}).loose()).optional(),
|
|
15937
|
+
summary: z12.string().optional(),
|
|
15938
|
+
frame_prompt: z12.string().optional(),
|
|
15939
|
+
motion_prompt: z12.string().optional()
|
|
15597
15940
|
}).loose();
|
|
15598
|
-
var SceneComposition =
|
|
15941
|
+
var SceneComposition = z12.object({
|
|
15599
15942
|
// full_frame (default) | split_screen | pip | keyed_overlay
|
|
15600
|
-
layout:
|
|
15943
|
+
layout: z12.string().optional(),
|
|
15601
15944
|
// split_screen only: vertical (top/bottom) | horizontal (left/right).
|
|
15602
|
-
split_axis:
|
|
15603
|
-
regions:
|
|
15945
|
+
split_axis: z12.string().optional(),
|
|
15946
|
+
regions: z12.array(CompositionRegion).optional()
|
|
15604
15947
|
}).loose();
|
|
15605
|
-
var CameraMotion =
|
|
15606
|
-
var TranscriptWord =
|
|
15607
|
-
var Scene =
|
|
15608
|
-
start_s:
|
|
15609
|
-
end_s:
|
|
15610
|
-
duration_s:
|
|
15611
|
-
summary:
|
|
15612
|
-
action_detail:
|
|
15948
|
+
var CameraMotion = z12.object({ movement: z12.string().optional(), detail: z12.string().optional() }).loose();
|
|
15949
|
+
var TranscriptWord = z12.object({ text: z12.string().optional() }).loose();
|
|
15950
|
+
var Scene = z12.object({
|
|
15951
|
+
start_s: z12.number().optional(),
|
|
15952
|
+
end_s: z12.number().optional(),
|
|
15953
|
+
duration_s: z12.number().optional(),
|
|
15954
|
+
summary: z12.string().optional(),
|
|
15955
|
+
action_detail: z12.string().optional(),
|
|
15613
15956
|
// The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
|
|
15614
15957
|
// A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
|
|
15615
15958
|
// builds one clip per region and stacks/overlays them into the scene picture.
|
|
@@ -15617,82 +15960,82 @@ var Scene = z13.object({
|
|
|
15617
15960
|
// The capture "look" for this scene — selected from the ad-native shoot-mode
|
|
15618
15961
|
// grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
|
|
15619
15962
|
// UGC/product mode; a human can override per scene by setting this.
|
|
15620
|
-
shoot_mode:
|
|
15963
|
+
shoot_mode: z12.string().optional(),
|
|
15621
15964
|
// Diegetic ambient the clip's native audio should carry (no music). When
|
|
15622
15965
|
// absent the scene falls back to its shoot mode's default ambience.
|
|
15623
|
-
ambient:
|
|
15966
|
+
ambient: z12.string().optional(),
|
|
15624
15967
|
camera_motion: CameraMotion.optional(),
|
|
15625
|
-
start_frame_prompt:
|
|
15626
|
-
end_frame_prompt:
|
|
15627
|
-
motion_prompt:
|
|
15968
|
+
start_frame_prompt: z12.string().optional(),
|
|
15969
|
+
end_frame_prompt: z12.string().optional(),
|
|
15970
|
+
motion_prompt: z12.string().optional(),
|
|
15628
15971
|
// The scene's role in the ad's persuasion arc (DECON-supplied); drives the
|
|
15629
15972
|
// script re-craft checklist. Inferred from position when absent.
|
|
15630
|
-
narrative_role:
|
|
15973
|
+
narrative_role: z12.string().optional(),
|
|
15631
15974
|
// DECON-supplied on the HOOK scene: the engineered physical/emotional state that
|
|
15632
15975
|
// makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
|
|
15633
15976
|
// into the hook's start-frame description so the generator renders that state,
|
|
15634
15977
|
// not a calm influencer (CCA-11).
|
|
15635
|
-
hook_mechanic:
|
|
15978
|
+
hook_mechanic: z12.object({ mechanic: z12.string().optional(), why_it_stops_scroll: z12.string().optional() }).loose().optional(),
|
|
15636
15979
|
// DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
|
|
15637
|
-
scene_setting:
|
|
15980
|
+
scene_setting: z12.string().optional(),
|
|
15638
15981
|
// How this scene cuts to the next (DECON-supplied). A recognized non-cut type
|
|
15639
15982
|
// (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
|
|
15640
15983
|
// boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
|
|
15641
15984
|
// ignored (nothing follows it).
|
|
15642
|
-
transition_out:
|
|
15643
|
-
dialogue:
|
|
15644
|
-
sfx:
|
|
15645
|
-
overlays:
|
|
15646
|
-
floating_elements:
|
|
15985
|
+
transition_out: z12.object({ type: z12.string().optional(), description: z12.string().optional() }).loose().optional(),
|
|
15986
|
+
dialogue: z12.array(DialogueLine).optional(),
|
|
15987
|
+
sfx: z12.array(Sfx).optional(),
|
|
15988
|
+
overlays: z12.array(z12.unknown()).optional(),
|
|
15989
|
+
floating_elements: z12.array(z12.unknown()).optional(),
|
|
15647
15990
|
// DECON-supplied: how much the picture itself moves within the shot. Gates the
|
|
15648
15991
|
// flash-hold optimization — a sub-2s b-roll flash with REAL subject motion
|
|
15649
15992
|
// (pouring, spreading, hands working) must stay a real clip; freezing it turns
|
|
15650
15993
|
// a montage into a slideshow. Absent (old blueprints) keeps the cheap still.
|
|
15651
|
-
motion_level:
|
|
15652
|
-
transcript_slice:
|
|
15994
|
+
motion_level: z12.enum(["static", "subtle", "dynamic"]).optional(),
|
|
15995
|
+
transcript_slice: z12.array(TranscriptWord).optional(),
|
|
15653
15996
|
start_frame_asset: FrameAsset,
|
|
15654
15997
|
end_frame_asset: FrameAsset,
|
|
15655
15998
|
// DECON-supplied: true when this scene is a length-split CONTINUATION of the
|
|
15656
15999
|
// previous one (the SAME physical shot, broken up only because it exceeded the
|
|
15657
16000
|
// clip ceiling). The scaffold then shares the splice keyframe — this scene's
|
|
15658
16001
|
// start frame IS the previous scene's end frame — so the join is seamless.
|
|
15659
|
-
continues_previous:
|
|
16002
|
+
continues_previous: z12.boolean().optional()
|
|
15660
16003
|
}).loose();
|
|
15661
|
-
var VideoBlueprint =
|
|
15662
|
-
source:
|
|
15663
|
-
global:
|
|
15664
|
-
music:
|
|
15665
|
-
present:
|
|
15666
|
-
music_prompt:
|
|
16004
|
+
var VideoBlueprint = z12.object({
|
|
16005
|
+
source: z12.object({ aspect_ratio: z12.string().optional(), duration_s: z12.number().optional() }).loose().optional(),
|
|
16006
|
+
global: z12.object({
|
|
16007
|
+
music: z12.object({
|
|
16008
|
+
present: z12.boolean().optional(),
|
|
16009
|
+
music_prompt: z12.string().optional(),
|
|
15667
16010
|
// Absolute second the music enters in the reference (the bed often
|
|
15668
16011
|
// kicks in mid-ad, after the hook). We start the regenerated track here
|
|
15669
16012
|
// instead of at 0 so the timing matches.
|
|
15670
|
-
starts_at_s:
|
|
16013
|
+
starts_at_s: z12.number().optional(),
|
|
15671
16014
|
// Populated by the deconstruct when AudD (Shazam-style) recognizes the
|
|
15672
16015
|
// reference track. We never reuse it — only style the regenerated bed.
|
|
15673
|
-
identified_track:
|
|
16016
|
+
identified_track: z12.object({ title: z12.string().optional(), artist: z12.string().optional() }).loose().nullish()
|
|
15674
16017
|
}).loose().optional(),
|
|
15675
|
-
cast:
|
|
15676
|
-
|
|
15677
|
-
id:
|
|
15678
|
-
description:
|
|
16018
|
+
cast: z12.array(
|
|
16019
|
+
z12.object({
|
|
16020
|
+
id: z12.string().optional(),
|
|
16021
|
+
description: z12.string().optional(),
|
|
15679
16022
|
// The deconstruct's note on the target-market localization (e.g. "native
|
|
15680
16023
|
// French speaker") — read to derive the spoken-track language code.
|
|
15681
|
-
market_localization_note:
|
|
16024
|
+
market_localization_note: z12.string().optional()
|
|
15682
16025
|
}).loose()
|
|
15683
16026
|
).optional(),
|
|
15684
|
-
voiceover:
|
|
16027
|
+
voiceover: z12.object({
|
|
15685
16028
|
// on_camera | mixed → mouths are on screen (lip-sync candidates);
|
|
15686
16029
|
// voiceover | none → narration over the picture (no lip-sync).
|
|
15687
|
-
mode:
|
|
15688
|
-
voice_description:
|
|
15689
|
-
persona:
|
|
16030
|
+
mode: z12.string().optional(),
|
|
16031
|
+
voice_description: z12.string().optional(),
|
|
16032
|
+
persona: z12.string().optional()
|
|
15690
16033
|
}).loose().optional(),
|
|
15691
16034
|
// Visual palette — read only to colour a clean brand-card/CTA plate (the
|
|
15692
16035
|
// first hex is the dominant brand colour); never to drive frame generation.
|
|
15693
|
-
style:
|
|
16036
|
+
style: z12.object({ palette: z12.array(z12.object({ hex: z12.string().optional() }).loose()).optional() }).loose().optional()
|
|
15694
16037
|
}).loose().optional(),
|
|
15695
|
-
scenes:
|
|
16038
|
+
scenes: z12.array(Scene).min(1)
|
|
15696
16039
|
}).loose();
|
|
15697
16040
|
function injectHookPhysicality(blueprint) {
|
|
15698
16041
|
for (const scene of blueprint.scenes) {
|
|
@@ -15702,26 +16045,26 @@ function injectHookPhysicality(blueprint) {
|
|
|
15702
16045
|
scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
|
|
15703
16046
|
}
|
|
15704
16047
|
}
|
|
15705
|
-
var AppearsItem =
|
|
15706
|
-
var RecurringElement =
|
|
16048
|
+
var AppearsItem = z12.union([z12.number(), z12.object({ scene: z12.number(), edge: z12.string().optional() }).loose()]);
|
|
16049
|
+
var RecurringElement = z12.object({
|
|
15707
16050
|
// person | animal | product | logo | badge | other
|
|
15708
|
-
type:
|
|
15709
|
-
label:
|
|
15710
|
-
description:
|
|
15711
|
-
expression:
|
|
16051
|
+
type: z12.string(),
|
|
16052
|
+
label: z12.string().optional(),
|
|
16053
|
+
description: z12.string().optional(),
|
|
16054
|
+
expression: z12.string().nullable().optional(),
|
|
15712
16055
|
// When the element maps to a global cast entry, its stable id (for annotation).
|
|
15713
|
-
cast_id:
|
|
16056
|
+
cast_id: z12.string().nullable().optional(),
|
|
15714
16057
|
// The label of another element that is the SAME individual as this one, shown
|
|
15715
16058
|
// in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
|
|
15716
16059
|
// pink shirt and believer in a white shirt). Each look gets its own reference
|
|
15717
16060
|
// slot, but the face/identity must stay identical across them.
|
|
15718
|
-
same_as:
|
|
16061
|
+
same_as: z12.string().nullable().optional(),
|
|
15719
16062
|
// Scenes the element appears in. Either a bare list of scene indices (both
|
|
15720
16063
|
// edges) or per-{scene,edge} entries. Both forms are accepted and merged.
|
|
15721
|
-
scenes:
|
|
15722
|
-
appears_in:
|
|
16064
|
+
scenes: z12.array(z12.number()).optional(),
|
|
16065
|
+
appears_in: z12.array(AppearsItem).optional()
|
|
15723
16066
|
}).loose();
|
|
15724
|
-
var RecurringElements =
|
|
16067
|
+
var RecurringElements = z12.array(RecurringElement);
|
|
15725
16068
|
function sanitizeId2(raw, fallback) {
|
|
15726
16069
|
const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
15727
16070
|
return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
|
|
@@ -16139,7 +16482,7 @@ function scrubFloatSentences(text, floatDescs) {
|
|
|
16139
16482
|
return kept;
|
|
16140
16483
|
}
|
|
16141
16484
|
function sceneFloatDescs(scene) {
|
|
16142
|
-
const floats =
|
|
16485
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
16143
16486
|
if (!floats.success) return [];
|
|
16144
16487
|
return floats.data.map((f) => f.description?.trim() ?? "").filter(Boolean);
|
|
16145
16488
|
}
|
|
@@ -17479,25 +17822,25 @@ function buildSfxMusic(blueprint, nodes) {
|
|
|
17479
17822
|
}
|
|
17480
17823
|
return tracks;
|
|
17481
17824
|
}
|
|
17482
|
-
var OverlayStyle =
|
|
17483
|
-
var Overlay =
|
|
17484
|
-
text:
|
|
17485
|
-
appears_at_s:
|
|
17486
|
-
duration_s:
|
|
17487
|
-
position:
|
|
17488
|
-
role:
|
|
17489
|
-
animation:
|
|
17490
|
-
animation_detail:
|
|
17825
|
+
var OverlayStyle = z12.object({ color_hex: z12.string().optional(), background: z12.string().optional(), size: z12.string().optional() }).loose();
|
|
17826
|
+
var Overlay = z12.object({
|
|
17827
|
+
text: z12.string().optional(),
|
|
17828
|
+
appears_at_s: z12.number().optional(),
|
|
17829
|
+
duration_s: z12.number().optional(),
|
|
17830
|
+
position: z12.string().optional(),
|
|
17831
|
+
role: z12.string().optional(),
|
|
17832
|
+
animation: z12.string().optional(),
|
|
17833
|
+
animation_detail: z12.string().optional(),
|
|
17491
17834
|
style: OverlayStyle.optional()
|
|
17492
17835
|
}).loose();
|
|
17493
|
-
var FloatingElement =
|
|
17494
|
-
kind:
|
|
17495
|
-
description:
|
|
17496
|
-
brand_name:
|
|
17497
|
-
what_it_represents:
|
|
17498
|
-
appears_at_s:
|
|
17499
|
-
duration_s:
|
|
17500
|
-
position:
|
|
17836
|
+
var FloatingElement = z12.object({
|
|
17837
|
+
kind: z12.string().optional(),
|
|
17838
|
+
description: z12.string().optional(),
|
|
17839
|
+
brand_name: z12.string().nullish(),
|
|
17840
|
+
what_it_represents: z12.string().optional(),
|
|
17841
|
+
appears_at_s: z12.number().optional(),
|
|
17842
|
+
duration_s: z12.number().optional(),
|
|
17843
|
+
position: z12.string().optional()
|
|
17501
17844
|
}).loose();
|
|
17502
17845
|
function escapeHtml(s) {
|
|
17503
17846
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -17529,7 +17872,7 @@ function positionClass(position) {
|
|
|
17529
17872
|
function collectCaptions(blueprint) {
|
|
17530
17873
|
return blueprint.scenes.flatMap((scene) => {
|
|
17531
17874
|
const sceneStart = scene.start_s ?? 0;
|
|
17532
|
-
const overlays =
|
|
17875
|
+
const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
|
|
17533
17876
|
return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
|
|
17534
17877
|
const at = ov.appears_at_s ?? sceneStart;
|
|
17535
17878
|
return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
|
|
@@ -17609,7 +17952,7 @@ function collectFloatWindows(blueprint, uiRouted) {
|
|
|
17609
17952
|
const windows = /* @__PURE__ */ new Map();
|
|
17610
17953
|
blueprint.scenes.forEach((scene, i) => {
|
|
17611
17954
|
const sceneStart = scene.start_s ?? 0;
|
|
17612
|
-
const floats =
|
|
17955
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
17613
17956
|
if (!floats.success) return;
|
|
17614
17957
|
for (const fe of floats.data) {
|
|
17615
17958
|
const at = fe.appears_at_s ?? sceneStart;
|
|
@@ -17995,8 +18338,8 @@ function buildMotionBoard(blueprint) {
|
|
|
17995
18338
|
const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
|
|
17996
18339
|
cursor = end_s;
|
|
17997
18340
|
const spoken = sceneSpokenText(scene);
|
|
17998
|
-
const overlays =
|
|
17999
|
-
const floats =
|
|
18341
|
+
const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
|
|
18342
|
+
const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
|
|
18000
18343
|
const graphics = [
|
|
18001
18344
|
...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
|
|
18002
18345
|
kind: "text",
|
|
@@ -18223,23 +18566,23 @@ function videoReport(input, elementsInput) {
|
|
|
18223
18566
|
|
|
18224
18567
|
// src/commands/canvas/composition-path.ts
|
|
18225
18568
|
import { existsSync as existsSync3 } from "fs";
|
|
18226
|
-
import
|
|
18569
|
+
import path9 from "path";
|
|
18227
18570
|
function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
|
|
18228
|
-
const rel =
|
|
18571
|
+
const rel = path9.join("canvas", name);
|
|
18229
18572
|
let dir = startDir;
|
|
18230
18573
|
for (let i = 0; i < maxDepth; i++) {
|
|
18231
|
-
const candidate =
|
|
18232
|
-
if (exists(
|
|
18233
|
-
const parent =
|
|
18574
|
+
const candidate = path9.join(dir, rel);
|
|
18575
|
+
if (exists(path9.join(candidate, "meta.json"))) return candidate;
|
|
18576
|
+
const parent = path9.dirname(dir);
|
|
18234
18577
|
if (parent === dir) break;
|
|
18235
18578
|
dir = parent;
|
|
18236
18579
|
}
|
|
18237
|
-
return
|
|
18580
|
+
return path9.resolve(startDir, "../../../", rel);
|
|
18238
18581
|
}
|
|
18239
18582
|
|
|
18240
18583
|
// src/commands/canvas/gitignore.ts
|
|
18241
18584
|
import { appendFile, readFile as readFile5 } from "fs/promises";
|
|
18242
|
-
import
|
|
18585
|
+
import path10 from "path";
|
|
18243
18586
|
function missingGitignoreEntries(existing, entries) {
|
|
18244
18587
|
const present = new Set(
|
|
18245
18588
|
existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
@@ -18247,7 +18590,7 @@ function missingGitignoreEntries(existing, entries) {
|
|
|
18247
18590
|
return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
|
|
18248
18591
|
}
|
|
18249
18592
|
async function ensureGitignore(dir, entries) {
|
|
18250
|
-
const file =
|
|
18593
|
+
const file = path10.join(dir, ".gitignore");
|
|
18251
18594
|
let existing;
|
|
18252
18595
|
try {
|
|
18253
18596
|
existing = await readFile5(file, "utf8");
|
|
@@ -18308,8 +18651,8 @@ async function loadTranscriptBestEffort(ref) {
|
|
|
18308
18651
|
async function stageCaptions(outDir, transcript) {
|
|
18309
18652
|
const text = transcript?.trim();
|
|
18310
18653
|
if (!text || text === "[]") return {};
|
|
18311
|
-
const compositionPath =
|
|
18312
|
-
await
|
|
18654
|
+
const compositionPath = path11.join(outDir, "tiktok-captions-composition");
|
|
18655
|
+
await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
|
|
18313
18656
|
return { compositionPath };
|
|
18314
18657
|
}
|
|
18315
18658
|
function patchCompositionMeta(metaJson, dims) {
|
|
@@ -18326,10 +18669,10 @@ function patchCompositionHtml(html, dims) {
|
|
|
18326
18669
|
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`);
|
|
18327
18670
|
}
|
|
18328
18671
|
async function stampCompositionDims(compositionDir, dims) {
|
|
18329
|
-
const metaPath =
|
|
18672
|
+
const metaPath = path11.join(compositionDir, "meta.json");
|
|
18330
18673
|
const rawMeta = await readFile6(metaPath, "utf8");
|
|
18331
18674
|
await writeFile2(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
|
|
18332
|
-
const htmlPath =
|
|
18675
|
+
const htmlPath = path11.join(compositionDir, "index.html");
|
|
18333
18676
|
const rawHtml = await readFile6(htmlPath, "utf8");
|
|
18334
18677
|
await writeFile2(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
|
|
18335
18678
|
}
|
|
@@ -18469,6 +18812,10 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18469
18812
|
args: {
|
|
18470
18813
|
file: { type: "positional", required: true, description: "Path to the reference video" },
|
|
18471
18814
|
out: { type: "string", description: "Output canvas path (default <video-dir>/<name>.video.canvas.json)" },
|
|
18815
|
+
slug: {
|
|
18816
|
+
type: "string",
|
|
18817
|
+
description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
|
|
18818
|
+
},
|
|
18472
18819
|
frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
|
|
18473
18820
|
ambient: {
|
|
18474
18821
|
type: "boolean",
|
|
@@ -18495,11 +18842,19 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18495
18842
|
}
|
|
18496
18843
|
},
|
|
18497
18844
|
async run({ args }) {
|
|
18498
|
-
const videoPath =
|
|
18499
|
-
const base =
|
|
18500
|
-
const
|
|
18501
|
-
|
|
18502
|
-
|
|
18845
|
+
const videoPath = path11.resolve(String(args.file));
|
|
18846
|
+
const base = path11.basename(videoPath, path11.extname(videoPath));
|
|
18847
|
+
const slug = args.slug ? String(args.slug) : void 0;
|
|
18848
|
+
if (slug && !isValidScaffoldSlug(slug)) {
|
|
18849
|
+
process.stderr.write(
|
|
18850
|
+
`${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
|
|
18851
|
+
`
|
|
18852
|
+
);
|
|
18853
|
+
process.exit(2);
|
|
18854
|
+
}
|
|
18855
|
+
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`);
|
|
18856
|
+
const outDir = path11.dirname(outPath);
|
|
18857
|
+
const blueprintPath = path11.join(outDir, "prompt.json");
|
|
18503
18858
|
const frames = args.frames === "reuse" ? "reuse" : "generate";
|
|
18504
18859
|
const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
|
|
18505
18860
|
if (Number.isFinite(maxScenes)) {
|
|
@@ -18518,7 +18873,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18518
18873
|
shotCuts
|
|
18519
18874
|
});
|
|
18520
18875
|
const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
|
|
18521
|
-
await
|
|
18876
|
+
await mkdir2(outDir, { recursive: true });
|
|
18522
18877
|
const annotated = annotateBlueprintWithElements(blueprint, elements);
|
|
18523
18878
|
await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
|
|
18524
18879
|
`, "utf8");
|
|
@@ -18539,10 +18894,10 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18539
18894
|
`
|
|
18540
18895
|
);
|
|
18541
18896
|
}
|
|
18542
|
-
const compositionDest =
|
|
18543
|
-
await
|
|
18897
|
+
const compositionDest = path11.join(outDir, "video-overlay-composition");
|
|
18898
|
+
await cp2(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
|
|
18544
18899
|
await stampCompositionDims(compositionDest, outDims);
|
|
18545
|
-
const indexPath =
|
|
18900
|
+
const indexPath = path11.join(compositionDest, "index.html");
|
|
18546
18901
|
const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
|
|
18547
18902
|
const indexHtml = await readFile6(indexPath, "utf8");
|
|
18548
18903
|
const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
@@ -18558,9 +18913,9 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18558
18913
|
const opts = {
|
|
18559
18914
|
imageModel,
|
|
18560
18915
|
videoModel,
|
|
18561
|
-
overlayCompositionPath:
|
|
18562
|
-
captionsCompositionPath: captions.compositionPath ?
|
|
18563
|
-
blueprintPath:
|
|
18916
|
+
overlayCompositionPath: path11.relative(outDir, compositionDest),
|
|
18917
|
+
captionsCompositionPath: captions.compositionPath ? path11.relative(outDir, captions.compositionPath) : void 0,
|
|
18918
|
+
blueprintPath: path11.relative(outDir, blueprintPath),
|
|
18564
18919
|
frames,
|
|
18565
18920
|
ambient: Boolean(args.ambient),
|
|
18566
18921
|
...args.aspect ? { aspect: String(args.aspect) } : {},
|
|
@@ -18618,7 +18973,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18618
18973
|
run_estimated_credits: validation.estimatedCredits
|
|
18619
18974
|
},
|
|
18620
18975
|
checklist: {
|
|
18621
|
-
edit_prompt: `Edit ${
|
|
18976
|
+
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.`,
|
|
18622
18977
|
recurring_elements_to_supply: report.elements,
|
|
18623
18978
|
voices_to_confirm: report.dialogue.map((d) => ({
|
|
18624
18979
|
scene: d.scene,
|
|
@@ -18645,7 +19000,7 @@ var scaffoldVideoCommand = defineCommand90({
|
|
|
18645
19000
|
|
|
18646
19001
|
// src/commands/canvas/set-prompt.ts
|
|
18647
19002
|
import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
|
|
18648
|
-
import
|
|
19003
|
+
import path12 from "path";
|
|
18649
19004
|
import { defineCommand as defineCommand91 } from "citty";
|
|
18650
19005
|
function setNodePrompt(canvas, nodeId, text) {
|
|
18651
19006
|
const nodes = canvas?.nodes;
|
|
@@ -18673,7 +19028,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18673
19028
|
"text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
|
|
18674
19029
|
},
|
|
18675
19030
|
async run({ args }) {
|
|
18676
|
-
const filePath =
|
|
19031
|
+
const filePath = path12.resolve(String(args.file));
|
|
18677
19032
|
let canvas;
|
|
18678
19033
|
try {
|
|
18679
19034
|
canvas = JSON.parse(await readFile7(filePath, "utf8"));
|
|
@@ -18683,7 +19038,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18683
19038
|
process.exit(2);
|
|
18684
19039
|
}
|
|
18685
19040
|
let text;
|
|
18686
|
-
if (args["text-file"]) text = await readFile7(
|
|
19041
|
+
if (args["text-file"]) text = await readFile7(path12.resolve(String(args["text-file"])), "utf8");
|
|
18687
19042
|
else if (args.text !== void 0) text = String(args.text);
|
|
18688
19043
|
else {
|
|
18689
19044
|
process.stderr.write(
|
|
@@ -18704,7 +19059,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18704
19059
|
process.exit(2);
|
|
18705
19060
|
return;
|
|
18706
19061
|
}
|
|
18707
|
-
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated,
|
|
19062
|
+
const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path12.dirname(filePath)), defaultRegistry());
|
|
18708
19063
|
if (!validation.ok) {
|
|
18709
19064
|
process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
|
|
18710
19065
|
`);
|
|
@@ -18720,7 +19075,7 @@ var setPromptCommand = defineCommand91({
|
|
|
18720
19075
|
|
|
18721
19076
|
// src/commands/canvas/validate.ts
|
|
18722
19077
|
import { readFile as readFile8 } from "fs/promises";
|
|
18723
|
-
import
|
|
19078
|
+
import path13 from "path";
|
|
18724
19079
|
import { defineCommand as defineCommand92 } from "citty";
|
|
18725
19080
|
var validateCommand = defineCommand92({
|
|
18726
19081
|
meta: {
|
|
@@ -18729,7 +19084,7 @@ var validateCommand = defineCommand92({
|
|
|
18729
19084
|
},
|
|
18730
19085
|
args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
|
|
18731
19086
|
async run({ args }) {
|
|
18732
|
-
const filePath =
|
|
19087
|
+
const filePath = path13.resolve(String(args.file));
|
|
18733
19088
|
const raw = await readFile8(filePath, "utf8");
|
|
18734
19089
|
let parsed;
|
|
18735
19090
|
try {
|
|
@@ -18740,7 +19095,7 @@ var validateCommand = defineCommand92({
|
|
|
18740
19095
|
`);
|
|
18741
19096
|
process.exit(2);
|
|
18742
19097
|
}
|
|
18743
|
-
parsed = resolveRelativeCanvasPaths(parsed,
|
|
19098
|
+
parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
|
|
18744
19099
|
const result = await validateCanvasDeep(parsed, defaultRegistry());
|
|
18745
19100
|
if (!result.ok) {
|
|
18746
19101
|
process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
|
|
@@ -18877,6 +19232,16 @@ registerSchema({
|
|
|
18877
19232
|
type: "string",
|
|
18878
19233
|
description: "Optional URL of the original reference ad",
|
|
18879
19234
|
required: false
|
|
19235
|
+
},
|
|
19236
|
+
slug: {
|
|
19237
|
+
type: "string",
|
|
19238
|
+
description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
|
|
19239
|
+
required: false
|
|
19240
|
+
},
|
|
19241
|
+
runId: {
|
|
19242
|
+
type: "string",
|
|
19243
|
+
description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
|
|
19244
|
+
required: false
|
|
18880
19245
|
}
|
|
18881
19246
|
}
|
|
18882
19247
|
});
|
|
@@ -18886,6 +19251,13 @@ function detectCreativeContentType(filePath) {
|
|
|
18886
19251
|
unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
|
|
18887
19252
|
});
|
|
18888
19253
|
}
|
|
19254
|
+
function chatIdFromEnv() {
|
|
19255
|
+
try {
|
|
19256
|
+
return getEnv().BAKER_CHAT_ID || void 0;
|
|
19257
|
+
} catch {
|
|
19258
|
+
return void 0;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
18889
19261
|
function parseOptionalUrl(value) {
|
|
18890
19262
|
if (value === void 0 || value.trim() === "") {
|
|
18891
19263
|
return void 0;
|
|
@@ -18916,7 +19288,11 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
|
|
|
18916
19288
|
return publishImageAsCreative(deps, {
|
|
18917
19289
|
imageId: upload.imageId,
|
|
18918
19290
|
title,
|
|
18919
|
-
sourceReferenceUrl
|
|
19291
|
+
sourceReferenceUrl,
|
|
19292
|
+
slug: args.slug,
|
|
19293
|
+
runId: args.runId,
|
|
19294
|
+
// Attribute the publish to the driving chat (injected by the bridge).
|
|
19295
|
+
chatId: chatIdFromEnv()
|
|
18920
19296
|
});
|
|
18921
19297
|
}
|
|
18922
19298
|
var publishCommand = defineCommand94({
|
|
@@ -18932,6 +19308,16 @@ var publishCommand = defineCommand94({
|
|
|
18932
19308
|
type: "string",
|
|
18933
19309
|
description: "Optional URL of the original reference ad",
|
|
18934
19310
|
required: false
|
|
19311
|
+
},
|
|
19312
|
+
slug: {
|
|
19313
|
+
type: "string",
|
|
19314
|
+
description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
|
|
19315
|
+
required: false
|
|
19316
|
+
},
|
|
19317
|
+
runId: {
|
|
19318
|
+
type: "string",
|
|
19319
|
+
description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
|
|
19320
|
+
required: false
|
|
18935
19321
|
}
|
|
18936
19322
|
},
|
|
18937
19323
|
run: async ({ args }) => {
|
|
@@ -18950,7 +19336,9 @@ var publishCommand = defineCommand94({
|
|
|
18950
19336
|
file,
|
|
18951
19337
|
title,
|
|
18952
19338
|
context: args.context,
|
|
18953
|
-
sourceReferenceUrl: args.sourceReferenceUrl
|
|
19339
|
+
sourceReferenceUrl: args.sourceReferenceUrl,
|
|
19340
|
+
slug: args.slug,
|
|
19341
|
+
runId: args.runId
|
|
18954
19342
|
});
|
|
18955
19343
|
writeJson({ ok: true, data });
|
|
18956
19344
|
} catch (err) {
|
|
@@ -19848,9 +20236,9 @@ async function readImageBuffer(pathOrUrl) {
|
|
|
19848
20236
|
}
|
|
19849
20237
|
return readFile10(pathOrUrl);
|
|
19850
20238
|
}
|
|
19851
|
-
async function isDirectory(
|
|
20239
|
+
async function isDirectory(path14) {
|
|
19852
20240
|
try {
|
|
19853
|
-
const s = await stat2(
|
|
20241
|
+
const s = await stat2(path14);
|
|
19854
20242
|
return s.isDirectory();
|
|
19855
20243
|
} catch {
|
|
19856
20244
|
return false;
|
|
@@ -23912,121 +24300,11 @@ var schemaCommand = defineCommand147({
|
|
|
23912
24300
|
}
|
|
23913
24301
|
});
|
|
23914
24302
|
|
|
23915
|
-
// src/commands/tags/index.ts
|
|
23916
|
-
import { defineCommand as defineCommand148 } from "citty";
|
|
23917
|
-
|
|
23918
|
-
// src/commands/tags/shared.ts
|
|
23919
|
-
function failApi3(err) {
|
|
23920
|
-
if (err instanceof ApiError) {
|
|
23921
|
-
writeJson({ ok: false, error: { code: err.code, message: err.message } });
|
|
23922
|
-
process.exit(1);
|
|
23923
|
-
}
|
|
23924
|
-
if (err instanceof Error) {
|
|
23925
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: err.message } });
|
|
23926
|
-
process.exit(1);
|
|
23927
|
-
}
|
|
23928
|
-
writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
|
|
23929
|
-
process.exit(1);
|
|
23930
|
-
}
|
|
23931
|
-
function renderEffectiveEntry(entry) {
|
|
23932
|
-
const parts = [entry.ref, entry.type];
|
|
23933
|
-
if (entry.identifier !== void 0) {
|
|
23934
|
-
parts.push(entry.identifier);
|
|
23935
|
-
}
|
|
23936
|
-
if (entry.staged !== void 0) {
|
|
23937
|
-
parts.push(`[staged: ${entry.staged}]`);
|
|
23938
|
-
}
|
|
23939
|
-
const secretBits = [
|
|
23940
|
-
...entry.secretsSet.map((field) => `${field} \u2713 set`),
|
|
23941
|
-
...entry.secretsPending.map((field) => `${field} \u23F3 pending`)
|
|
23942
|
-
];
|
|
23943
|
-
if (secretBits.length > 0) {
|
|
23944
|
-
parts.push(`[secrets: ${secretBits.join(", ")}]`);
|
|
23945
|
-
}
|
|
23946
|
-
return parts.join(" ");
|
|
23947
|
-
}
|
|
23948
|
-
|
|
23949
|
-
// src/commands/tags/index.ts
|
|
23950
|
-
registerSchema({
|
|
23951
|
-
command: "tags.list",
|
|
23952
|
-
description: "Effective marketing tags for this chat: production tags overlaid with the changes staged in this chat. 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.",
|
|
23953
|
-
args: {
|
|
23954
|
-
json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
|
|
23955
|
-
}
|
|
23956
|
-
});
|
|
23957
|
-
async function listTags(json) {
|
|
23958
|
-
try {
|
|
23959
|
-
const chatId = requireChatId();
|
|
23960
|
-
const response = await apiPost("/api/tags/list", { chatId });
|
|
23961
|
-
if (json) {
|
|
23962
|
-
writeJson({ ok: true, data: response });
|
|
23963
|
-
return;
|
|
23964
|
-
}
|
|
23965
|
-
if (response.tags.length === 0) {
|
|
23966
|
-
process.stdout.write("No tags configured. Propose one with the request_tag_input tool (baker_ui).\n");
|
|
23967
|
-
return;
|
|
23968
|
-
}
|
|
23969
|
-
process.stdout.write(`${response.tags.map(renderEffectiveEntry).join("\n")}
|
|
23970
|
-
`);
|
|
23971
|
-
} catch (err) {
|
|
23972
|
-
failApi3(err);
|
|
23973
|
-
}
|
|
23974
|
-
}
|
|
23975
|
-
var listCommand7 = defineCommand148({
|
|
23976
|
-
meta: {
|
|
23977
|
-
name: "list",
|
|
23978
|
-
description: "Effective tags for this chat (production + staged). Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
|
|
23979
|
-
},
|
|
23980
|
-
args: { json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" } },
|
|
23981
|
-
run: async ({ args }) => {
|
|
23982
|
-
await listTags(args.json === true);
|
|
23983
|
-
}
|
|
23984
|
-
});
|
|
23985
|
-
async function listDraft3() {
|
|
23986
|
-
try {
|
|
23987
|
-
const chatId = requireChatId();
|
|
23988
|
-
const response = await apiPost("/api/tags/draft", { chatId });
|
|
23989
|
-
writeJson({ ok: true, data: response });
|
|
23990
|
-
} catch (err) {
|
|
23991
|
-
failApi3(err);
|
|
23992
|
-
}
|
|
23993
|
-
}
|
|
23994
|
-
var draftCommand3 = defineCommand148({
|
|
23995
|
-
meta: {
|
|
23996
|
-
name: "draft",
|
|
23997
|
-
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)."
|
|
23998
|
-
},
|
|
23999
|
-
run: async () => {
|
|
24000
|
-
await listDraft3();
|
|
24001
|
-
}
|
|
24002
|
-
});
|
|
24003
|
-
var tagsCommand3 = defineCommand148({
|
|
24004
|
-
meta: {
|
|
24005
|
-
name: "tags",
|
|
24006
|
-
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.
|
|
24007
|
-
|
|
24008
|
-
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.
|
|
24009
|
-
|
|
24010
|
-
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.
|
|
24011
|
-
|
|
24012
|
-
Examples:
|
|
24013
|
-
baker tags list # production + staged, with secret status
|
|
24014
|
-
baker tags draft # review the staged changes awaiting publish`
|
|
24015
|
-
},
|
|
24016
|
-
subCommands: {
|
|
24017
|
-
list: listCommand7,
|
|
24018
|
-
draft: draftCommand3
|
|
24019
|
-
},
|
|
24020
|
-
run: async () => {
|
|
24021
|
-
await listTags(false);
|
|
24022
|
-
}
|
|
24023
|
-
});
|
|
24024
|
-
|
|
24025
24303
|
// src/commands/testimonials/index.ts
|
|
24026
|
-
import { defineCommand as
|
|
24304
|
+
import { defineCommand as defineCommand151 } from "citty";
|
|
24027
24305
|
|
|
24028
24306
|
// src/commands/testimonials/get.ts
|
|
24029
|
-
import { defineCommand as
|
|
24307
|
+
import { defineCommand as defineCommand148 } from "citty";
|
|
24030
24308
|
registerSchema({
|
|
24031
24309
|
command: "testimonials.get",
|
|
24032
24310
|
description: "Get a single testimonial by ID",
|
|
@@ -24034,7 +24312,7 @@ registerSchema({
|
|
|
24034
24312
|
id: { type: "string", description: "Testimonial ID", required: true }
|
|
24035
24313
|
}
|
|
24036
24314
|
});
|
|
24037
|
-
var getCommand4 =
|
|
24315
|
+
var getCommand4 = defineCommand148({
|
|
24038
24316
|
meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
|
|
24039
24317
|
args: {
|
|
24040
24318
|
id: { type: "positional", description: "Testimonial ID", required: false },
|
|
@@ -24071,7 +24349,7 @@ var getCommand4 = defineCommand149({
|
|
|
24071
24349
|
});
|
|
24072
24350
|
|
|
24073
24351
|
// src/commands/testimonials/list.ts
|
|
24074
|
-
import { defineCommand as
|
|
24352
|
+
import { defineCommand as defineCommand149 } from "citty";
|
|
24075
24353
|
registerSchema({
|
|
24076
24354
|
command: "testimonials.list",
|
|
24077
24355
|
description: "List testimonials with optional filters.",
|
|
@@ -24101,7 +24379,7 @@ registerSchema({
|
|
|
24101
24379
|
limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
|
|
24102
24380
|
}
|
|
24103
24381
|
});
|
|
24104
|
-
var
|
|
24382
|
+
var listCommand7 = defineCommand149({
|
|
24105
24383
|
meta: {
|
|
24106
24384
|
name: "list",
|
|
24107
24385
|
description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
|
|
@@ -24150,7 +24428,7 @@ var listCommand8 = defineCommand150({
|
|
|
24150
24428
|
});
|
|
24151
24429
|
|
|
24152
24430
|
// src/commands/testimonials/search.ts
|
|
24153
|
-
import { defineCommand as
|
|
24431
|
+
import { defineCommand as defineCommand150 } from "citty";
|
|
24154
24432
|
registerSchema({
|
|
24155
24433
|
command: "testimonials.search",
|
|
24156
24434
|
description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
|
|
@@ -24181,7 +24459,7 @@ registerSchema({
|
|
|
24181
24459
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
24182
24460
|
}
|
|
24183
24461
|
});
|
|
24184
|
-
var searchCommand2 =
|
|
24462
|
+
var searchCommand2 = defineCommand150({
|
|
24185
24463
|
meta: {
|
|
24186
24464
|
name: "search",
|
|
24187
24465
|
description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
|
|
@@ -24252,10 +24530,10 @@ var searchCommand2 = defineCommand151({
|
|
|
24252
24530
|
});
|
|
24253
24531
|
|
|
24254
24532
|
// src/commands/testimonials/tags.ts
|
|
24255
|
-
var
|
|
24533
|
+
var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
|
|
24256
24534
|
|
|
24257
24535
|
// src/commands/testimonials/index.ts
|
|
24258
|
-
var testimonialsCommand =
|
|
24536
|
+
var testimonialsCommand = defineCommand151({
|
|
24259
24537
|
meta: {
|
|
24260
24538
|
name: "testimonials",
|
|
24261
24539
|
description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
|
|
@@ -24270,16 +24548,16 @@ Examples:
|
|
|
24270
24548
|
subCommands: {
|
|
24271
24549
|
get: getCommand4,
|
|
24272
24550
|
search: searchCommand2,
|
|
24273
|
-
list:
|
|
24274
|
-
tags:
|
|
24551
|
+
list: listCommand7,
|
|
24552
|
+
tags: tagsCommand3
|
|
24275
24553
|
}
|
|
24276
24554
|
});
|
|
24277
24555
|
|
|
24278
24556
|
// src/commands/videos/index.ts
|
|
24279
|
-
import { defineCommand as
|
|
24557
|
+
import { defineCommand as defineCommand156 } from "citty";
|
|
24280
24558
|
|
|
24281
24559
|
// src/commands/videos/delete.ts
|
|
24282
|
-
import { defineCommand as
|
|
24560
|
+
import { defineCommand as defineCommand152 } from "citty";
|
|
24283
24561
|
registerSchema({
|
|
24284
24562
|
command: "videos.delete",
|
|
24285
24563
|
description: "Delete a video by ID",
|
|
@@ -24293,7 +24571,7 @@ registerSchema({
|
|
|
24293
24571
|
}
|
|
24294
24572
|
}
|
|
24295
24573
|
});
|
|
24296
|
-
var deleteCommand3 =
|
|
24574
|
+
var deleteCommand3 = defineCommand152({
|
|
24297
24575
|
meta: {
|
|
24298
24576
|
name: "delete",
|
|
24299
24577
|
description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
|
|
@@ -24334,7 +24612,7 @@ var deleteCommand3 = defineCommand153({
|
|
|
24334
24612
|
});
|
|
24335
24613
|
|
|
24336
24614
|
// src/commands/videos/get.ts
|
|
24337
|
-
import { defineCommand as
|
|
24615
|
+
import { defineCommand as defineCommand153 } from "citty";
|
|
24338
24616
|
registerSchema({
|
|
24339
24617
|
command: "videos.get",
|
|
24340
24618
|
description: "Get a single video by ID",
|
|
@@ -24342,7 +24620,7 @@ registerSchema({
|
|
|
24342
24620
|
id: { type: "string", description: "Video ID", required: true }
|
|
24343
24621
|
}
|
|
24344
24622
|
});
|
|
24345
|
-
var getCommand5 =
|
|
24623
|
+
var getCommand5 = defineCommand153({
|
|
24346
24624
|
meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
|
|
24347
24625
|
args: {
|
|
24348
24626
|
id: { type: "positional", description: "Video ID", required: false },
|
|
@@ -24379,7 +24657,7 @@ var getCommand5 = defineCommand154({
|
|
|
24379
24657
|
});
|
|
24380
24658
|
|
|
24381
24659
|
// src/commands/videos/search.ts
|
|
24382
|
-
import { defineCommand as
|
|
24660
|
+
import { defineCommand as defineCommand154 } from "citty";
|
|
24383
24661
|
registerSchema({
|
|
24384
24662
|
command: "videos.search",
|
|
24385
24663
|
description: "Search videos by text query. Only returns ready videos.",
|
|
@@ -24389,7 +24667,7 @@ registerSchema({
|
|
|
24389
24667
|
tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
|
|
24390
24668
|
}
|
|
24391
24669
|
});
|
|
24392
|
-
var searchCommand3 =
|
|
24670
|
+
var searchCommand3 = defineCommand154({
|
|
24393
24671
|
meta: {
|
|
24394
24672
|
name: "search",
|
|
24395
24673
|
description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
|
|
@@ -24436,12 +24714,12 @@ var searchCommand3 = defineCommand155({
|
|
|
24436
24714
|
});
|
|
24437
24715
|
|
|
24438
24716
|
// src/commands/videos/tags.ts
|
|
24439
|
-
var
|
|
24717
|
+
var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
|
|
24440
24718
|
|
|
24441
24719
|
// src/commands/videos/upload.ts
|
|
24442
24720
|
import { readFile as readFile12, stat as stat3 } from "fs/promises";
|
|
24443
24721
|
import { extname as extname3 } from "path";
|
|
24444
|
-
import { defineCommand as
|
|
24722
|
+
import { defineCommand as defineCommand155 } from "citty";
|
|
24445
24723
|
var MIME_MAP = {
|
|
24446
24724
|
".mp4": "video/mp4",
|
|
24447
24725
|
".mov": "video/quicktime",
|
|
@@ -24475,7 +24753,7 @@ function detectContentType(filePath) {
|
|
|
24475
24753
|
}
|
|
24476
24754
|
return mime;
|
|
24477
24755
|
}
|
|
24478
|
-
var uploadCommand2 =
|
|
24756
|
+
var uploadCommand2 = defineCommand155({
|
|
24479
24757
|
meta: {
|
|
24480
24758
|
name: "upload",
|
|
24481
24759
|
description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
|
|
@@ -24529,7 +24807,7 @@ var uploadCommand2 = defineCommand156({
|
|
|
24529
24807
|
});
|
|
24530
24808
|
|
|
24531
24809
|
// src/commands/videos/index.ts
|
|
24532
|
-
var videosCommand =
|
|
24810
|
+
var videosCommand = defineCommand156({
|
|
24533
24811
|
meta: {
|
|
24534
24812
|
name: "videos",
|
|
24535
24813
|
description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
|
|
@@ -24547,15 +24825,15 @@ Examples:
|
|
|
24547
24825
|
search: searchCommand3,
|
|
24548
24826
|
upload: uploadCommand2,
|
|
24549
24827
|
delete: deleteCommand3,
|
|
24550
|
-
tags:
|
|
24828
|
+
tags: tagsCommand4
|
|
24551
24829
|
}
|
|
24552
24830
|
});
|
|
24553
24831
|
|
|
24554
24832
|
// src/commands/winning-ads/index.ts
|
|
24555
|
-
import { defineCommand as
|
|
24833
|
+
import { defineCommand as defineCommand159 } from "citty";
|
|
24556
24834
|
|
|
24557
24835
|
// src/commands/winning-ads/advertisers.ts
|
|
24558
|
-
import { defineCommand as
|
|
24836
|
+
import { defineCommand as defineCommand157 } from "citty";
|
|
24559
24837
|
registerSchema({
|
|
24560
24838
|
command: "winning-ads.advertisers",
|
|
24561
24839
|
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).",
|
|
@@ -24568,7 +24846,7 @@ registerSchema({
|
|
|
24568
24846
|
function identity(record) {
|
|
24569
24847
|
return record;
|
|
24570
24848
|
}
|
|
24571
|
-
var advertisersCommand2 =
|
|
24849
|
+
var advertisersCommand2 = defineCommand157({
|
|
24572
24850
|
meta: {
|
|
24573
24851
|
name: "advertisers",
|
|
24574
24852
|
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'
|
|
@@ -24619,7 +24897,7 @@ var advertisersCommand2 = defineCommand158({
|
|
|
24619
24897
|
});
|
|
24620
24898
|
|
|
24621
24899
|
// src/commands/winning-ads/search.ts
|
|
24622
|
-
import { defineCommand as
|
|
24900
|
+
import { defineCommand as defineCommand158 } from "citty";
|
|
24623
24901
|
registerSchema({
|
|
24624
24902
|
command: "winning-ads.search",
|
|
24625
24903
|
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.",
|
|
@@ -24727,7 +25005,7 @@ function buildSearchBody(args) {
|
|
|
24727
25005
|
}
|
|
24728
25006
|
return body;
|
|
24729
25007
|
}
|
|
24730
|
-
var searchCommand4 =
|
|
25008
|
+
var searchCommand4 = defineCommand158({
|
|
24731
25009
|
meta: {
|
|
24732
25010
|
name: "search",
|
|
24733
25011
|
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"
|
|
@@ -24839,7 +25117,7 @@ var searchCommand4 = defineCommand159({
|
|
|
24839
25117
|
});
|
|
24840
25118
|
|
|
24841
25119
|
// src/commands/winning-ads/index.ts
|
|
24842
|
-
var winningAdsCommand =
|
|
25120
|
+
var winningAdsCommand = defineCommand159({
|
|
24843
25121
|
meta: {
|
|
24844
25122
|
name: "winning-ads",
|
|
24845
25123
|
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.
|
|
@@ -24879,11 +25157,11 @@ function getCliVersion() {
|
|
|
24879
25157
|
}
|
|
24880
25158
|
|
|
24881
25159
|
// src/cli.ts
|
|
24882
|
-
var main =
|
|
25160
|
+
var main = defineCommand160({
|
|
24883
25161
|
meta: {
|
|
24884
25162
|
name: "baker",
|
|
24885
25163
|
version: getCliVersion(),
|
|
24886
|
-
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions,
|
|
25164
|
+
description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, and ad platform data in Baker.
|
|
24887
25165
|
|
|
24888
25166
|
Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
|
|
24889
25167
|
Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
|
|
@@ -24903,7 +25181,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
|
|
|
24903
25181
|
videos: videosCommand,
|
|
24904
25182
|
testimonials: testimonialsCommand,
|
|
24905
25183
|
canvas: canvasCommand,
|
|
24906
|
-
tags: tagsCommand3,
|
|
24907
25184
|
"winning-ads": winningAdsCommand,
|
|
24908
25185
|
mcp: mcpCommand,
|
|
24909
25186
|
schema: schemaCommand
|