@koda-sl/baker-cli 0.121.0-dev.3a1b48e85 → 0.121.0-dev.3b02f951b

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/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-MWFJ5NOP.js";
22
+ } from "./chunk-7WLX7E7H.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 defineCommand161, runMain } from "citty";
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,307 +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 TAG_SECRET_FIELDS = {
1943
- meta: ["accessToken"],
1944
- amplitude: [],
1945
- googleAds: ["oauthProviderId", "customerAccountId", "customerId", "loginCustomerId"],
1946
- tiktok: ["accessToken"],
1947
- vwo: [],
1948
- hotjar: [],
1949
- clarity: [],
1950
- pinterest: ["conversionToken"],
1951
- code: [],
1952
- googleAnalytics: ["apiSecret"],
1953
- googleTagManager: ["authorizationToken"],
1954
- hubspot: [],
1955
- linkedinInsightTag: ["oauthProviderId"],
1956
- onetrust: [],
1957
- posthog: [],
1958
- datafast: ["apiKey"],
1959
- recaptcha: [],
1960
- twitterAds: ["oauthProviderId"]
1961
- };
1962
- var TAG_REQUESTABLE_SECRET_FIELDS = {
1963
- meta: ["accessToken"],
1964
- amplitude: [],
1965
- googleAds: ["oauthProviderId", "customerAccountId"],
1966
- tiktok: ["accessToken"],
1967
- vwo: [],
1968
- hotjar: [],
1969
- clarity: [],
1970
- pinterest: ["conversionToken"],
1971
- code: [],
1972
- googleAnalytics: ["apiSecret"],
1973
- googleTagManager: ["authorizationToken"],
1974
- hubspot: [],
1975
- linkedinInsightTag: ["oauthProviderId"],
1976
- onetrust: [],
1977
- posthog: [],
1978
- datafast: ["apiKey"],
1979
- recaptcha: [],
1980
- twitterAds: ["oauthProviderId"]
1981
- };
1982
- var tagDraftOpKindSchema = z5.enum(["create", "update", "delete"]);
1983
- var tagDraftOpViewSchema = z5.object({
1984
- /** `tag_temp_*` for staged creates; the real tag id for update/delete ops. */
1985
- ref: z5.string(),
1986
- kind: tagDraftOpKindSchema,
1987
- type: tagTypeSchema,
1988
- /** Present on update/delete ops — the real tag this op targets. */
1989
- tagId: z5.string().optional(),
1990
- /** Non-secret config (create: full; update: the staged patch). Secrets are structurally absent. */
1991
- config: z5.record(z5.string(), z5.string()),
1992
- /** Update only — fields the op explicitly clears. */
1993
- clearFields: z5.array(z5.string()).optional(),
1994
- /** Names of secret fields already provided via the dashboard secure form. Never values. */
1995
- secretsSet: z5.array(z5.string()),
1996
- /** Names of secret fields still awaiting user input. */
1997
- secretsPending: z5.array(z5.string()),
1998
- summary: z5.string(),
1999
- stagedAt: z5.number()
2000
- });
2001
- var tagsEffectiveEntrySchema = z5.object({
2002
- /** Real tag id, or `tag_temp_*` for staged creates. Use as flow side-effect `tagIds` value. */
2003
- ref: z5.string(),
2004
- tagId: z5.string().optional(),
2005
- type: tagTypeSchema,
2006
- /** Value of the type's identifying field, when set. */
2007
- identifier: z5.string().optional(),
2008
- /** Redacted config; for staged updates, production config with the patch merged. */
2009
- config: z5.record(z5.string(), z5.string()),
2010
- /** Absent = live production tag with no staged changes in this chat. */
2011
- staged: tagDraftOpKindSchema.optional(),
2012
- secretsSet: z5.array(z5.string()),
2013
- secretsPending: z5.array(z5.string())
2014
- });
2015
- var tagsListRequestSchema = z5.object({ chatId: z5.string() });
2016
- var tagsListResponseSchema = z5.object({ tags: z5.array(tagsEffectiveEntrySchema) });
2017
- var tagsDraftStageRequestSchema = z5.discriminatedUnion("kind", [
2018
- z5.object({
2019
- kind: z5.literal("create"),
2020
- chatId: z5.string(),
2021
- type: tagTypeSchema,
2022
- config: z5.record(z5.string(), z5.string()),
2023
- requestSecrets: z5.array(z5.string()).optional(),
2024
- summary: z5.string().optional()
2025
- }),
2026
- z5.object({
2027
- kind: z5.literal("update"),
2028
- chatId: z5.string(),
2029
- ref: z5.string(),
2030
- config: z5.record(z5.string(), z5.string()).optional(),
2031
- clearFields: z5.array(z5.string()).optional(),
2032
- requestSecrets: z5.array(z5.string()).optional(),
2033
- summary: z5.string().optional()
2034
- }),
2035
- z5.object({
2036
- kind: z5.literal("delete"),
2037
- chatId: z5.string(),
2038
- ref: z5.string()
2039
- })
2040
- ]);
2041
- var tagsDraftStageResponseSchema = z5.object({
2042
- /** Null when the request dissolved a staged create (delete/clearing an unpublished temp ref). */
2043
- op: tagDraftOpViewSchema.nullable(),
2044
- /** True when a `delete <tag_temp_*>` dropped the staged create instead of staging a delete. */
2045
- removedStagedCreate: z5.boolean().optional()
2046
- });
2047
- var tagsDraftListRequestSchema = z5.object({ chatId: z5.string() });
2048
- var tagsDraftListResponseSchema = z5.object({
2049
- status: z5.enum(["active", "publishing", "applied", "discarded", "none"]),
2050
- ops: z5.array(tagDraftOpViewSchema)
2051
- });
2052
- var tagsDraftRemoveRequestSchema = z5.object({ chatId: z5.string(), ref: z5.string() });
2053
- var tagsDraftRemoveResponseSchema = z5.object({ removed: z5.boolean() });
2054
- var tagsDraftClearRequestSchema = z5.object({ chatId: z5.string() });
2055
- var tagsDraftClearResponseSchema = z5.object({ cleared: z5.number() });
2056
- var tagInputRequestSchema = z5.object({
2057
- mode: z5.enum(["create", "edit"]),
2058
- tagType: tagTypeSchema,
2059
- /** Edit mode — the real tag id or `tag_temp_*` ref being edited. */
2060
- ref: z5.string().optional(),
2061
- /** Non-secret values the agent proposes to prefill. Secret keys are stripped at every boundary. */
2062
- prefilledConfig: z5.record(z5.string(), z5.string()).optional(),
2063
- /** Secret field names the agent asks the user to provide. */
2064
- requestedSecretFields: z5.array(z5.string()).optional(),
2065
- /** Short message shown above the form explaining why the input is needed. */
2066
- message: z5.string().optional()
2067
- });
2068
- var tagInputResultSchema = z5.discriminatedUnion("status", [
2069
- z5.object({
2070
- status: z5.literal("submitted"),
2071
- ref: z5.string(),
2072
- type: tagTypeSchema,
2073
- /** Identifying field name → value (non-secret), when the type has one. */
2074
- identifier: z5.record(z5.string(), z5.string()).optional(),
2075
- secretFieldsSet: z5.array(z5.string()),
2076
- note: z5.string().optional()
2077
- }),
2078
- z5.object({
2079
- status: z5.literal("declined"),
2080
- reason: z5.string().optional()
2081
- })
2082
- ]);
2083
-
2084
1927
  // ../api/src/testimonials.ts
2085
- import { z as z6 } from "zod";
2086
- var testimonialSourceTypeSchema = z6.enum(["google", "trustpilot"]);
2087
- var testimonialStatusSchema = z6.enum(["pending", "processing", "ready", "error"]);
2088
- var testimonialSentimentSchema = z6.enum(["positive", "neutral", "negative"]);
2089
- var testimonialDocSchema = z6.object({
2090
- _id: z6.string(),
2091
- _creationTime: z6.number(),
2092
- companyId: z6.string(),
2093
- sourceId: z6.string(),
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(),
2094
1937
  sourceType: testimonialSourceTypeSchema,
2095
- reviewText: z6.string(),
2096
- reviewTitle: z6.string().optional(),
2097
- searchText: z6.string().optional(),
2098
- reviewerName: z6.string().optional(),
2099
- reviewerImageUrl: z6.string().optional(),
2100
- reviewerImageId: z6.string().optional(),
2101
- reviewerLocation: z6.string().optional(),
2102
- rating: z6.number().optional(),
2103
- reviewDate: z6.number().optional(),
2104
- ownerAnswer: z6.string().optional(),
2105
- mediaUrls: z6.array(z6.string()).optional(),
2106
- imageIds: z6.array(z6.string()).optional(),
2107
- videoIds: z6.array(z6.string()).optional(),
2108
- sourceUrl: z6.string().optional(),
2109
- rawData: z6.unknown().optional(),
2110
- tags: z6.array(z6.string()),
2111
- highlight: z6.string().optional(),
2112
- language: z6.string().optional(),
2113
- summary: z6.string().optional(),
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(),
2114
1957
  sentiment: testimonialSentimentSchema.optional(),
2115
- textEmbedding: z6.array(z6.number()).optional(),
2116
- externalId: z6.string().optional(),
2117
- contentHash: z6.string().optional(),
1958
+ textEmbedding: z5.array(z5.number()).optional(),
1959
+ externalId: z5.string().optional(),
1960
+ contentHash: z5.string().optional(),
2118
1961
  status: testimonialStatusSchema,
2119
- errorMessage: z6.string().optional(),
2120
- createdAt: z6.number(),
2121
- updatedAt: z6.number()
1962
+ errorMessage: z5.string().optional(),
1963
+ createdAt: z5.number(),
1964
+ updatedAt: z5.number()
2122
1965
  });
2123
- var testimonialsListRequestSchema = z6.object({
1966
+ var testimonialsListRequestSchema = z5.object({
2124
1967
  source: testimonialSourceTypeSchema.optional(),
2125
- rating_min: z6.coerce.number().int().min(1).max(5).optional(),
2126
- rating_max: z6.coerce.number().int().min(1).max(5).optional(),
2127
- tags: z6.string().transform((s) => s.split(",").filter(Boolean)).optional(),
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(),
2128
1971
  status: testimonialStatusSchema.optional(),
2129
1972
  sentiment: testimonialSentimentSchema.optional(),
2130
- language: z6.string().min(2).max(5).optional(),
2131
- limit: z6.coerce.number().int().positive().max(200).optional()
2132
- });
2133
- var testimonialsListResponseSchema = z6.array(testimonialDocSchema);
2134
- var testimonialsGetRequestSchema = z6.object({ id: z6.string().min(1, "Missing id parameter") });
2135
- var testimonialsSearchRequestSchema = z6.object({
2136
- query: z6.string().min(1),
2137
- limit: z6.coerce.number().int().positive().max(100).optional(),
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(),
2138
1981
  source: testimonialSourceTypeSchema.optional(),
2139
- rating_min: z6.coerce.number().int().min(1).max(5).optional(),
2140
- rating_max: z6.coerce.number().int().min(1).max(5).optional(),
2141
- tags: z6.array(z6.string()).optional(),
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(),
2142
1985
  status: testimonialStatusSchema.optional(),
2143
1986
  sentiment: testimonialSentimentSchema.optional(),
2144
- language: z6.string().min(2).max(5).optional()
1987
+ language: z5.string().min(2).max(5).optional()
2145
1988
  }).refine(
2146
1989
  (data) => data.rating_min === void 0 || data.rating_max === void 0 || data.rating_min <= data.rating_max,
2147
1990
  { message: "rating_min must be less than or equal to rating_max" }
2148
1991
  );
2149
- var testimonialsSearchResponseSchema = z6.array(testimonialDocSchema);
2150
- var testimonialsOutscraperWebhookResponseSchema = z6.object({
2151
- ok: z6.literal(true),
2152
- note: z6.string().optional()
1992
+ var testimonialsSearchResponseSchema = z5.array(testimonialDocSchema);
1993
+ var testimonialsOutscraperWebhookResponseSchema = z5.object({
1994
+ ok: z5.literal(true),
1995
+ note: z5.string().optional()
2153
1996
  });
2154
1997
 
2155
1998
  // ../api/src/videos.ts
2156
- import { z as z7 } from "zod";
2157
- var videoStatusSchema = z7.enum(["uploading", "uploaded", "processing", "ready", "error"]);
2158
- var videoTranscriptSegmentSchema = z7.object({
2159
- text: z7.string(),
2160
- startSecond: z7.number(),
2161
- endSecond: z7.number()
2162
- });
2163
- var videoSceneSchema = z7.object({
2164
- title: z7.string(),
2165
- description: z7.string(),
2166
- startSecond: z7.number(),
2167
- endSecond: z7.number(),
2168
- thumbnailTime: z7.number()
2169
- });
2170
- var videoDocSchema = z7.object({
2171
- _id: z7.string(),
2172
- _creationTime: z7.number(),
2173
- companyId: z7.string(),
2174
- muxAssetId: z7.string(),
2175
- muxPlaybackId: z7.string(),
2176
- muxUploadId: z7.string(),
2177
- name: z7.string(),
2178
- description: z7.string(),
2179
- tags: z7.array(z7.string()),
2180
- source: z7.string(),
2181
- externalId: z7.string().optional(),
2182
- sourceId: z7.string().optional(),
2183
- width: z7.number().optional(),
2184
- height: z7.number().optional(),
2185
- aspectRatio: z7.number().optional(),
2186
- duration: z7.number().optional(),
2187
- transcript: z7.string().optional(),
2188
- transcriptSegments: z7.array(videoTranscriptSegmentSchema).optional(),
2189
- scenes: z7.array(videoSceneSchema).optional(),
2190
- descriptionEmbedding: z7.array(z7.number()).optional(),
2191
- searchText: z7.string().optional(),
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(),
2192
2035
  status: videoStatusSchema,
2193
- errorMessage: z7.string().optional(),
2194
- createdAt: z7.number(),
2195
- updatedAt: z7.number(),
2196
- thumbnailUrl: z7.string()
2197
- });
2198
- var videosWebhookResponseSchema = z7.object({ ok: z7.literal(true) });
2199
- var videosGetRequestSchema = z7.object({ id: z7.string().min(1, "Missing id parameter") });
2200
- var videosSearchRequestSchema = z7.object({
2201
- query: z7.string().min(1),
2202
- limit: z7.coerce.number().int().positive().max(100).optional(),
2203
- tags: z7.array(z7.string()).optional()
2204
- });
2205
- var videoSearchResultSchema = z7.object({
2206
- _id: z7.string(),
2207
- thumbnailUrl: z7.string(),
2208
- name: z7.string(),
2209
- description: z7.string(),
2210
- tags: z7.array(z7.string()),
2211
- status: z7.string(),
2212
- duration: z7.number().optional(),
2213
- muxPlaybackId: z7.string(),
2214
- createdAt: z7.number()
2215
- });
2216
- var videosSearchResponseSchema = z7.array(videoSearchResultSchema);
2217
- var videosUploadResponseSchema = z7.object({ uploadUrl: z7.string(), videoId: z7.string() });
2218
- var videosDeleteRequestSchema = z7.object({ id: z7.string().min(1, "Missing video ID") });
2219
- var videosDeleteResponseSchema = z7.object({ ok: z7.literal(true) });
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) });
2220
2063
 
2221
2064
  // src/commands/actions/complete.ts
2222
2065
  import { defineCommand as defineCommand2 } from "citty";
@@ -4029,37 +3872,37 @@ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
4029
3872
  var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
4030
3873
 
4031
3874
  // ../api/src/ads-google/ops.ts
4032
- import { z as z8 } from "zod";
4033
- var tempRefSchema2 = z8.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
4034
- var refSchema = z8.union([
4035
- z8.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
4036
- z8.string().regex(NUMERIC_ID_REGEX2, "expected a numeric id"),
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"),
4037
3880
  tempRefSchema2
4038
3881
  ]);
4039
3882
  var targetRefSchema = refSchema;
4040
- var microsSchema = z8.number().int().positive("expected a positive micros amount");
4041
- var httpsUrlSchema2 = z8.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
4042
- var customerIdSchema = z8.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
4043
- var stageableStatusSchema2 = z8.enum(STAGEABLE_CREATE_STATUSES2);
4044
- var matchTypeSchema = z8.enum(KEYWORD_MATCH_TYPES);
4045
- var keywordTextSchema = z8.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");
4046
- var budgetCreateSchema = z8.object({
4047
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax),
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),
4048
3891
  amountMicros: microsSchema,
4049
- deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
4050
- explicitlyShared: z8.boolean().default(false)
3892
+ deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
3893
+ explicitlyShared: z7.boolean().default(false)
4051
3894
  });
4052
- var budgetUpdateSchema = z8.object({
4053
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
3895
+ var budgetUpdateSchema = z7.object({
3896
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.budget.nameMax).optional(),
4054
3897
  amountMicros: microsSchema.optional(),
4055
- deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).optional()
3898
+ deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).optional()
4056
3899
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4057
- var biddingConfigSchema = z8.object({
4058
- type: z8.enum(BIDDING_STRATEGY_TYPES),
3900
+ var biddingConfigSchema = z7.object({
3901
+ type: z7.enum(BIDDING_STRATEGY_TYPES),
4059
3902
  targetCpaMicros: microsSchema.optional(),
4060
- targetRoas: z8.number().positive().optional(),
3903
+ targetRoas: z7.number().positive().optional(),
4061
3904
  cpcBidCeilingMicros: microsSchema.optional(),
4062
- enhancedCpcEnabled: z8.boolean().optional()
3905
+ enhancedCpcEnabled: z7.boolean().optional()
4063
3906
  }).superRefine((p, ctx) => {
4064
3907
  if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
4065
3908
  ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
@@ -4068,17 +3911,17 @@ var biddingConfigSchema = z8.object({
4068
3911
  ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
4069
3912
  }
4070
3913
  });
4071
- var networkSettingsSchema = z8.object({
4072
- targetGoogleSearch: z8.boolean().optional(),
4073
- targetSearchNetwork: z8.boolean().optional(),
4074
- targetContentNetwork: z8.boolean().optional(),
4075
- targetPartnerSearchNetwork: z8.boolean().optional()
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()
4076
3919
  });
4077
- var dateSchema = z8.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
4078
- var campaignCreateSchema2 = z8.object({
4079
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
4080
- channelType: z8.enum(ADVERTISING_CHANNEL_TYPES),
4081
- channelSubType: z8.enum(ADVERTISING_CHANNEL_SUB_TYPES).optional(),
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(),
4082
3925
  budget: refSchema,
4083
3926
  /** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
4084
3927
  bidding: biddingConfigSchema.optional(),
@@ -4087,7 +3930,7 @@ var campaignCreateSchema2 = z8.object({
4087
3930
  startDate: dateSchema.optional(),
4088
3931
  endDate: dateSchema.optional(),
4089
3932
  /** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
4090
- objective: z8.enum(CAMPAIGN_OBJECTIVES).optional(),
3933
+ objective: z7.enum(CAMPAIGN_OBJECTIVES).optional(),
4091
3934
  status: stageableStatusSchema2.default("PAUSED")
4092
3935
  }).superRefine((p, ctx) => {
4093
3936
  if (!p.bidding && !p.biddingStrategy) {
@@ -4111,129 +3954,129 @@ var campaignCreateSchema2 = z8.object({
4111
3954
  ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
4112
3955
  }
4113
3956
  });
4114
- var campaignUpdateSchema2 = z8.object({
4115
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
3957
+ var campaignUpdateSchema2 = z7.object({
3958
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax).optional(),
4116
3959
  budget: refSchema.optional(),
4117
3960
  bidding: biddingConfigSchema.optional(),
4118
3961
  networkSettings: networkSettingsSchema.optional(),
4119
3962
  startDate: dateSchema.optional(),
4120
3963
  endDate: dateSchema.optional(),
4121
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3964
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4122
3965
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4123
- var adGroupCreateSchema = z8.object({
4124
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
3966
+ var adGroupCreateSchema = z7.object({
3967
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax),
4125
3968
  campaign: refSchema,
4126
- type: z8.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
3969
+ type: z7.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
4127
3970
  cpcBidMicros: microsSchema.optional(),
4128
3971
  status: stageableStatusSchema2.default("PAUSED")
4129
3972
  });
4130
- var adGroupUpdateSchema = z8.object({
4131
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
3973
+ var adGroupUpdateSchema = z7.object({
3974
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.adGroup.nameMax).optional(),
4132
3975
  cpcBidMicros: microsSchema.optional(),
4133
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3976
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4134
3977
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4135
- var keywordAddSchema = z8.object({
3978
+ var keywordAddSchema = z7.object({
4136
3979
  adGroup: refSchema,
4137
3980
  text: keywordTextSchema,
4138
3981
  matchType: matchTypeSchema,
4139
3982
  cpcBidMicros: microsSchema.optional(),
4140
- finalUrls: z8.array(httpsUrlSchema2).optional(),
3983
+ finalUrls: z7.array(httpsUrlSchema2).optional(),
4141
3984
  status: stageableStatusSchema2.default("ENABLED")
4142
3985
  });
4143
- var keywordUpdateSchema = z8.object({
3986
+ var keywordUpdateSchema = z7.object({
4144
3987
  cpcBidMicros: microsSchema.optional(),
4145
- finalUrls: z8.array(httpsUrlSchema2).optional(),
4146
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3988
+ finalUrls: z7.array(httpsUrlSchema2).optional(),
3989
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4147
3990
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4148
- var negativeKeywordAddSchema = z8.object({
4149
- level: z8.enum(["adGroup", "campaign"]),
3991
+ var negativeKeywordAddSchema = z7.object({
3992
+ level: z7.enum(["adGroup", "campaign"]),
4150
3993
  parent: refSchema,
4151
3994
  text: keywordTextSchema,
4152
3995
  matchType: matchTypeSchema
4153
3996
  });
4154
- var sharedSetCreateSchema = z8.object({
4155
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
4156
- type: z8.enum(SHARED_SET_TYPES).default("NEGATIVE_KEYWORDS")
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")
4157
4000
  });
4158
- var sharedSetMemberAddSchema = z8.object({
4001
+ var sharedSetMemberAddSchema = z7.object({
4159
4002
  sharedSet: refSchema,
4160
4003
  text: keywordTextSchema,
4161
4004
  matchType: matchTypeSchema
4162
4005
  });
4163
- var campaignSharedSetAttachSchema = z8.object({
4006
+ var campaignSharedSetAttachSchema = z7.object({
4164
4007
  campaign: refSchema,
4165
4008
  sharedSet: refSchema
4166
4009
  });
4167
- var adTextAssetSchema = z8.object({
4168
- text: z8.string().min(1),
4169
- pinnedField: z8.enum(PINNED_FIELDS).optional()
4010
+ var adTextAssetSchema = z7.object({
4011
+ text: z7.string().min(1),
4012
+ pinnedField: z7.enum(PINNED_FIELDS).optional()
4170
4013
  });
4171
- var responsiveSearchAdSchema = z8.object({
4172
- format: z8.literal("responsiveSearch"),
4173
- headlines: z8.array(
4014
+ var responsiveSearchAdSchema = z7.object({
4015
+ format: z7.literal("responsiveSearch"),
4016
+ headlines: z7.array(
4174
4017
  adTextAssetSchema.refine(
4175
4018
  (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
4176
4019
  "headline exceeds 30 chars"
4177
4020
  )
4178
4021
  ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
4179
- descriptions: z8.array(
4022
+ descriptions: z7.array(
4180
4023
  adTextAssetSchema.refine(
4181
4024
  (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
4182
4025
  "description exceeds 90 chars"
4183
4026
  )
4184
4027
  ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
4185
- path1: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4186
- path2: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4187
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4188
- });
4189
- var responsiveDisplayAdSchema = z8.object({
4190
- format: z8.literal("responsiveDisplay"),
4191
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
4192
- longHeadline: z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
4193
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
4194
- businessName: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.businessNameMax),
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),
4195
4038
  // A Responsive Display Ad's images are fields on the ad's own content (never campaign-level
4196
4039
  // asset links). Google requires ≥1 landscape marketing image (1.91:1) AND ≥1 square marketing
4197
4040
  // image (1:1) to serve; the logo images are optional.
4198
- marketingImageAssets: z8.array(refSchema).optional(),
4199
- squareMarketingImageAssets: z8.array(refSchema).optional(),
4200
- logoImageAssets: z8.array(refSchema).optional(),
4201
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4202
- });
4203
- var callAdSchema = z8.object({
4204
- format: z8.literal("call"),
4205
- countryCode: z8.string().length(2),
4206
- phoneNumber: z8.string().min(3),
4207
- headline1: z8.string().min(1).max(30),
4208
- headline2: z8.string().min(1).max(30),
4209
- description1: z8.string().min(1).max(90),
4210
- description2: z8.string().min(1).max(90),
4211
- businessName: z8.string().min(1).max(25),
4212
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4213
- });
4214
- var appAdSchema = z8.object({
4215
- format: z8.literal("app"),
4216
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(1),
4217
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1)
4218
- });
4219
- var videoAdSchema = z8.object({
4220
- format: z8.literal("video"),
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"),
4221
4064
  // A raw YouTube id is not a publishable Google Ads reference — the video must be staged as
4222
4065
  // its own `google.asset.create` (type: youtubeVideo) first, then referenced here by asset ref.
4223
- videoAssets: z8.array(refSchema).min(1),
4224
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4225
- });
4226
- var demandGenAdSchema = z8.object({
4227
- format: z8.literal("demandGen"),
4228
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(40) })).min(1).max(5),
4229
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1).max(5),
4230
- businessName: z8.string().min(1).max(25),
4231
- finalUrls: z8.array(httpsUrlSchema2).min(1),
4232
- imageAssets: z8.array(refSchema).optional(),
4233
- squareImageAssets: z8.array(refSchema).optional(),
4234
- logoImageAssets: z8.array(refSchema).optional()
4235
- });
4236
- var adContentSchema = z8.discriminatedUnion("format", [
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", [
4237
4080
  responsiveSearchAdSchema,
4238
4081
  responsiveDisplayAdSchema,
4239
4082
  callAdSchema,
@@ -4241,45 +4084,45 @@ var adContentSchema = z8.discriminatedUnion("format", [
4241
4084
  videoAdSchema,
4242
4085
  demandGenAdSchema
4243
4086
  ]);
4244
- var adCreateSchema = z8.object({
4087
+ var adCreateSchema = z7.object({
4245
4088
  adGroup: refSchema,
4246
4089
  status: stageableStatusSchema2.default("PAUSED"),
4247
4090
  content: adContentSchema
4248
4091
  });
4249
- var adUpdateSchema = z8.object({
4250
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4092
+ var adUpdateSchema = z7.object({
4093
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4251
4094
  /** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
4252
- content: z8.record(z8.string(), z8.unknown()).optional()
4095
+ content: z7.record(z7.string(), z7.unknown()).optional()
4253
4096
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4254
- var textAssetSchema = z8.object({ type: z8.literal("text"), text: z8.string().min(1) });
4255
- var imageAssetSchema = z8.object({
4256
- type: z8.literal("image"),
4257
- imageId: z8.string().min(1),
4258
- name: z8.string().optional()
4259
- });
4260
- var youtubeVideoAssetSchema = z8.object({
4261
- type: z8.literal("youtubeVideo"),
4262
- youtubeVideoId: z8.string().min(1),
4263
- name: z8.string().optional()
4264
- });
4265
- var sitelinkAssetSchema = z8.object({
4266
- type: z8.literal("sitelink"),
4267
- linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
4268
- description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4269
- description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4270
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4271
- });
4272
- var calloutAssetSchema = z8.object({
4273
- type: z8.literal("callout"),
4274
- calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
4275
- });
4276
- var structuredSnippetAssetSchema = z8.object({
4277
- type: z8.literal("structuredSnippet"),
4278
- header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
4279
- values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
4280
- });
4281
- var callToActionAssetSchema = z8.object({ type: z8.literal("callToAction"), callToAction: z8.string().min(1) });
4282
- var assetCreateSchema = z8.discriminatedUnion("type", [
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", [
4283
4126
  textAssetSchema,
4284
4127
  imageAssetSchema,
4285
4128
  youtubeVideoAssetSchema,
@@ -4288,136 +4131,136 @@ var assetCreateSchema = z8.discriminatedUnion("type", [
4288
4131
  structuredSnippetAssetSchema,
4289
4132
  callToActionAssetSchema
4290
4133
  ]);
4291
- var assetUpdateSchema = z8.object({
4292
- name: z8.string().min(1).optional(),
4293
- linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax).optional(),
4294
- description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4295
- description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4296
- finalUrls: z8.array(httpsUrlSchema2).min(1).optional(),
4297
- calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax).optional(),
4298
- header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax).optional(),
4299
- values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
4300
- callToAction: z8.string().min(1).optional(),
4301
- text: z8.string().min(1).optional()
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()
4302
4145
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4303
- var assetLinkAttachSchema = z8.object({
4304
- level: z8.enum(["campaign", "adGroup", "customer"]),
4146
+ var assetLinkAttachSchema = z7.object({
4147
+ level: z7.enum(["campaign", "adGroup", "customer"]),
4305
4148
  parent: refSchema.optional(),
4306
4149
  asset: refSchema,
4307
- fieldType: z8.enum(ASSET_FIELD_TYPES)
4150
+ fieldType: z7.enum(ASSET_FIELD_TYPES)
4308
4151
  }).superRefine((value, ctx) => {
4309
4152
  if (value.level !== "customer" && !value.parent) {
4310
4153
  ctx.addIssue({
4311
- code: z8.ZodIssueCode.custom,
4154
+ code: z7.ZodIssueCode.custom,
4312
4155
  path: ["parent"],
4313
4156
  message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
4314
4157
  });
4315
4158
  }
4316
4159
  });
4317
- var assetGroupCreateSchema = z8.object({
4160
+ var assetGroupCreateSchema = z7.object({
4318
4161
  campaign: refSchema,
4319
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax),
4320
- finalUrls: z8.array(httpsUrlSchema2).min(1),
4321
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.headlineTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.headlinesMin).max(GOOGLE_ADS_LIMITS.assetGroup.headlinesMax),
4322
- longHeadlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.longHeadlineTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.longHeadlinesMin).max(GOOGLE_ADS_LIMITS.assetGroup.longHeadlinesMax),
4323
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.descriptionTextMax) })).min(GOOGLE_ADS_LIMITS.assetGroup.descriptionsMin).max(GOOGLE_ADS_LIMITS.assetGroup.descriptionsMax),
4324
- businessName: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.businessNameMax),
4325
- imageAssets: z8.array(refSchema).optional(),
4326
- squareImageAssets: z8.array(refSchema).optional(),
4327
- logoAssets: z8.array(refSchema).optional(),
4328
- status: z8.enum(["ENABLED", "PAUSED"]).default("PAUSED")
4329
- });
4330
- var assetGroupUpdateSchema = z8.object({
4331
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax).optional(),
4332
- finalUrls: z8.array(httpsUrlSchema2).min(1).optional(),
4333
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
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()
4334
4177
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4335
- var audienceCreateSchema2 = z8.object({
4336
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
4337
- type: z8.enum(USER_LIST_TYPES).default("BASIC"),
4338
- description: z8.string().optional(),
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(),
4339
4182
  /** Customer-match members (crm-based) — file-first for large lists. */
4340
- members: z8.array(z8.record(z8.string(), z8.string())).optional(),
4341
- sourceFileRef: z8.string().optional()
4183
+ members: z7.array(z7.record(z7.string(), z7.string())).optional(),
4184
+ sourceFileRef: z7.string().optional()
4342
4185
  });
4343
- var audienceCriterionAttachSchema = z8.object({
4344
- level: z8.enum(["campaign", "adGroup"]),
4186
+ var audienceCriterionAttachSchema = z7.object({
4187
+ level: z7.enum(["campaign", "adGroup"]),
4345
4188
  parent: refSchema,
4346
4189
  userList: refSchema,
4347
- negative: z8.boolean().default(false)
4190
+ negative: z7.boolean().default(false)
4348
4191
  });
4349
- var conversionActionCreateSchema = z8.object({
4350
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
4351
- type: z8.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
4352
- category: z8.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
4353
- countingType: z8.enum(CONVERSION_COUNTING_TYPES).default("ONE_PER_CLICK"),
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"),
4354
4197
  defaultValueMicros: microsSchema.optional(),
4355
- defaultCurrencyCode: z8.string().length(3).optional(),
4356
- clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4357
- viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4358
- status: z8.enum(["ENABLED", "PAUSED"]).default("ENABLED")
4359
- });
4360
- var conversionActionUpdateSchema = z8.object({
4361
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
4362
- category: z8.enum(CONVERSION_ACTION_CATEGORIES).optional(),
4363
- countingType: z8.enum(CONVERSION_COUNTING_TYPES).optional(),
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(),
4364
4207
  defaultValueMicros: microsSchema.optional(),
4365
- defaultCurrencyCode: z8.string().length(3).optional(),
4366
- clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4367
- viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4368
- status: z8.enum(["ENABLED", "REMOVED", "HIDDEN"]).optional()
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()
4369
4212
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4370
- var biddingStrategyCreateSchema = z8.object({
4371
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
4213
+ var biddingStrategyCreateSchema = z7.object({
4214
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax),
4372
4215
  config: biddingConfigSchema
4373
4216
  }).superRefine((p, ctx) => {
4374
4217
  if (p.config.type === "MANUAL_CPC") {
4375
4218
  ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
4376
4219
  }
4377
4220
  });
4378
- var biddingStrategyUpdateSchema = z8.object({
4379
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
4221
+ var biddingStrategyUpdateSchema = z7.object({
4222
+ name: z7.string().min(1).max(GOOGLE_ADS_LIMITS.biddingStrategy.nameMax).optional(),
4380
4223
  config: biddingConfigSchema.optional()
4381
4224
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4382
- var labelCreateSchema = z8.object({
4383
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
4384
- backgroundColor: z8.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
4385
- description: z8.string().optional()
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()
4386
4229
  });
4387
- var labelAttachSchema = z8.object({
4388
- level: z8.enum(["campaign", "adGroup", "ad"]),
4230
+ var labelAttachSchema = z7.object({
4231
+ level: z7.enum(["campaign", "adGroup", "ad"]),
4389
4232
  parent: refSchema,
4390
4233
  label: refSchema
4391
4234
  });
4392
- var locationCriterionSchema = z8.object({
4393
- criterionType: z8.literal("location"),
4394
- geoTargetConstant: z8.union([z8.string().regex(GEO_TARGET_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4395
- });
4396
- var languageCriterionSchema = z8.object({
4397
- criterionType: z8.literal("language"),
4398
- languageConstant: z8.union([z8.string().regex(LANGUAGE_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4399
- });
4400
- var adScheduleCriterionSchema = z8.object({
4401
- criterionType: z8.literal("adSchedule"),
4402
- dayOfWeek: z8.enum(DAYS_OF_WEEK),
4403
- startHour: z8.number().int().min(0).max(23),
4404
- startMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
4405
- endHour: z8.number().int().min(0).max(24),
4406
- endMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
4407
- });
4408
- var deviceCriterionSchema = z8.object({
4409
- criterionType: z8.literal("device"),
4410
- device: z8.enum(DEVICE_TYPES),
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),
4411
4254
  // Google's `CampaignCriterion.bid_modifier`: "The modifier must be in the range 0.1 - 10.0. Use 0
4412
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.
4413
- bidModifier: z8.number().min(0).max(10).optional().refine((v) => v === void 0 || v === 0 || v >= 0.1, {
4256
+ bidModifier: z7.number().min(0).max(10).optional().refine((v) => v === void 0 || v === 0 || v >= 0.1, {
4414
4257
  message: "bid modifier must be 0 (exclude the device) or between 0.1 and 10.0"
4415
4258
  })
4416
4259
  });
4417
- var campaignCriterionAddSchema = z8.object({
4260
+ var campaignCriterionAddSchema = z7.object({
4418
4261
  campaign: refSchema,
4419
- negative: z8.boolean().default(false),
4420
- criterion: z8.discriminatedUnion("criterionType", [
4262
+ negative: z7.boolean().default(false),
4263
+ criterion: z7.discriminatedUnion("criterionType", [
4421
4264
  locationCriterionSchema,
4422
4265
  languageCriterionSchema,
4423
4266
  adScheduleCriterionSchema,
@@ -4427,7 +4270,7 @@ var campaignCriterionAddSchema = z8.object({
4427
4270
  const c = val.criterion;
4428
4271
  if (c.criterionType === "adSchedule" && c.endHour === 24 && c.endMinute !== "ZERO") {
4429
4272
  ctx.addIssue({
4430
- code: z8.ZodIssueCode.custom,
4273
+ code: z7.ZodIssueCode.custom,
4431
4274
  message: "endHour 24 (midnight) cannot have a non-zero endMinute",
4432
4275
  path: ["criterion", "endMinute"]
4433
4276
  });
@@ -4479,17 +4322,17 @@ var GOOGLE_DRAFT_OP_KINDS = [
4479
4322
  "google.campaignCriterion.add",
4480
4323
  "google.campaignCriterion.remove"
4481
4324
  ];
4482
- var googleDraftOpKindSchema = z8.enum(GOOGLE_DRAFT_OP_KINDS);
4325
+ var googleDraftOpKindSchema = z7.enum(GOOGLE_DRAFT_OP_KINDS);
4483
4326
  function createOp2(kind, payload) {
4484
- return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, payload });
4327
+ return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, payload });
4485
4328
  }
4486
4329
  function updateOp2(kind, payload) {
4487
- return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
4330
+ return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema, payload });
4488
4331
  }
4489
4332
  function targetOp(kind) {
4490
- return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4333
+ return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4491
4334
  }
4492
- var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4335
+ var googleDraftOpInputSchema = z7.discriminatedUnion("kind", [
4493
4336
  createOp2("google.budget.create", budgetCreateSchema),
4494
4337
  updateOp2("google.budget.update", budgetUpdateSchema),
4495
4338
  createOp2("google.campaign.create", campaignCreateSchema2),
@@ -4537,132 +4380,132 @@ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4537
4380
  ]);
4538
4381
 
4539
4382
  // ../api/src/ads-google/wire.ts
4540
- import { z as z9 } from "zod";
4541
- var googleWriteModeSchema = z9.enum(["live", "simulated"]);
4542
- var googleDraftOpResultSchema = z9.object({
4543
- status: z9.enum(["applied", "simulated", "failed", "skipped"]),
4544
- resourceName: z9.string().optional(),
4545
- error: z9.string().optional(),
4546
- skippedBecause: z9.string().optional(),
4547
- executedAt: z9.number().optional()
4548
- });
4549
- var googleDraftStageRequestSchema = z9.object({
4550
- chatId: z9.string(),
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(),
4551
4394
  op: googleDraftOpInputSchema
4552
4395
  });
4553
- var googleDraftStageResponseSchema = z9.object({
4554
- staged: z9.literal(true),
4555
- ref: z9.string(),
4396
+ var googleDraftStageResponseSchema = z8.object({
4397
+ staged: z8.literal(true),
4398
+ ref: z8.string(),
4556
4399
  kind: googleDraftOpKindSchema,
4557
4400
  mode: googleWriteModeSchema,
4558
- dependsOn: z9.array(z9.string()),
4559
- summary: z9.string(),
4560
- warnings: z9.array(z9.string()),
4401
+ dependsOn: z8.array(z8.string()),
4402
+ summary: z8.string(),
4403
+ warnings: z8.array(z8.string()),
4561
4404
  /** True when the op amended an already-staged op in place instead of appending a new one. */
4562
- amended: z9.boolean().optional()
4405
+ amended: z8.boolean().optional()
4563
4406
  });
4564
- var googleDraftAmendRequestSchema = z9.object({
4565
- chatId: z9.string(),
4566
- ref: z9.string(),
4567
- patch: z9.record(z9.string(), z9.unknown())
4407
+ var googleDraftAmendRequestSchema = z8.object({
4408
+ chatId: z8.string(),
4409
+ ref: z8.string(),
4410
+ patch: z8.record(z8.string(), z8.unknown())
4568
4411
  });
4569
- var googleDraftShowRequestSchema = z9.object({
4570
- chatId: z9.string(),
4571
- ref: z9.string()
4412
+ var googleDraftShowRequestSchema = z8.object({
4413
+ chatId: z8.string(),
4414
+ ref: z8.string()
4572
4415
  });
4573
4416
  var GOOGLE_DRAFT_BATCH_MAX = 500;
4574
- var googleDraftStageBatchRequestSchema = z9.object({
4575
- chatId: z9.string(),
4576
- ops: z9.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
4417
+ var googleDraftStageBatchRequestSchema = z8.object({
4418
+ chatId: z8.string(),
4419
+ ops: z8.array(googleDraftOpInputSchema).min(1).max(GOOGLE_DRAFT_BATCH_MAX)
4577
4420
  });
4578
- var googleDraftStageBatchResponseSchema = z9.object({
4579
- staged: z9.literal(true),
4421
+ var googleDraftStageBatchResponseSchema = z8.object({
4422
+ staged: z8.literal(true),
4580
4423
  mode: googleWriteModeSchema,
4581
- count: z9.number(),
4582
- ops: z9.array(
4583
- z9.object({
4584
- ref: z9.string(),
4424
+ count: z8.number(),
4425
+ ops: z8.array(
4426
+ z8.object({
4427
+ ref: z8.string(),
4585
4428
  kind: googleDraftOpKindSchema,
4586
- dependsOn: z9.array(z9.string()),
4587
- summary: z9.string(),
4588
- warnings: z9.array(z9.string())
4429
+ dependsOn: z8.array(z8.string()),
4430
+ summary: z8.string(),
4431
+ warnings: z8.array(z8.string())
4589
4432
  })
4590
4433
  )
4591
4434
  });
4592
- var googleDraftOpViewSchema = z9.object({
4593
- ref: z9.string(),
4435
+ var googleDraftOpViewSchema = z8.object({
4436
+ ref: z8.string(),
4594
4437
  kind: googleDraftOpKindSchema,
4595
- customerId: z9.string(),
4596
- target: z9.string().optional(),
4597
- dependsOn: z9.array(z9.string()),
4598
- summary: z9.string(),
4599
- stagedAt: z9.number(),
4438
+ customerId: z8.string(),
4439
+ target: z8.string().optional(),
4440
+ dependsOn: z8.array(z8.string()),
4441
+ summary: z8.string(),
4442
+ stagedAt: z8.number(),
4600
4443
  result: googleDraftOpResultSchema.optional()
4601
4444
  });
4602
- var googleDraftShowResponseSchema = z9.object({
4445
+ var googleDraftShowResponseSchema = z8.object({
4603
4446
  op: googleDraftOpViewSchema.extend({
4604
- payload: z9.unknown().optional(),
4605
- warnings: z9.array(z9.string()).optional(),
4606
- annotations: z9.unknown().optional()
4447
+ payload: z8.unknown().optional(),
4448
+ warnings: z8.array(z8.string()).optional(),
4449
+ annotations: z8.unknown().optional()
4607
4450
  })
4608
4451
  });
4609
- var googleDraftListRequestSchema = z9.object({
4610
- chatId: z9.string()
4452
+ var googleDraftListRequestSchema = z8.object({
4453
+ chatId: z8.string()
4611
4454
  });
4612
- var googleDraftAdvisorySchema = z9.object({
4613
- scope: z9.enum(["campaign", "adGroup"]),
4614
- message: z9.string()
4455
+ var googleDraftAdvisorySchema = z8.object({
4456
+ scope: z8.enum(["campaign", "adGroup"]),
4457
+ message: z8.string()
4615
4458
  });
4616
- var googleDraftStatusCollectionSchema = z9.object({
4617
- label: z9.string(),
4618
- added: z9.number(),
4619
- removed: z9.number(),
4620
- existing: z9.number()
4459
+ var googleDraftStatusCollectionSchema = z8.object({
4460
+ label: z8.string(),
4461
+ added: z8.number(),
4462
+ removed: z8.number(),
4463
+ existing: z8.number()
4621
4464
  });
4622
- var googleDraftChangeOperationSchema = z9.enum(["create", "update", "pause", "resume", "remove"]);
4623
- var googleDraftStatusNodeSchema = z9.lazy(
4624
- () => z9.object({
4625
- entity: z9.string(),
4626
- name: z9.string(),
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(),
4627
4470
  operation: googleDraftChangeOperationSchema.optional(),
4628
- existing: z9.boolean(),
4629
- collections: z9.array(googleDraftStatusCollectionSchema),
4630
- children: z9.array(googleDraftStatusNodeSchema),
4631
- warnings: z9.array(z9.string()).optional()
4471
+ existing: z8.boolean(),
4472
+ collections: z8.array(googleDraftStatusCollectionSchema),
4473
+ children: z8.array(googleDraftStatusNodeSchema),
4474
+ warnings: z8.array(z8.string()).optional()
4632
4475
  })
4633
4476
  );
4634
- var googleDraftListResponseSchema = z9.object({
4635
- status: z9.enum(["active", "publishing", "applied", "discarded", "none"]),
4477
+ var googleDraftListResponseSchema = z8.object({
4478
+ status: z8.enum(["active", "publishing", "applied", "discarded", "none"]),
4636
4479
  mode: googleWriteModeSchema,
4637
- count: z9.number(),
4638
- ops: z9.array(googleDraftOpViewSchema),
4480
+ count: z8.number(),
4481
+ ops: z8.array(googleDraftOpViewSchema),
4639
4482
  /** Grouped campaign ▸ ad group ▸ ad tree for the readable CLI status view. */
4640
- tree: z9.array(googleDraftStatusNodeSchema).optional(),
4483
+ tree: z8.array(googleDraftStatusNodeSchema).optional(),
4641
4484
  /** Non-blocking completeness advisories for the whole draft. */
4642
- advisories: z9.array(googleDraftAdvisorySchema).optional()
4485
+ advisories: z8.array(googleDraftAdvisorySchema).optional()
4643
4486
  });
4644
- var googleDraftRemoveRequestSchema = z9.object({
4645
- chatId: z9.string(),
4646
- ref: z9.string()
4487
+ var googleDraftRemoveRequestSchema = z8.object({
4488
+ chatId: z8.string(),
4489
+ ref: z8.string()
4647
4490
  });
4648
- var googleDraftRemoveResponseSchema = z9.object({
4491
+ var googleDraftRemoveResponseSchema = z8.object({
4649
4492
  /** The requested ref plus any dependents removed by cascade. */
4650
- removed: z9.array(z9.string())
4493
+ removed: z8.array(z8.string())
4651
4494
  });
4652
- var googleDraftClearRequestSchema = z9.object({
4653
- chatId: z9.string()
4495
+ var googleDraftClearRequestSchema = z8.object({
4496
+ chatId: z8.string()
4654
4497
  });
4655
- var googleDraftClearResponseSchema = z9.object({
4656
- cleared: z9.number()
4498
+ var googleDraftClearResponseSchema = z8.object({
4499
+ cleared: z8.number()
4657
4500
  });
4658
- var googleFieldErrorSchema = z9.object({
4659
- path: z9.string(),
4660
- message: z9.string()
4501
+ var googleFieldErrorSchema = z8.object({
4502
+ path: z8.string(),
4503
+ message: z8.string()
4661
4504
  });
4662
- var googleDraftErrorResponseSchema = z9.object({
4663
- code: z9.string(),
4664
- error: z9.string(),
4665
- fields: z9.array(googleFieldErrorSchema).optional()
4505
+ var googleDraftErrorResponseSchema = z8.object({
4506
+ code: z8.string(),
4507
+ error: z8.string(),
4508
+ fields: z8.array(googleFieldErrorSchema).optional()
4666
4509
  });
4667
4510
 
4668
4511
  // src/commands/ads/google/draft-status.ts
@@ -4827,11 +4670,11 @@ function rawTextEntries(value) {
4827
4670
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
4828
4671
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
4829
4672
  }
4830
- function rawFileEntries(path12) {
4831
- if (typeof path12 !== "string" || path12.length === 0) {
4673
+ function rawFileEntries(path14) {
4674
+ if (typeof path14 !== "string" || path14.length === 0) {
4832
4675
  return [];
4833
4676
  }
4834
- return readFileSync2(path12, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4677
+ return readFileSync2(path14, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
4835
4678
  }
4836
4679
  function keywordEntries(args) {
4837
4680
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -4854,19 +4697,19 @@ function keywordEntries(args) {
4854
4697
  }
4855
4698
  return entries;
4856
4699
  }
4857
- function loadJsonFileArg(path12) {
4858
- if (typeof path12 !== "string" || path12.length === 0) {
4700
+ function loadJsonFileArg(path14) {
4701
+ if (typeof path14 !== "string" || path14.length === 0) {
4859
4702
  return {};
4860
4703
  }
4861
4704
  try {
4862
- const parsed = JSON.parse(readFileSync2(path12, "utf8"));
4705
+ const parsed = JSON.parse(readFileSync2(path14, "utf8"));
4863
4706
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4864
- failWriteValidation(`${path12} must contain a JSON object`);
4707
+ failWriteValidation(`${path14} must contain a JSON object`);
4865
4708
  }
4866
4709
  return parsed;
4867
4710
  } catch (err) {
4868
4711
  if (err instanceof SyntaxError) {
4869
- failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
4712
+ failWriteValidation(`${path14} is not valid JSON: ${err.message}`);
4870
4713
  }
4871
4714
  throw err;
4872
4715
  }
@@ -4977,10 +4820,10 @@ async function stageUpdate(kind, customerId, target, payload) {
4977
4820
  async function stageTarget(kind, customerId, target) {
4978
4821
  await stageGoogleOp({ kind, customerId, target });
4979
4822
  }
4980
- async function draftAction(path12, body) {
4823
+ async function draftAction(path14, body) {
4981
4824
  try {
4982
4825
  const chatId = requireChatId();
4983
- const response = await apiPost(path12, { chatId, ...body });
4826
+ const response = await apiPost(path14, { chatId, ...body });
4984
4827
  writeJsonEnvelope(response);
4985
4828
  } catch (err) {
4986
4829
  handleGoogleError(err);
@@ -8735,19 +8578,19 @@ function failWriteValidation2(message) {
8735
8578
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
8736
8579
  process.exit(1);
8737
8580
  }
8738
- function loadJsonFileArg2(path12) {
8739
- if (typeof path12 !== "string" || path12.length === 0) {
8581
+ function loadJsonFileArg2(path14) {
8582
+ if (typeof path14 !== "string" || path14.length === 0) {
8740
8583
  return {};
8741
8584
  }
8742
8585
  try {
8743
- const parsed = JSON.parse(readFileSync6(path12, "utf8"));
8586
+ const parsed = JSON.parse(readFileSync6(path14, "utf8"));
8744
8587
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
8745
- failWriteValidation2(`${path12} must contain a JSON object`);
8588
+ failWriteValidation2(`${path14} must contain a JSON object`);
8746
8589
  }
8747
8590
  return parsed;
8748
8591
  } catch (err) {
8749
8592
  if (err instanceof SyntaxError) {
8750
- failWriteValidation2(`${path12} is not valid JSON: ${err.message}`);
8593
+ failWriteValidation2(`${path14} is not valid JSON: ${err.message}`);
8751
8594
  }
8752
8595
  throw err;
8753
8596
  }
@@ -8832,15 +8675,15 @@ function parseLocaleFlag(value) {
8832
8675
  }
8833
8676
  return { language: match[1], country: match[2].toUpperCase() };
8834
8677
  }
8835
- function loadTargetingFileArg(path12) {
8836
- if (typeof path12 !== "string" || path12.length === 0) {
8678
+ function loadTargetingFileArg(path14) {
8679
+ if (typeof path14 !== "string" || path14.length === 0) {
8837
8680
  return void 0;
8838
8681
  }
8839
- const parsed = loadJsonFileArg2(path12);
8682
+ const parsed = loadJsonFileArg2(path14);
8840
8683
  const criteria = parsed.targetingCriteria ?? parsed;
8841
8684
  if (!criteria.include) {
8842
8685
  failWriteValidation2(
8843
- `${path12} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
8686
+ `${path14} must contain targeting criteria with an "include" block (see baker schema ads.linkedin.campaigns.create)`
8844
8687
  );
8845
8688
  }
8846
8689
  return criteria;
@@ -8875,14 +8718,14 @@ function parseCsvLine(line) {
8875
8718
  cells.push(current);
8876
8719
  return cells.map((cell) => cell.trim());
8877
8720
  }
8878
- function parseListFileArg(path12, maxRows) {
8879
- if (typeof path12 !== "string" || path12.length === 0) {
8721
+ function parseListFileArg(path14, maxRows) {
8722
+ if (typeof path14 !== "string" || path14.length === 0) {
8880
8723
  return void 0;
8881
8724
  }
8882
- const raw = readFileSync6(path12, "utf8");
8725
+ const raw = readFileSync6(path14, "utf8");
8883
8726
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
8884
8727
  if (lines.length < 2) {
8885
- failWriteValidation2(`${path12} needs a header row and at least one data row`);
8728
+ failWriteValidation2(`${path14} needs a header row and at least one data row`);
8886
8729
  }
8887
8730
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
8888
8731
  const rows = [];
@@ -8901,7 +8744,7 @@ function parseListFileArg(path12, maxRows) {
8901
8744
  }
8902
8745
  }
8903
8746
  if (rows.length > maxRows) {
8904
- failWriteValidation2(`${path12} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8747
+ failWriteValidation2(`${path14} has ${rows.length} rows \u2014 the inline limit is ${maxRows}. Split the list.`);
8905
8748
  }
8906
8749
  return { columns, rows };
8907
8750
  }
@@ -9546,7 +9389,7 @@ var leadFormsCreateCommand = defineCommand38({
9546
9389
  Required: name, headline (\u226460), privacyPolicyUrl, questions[] (\u226412; playbook: \u22644 for completion).
9547
9390
  Each question is a predefined profile field ({ name, predefinedField: "EMAIL" }) or a custom question ({ name, questionType: "MULTIPLE_CHOICE", options: [...] }; \u22643 custom).
9548
9391
  Best-practice fields the preview will nudge for if missing: 1-3 qualifying questions, consents[] (disclosure checkboxes), thankYou.message + thankYou.landingUrl|appointmentUrl.
9549
- 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`
9550
9393
  },
9551
9394
  args: {
9552
9395
  ...accountArgs,
@@ -10970,72 +10813,72 @@ var NUMERIC_ID_REGEX3 = /^\d+$/;
10970
10813
  var IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;
10971
10814
 
10972
10815
  // ../api/src/ads-meta/ops.ts
10973
- import { z as z10 } from "zod";
10974
- var tempRefSchema3 = z10.string().regex(TEMP_REF_REGEX3, "expected a meta_temp_* reference");
10975
- var parentRefSchema2 = z10.union([z10.string().regex(NUMERIC_ID_REGEX3, "expected a numeric id"), tempRefSchema3]);
10976
- var moneySchema2 = z10.object({
10977
- amount: z10.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"),
10978
- currencyCode: z10.string().length(3).optional()
10979
- });
10980
- var httpsUrlSchema3 = z10.string().url().refine((u) => u.startsWith("https://"), "destination URLs must be https");
10981
- var bakerMediaIdSchema2 = z10.string().min(1);
10982
- var stageableStatusSchema3 = z10.enum(STAGEABLE_CREATE_STATUSES3);
10983
- var updateStatusSchema = z10.enum(UPDATE_STATUSES);
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);
10984
10827
  function currencyMinimums2(currencyCode) {
10985
10828
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
10986
10829
  }
10987
- function validateDailyBudgetFloor(money, ctx, path12) {
10830
+ function validateDailyBudgetFloor(money, ctx, path14) {
10988
10831
  if (money?.currencyCode) {
10989
10832
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
10990
10833
  if (Number(money.amount) < min) {
10991
- ctx.addIssue({ code: "custom", path: path12, message: `below the ${min} ${money.currencyCode} daily minimum` });
10834
+ ctx.addIssue({ code: "custom", path: path14, message: `below the ${min} ${money.currencyCode} daily minimum` });
10992
10835
  }
10993
10836
  }
10994
10837
  }
10995
- var geoLocationsSchema = z10.object({
10996
- countries: z10.array(z10.string().length(2)).optional(),
10997
- regions: z10.array(z10.object({ key: z10.string() })).optional(),
10998
- cities: z10.array(z10.object({ key: z10.string(), radius: z10.number().optional(), distance_unit: z10.string().optional() })).optional(),
10999
- zips: z10.array(z10.object({ key: z10.string() })).optional(),
11000
- location_types: z10.array(z10.string()).optional()
11001
- }).catchall(z10.unknown());
11002
- var idNameSchema = z10.object({ id: z10.string(), name: z10.string().optional() });
11003
- var metaTargetingSchema = z10.object({
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({
11004
10847
  geo_locations: geoLocationsSchema.optional(),
11005
10848
  excluded_geo_locations: geoLocationsSchema.optional(),
11006
- age_min: z10.number().int().min(13).max(65).optional(),
11007
- age_max: z10.number().int().min(13).max(65).optional(),
11008
- genders: z10.array(z10.union([z10.literal(1), z10.literal(2)])).optional(),
11009
- locales: z10.array(z10.number().int()).optional(),
11010
- interests: z10.array(idNameSchema).optional(),
11011
- behaviors: z10.array(idNameSchema).optional(),
11012
- custom_audiences: z10.array(z10.object({ id: parentRefSchema2 })).optional(),
11013
- excluded_custom_audiences: z10.array(z10.object({ id: parentRefSchema2 })).optional(),
11014
- flexible_spec: z10.array(z10.record(z10.string(), z10.unknown())).optional(),
11015
- exclusions: z10.record(z10.string(), z10.unknown()).optional(),
11016
- publisher_platforms: z10.array(z10.string()).optional(),
11017
- facebook_positions: z10.array(z10.string()).optional(),
11018
- instagram_positions: z10.array(z10.string()).optional(),
11019
- audience_network_positions: z10.array(z10.string()).optional(),
11020
- messenger_positions: z10.array(z10.string()).optional(),
11021
- device_platforms: z10.array(z10.string()).optional(),
11022
- targeting_automation: z10.object({ advantage_audience: z10.union([z10.literal(0), z10.literal(1)]) }).partial().optional()
11023
- }).catchall(z10.unknown());
11024
- var specialAdCategoriesSchema = z10.array(z10.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
11025
- var campaignCreateSchema3 = z10.object({
11026
- name: z10.string().min(1).max(META_LIMITS.campaign.nameMax),
11027
- objective: z10.enum(OBJECTIVES),
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),
11028
10871
  status: stageableStatusSchema3.default("PAUSED"),
11029
10872
  special_ad_categories: specialAdCategoriesSchema,
11030
- special_ad_category_country: z10.array(z10.string().length(2)).optional(),
11031
- buying_type: z10.enum(BUYING_TYPES).default("AUCTION"),
11032
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
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(),
11033
10876
  /** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */
11034
10877
  dailyBudget: moneySchema2.optional(),
11035
10878
  lifetimeBudget: moneySchema2.optional(),
11036
10879
  spendCap: moneySchema2.optional(),
11037
- start_time: z10.number().int().positive().optional(),
11038
- stop_time: z10.number().int().positive().optional()
10880
+ start_time: z9.number().int().positive().optional(),
10881
+ stop_time: z9.number().int().positive().optional()
11039
10882
  }).superRefine((p, ctx) => {
11040
10883
  if (p.dailyBudget && p.lifetimeBudget) {
11041
10884
  ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
@@ -11045,15 +10888,15 @@ var campaignCreateSchema3 = z10.object({
11045
10888
  ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
11046
10889
  }
11047
10890
  });
11048
- var campaignUpdateSchema3 = z10.object({
11049
- name: z10.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
10891
+ var campaignUpdateSchema3 = z9.object({
10892
+ name: z9.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
11050
10893
  status: updateStatusSchema.optional(),
11051
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
10894
+ bid_strategy: z9.enum(BID_STRATEGIES).optional(),
11052
10895
  dailyBudget: moneySchema2.optional(),
11053
10896
  lifetimeBudget: moneySchema2.optional(),
11054
10897
  spendCap: moneySchema2.optional(),
11055
- start_time: z10.number().int().positive().optional(),
11056
- stop_time: z10.number().int().positive().optional()
10898
+ start_time: z9.number().int().positive().optional(),
10899
+ stop_time: z9.number().int().positive().optional()
11057
10900
  }).superRefine((p, ctx) => {
11058
10901
  if (!Object.values(p).some((val) => val !== void 0)) {
11059
10902
  ctx.addIssue({ code: "custom", message: "update needs at least one field" });
@@ -11063,38 +10906,38 @@ var campaignUpdateSchema3 = z10.object({
11063
10906
  }
11064
10907
  validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
11065
10908
  });
11066
- var promotedObjectSchema = z10.object({
10909
+ var promotedObjectSchema = z9.object({
11067
10910
  page_id: parentRefSchema2.optional(),
11068
- pixel_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11069
- custom_event_type: z10.enum(CUSTOM_EVENT_TYPES).optional(),
11070
- application_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11071
- object_store_url: z10.string().url().optional(),
11072
- product_catalog_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11073
- product_set_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11074
- whatsapp_phone_number: z10.string().optional(),
11075
- offline_conversion_data_set_id: z10.string().regex(NUMERIC_ID_REGEX3).optional()
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()
11076
10919
  }).partial();
11077
- var attributionSpecSchema = z10.array(
11078
- z10.object({
11079
- event_type: z10.enum(ATTRIBUTION_EVENT_TYPES),
11080
- window_days: z10.union([z10.literal(1), z10.literal(7), z10.literal(28)])
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)])
11081
10924
  })
11082
10925
  );
11083
10926
  var adSetFields = {
11084
- name: z10.string().min(1).max(META_LIMITS.adSet.nameMax),
10927
+ name: z9.string().min(1).max(META_LIMITS.adSet.nameMax),
11085
10928
  campaign_id: parentRefSchema2,
11086
10929
  status: stageableStatusSchema3.default("PAUSED"),
11087
10930
  dailyBudget: moneySchema2.optional(),
11088
10931
  lifetimeBudget: moneySchema2.optional(),
11089
10932
  bidAmount: moneySchema2.optional(),
11090
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
11091
- billing_event: z10.enum(BILLING_EVENTS),
11092
- optimization_goal: z10.enum(OPTIMIZATION_GOALS),
11093
- destination_type: z10.enum(DESTINATION_TYPES).optional(),
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(),
11094
10937
  promoted_object: promotedObjectSchema.optional(),
11095
10938
  attribution_spec: attributionSpecSchema.optional(),
11096
- start_time: z10.number().int().positive().optional(),
11097
- end_time: z10.number().int().positive().optional(),
10939
+ start_time: z9.number().int().positive().optional(),
10940
+ end_time: z9.number().int().positive().optional(),
11098
10941
  targeting: metaTargetingSchema
11099
10942
  };
11100
10943
  function validateAdSetBudgetAndBid(p, ctx) {
@@ -11112,22 +10955,22 @@ function validateAdSetBudgetAndBid(p, ctx) {
11112
10955
  ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
11113
10956
  }
11114
10957
  }
11115
- var adSetCreateSchema = z10.object(adSetFields).superRefine((p, ctx) => {
10958
+ var adSetCreateSchema = z9.object(adSetFields).superRefine((p, ctx) => {
11116
10959
  validateAdSetBudgetAndBid(p, ctx);
11117
10960
  });
11118
- var adSetUpdateSchema = z10.object({
10961
+ var adSetUpdateSchema = z9.object({
11119
10962
  name: adSetFields.name.optional(),
11120
10963
  status: updateStatusSchema.optional(),
11121
10964
  dailyBudget: moneySchema2.optional(),
11122
10965
  lifetimeBudget: moneySchema2.optional(),
11123
10966
  bidAmount: moneySchema2.optional(),
11124
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
11125
- optimization_goal: z10.enum(OPTIMIZATION_GOALS).optional(),
11126
- destination_type: z10.enum(DESTINATION_TYPES).optional(),
10967
+ bid_strategy: z9.enum(BID_STRATEGIES).optional(),
10968
+ optimization_goal: z9.enum(OPTIMIZATION_GOALS).optional(),
10969
+ destination_type: z9.enum(DESTINATION_TYPES).optional(),
11127
10970
  promoted_object: promotedObjectSchema.optional(),
11128
10971
  attribution_spec: attributionSpecSchema.optional(),
11129
- start_time: z10.number().int().positive().optional(),
11130
- end_time: z10.number().int().positive().optional(),
10972
+ start_time: z9.number().int().positive().optional(),
10973
+ end_time: z9.number().int().positive().optional(),
11131
10974
  targeting: metaTargetingSchema.optional()
11132
10975
  }).superRefine((p, ctx) => {
11133
10976
  if (!Object.values(p).some((val) => val !== void 0)) {
@@ -11135,38 +10978,38 @@ var adSetUpdateSchema = z10.object({
11135
10978
  }
11136
10979
  validateAdSetBudgetAndBid(p, ctx);
11137
10980
  });
11138
- var messageSchema = z10.string().min(1).max(META_LIMITS.creative.messageHardMax);
11139
- var headlineSchema2 = z10.string().min(1).max(META_LIMITS.creative.headlineMax);
11140
- var descriptionSchema = z10.string().min(1).max(META_LIMITS.creative.descriptionMax);
11141
- var callToActionSchema = z10.object({
11142
- type: z10.enum(CTA_TYPES2),
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),
11143
10986
  /** Overrides the base link for the CTA button; defaults to the ad's link. */
11144
10987
  link: httpsUrlSchema3.optional()
11145
10988
  });
11146
- var creativeEnhancementsSchema = z10.object({
11147
- standardEnhancements: z10.enum(ENROLL_STATUSES).optional(),
11148
- features: z10.record(z10.string(), z10.enum(ENROLL_STATUSES)).optional()
10989
+ var creativeEnhancementsSchema = z9.object({
10990
+ standardEnhancements: z9.enum(ENROLL_STATUSES).optional(),
10991
+ features: z9.record(z9.string(), z9.enum(ENROLL_STATUSES)).optional()
11149
10992
  });
11150
10993
  var creativeSharedFields = {
11151
- name: z10.string().max(META_LIMITS.creative.nameMax).optional(),
10994
+ name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
11152
10995
  /** Facebook Page id backing the ad's identity. */
11153
10996
  page_id: parentRefSchema2,
11154
10997
  /** Instagram account id for IG placements (aka instagram_actor_id on read). */
11155
- instagram_user_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
10998
+ instagram_user_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
11156
10999
  /** URL tracking parameters appended to the destination, e.g. "utm_source=fb&utm_campaign=x". */
11157
- url_tags: z10.string().max(1e3).optional(),
11000
+ url_tags: z9.string().max(1e3).optional(),
11158
11001
  enhancements: creativeEnhancementsSchema.optional()
11159
11002
  };
11160
11003
  var imageMediaFields = {
11161
- imageHash: z10.string().regex(IMAGE_HASH_REGEX).optional(),
11004
+ imageHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
11162
11005
  imageRef: tempRefSchema3.optional()
11163
11006
  };
11164
11007
  var videoMediaFields = {
11165
- videoId: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11008
+ videoId: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
11166
11009
  videoRef: tempRefSchema3.optional(),
11167
11010
  /** Thumbnail for a video creative — image hash, ref, or public url. */
11168
- thumbnailHash: z10.string().regex(IMAGE_HASH_REGEX).optional(),
11169
- imageUrl: z10.string().url().optional()
11011
+ thumbnailHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
11012
+ imageUrl: z9.string().url().optional()
11170
11013
  };
11171
11014
  function countImageRefs(p) {
11172
11015
  return [p.imageHash, p.imageRef].filter(Boolean).length;
@@ -11174,8 +11017,8 @@ function countImageRefs(p) {
11174
11017
  function countVideoRefs(p) {
11175
11018
  return [p.videoId, p.videoRef].filter(Boolean).length;
11176
11019
  }
11177
- var singleCreativeSchema = z10.object({
11178
- creativeType: z10.literal("single"),
11020
+ var singleCreativeSchema = z9.object({
11021
+ creativeType: z9.literal("single"),
11179
11022
  ...creativeSharedFields,
11180
11023
  /** Primary text. */
11181
11024
  message: messageSchema,
@@ -11184,7 +11027,7 @@ var singleCreativeSchema = z10.object({
11184
11027
  headline: headlineSchema2.optional(),
11185
11028
  description: descriptionSchema.optional(),
11186
11029
  /** Display URL / caption shown under the headline. */
11187
- caption: z10.string().max(255).optional(),
11030
+ caption: z9.string().max(255).optional(),
11188
11031
  call_to_action: callToActionSchema.optional(),
11189
11032
  ...imageMediaFields,
11190
11033
  ...videoMediaFields
@@ -11208,10 +11051,10 @@ var singleCreativeSchema = z10.object({
11208
11051
  });
11209
11052
  }
11210
11053
  });
11211
- var carouselCardSchema = z10.object({
11054
+ var carouselCardSchema = z9.object({
11212
11055
  link: httpsUrlSchema3,
11213
- headline: z10.string().max(META_LIMITS.creative.headlineMax).optional(),
11214
- description: z10.string().max(META_LIMITS.creative.descriptionMax).optional(),
11056
+ headline: z9.string().max(META_LIMITS.creative.headlineMax).optional(),
11057
+ description: z9.string().max(META_LIMITS.creative.descriptionMax).optional(),
11215
11058
  call_to_action: callToActionSchema.optional(),
11216
11059
  ...imageMediaFields,
11217
11060
  ...videoMediaFields
@@ -11231,35 +11074,35 @@ var carouselCardSchema = z10.object({
11231
11074
  ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
11232
11075
  }
11233
11076
  });
11234
- var carouselCreativeSchema2 = z10.object({
11235
- creativeType: z10.literal("carousel"),
11077
+ var carouselCreativeSchema2 = z9.object({
11078
+ creativeType: z9.literal("carousel"),
11236
11079
  ...creativeSharedFields,
11237
11080
  message: messageSchema,
11238
11081
  /** Optional "see more" card destination applied when a card has no own link. */
11239
11082
  link: httpsUrlSchema3.optional(),
11240
11083
  call_to_action: callToActionSchema.optional(),
11241
- cards: z10.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax)
11084
+ cards: z9.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax)
11242
11085
  });
11243
- var dynamicImageSchema = z10.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
11244
- var dynamicVideoSchema = z10.object({
11086
+ var dynamicImageSchema = z9.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
11087
+ var dynamicVideoSchema = z9.object({
11245
11088
  videoId: videoMediaFields.videoId,
11246
11089
  videoRef: videoMediaFields.videoRef,
11247
11090
  thumbnailHash: videoMediaFields.thumbnailHash
11248
11091
  }).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
11249
11092
  var DYN = META_LIMITS.creative;
11250
- var dynamicCreativeSchema = z10.object({
11251
- creativeType: z10.literal("dynamic"),
11093
+ var dynamicCreativeSchema = z9.object({
11094
+ creativeType: z9.literal("dynamic"),
11252
11095
  ...creativeSharedFields,
11253
- bodies: z10.array(z10.object({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
11254
- titles: z10.array(z10.object({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
11255
- descriptions: z10.array(z10.object({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
11256
- images: z10.array(dynamicImageSchema).optional(),
11257
- videos: z10.array(dynamicVideoSchema).optional(),
11258
- ad_formats: z10.array(z10.enum(AD_FORMATS2)).min(1),
11259
- call_to_action_types: z10.array(z10.enum(CTA_TYPES2)).optional(),
11260
- link_urls: z10.array(z10.object({ website_url: httpsUrlSchema3, display_url: z10.string().optional() })).min(1),
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),
11261
11104
  /** Multi-language / placement customization — structural passthrough for v1. */
11262
- asset_customization_rules: z10.array(z10.record(z10.string(), z10.unknown())).optional()
11105
+ asset_customization_rules: z9.array(z9.record(z9.string(), z9.unknown())).optional()
11263
11106
  }).superRefine((p, ctx) => {
11264
11107
  if (!(p.images?.length || p.videos?.length)) {
11265
11108
  ctx.addIssue({
@@ -11269,57 +11112,57 @@ var dynamicCreativeSchema = z10.object({
11269
11112
  });
11270
11113
  }
11271
11114
  });
11272
- var existingPostCreativeSchema = z10.object({
11273
- creativeType: z10.literal("existing_post"),
11115
+ var existingPostCreativeSchema = z9.object({
11116
+ creativeType: z9.literal("existing_post"),
11274
11117
  name: creativeSharedFields.name,
11275
11118
  /** "<page_id>_<post_id>" object story id of the post to promote. */
11276
- object_story_id: z10.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
11119
+ object_story_id: z9.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
11277
11120
  instagram_user_id: creativeSharedFields.instagram_user_id,
11278
11121
  url_tags: creativeSharedFields.url_tags,
11279
11122
  enhancements: creativeSharedFields.enhancements
11280
11123
  });
11281
- var creativeContentSchema2 = z10.discriminatedUnion("creativeType", [
11124
+ var creativeContentSchema2 = z9.discriminatedUnion("creativeType", [
11282
11125
  singleCreativeSchema,
11283
11126
  carouselCreativeSchema2,
11284
11127
  dynamicCreativeSchema,
11285
11128
  existingPostCreativeSchema
11286
11129
  ]);
11287
11130
  var adCreativeCreateSchema = creativeContentSchema2;
11288
- var adCreativeUpdateSchema = z10.object({
11289
- name: z10.string().max(META_LIMITS.creative.nameMax).optional(),
11131
+ var adCreativeUpdateSchema = z9.object({
11132
+ name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
11290
11133
  status: updateStatusSchema.optional(),
11291
11134
  /** Content patch — only honored when the target is a staged meta_temp_* creative. */
11292
- content: z10.record(z10.string(), z10.unknown()).optional()
11135
+ content: z9.record(z9.string(), z9.unknown()).optional()
11293
11136
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11294
- var adCreateSchema2 = z10.object({
11295
- name: z10.string().min(1).max(META_LIMITS.ad.nameMax),
11137
+ var adCreateSchema2 = z9.object({
11138
+ name: z9.string().min(1).max(META_LIMITS.ad.nameMax),
11296
11139
  adset_id: parentRefSchema2,
11297
11140
  status: stageableStatusSchema3.default("PAUSED"),
11298
- creative: z10.object({ creative_id: parentRefSchema2 }),
11141
+ creative: z9.object({ creative_id: parentRefSchema2 }),
11299
11142
  /** Conversion pixel / offline event set / view tags — structural passthrough. */
11300
- tracking_specs: z10.array(z10.record(z10.string(), z10.unknown())).optional()
11143
+ tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
11301
11144
  });
11302
- var adUpdateSchema2 = z10.object({
11303
- name: z10.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
11145
+ var adUpdateSchema2 = z9.object({
11146
+ name: z9.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
11304
11147
  status: updateStatusSchema.optional(),
11305
11148
  /** Swapping the creative is the Meta way to "edit" an ad's creative. */
11306
- creative: z10.object({ creative_id: parentRefSchema2 }).optional(),
11307
- tracking_specs: z10.array(z10.record(z10.string(), z10.unknown())).optional()
11149
+ creative: z9.object({ creative_id: parentRefSchema2 }).optional(),
11150
+ tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
11308
11151
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11309
- var lookalikeSpecSchema = z10.object({
11310
- origin: z10.array(z10.object({ id: parentRefSchema2 })).min(1),
11311
- ratio: z10.number().min(0.01).max(0.2).optional(),
11312
- country: z10.string().length(2).optional()
11313
- });
11314
- var customAudienceCreateSchema = z10.object({
11315
- name: z10.string().min(1).max(META_LIMITS.audience.nameMax),
11316
- subtype: z10.enum(CUSTOM_AUDIENCE_SUBTYPES),
11317
- description: z10.string().max(500).optional(),
11318
- customer_file_source: z10.string().optional(),
11319
- retention_days: z10.number().int().min(1).max(META_LIMITS.audience.retentionDaysMax).optional(),
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(),
11320
11163
  lookalike_spec: lookalikeSpecSchema.optional(),
11321
11164
  /** Website/engagement rule — structural passthrough validated by Meta. */
11322
- rule: z10.record(z10.string(), z10.unknown()).optional()
11165
+ rule: z9.record(z9.string(), z9.unknown()).optional()
11323
11166
  }).superRefine((p, ctx) => {
11324
11167
  if (p.subtype === "LOOKALIKE" && !p.lookalike_spec) {
11325
11168
  ctx.addIssue({ code: "custom", path: ["lookalike_spec"], message: "LOOKALIKE audiences need a lookalike_spec" });
@@ -11328,16 +11171,16 @@ var customAudienceCreateSchema = z10.object({
11328
11171
  ctx.addIssue({ code: "custom", path: ["rule"], message: `${p.subtype} audiences need a rule (use --file)` });
11329
11172
  }
11330
11173
  });
11331
- var customAudienceUpdateSchema = z10.object({
11332
- name: z10.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
11333
- description: z10.string().max(500).optional()
11174
+ var customAudienceUpdateSchema = z9.object({
11175
+ name: z9.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
11176
+ description: z9.string().max(500).optional()
11334
11177
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11335
- var mediaUploadSchema = z10.object({
11336
- kind: z10.enum(MEDIA_KINDS),
11178
+ var mediaUploadSchema = z9.object({
11179
+ kind: z9.enum(MEDIA_KINDS),
11337
11180
  bakerImageId: bakerMediaIdSchema2.optional(),
11338
11181
  bakerVideoId: bakerMediaIdSchema2.optional(),
11339
11182
  /** Optional display name / filename hint. */
11340
- name: z10.string().max(255).optional()
11183
+ name: z9.string().max(255).optional()
11341
11184
  }).superRefine((p, ctx) => {
11342
11185
  if (p.kind === "image" && !p.bakerImageId) {
11343
11186
  ctx.addIssue({ code: "custom", path: ["bakerImageId"], message: "image uploads need a bakerImageId" });
@@ -11359,16 +11202,16 @@ var META_DRAFT_OP_KINDS = [
11359
11202
  "customAudience.update",
11360
11203
  "media.upload"
11361
11204
  ];
11362
- var metaDraftOpKindSchema = z10.enum(META_DRAFT_OP_KINDS);
11363
- var accountIdSchema2 = z10.string().regex(NUMERIC_ID_REGEX3, "accountId must be the bare numeric ad account id");
11364
- var updateTargetSchema2 = z10.union([z10.string().regex(NUMERIC_ID_REGEX3), tempRefSchema3]);
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]);
11365
11208
  function createOp3(kind, payload) {
11366
- return z10.object({ kind: z10.literal(kind), accountId: accountIdSchema2, payload });
11209
+ return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, payload });
11367
11210
  }
11368
11211
  function updateOp3(kind, payload) {
11369
- return z10.object({ kind: z10.literal(kind), accountId: accountIdSchema2, target: updateTargetSchema2, payload });
11212
+ return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, target: updateTargetSchema2, payload });
11370
11213
  }
11371
- var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
11214
+ var metaDraftOpInputSchema = z9.discriminatedUnion("kind", [
11372
11215
  createOp3("campaign.create", campaignCreateSchema3),
11373
11216
  updateOp3("campaign.update", campaignUpdateSchema3),
11374
11217
  createOp3("adSet.create", adSetCreateSchema),
@@ -11383,89 +11226,89 @@ var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
11383
11226
  ]);
11384
11227
 
11385
11228
  // ../api/src/ads-meta/wire.ts
11386
- import { z as z11 } from "zod";
11387
- var metaWriteModeSchema = z11.enum(["live", "simulated"]);
11388
- var metaDraftOpResultSchema = z11.object({
11389
- status: z11.enum(["applied", "simulated", "failed", "skipped"]),
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"]),
11390
11233
  /** The resulting Meta node id (campaign/adset/creative/ad/audience) or simulated id. */
11391
- id: z11.string().optional(),
11234
+ id: z10.string().optional(),
11392
11235
  /** For media.upload ops: the resulting image hash. */
11393
- hash: z11.string().optional(),
11394
- error: z11.string().optional(),
11395
- skippedBecause: z11.string().optional(),
11396
- executedAt: z11.number().optional()
11236
+ hash: z10.string().optional(),
11237
+ error: z10.string().optional(),
11238
+ skippedBecause: z10.string().optional(),
11239
+ executedAt: z10.number().optional()
11397
11240
  });
11398
- var metaDraftStageRequestSchema = z11.object({
11399
- chatId: z11.string(),
11241
+ var metaDraftStageRequestSchema = z10.object({
11242
+ chatId: z10.string(),
11400
11243
  op: metaDraftOpInputSchema
11401
11244
  });
11402
- var metaDraftStageResponseSchema = z11.object({
11403
- staged: z11.literal(true),
11404
- ref: z11.string(),
11245
+ var metaDraftStageResponseSchema = z10.object({
11246
+ staged: z10.literal(true),
11247
+ ref: z10.string(),
11405
11248
  kind: metaDraftOpKindSchema,
11406
11249
  mode: metaWriteModeSchema,
11407
- dependsOn: z11.array(z11.string()),
11408
- summary: z11.string(),
11409
- warnings: z11.array(z11.string()),
11250
+ dependsOn: z10.array(z10.string()),
11251
+ summary: z10.string(),
11252
+ warnings: z10.array(z10.string()),
11410
11253
  /** True when the op amended an already-staged op in place instead of appending a new one. */
11411
- amended: z11.boolean().optional()
11412
- });
11413
- var metaDraftDuplicateRequestSchema = z11.object({
11414
- chatId: z11.string(),
11415
- accountId: z11.string(),
11416
- entity: z11.enum(["campaign", "adSet", "ad"]),
11417
- sourceId: z11.string(),
11418
- overrides: z11.record(z11.string(), z11.unknown()).optional(),
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(),
11419
11262
  /** Pause the original after the copy publishes. */
11420
- replace: z11.boolean().optional()
11263
+ replace: z10.boolean().optional()
11421
11264
  });
11422
- var metaDraftOpViewSchema = z11.object({
11423
- ref: z11.string(),
11265
+ var metaDraftOpViewSchema = z10.object({
11266
+ ref: z10.string(),
11424
11267
  kind: metaDraftOpKindSchema,
11425
- accountId: z11.string(),
11426
- target: z11.string().optional(),
11427
- dependsOn: z11.array(z11.string()),
11428
- summary: z11.string(),
11429
- stagedAt: z11.number(),
11268
+ accountId: z10.string(),
11269
+ target: z10.string().optional(),
11270
+ dependsOn: z10.array(z10.string()),
11271
+ summary: z10.string(),
11272
+ stagedAt: z10.number(),
11430
11273
  result: metaDraftOpResultSchema.optional()
11431
11274
  });
11432
- var metaDraftListRequestSchema = z11.object({
11433
- chatId: z11.string()
11275
+ var metaDraftListRequestSchema = z10.object({
11276
+ chatId: z10.string()
11434
11277
  });
11435
- var metaDraftAdvisorySchema = z11.object({
11436
- ref: z11.string(),
11437
- message: z11.string()
11278
+ var metaDraftAdvisorySchema = z10.object({
11279
+ ref: z10.string(),
11280
+ message: z10.string()
11438
11281
  });
11439
- var metaDraftListResponseSchema = z11.object({
11440
- status: z11.enum(["active", "publishing", "applied", "discarded", "none"]),
11282
+ var metaDraftListResponseSchema = z10.object({
11283
+ status: z10.enum(["active", "publishing", "applied", "discarded", "none"]),
11441
11284
  mode: metaWriteModeSchema,
11442
- count: z11.number(),
11443
- ops: z11.array(metaDraftOpViewSchema),
11285
+ count: z10.number(),
11286
+ ops: z10.array(metaDraftOpViewSchema),
11444
11287
  /** Non-blocking cross-op quality advisories — "good campaign, not just valid". */
11445
- advisories: z11.array(metaDraftAdvisorySchema)
11288
+ advisories: z10.array(metaDraftAdvisorySchema)
11446
11289
  });
11447
- var metaDraftRemoveRequestSchema = z11.object({
11448
- chatId: z11.string(),
11449
- ref: z11.string()
11290
+ var metaDraftRemoveRequestSchema = z10.object({
11291
+ chatId: z10.string(),
11292
+ ref: z10.string()
11450
11293
  });
11451
- var metaDraftRemoveResponseSchema = z11.object({
11294
+ var metaDraftRemoveResponseSchema = z10.object({
11452
11295
  /** The requested ref plus any dependents removed by cascade. */
11453
- removed: z11.array(z11.string())
11296
+ removed: z10.array(z10.string())
11454
11297
  });
11455
- var metaDraftClearRequestSchema = z11.object({
11456
- chatId: z11.string()
11298
+ var metaDraftClearRequestSchema = z10.object({
11299
+ chatId: z10.string()
11457
11300
  });
11458
- var metaDraftClearResponseSchema = z11.object({
11459
- cleared: z11.number()
11301
+ var metaDraftClearResponseSchema = z10.object({
11302
+ cleared: z10.number()
11460
11303
  });
11461
- var metaFieldErrorSchema = z11.object({
11462
- path: z11.string(),
11463
- message: z11.string()
11304
+ var metaFieldErrorSchema = z10.object({
11305
+ path: z10.string(),
11306
+ message: z10.string()
11464
11307
  });
11465
- var metaDraftErrorResponseSchema = z11.object({
11466
- code: z11.string(),
11467
- error: z11.string(),
11468
- fields: z11.array(metaFieldErrorSchema).optional()
11308
+ var metaDraftErrorResponseSchema = z10.object({
11309
+ code: z10.string(),
11310
+ error: z10.string(),
11311
+ fields: z10.array(metaFieldErrorSchema).optional()
11469
11312
  });
11470
11313
 
11471
11314
  // src/commands/ads/meta/write-shared.ts
@@ -11476,19 +11319,19 @@ function failWriteValidation3(message) {
11476
11319
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
11477
11320
  process.exit(1);
11478
11321
  }
11479
- function loadJsonFileArg3(path12) {
11480
- if (typeof path12 !== "string" || path12.length === 0) {
11322
+ function loadJsonFileArg3(path14) {
11323
+ if (typeof path14 !== "string" || path14.length === 0) {
11481
11324
  return {};
11482
11325
  }
11483
11326
  try {
11484
- const parsed = JSON.parse(readFileSync8(path12, "utf8"));
11327
+ const parsed = JSON.parse(readFileSync8(path14, "utf8"));
11485
11328
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
11486
- failWriteValidation3(`${path12} must contain a JSON object`);
11329
+ failWriteValidation3(`${path14} must contain a JSON object`);
11487
11330
  }
11488
11331
  return parsed;
11489
11332
  } catch (err) {
11490
11333
  if (err instanceof SyntaxError) {
11491
- failWriteValidation3(`${path12} is not valid JSON: ${err.message}`);
11334
+ failWriteValidation3(`${path14} is not valid JSON: ${err.message}`);
11492
11335
  }
11493
11336
  throw err;
11494
11337
  }
@@ -14551,7 +14394,7 @@ async function probeDuration(filePath) {
14551
14394
 
14552
14395
  // src/commands/canvas/run.ts
14553
14396
  import { readFile as readFile2 } from "fs/promises";
14554
- import path4 from "path";
14397
+ import path5 from "path";
14555
14398
  import { defineCommand as defineCommand88 } from "citty";
14556
14399
 
14557
14400
  // src/commands/canvas/placeholders.ts
@@ -14595,9 +14438,102 @@ function isResolvableRelative(value) {
14595
14438
  return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
14596
14439
  }
14597
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_CREATIVE_SLUG_LENGTH = 100;
14447
+ function creativeSlugFromCanvasPath(filePath) {
14448
+ const normalized = filePath.split(path3.sep).join("/");
14449
+ const match = normalized.match(/(?:^|\/)src\/creatives\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\//);
14450
+ const slug = match?.[1] ?? null;
14451
+ return slug && slug.length <= MAX_CREATIVE_SLUG_LENGTH ? slug : null;
14452
+ }
14453
+ var OUTPUT_KINDS = /* @__PURE__ */ new Set(["image", "video", "audio", "json", "text", "font"]);
14454
+ function toRecordOutput(slot, value) {
14455
+ const refs = collectAssetRefLikes(value);
14456
+ const ref = refs.length === 1 ? refs[0] : null;
14457
+ if (!ref || !isPersistedAssetRef(ref)) return null;
14458
+ const kind = typeof ref.kind === "string" && OUTPUT_KINDS.has(ref.kind) ? ref.kind : null;
14459
+ if (!kind) return null;
14460
+ return {
14461
+ slot,
14462
+ kind,
14463
+ sha256: ref.sha256,
14464
+ url: ref.url,
14465
+ mime: ref.mime,
14466
+ width: typeof ref.width === "number" ? ref.width : void 0,
14467
+ height: typeof ref.height === "number" ? ref.height : void 0,
14468
+ durationMs: typeof ref.duration_ms === "number" ? ref.duration_ms : void 0
14469
+ };
14470
+ }
14471
+ function nodeOutputsToRecord(nodeOutputs) {
14472
+ const out = [];
14473
+ for (const [slot, value] of Object.entries(nodeOutputs)) {
14474
+ if (Array.isArray(value)) {
14475
+ value.forEach((item, i) => {
14476
+ const rec = toRecordOutput(`${slot}#${i}`, item);
14477
+ if (rec) out.push(rec);
14478
+ });
14479
+ } else {
14480
+ const rec = toRecordOutput(slot, value);
14481
+ if (rec) out.push(rec);
14482
+ }
14483
+ }
14484
+ return out.slice(0, MAX_OUTPUTS_PER_NODE);
14485
+ }
14486
+ function finalOutputsToRecord(output) {
14487
+ if (Array.isArray(output)) {
14488
+ return output.map((item, i) => toRecordOutput(`final#${i}`, item)).filter((rec2) => rec2 !== null).slice(0, MAX_FINAL_OUTPUTS);
14489
+ }
14490
+ const rec = toRecordOutput("final", output);
14491
+ return rec ? [rec] : [];
14492
+ }
14493
+ function buildRunRecord(result, meta) {
14494
+ const nodes = result.node_runs.slice(0, MAX_RUN_NODES).map((run) => ({
14495
+ nodeId: run.node_id,
14496
+ nodeType: run.node_type,
14497
+ cached: run.cached,
14498
+ credits: run.credits,
14499
+ durationMs: run.duration_ms,
14500
+ outputs: nodeOutputsToRecord(result.outputs_by_node[run.node_id] ?? {})
14501
+ }));
14502
+ const finalOutputs = finalOutputsToRecord(result.output);
14503
+ return {
14504
+ runId: result.run_id,
14505
+ creativeSlug: meta.creativeSlug,
14506
+ canvasPath: meta.canvasPath,
14507
+ canvasSha: meta.canvasSha,
14508
+ chatId: meta.chatId,
14509
+ status: "completed",
14510
+ stats: {
14511
+ totalNodes: result.stats.total_nodes,
14512
+ cachedNodes: result.stats.cached_nodes,
14513
+ totalCredits: result.stats.total_credits,
14514
+ durationMs: result.stats.duration_ms
14515
+ },
14516
+ nodes,
14517
+ finalOutputs: finalOutputs.length > 0 ? finalOutputs : void 0
14518
+ };
14519
+ }
14520
+ function buildFailedRunRecord(runId, errorMessage, meta) {
14521
+ return {
14522
+ runId,
14523
+ creativeSlug: meta.creativeSlug,
14524
+ canvasPath: meta.canvasPath,
14525
+ canvasSha: meta.canvasSha,
14526
+ chatId: meta.chatId,
14527
+ status: "failed",
14528
+ errorMessage: errorMessage.slice(0, 2e3),
14529
+ stats: { totalNodes: 0, cachedNodes: 0, totalCredits: 0, durationMs: 0 },
14530
+ nodes: []
14531
+ };
14532
+ }
14533
+
14598
14534
  // src/commands/canvas/run-retention.ts
14599
14535
  import { rm } from "fs/promises";
14600
- import path3 from "path";
14536
+ import path4 from "path";
14601
14537
  function runDirsToPrune(entries, keep, currentRunId) {
14602
14538
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
14603
14539
  if (keep <= 0) return runs;
@@ -14614,7 +14550,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
14614
14550
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
14615
14551
  if (toPrune.length === 0) return;
14616
14552
  for (const dir of toPrune) {
14617
- await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
14553
+ await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
14618
14554
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
14619
14555
  );
14620
14556
  }
@@ -14641,10 +14577,22 @@ var runCommand = defineCommand88({
14641
14577
  "keep-runs": {
14642
14578
  type: "string",
14643
14579
  description: "After the run, prune old r_* run dirs, keeping the N newest (off by default)"
14580
+ },
14581
+ "remote-cache": {
14582
+ type: "string",
14583
+ description: "on | off \u2014 company-scoped remote cache + durable asset persistence (default on; env BAKER_CANVAS_REMOTE_CACHE)"
14584
+ },
14585
+ // citty consumes any `--no-<flag>` as a negation of `<flag>`, so the
14586
+ // opt-out spelling `--no-record` requires the flag to be named `record`
14587
+ // (a literal "no-record" arg would never receive a value).
14588
+ record: {
14589
+ type: "boolean",
14590
+ default: true,
14591
+ description: "Post the durable run-history record to Baker (disable with --no-record)"
14644
14592
  }
14645
14593
  },
14646
14594
  async run({ args }) {
14647
- const filePath = path4.resolve(String(args.file));
14595
+ const filePath = path5.resolve(String(args.file));
14648
14596
  const raw = await readFile2(filePath, "utf8");
14649
14597
  let parsed;
14650
14598
  try {
@@ -14655,7 +14603,7 @@ var runCommand = defineCommand88({
14655
14603
  `);
14656
14604
  process.exit(2);
14657
14605
  }
14658
- parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
14606
+ parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
14659
14607
  const pending = unsuppliedPlaceholderAssets(parsed);
14660
14608
  if (pending.length > 0) {
14661
14609
  process.stderr.write(
@@ -14675,16 +14623,26 @@ var runCommand = defineCommand88({
14675
14623
  );
14676
14624
  process.exit(2);
14677
14625
  }
14626
+ const remoteCache = args["remote-cache"] !== void 0 ? String(args["remote-cache"]) !== "off" : void 0;
14678
14627
  const engine = createEngineFromEnv({
14679
14628
  cacheDir: args["cache-dir"] ? String(args["cache-dir"]) : void 0,
14680
14629
  outputsDir: args["outputs-dir"] ? String(args["outputs-dir"]) : void 0,
14681
14630
  log: (line) => process.stdout.write(`${line}
14682
- `)
14631
+ `),
14632
+ remoteCache
14683
14633
  });
14634
+ const runId = args["run-id"] ? String(args["run-id"]) : `r_${ulid()}`;
14635
+ const recordMeta = {
14636
+ creativeSlug: creativeSlugFromCanvasPath(filePath) ?? void 0,
14637
+ canvasPath: path5.relative(process.cwd(), filePath) || void 0,
14638
+ canvasSha: sha256Hex(Buffer.from(raw)),
14639
+ chatId: getEnv().BAKER_CHAT_ID || void 0
14640
+ };
14641
+ const record = args.record === false ? null : buildRecorder();
14684
14642
  try {
14685
14643
  const policy = args["cache-policy"] ?? "read_write";
14686
14644
  const result = await engine.run(parsed, {
14687
- run_id: args["run-id"] ? String(args["run-id"]) : void 0,
14645
+ run_id: runId,
14688
14646
  cache_policy: policy,
14689
14647
  concurrency: resolveConcurrency(
14690
14648
  // --concurrency wins; --parallel is the discoverable alias for the same bound.
@@ -14692,9 +14650,10 @@ var runCommand = defineCommand88({
14692
14650
  process.env.BAKER_CANVAS_CONCURRENCY
14693
14651
  )
14694
14652
  });
14653
+ if (record) await record(buildRunRecord(result, recordMeta));
14695
14654
  const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
14696
14655
  if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
14697
- const outputsDir = args["outputs-dir"] ? path4.resolve(String(args["outputs-dir"])) : path4.resolve("canvas");
14656
+ const outputsDir = args["outputs-dir"] ? path5.resolve(String(args["outputs-dir"])) : path5.resolve("canvas");
14698
14657
  await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
14699
14658
  `));
14700
14659
  }
@@ -14722,6 +14681,7 @@ var runCommand = defineCommand88({
14722
14681
  }
14723
14682
  if (e instanceof LayerExecutionError) {
14724
14683
  const failures = e.failures.map((f) => ({ node_id: f.nodeId, message: describeFailureReason(f.reason) }));
14684
+ if (record) await record(buildFailedRunRecord(runId, e.message, recordMeta));
14725
14685
  process.stderr.write(
14726
14686
  `${JSON.stringify({ ok: false, error: { code: "runtime", message: e.message, failures } }, null, 2)}
14727
14687
  `
@@ -14729,40 +14689,54 @@ var runCommand = defineCommand88({
14729
14689
  process.exit(1);
14730
14690
  }
14731
14691
  const msg = e instanceof Error ? e.message : String(e);
14692
+ if (record) await record(buildFailedRunRecord(runId, msg, recordMeta));
14732
14693
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "runtime", message: msg } }, null, 2)}
14733
14694
  `);
14734
14695
  process.exit(1);
14735
14696
  }
14736
14697
  }
14737
14698
  });
14699
+ function buildRecorder() {
14700
+ return async (payload) => {
14701
+ try {
14702
+ const creds = requireCredentialsFromEnv();
14703
+ const client = new BackendClient({ baseUrl: creds.url, apiKey: creds.apiKey });
14704
+ await client.recordRun(payload);
14705
+ } catch (e) {
14706
+ const msg = e instanceof Error ? e.message : String(e);
14707
+ process.stderr.write(`[warn] run record not persisted (${msg})
14708
+ `);
14709
+ }
14710
+ };
14711
+ }
14738
14712
 
14739
14713
  // src/commands/canvas/scaffold-static-ad.ts
14740
- import { readFile as readFile3, writeFile } from "fs/promises";
14741
- import path6 from "path";
14714
+ import { access, cp, mkdir, readFile as readFile3, writeFile } from "fs/promises";
14715
+ import path8 from "path";
14742
14716
  import { defineCommand as defineCommand89 } from "citty";
14743
14717
 
14744
14718
  // src/engine/scaffold/staticAd.ts
14745
- import { z as z12 } from "zod";
14719
+ import { z as z11 } from "zod";
14746
14720
  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"]);
14747
14721
  var DEFAULT_ASPECT_RATIO = "9:16";
14748
- var Blueprint = z12.object({
14749
- meta: z12.object({ estimated_aspect_ratio: z12.string().optional() }).loose().optional(),
14750
- text_content: z12.array(z12.object({ text: z12.string().optional() }).loose()).optional()
14722
+ var Blueprint = z11.object({
14723
+ meta: z11.object({ estimated_aspect_ratio: z11.string().optional() }).loose().optional(),
14724
+ text_content: z11.array(z11.object({ text: z11.string().optional() }).loose()).optional()
14751
14725
  }).loose();
14752
- var ElementLocator = z12.object({
14753
- collection: z12.enum(["subjects", "people", "brands_logos"]),
14754
- index: z12.number().int().nonnegative()
14726
+ var ElementLocator = z11.object({
14727
+ collection: z11.enum(["subjects", "people", "brands_logos"]),
14728
+ index: z11.number().int().nonnegative()
14755
14729
  }).loose();
14756
- var MainElement = z12.object({
14730
+ var MainElement = z11.object({
14757
14731
  // logo | product | person | animal | badge | other
14758
- type: z12.string(),
14759
- label: z12.string().optional(),
14760
- description: z12.string().optional(),
14761
- expression: z12.string().nullable().optional(),
14762
- reason: z12.string().optional(),
14732
+ type: z11.string(),
14733
+ label: z11.string().optional(),
14734
+ description: z11.string().optional(),
14735
+ expression: z11.string().nullable().optional(),
14736
+ reason: z11.string().optional(),
14763
14737
  locator: ElementLocator.optional()
14764
14738
  }).loose();
14765
- var MainElements = z12.array(MainElement);
14739
+ var MainElements = z11.array(MainElement);
14766
14740
  function sanitizeId(raw, fallback) {
14767
14741
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
14768
14742
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -14924,18 +14898,106 @@ function staticAdReport(input, elementsInput, opts) {
14924
14898
  };
14925
14899
  }
14926
14900
 
14901
+ // src/commands/canvas/creative-definition.ts
14902
+ import path6 from "path";
14903
+ var PLATFORM_VALUES = ["meta", "google", "linkedin", "tiktok", "youtube", "x", "other"];
14904
+ var FORMAT_VALUES = ["1:1", "4:5", "9:16", "16:9", "1.91:1"];
14905
+ function titleFromSlug(slug) {
14906
+ const title = slug.split("-").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
14907
+ return title || slug;
14908
+ }
14909
+ function resolvePlatform(platform) {
14910
+ const value = platform?.trim();
14911
+ return value && PLATFORM_VALUES.includes(value) ? value : "meta";
14912
+ }
14913
+ function resolveFormats(aspect) {
14914
+ const value = aspect?.trim();
14915
+ return value && FORMAT_VALUES.includes(value) ? [value] : ["4:5"];
14916
+ }
14917
+ function referenceRelativePath(kind, ext) {
14918
+ const name = kind === "video" ? "source" : "original";
14919
+ return `references/${name}${ext}`;
14920
+ }
14921
+ function sourceExtension(source, isUrl, kind) {
14922
+ const raw = isUrl ? urlPathname(source) : source;
14923
+ const ext = path6.extname(raw).toLowerCase();
14924
+ if (/^\.[a-z0-9]{1,5}$/.test(ext)) return ext;
14925
+ return kind === "video" ? ".mp4" : ".jpg";
14926
+ }
14927
+ function urlPathname(source) {
14928
+ try {
14929
+ return new URL(source).pathname;
14930
+ } catch {
14931
+ return source;
14932
+ }
14933
+ }
14934
+ function describeBlueprintIntent(blueprint) {
14935
+ const intent = blueprint?.ad_intent;
14936
+ if (typeof intent === "string" && intent.trim()) return intent.trim();
14937
+ if (intent && typeof intent === "object") {
14938
+ const summary = intent.summary ?? intent.feeling;
14939
+ if (typeof summary === "string" && summary.trim()) return summary.trim();
14940
+ }
14941
+ return void 0;
14942
+ }
14943
+ function yamlScalar(value) {
14944
+ return JSON.stringify(value);
14945
+ }
14946
+ function buildCreativeDefinition(input) {
14947
+ const lines = ["---", `title: ${yamlScalar(input.title)}`, `kind: ${input.kind}`, `platform: ${input.platform}`];
14948
+ lines.push(`formats: [${input.formats.map(yamlScalar).join(", ")}]`);
14949
+ lines.push(`status: ${input.status ?? "draft"}`);
14950
+ if (input.sourceReferenceUrl) lines.push(`sourceReferenceUrl: ${yamlScalar(input.sourceReferenceUrl)}`);
14951
+ if (input.sourceAdvertiser) lines.push(`sourceAdvertiser: ${yamlScalar(input.sourceAdvertiser)}`);
14952
+ if (input.sourceKind) lines.push(`sourceKind: ${input.sourceKind}`);
14953
+ if (input.sourcePath) lines.push(`sourcePath: ${yamlScalar(input.sourcePath)}`);
14954
+ lines.push("---", "");
14955
+ lines.push(input.description?.trim() || `${input.title} \u2014 canvas-built ${input.kind} ad for ${input.platform}.`);
14956
+ lines.push("");
14957
+ return lines.join("\n");
14958
+ }
14959
+
14927
14960
  // src/commands/canvas/scaffold-static-ad-paths.ts
14928
- import path5 from "path";
14929
- function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd()) {
14961
+ import path7 from "path";
14962
+ function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
14930
14963
  const file = rawFile.trim();
14931
14964
  const imageIsUrl = /^https?:\/\//i.test(file);
14932
- const imageSource = imageIsUrl ? file : path5.resolve(cwd, file);
14933
- const outPath = out ? path5.resolve(cwd, out) : imageIsUrl ? path5.join(cwd, "static-ad.canvas.json") : path5.join(path5.dirname(imageSource), "static-ad.canvas.json");
14934
- const blueprintPath = path5.join(path5.dirname(outPath), "prompt.json");
14935
- return { imageIsUrl, imageSource, outPath, blueprintPath };
14965
+ const imageSource = imageIsUrl ? file : path7.resolve(cwd, file);
14966
+ 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");
14967
+ const blueprintPath = path7.join(path7.dirname(outPath), "prompt.json");
14968
+ const creativeDir = slug ? path7.dirname(outPath) : null;
14969
+ const definitionPath = creativeDir ? path7.join(creativeDir, "_definition.md") : null;
14970
+ const referencesDir = creativeDir ? path7.join(creativeDir, "references") : null;
14971
+ return { imageIsUrl, imageSource, outPath, blueprintPath, creativeDir, definitionPath, referencesDir };
14972
+ }
14973
+ var SCAFFOLD_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
14974
+ var SCAFFOLD_SLUG_MAX_LENGTH = 100;
14975
+ function isValidScaffoldSlug(slug) {
14976
+ return slug.length <= SCAFFOLD_SLUG_MAX_LENGTH && SCAFFOLD_SLUG_PATTERN.test(slug);
14936
14977
  }
14937
14978
 
14938
14979
  // src/commands/canvas/scaffold-static-ad.ts
14980
+ async function fileExists(target) {
14981
+ try {
14982
+ await access(target);
14983
+ return true;
14984
+ } catch {
14985
+ return false;
14986
+ }
14987
+ }
14988
+ async function copySourceIntoReferences(source, isUrl, referencesDir) {
14989
+ await mkdir(referencesDir, { recursive: true });
14990
+ const relPath = referenceRelativePath("image", sourceExtension(source, isUrl, "image"));
14991
+ const dest = path8.join(referencesDir, path8.basename(relPath));
14992
+ if (isUrl) {
14993
+ const res = await fetch(source);
14994
+ if (!res.ok) throw new Error(`failed to download source image (${res.status})`);
14995
+ await writeFile(dest, Buffer.from(await res.arrayBuffer()));
14996
+ } else {
14997
+ await cp(source, dest);
14998
+ }
14999
+ return relPath;
15000
+ }
14939
15001
  function resolveModel(kind, preferred) {
14940
15002
  const ids = Object.keys(MODEL_REGISTRY[kind]);
14941
15003
  return ids.includes(preferred) ? preferred : ids[0] ?? preferred;
@@ -15095,6 +15157,16 @@ var scaffoldStaticAdCommand = defineCommand89({
15095
15157
  file: { type: "positional", required: true, description: "Path or http(s) URL to the source/inspiration image" },
15096
15158
  context: { type: "string", description: "Known provenance (advertiser, category, market) to ground the describe" },
15097
15159
  out: { type: "string", description: "Output canvas path (default <image-dir>/static-ad.canvas.json)" },
15160
+ slug: {
15161
+ type: "string",
15162
+ description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
15163
+ },
15164
+ title: { type: "string", description: "Creative title for _definition.md (default: title-cased slug)" },
15165
+ platform: {
15166
+ type: "string",
15167
+ description: "Ad platform for _definition.md (meta|google|linkedin|tiktok|youtube|x|other; default meta)"
15168
+ },
15169
+ advertiser: { type: "string", description: "Source advertiser recorded in _definition.md" },
15098
15170
  "describe-model": { type: "string", description: "Override the image_describe model id" },
15099
15171
  "select-model": { type: "string", description: "Override the text_generate model id for element selection" },
15100
15172
  "layout-model": { type: "string", description: "Override the text_generate model id for the layout pass" },
@@ -15103,10 +15175,21 @@ var scaffoldStaticAdCommand = defineCommand89({
15103
15175
  "skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
15104
15176
  },
15105
15177
  async run({ args }) {
15106
- const { imageIsUrl, imageSource, outPath, blueprintPath } = resolveScaffoldStaticAdPaths(
15178
+ const slug = args.slug ? String(args.slug) : void 0;
15179
+ if (slug && !isValidScaffoldSlug(slug)) {
15180
+ process.stderr.write(
15181
+ `${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
15182
+ `
15183
+ );
15184
+ process.exit(2);
15185
+ }
15186
+ const { imageIsUrl, imageSource, outPath, blueprintPath, definitionPath, referencesDir } = resolveScaffoldStaticAdPaths(
15107
15187
  String(args.file),
15108
- args.out ? String(args.out) : void 0
15188
+ args.out ? String(args.out) : void 0,
15189
+ process.cwd(),
15190
+ slug
15109
15191
  );
15192
+ await mkdir(path8.dirname(outPath), { recursive: true });
15110
15193
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
15111
15194
  const describeCanvas = buildDescribeCanvas(
15112
15195
  imageSource,
@@ -15123,11 +15206,21 @@ var scaffoldStaticAdCommand = defineCommand89({
15123
15206
  }
15124
15207
  await writeFile(blueprintPath, `${JSON.stringify(annotated, null, 2)}
15125
15208
  `, "utf8");
15209
+ let canvasImagePath = imageSource;
15210
+ let canvasImageIsUrl = imageIsUrl;
15211
+ let canvasBlueprintPath = blueprintPath;
15212
+ let sourceRelPath;
15213
+ if (referencesDir) {
15214
+ sourceRelPath = await copySourceIntoReferences(imageSource, imageIsUrl, referencesDir);
15215
+ canvasImagePath = sourceRelPath;
15216
+ canvasImageIsUrl = false;
15217
+ canvasBlueprintPath = "./prompt.json";
15218
+ }
15126
15219
  const opts = {
15127
15220
  genModel,
15128
- imagePath: imageSource,
15129
- imageIsUrl,
15130
- blueprintPath,
15221
+ imagePath: canvasImagePath,
15222
+ imageIsUrl: canvasImageIsUrl,
15223
+ blueprintPath: canvasBlueprintPath,
15131
15224
  aspectRatio: args.aspect ? String(args.aspect) : void 0,
15132
15225
  includeFont: !args["skip-font"]
15133
15226
  };
@@ -15149,12 +15242,31 @@ var scaffoldStaticAdCommand = defineCommand89({
15149
15242
  }
15150
15243
  await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}
15151
15244
  `, "utf8");
15245
+ if (definitionPath && !await fileExists(definitionPath)) {
15246
+ await writeFile(
15247
+ definitionPath,
15248
+ buildCreativeDefinition({
15249
+ title: args.title ? String(args.title) : titleFromSlug(slug ?? ""),
15250
+ kind: "static",
15251
+ platform: resolvePlatform(args.platform ? String(args.platform) : void 0),
15252
+ formats: resolveFormats(args.aspect ? String(args.aspect) : report.aspect_ratio),
15253
+ sourceReferenceUrl: imageIsUrl ? imageSource : void 0,
15254
+ sourceAdvertiser: args.advertiser ? String(args.advertiser) : args.context ? String(args.context) : void 0,
15255
+ sourceKind: "image",
15256
+ sourcePath: sourceRelPath,
15257
+ description: describeBlueprintIntent(blueprint)
15258
+ }),
15259
+ "utf8"
15260
+ );
15261
+ }
15152
15262
  process.stdout.write(
15153
15263
  `${JSON.stringify(
15154
15264
  {
15155
15265
  ok: true,
15156
15266
  canvas_path: outPath,
15157
15267
  prompt_path: blueprintPath,
15268
+ definition_path: definitionPath ?? void 0,
15269
+ source_reference: sourceRelPath ?? void 0,
15158
15270
  output: canvas.output,
15159
15271
  models: { describe: describeModel, select: selectModel, layout: layoutModel, gen: opts.genModel },
15160
15272
  aspect_ratio: report.aspect_ratio,
@@ -15165,7 +15277,7 @@ var scaffoldStaticAdCommand = defineCommand89({
15165
15277
  run_estimated_credits: validation.estimatedCredits
15166
15278
  },
15167
15279
  checklist: {
15168
- edit_prompt: `Edit ${path6.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.`,
15280
+ 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.`,
15169
15281
  assets_to_supply: report.elements,
15170
15282
  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)",
15171
15283
  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."
@@ -15180,8 +15292,8 @@ var scaffoldStaticAdCommand = defineCommand89({
15180
15292
  });
15181
15293
 
15182
15294
  // src/commands/canvas/scaffold-video.ts
15183
- import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
15184
- import path9 from "path";
15295
+ import { cp as cp2, mkdir as mkdir2, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
15296
+ import path11 from "path";
15185
15297
  import { defineCommand as defineCommand90 } from "citty";
15186
15298
 
15187
15299
  // src/engine/nodes/local/lib/sceneDetect.ts
@@ -15298,7 +15410,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
15298
15410
  import { toCardinal as nwNl } from "n2words/nl-NL";
15299
15411
  import { toCardinal as nwPl } from "n2words/pl-PL";
15300
15412
  import { toCardinal as nwPt } from "n2words/pt-PT";
15301
- import { z as z13 } from "zod";
15413
+ import { z as z12 } from "zod";
15302
15414
 
15303
15415
  // src/engine/scaffold/lib/shoot-modes.ts
15304
15416
  var SHOOT_MODES = [
@@ -15611,71 +15723,71 @@ function trimArgs(durationS, offsetS = 0, dims) {
15611
15723
  "{{out.video}}"
15612
15724
  ];
15613
15725
  }
15614
- var FrameAsset = z13.object({ url: z13.string().optional() }).loose().optional();
15615
- var DialogueLine = z13.object({
15616
- speaker: z13.string().optional(),
15617
- line: z13.string().optional(),
15726
+ var FrameAsset = z12.object({ url: z12.string().optional() }).loose().optional();
15727
+ var DialogueLine = z12.object({
15728
+ speaker: z12.string().optional(),
15729
+ line: z12.string().optional(),
15618
15730
  // Absolute seconds on the source timeline (the deconstruct emits both).
15619
- start_s: z13.number().optional(),
15620
- end_s: z13.number().optional(),
15621
- delivery: z13.string().optional(),
15622
- voice_description: z13.string().optional(),
15731
+ start_s: z12.number().optional(),
15732
+ end_s: z12.number().optional(),
15733
+ delivery: z12.string().optional(),
15734
+ voice_description: z12.string().optional(),
15623
15735
  // DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element
15624
15736
  // presence alone can't answer that — a founder pictured in a polaroid close-up is
15625
15737
  // "present" yet the line is voiceover, and treating it as on-camera produced a
15626
15738
  // native Seedance lip-sync clip of a still photograph. `false` pins the line to
15627
15739
  // the VO path; absent keeps the presence-based decision (old blueprints).
15628
- on_camera: z13.boolean().optional()
15740
+ on_camera: z12.boolean().optional()
15629
15741
  }).loose();
15630
- var Sfx = z13.object({
15631
- at_s: z13.number().optional(),
15632
- duration_s: z13.number().optional(),
15633
- sound_effect_prompt: z13.string().optional(),
15634
- description: z13.string().optional()
15742
+ var Sfx = z12.object({
15743
+ at_s: z12.number().optional(),
15744
+ duration_s: z12.number().optional(),
15745
+ sound_effect_prompt: z12.string().optional(),
15746
+ description: z12.string().optional()
15635
15747
  }).loose();
15636
- var CompositionRegion = z13.object({
15748
+ var CompositionRegion = z12.object({
15637
15749
  // full | top | bottom | left | right | inset
15638
- panel: z13.string().optional(),
15750
+ panel: z12.string().optional(),
15639
15751
  // 9-grid anchor for an `inset` presenter box.
15640
- position: z13.string().optional(),
15641
- is_presenter: z13.boolean().optional(),
15752
+ position: z12.string().optional(),
15753
+ is_presenter: z12.boolean().optional(),
15642
15754
  // The cast id shown/speaking in this region (routes lip-sync + element refs).
15643
- cast_ref: z13.string().optional(),
15755
+ cast_ref: z12.string().optional(),
15644
15756
  // What the region's content IS: camera | screen_capture | static_graphic |
15645
15757
  // generated. Authoritative for routing when present (regex-over-prose fallback
15646
15758
  // otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the
15647
15759
  // overlay layer, never AI-generated.
15648
- kind: z13.string().optional(),
15760
+ kind: z12.string().optional(),
15649
15761
  // Opaque id naming the SPECIFIC on-screen document/note/app-state this
15650
15762
  // screen_capture region shows. Two scenes share it only when they show the SAME
15651
15763
  // recording continuing (scrolling/typing/waiting within it) — a genuinely
15652
15764
  // DIFFERENT document/note/recording (a source video splicing two screen captures)
15653
15765
  // gets a different id. Breaks a persistent-layout run into separate surface stubs
15654
15766
  // instead of asking the operator for one screenshot that can't cover both.
15655
- surface_id: z13.string().optional(),
15767
+ surface_id: z12.string().optional(),
15656
15768
  // Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style
15657
15769
  // presenter bubble inside a screen recording) — video-in-video the reproduction
15658
15770
  // must re-composite, not paint into the surface.
15659
- nested: z13.array(z13.object({}).loose()).optional(),
15660
- summary: z13.string().optional(),
15661
- frame_prompt: z13.string().optional(),
15662
- motion_prompt: z13.string().optional()
15771
+ nested: z12.array(z12.object({}).loose()).optional(),
15772
+ summary: z12.string().optional(),
15773
+ frame_prompt: z12.string().optional(),
15774
+ motion_prompt: z12.string().optional()
15663
15775
  }).loose();
15664
- var SceneComposition = z13.object({
15776
+ var SceneComposition = z12.object({
15665
15777
  // full_frame (default) | split_screen | pip | keyed_overlay
15666
- layout: z13.string().optional(),
15778
+ layout: z12.string().optional(),
15667
15779
  // split_screen only: vertical (top/bottom) | horizontal (left/right).
15668
- split_axis: z13.string().optional(),
15669
- regions: z13.array(CompositionRegion).optional()
15780
+ split_axis: z12.string().optional(),
15781
+ regions: z12.array(CompositionRegion).optional()
15670
15782
  }).loose();
15671
- var CameraMotion = z13.object({ movement: z13.string().optional(), detail: z13.string().optional() }).loose();
15672
- var TranscriptWord = z13.object({ text: z13.string().optional() }).loose();
15673
- var Scene = z13.object({
15674
- start_s: z13.number().optional(),
15675
- end_s: z13.number().optional(),
15676
- duration_s: z13.number().optional(),
15677
- summary: z13.string().optional(),
15678
- action_detail: z13.string().optional(),
15783
+ var CameraMotion = z12.object({ movement: z12.string().optional(), detail: z12.string().optional() }).loose();
15784
+ var TranscriptWord = z12.object({ text: z12.string().optional() }).loose();
15785
+ var Scene = z12.object({
15786
+ start_s: z12.number().optional(),
15787
+ end_s: z12.number().optional(),
15788
+ duration_s: z12.number().optional(),
15789
+ summary: z12.string().optional(),
15790
+ action_detail: z12.string().optional(),
15679
15791
  // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
15680
15792
  // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
15681
15793
  // builds one clip per region and stacks/overlays them into the scene picture.
@@ -15683,82 +15795,82 @@ var Scene = z13.object({
15683
15795
  // The capture "look" for this scene — selected from the ad-native shoot-mode
15684
15796
  // grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
15685
15797
  // UGC/product mode; a human can override per scene by setting this.
15686
- shoot_mode: z13.string().optional(),
15798
+ shoot_mode: z12.string().optional(),
15687
15799
  // Diegetic ambient the clip's native audio should carry (no music). When
15688
15800
  // absent the scene falls back to its shoot mode's default ambience.
15689
- ambient: z13.string().optional(),
15801
+ ambient: z12.string().optional(),
15690
15802
  camera_motion: CameraMotion.optional(),
15691
- start_frame_prompt: z13.string().optional(),
15692
- end_frame_prompt: z13.string().optional(),
15693
- motion_prompt: z13.string().optional(),
15803
+ start_frame_prompt: z12.string().optional(),
15804
+ end_frame_prompt: z12.string().optional(),
15805
+ motion_prompt: z12.string().optional(),
15694
15806
  // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
15695
15807
  // script re-craft checklist. Inferred from position when absent.
15696
- narrative_role: z13.string().optional(),
15808
+ narrative_role: z12.string().optional(),
15697
15809
  // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
15698
15810
  // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
15699
15811
  // into the hook's start-frame description so the generator renders that state,
15700
15812
  // not a calm influencer (CCA-11).
15701
- hook_mechanic: z13.object({ mechanic: z13.string().optional(), why_it_stops_scroll: z13.string().optional() }).loose().optional(),
15813
+ hook_mechanic: z12.object({ mechanic: z12.string().optional(), why_it_stops_scroll: z12.string().optional() }).loose().optional(),
15702
15814
  // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
15703
- scene_setting: z13.string().optional(),
15815
+ scene_setting: z12.string().optional(),
15704
15816
  // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
15705
15817
  // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
15706
15818
  // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
15707
15819
  // ignored (nothing follows it).
15708
- transition_out: z13.object({ type: z13.string().optional(), description: z13.string().optional() }).loose().optional(),
15709
- dialogue: z13.array(DialogueLine).optional(),
15710
- sfx: z13.array(Sfx).optional(),
15711
- overlays: z13.array(z13.unknown()).optional(),
15712
- floating_elements: z13.array(z13.unknown()).optional(),
15820
+ transition_out: z12.object({ type: z12.string().optional(), description: z12.string().optional() }).loose().optional(),
15821
+ dialogue: z12.array(DialogueLine).optional(),
15822
+ sfx: z12.array(Sfx).optional(),
15823
+ overlays: z12.array(z12.unknown()).optional(),
15824
+ floating_elements: z12.array(z12.unknown()).optional(),
15713
15825
  // DECON-supplied: how much the picture itself moves within the shot. Gates the
15714
15826
  // flash-hold optimization — a sub-2s b-roll flash with REAL subject motion
15715
15827
  // (pouring, spreading, hands working) must stay a real clip; freezing it turns
15716
15828
  // a montage into a slideshow. Absent (old blueprints) keeps the cheap still.
15717
- motion_level: z13.enum(["static", "subtle", "dynamic"]).optional(),
15718
- transcript_slice: z13.array(TranscriptWord).optional(),
15829
+ motion_level: z12.enum(["static", "subtle", "dynamic"]).optional(),
15830
+ transcript_slice: z12.array(TranscriptWord).optional(),
15719
15831
  start_frame_asset: FrameAsset,
15720
15832
  end_frame_asset: FrameAsset,
15721
15833
  // DECON-supplied: true when this scene is a length-split CONTINUATION of the
15722
15834
  // previous one (the SAME physical shot, broken up only because it exceeded the
15723
15835
  // clip ceiling). The scaffold then shares the splice keyframe — this scene's
15724
15836
  // start frame IS the previous scene's end frame — so the join is seamless.
15725
- continues_previous: z13.boolean().optional()
15837
+ continues_previous: z12.boolean().optional()
15726
15838
  }).loose();
15727
- var VideoBlueprint = z13.object({
15728
- source: z13.object({ aspect_ratio: z13.string().optional(), duration_s: z13.number().optional() }).loose().optional(),
15729
- global: z13.object({
15730
- music: z13.object({
15731
- present: z13.boolean().optional(),
15732
- music_prompt: z13.string().optional(),
15839
+ var VideoBlueprint = z12.object({
15840
+ source: z12.object({ aspect_ratio: z12.string().optional(), duration_s: z12.number().optional() }).loose().optional(),
15841
+ global: z12.object({
15842
+ music: z12.object({
15843
+ present: z12.boolean().optional(),
15844
+ music_prompt: z12.string().optional(),
15733
15845
  // Absolute second the music enters in the reference (the bed often
15734
15846
  // kicks in mid-ad, after the hook). We start the regenerated track here
15735
15847
  // instead of at 0 so the timing matches.
15736
- starts_at_s: z13.number().optional(),
15848
+ starts_at_s: z12.number().optional(),
15737
15849
  // Populated by the deconstruct when AudD (Shazam-style) recognizes the
15738
15850
  // reference track. We never reuse it — only style the regenerated bed.
15739
- identified_track: z13.object({ title: z13.string().optional(), artist: z13.string().optional() }).loose().nullish()
15851
+ identified_track: z12.object({ title: z12.string().optional(), artist: z12.string().optional() }).loose().nullish()
15740
15852
  }).loose().optional(),
15741
- cast: z13.array(
15742
- z13.object({
15743
- id: z13.string().optional(),
15744
- description: z13.string().optional(),
15853
+ cast: z12.array(
15854
+ z12.object({
15855
+ id: z12.string().optional(),
15856
+ description: z12.string().optional(),
15745
15857
  // The deconstruct's note on the target-market localization (e.g. "native
15746
15858
  // French speaker") — read to derive the spoken-track language code.
15747
- market_localization_note: z13.string().optional()
15859
+ market_localization_note: z12.string().optional()
15748
15860
  }).loose()
15749
15861
  ).optional(),
15750
- voiceover: z13.object({
15862
+ voiceover: z12.object({
15751
15863
  // on_camera | mixed → mouths are on screen (lip-sync candidates);
15752
15864
  // voiceover | none → narration over the picture (no lip-sync).
15753
- mode: z13.string().optional(),
15754
- voice_description: z13.string().optional(),
15755
- persona: z13.string().optional()
15865
+ mode: z12.string().optional(),
15866
+ voice_description: z12.string().optional(),
15867
+ persona: z12.string().optional()
15756
15868
  }).loose().optional(),
15757
15869
  // Visual palette — read only to colour a clean brand-card/CTA plate (the
15758
15870
  // first hex is the dominant brand colour); never to drive frame generation.
15759
- style: z13.object({ palette: z13.array(z13.object({ hex: z13.string().optional() }).loose()).optional() }).loose().optional()
15871
+ style: z12.object({ palette: z12.array(z12.object({ hex: z12.string().optional() }).loose()).optional() }).loose().optional()
15760
15872
  }).loose().optional(),
15761
- scenes: z13.array(Scene).min(1)
15873
+ scenes: z12.array(Scene).min(1)
15762
15874
  }).loose();
15763
15875
  function injectHookPhysicality(blueprint) {
15764
15876
  for (const scene of blueprint.scenes) {
@@ -15768,26 +15880,26 @@ function injectHookPhysicality(blueprint) {
15768
15880
  scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
15769
15881
  }
15770
15882
  }
15771
- var AppearsItem = z13.union([z13.number(), z13.object({ scene: z13.number(), edge: z13.string().optional() }).loose()]);
15772
- var RecurringElement = z13.object({
15883
+ var AppearsItem = z12.union([z12.number(), z12.object({ scene: z12.number(), edge: z12.string().optional() }).loose()]);
15884
+ var RecurringElement = z12.object({
15773
15885
  // person | animal | product | logo | badge | other
15774
- type: z13.string(),
15775
- label: z13.string().optional(),
15776
- description: z13.string().optional(),
15777
- expression: z13.string().nullable().optional(),
15886
+ type: z12.string(),
15887
+ label: z12.string().optional(),
15888
+ description: z12.string().optional(),
15889
+ expression: z12.string().nullable().optional(),
15778
15890
  // When the element maps to a global cast entry, its stable id (for annotation).
15779
- cast_id: z13.string().nullable().optional(),
15891
+ cast_id: z12.string().nullable().optional(),
15780
15892
  // The label of another element that is the SAME individual as this one, shown
15781
15893
  // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
15782
15894
  // pink shirt and believer in a white shirt). Each look gets its own reference
15783
15895
  // slot, but the face/identity must stay identical across them.
15784
- same_as: z13.string().nullable().optional(),
15896
+ same_as: z12.string().nullable().optional(),
15785
15897
  // Scenes the element appears in. Either a bare list of scene indices (both
15786
15898
  // edges) or per-{scene,edge} entries. Both forms are accepted and merged.
15787
- scenes: z13.array(z13.number()).optional(),
15788
- appears_in: z13.array(AppearsItem).optional()
15899
+ scenes: z12.array(z12.number()).optional(),
15900
+ appears_in: z12.array(AppearsItem).optional()
15789
15901
  }).loose();
15790
- var RecurringElements = z13.array(RecurringElement);
15902
+ var RecurringElements = z12.array(RecurringElement);
15791
15903
  function sanitizeId2(raw, fallback) {
15792
15904
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
15793
15905
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -16205,7 +16317,7 @@ function scrubFloatSentences(text, floatDescs) {
16205
16317
  return kept;
16206
16318
  }
16207
16319
  function sceneFloatDescs(scene) {
16208
- const floats = z13.array(FloatingElement).safeParse(scene.floating_elements ?? []);
16320
+ const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
16209
16321
  if (!floats.success) return [];
16210
16322
  return floats.data.map((f) => f.description?.trim() ?? "").filter(Boolean);
16211
16323
  }
@@ -17545,25 +17657,25 @@ function buildSfxMusic(blueprint, nodes) {
17545
17657
  }
17546
17658
  return tracks;
17547
17659
  }
17548
- var OverlayStyle = z13.object({ color_hex: z13.string().optional(), background: z13.string().optional(), size: z13.string().optional() }).loose();
17549
- var Overlay = z13.object({
17550
- text: z13.string().optional(),
17551
- appears_at_s: z13.number().optional(),
17552
- duration_s: z13.number().optional(),
17553
- position: z13.string().optional(),
17554
- role: z13.string().optional(),
17555
- animation: z13.string().optional(),
17556
- animation_detail: z13.string().optional(),
17660
+ var OverlayStyle = z12.object({ color_hex: z12.string().optional(), background: z12.string().optional(), size: z12.string().optional() }).loose();
17661
+ var Overlay = z12.object({
17662
+ text: z12.string().optional(),
17663
+ appears_at_s: z12.number().optional(),
17664
+ duration_s: z12.number().optional(),
17665
+ position: z12.string().optional(),
17666
+ role: z12.string().optional(),
17667
+ animation: z12.string().optional(),
17668
+ animation_detail: z12.string().optional(),
17557
17669
  style: OverlayStyle.optional()
17558
17670
  }).loose();
17559
- var FloatingElement = z13.object({
17560
- kind: z13.string().optional(),
17561
- description: z13.string().optional(),
17562
- brand_name: z13.string().nullish(),
17563
- what_it_represents: z13.string().optional(),
17564
- appears_at_s: z13.number().optional(),
17565
- duration_s: z13.number().optional(),
17566
- position: z13.string().optional()
17671
+ var FloatingElement = z12.object({
17672
+ kind: z12.string().optional(),
17673
+ description: z12.string().optional(),
17674
+ brand_name: z12.string().nullish(),
17675
+ what_it_represents: z12.string().optional(),
17676
+ appears_at_s: z12.number().optional(),
17677
+ duration_s: z12.number().optional(),
17678
+ position: z12.string().optional()
17567
17679
  }).loose();
17568
17680
  function escapeHtml(s) {
17569
17681
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -17595,7 +17707,7 @@ function positionClass(position) {
17595
17707
  function collectCaptions(blueprint) {
17596
17708
  return blueprint.scenes.flatMap((scene) => {
17597
17709
  const sceneStart = scene.start_s ?? 0;
17598
- const overlays = z13.array(Overlay).safeParse(scene.overlays ?? []);
17710
+ const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
17599
17711
  return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
17600
17712
  const at = ov.appears_at_s ?? sceneStart;
17601
17713
  return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
@@ -17675,7 +17787,7 @@ function collectFloatWindows(blueprint, uiRouted) {
17675
17787
  const windows = /* @__PURE__ */ new Map();
17676
17788
  blueprint.scenes.forEach((scene, i) => {
17677
17789
  const sceneStart = scene.start_s ?? 0;
17678
- const floats = z13.array(FloatingElement).safeParse(scene.floating_elements ?? []);
17790
+ const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
17679
17791
  if (!floats.success) return;
17680
17792
  for (const fe of floats.data) {
17681
17793
  const at = fe.appears_at_s ?? sceneStart;
@@ -18061,8 +18173,8 @@ function buildMotionBoard(blueprint) {
18061
18173
  const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
18062
18174
  cursor = end_s;
18063
18175
  const spoken = sceneSpokenText(scene);
18064
- const overlays = z13.array(Overlay).safeParse(scene.overlays ?? []);
18065
- const floats = z13.array(FloatingElement).safeParse(scene.floating_elements ?? []);
18176
+ const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
18177
+ const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
18066
18178
  const graphics = [
18067
18179
  ...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
18068
18180
  kind: "text",
@@ -18289,23 +18401,23 @@ function videoReport(input, elementsInput) {
18289
18401
 
18290
18402
  // src/commands/canvas/composition-path.ts
18291
18403
  import { existsSync as existsSync3 } from "fs";
18292
- import path7 from "path";
18404
+ import path9 from "path";
18293
18405
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
18294
- const rel = path7.join("canvas", name);
18406
+ const rel = path9.join("canvas", name);
18295
18407
  let dir = startDir;
18296
18408
  for (let i = 0; i < maxDepth; i++) {
18297
- const candidate = path7.join(dir, rel);
18298
- if (exists(path7.join(candidate, "meta.json"))) return candidate;
18299
- const parent = path7.dirname(dir);
18409
+ const candidate = path9.join(dir, rel);
18410
+ if (exists(path9.join(candidate, "meta.json"))) return candidate;
18411
+ const parent = path9.dirname(dir);
18300
18412
  if (parent === dir) break;
18301
18413
  dir = parent;
18302
18414
  }
18303
- return path7.resolve(startDir, "../../../", rel);
18415
+ return path9.resolve(startDir, "../../../", rel);
18304
18416
  }
18305
18417
 
18306
18418
  // src/commands/canvas/gitignore.ts
18307
18419
  import { appendFile, readFile as readFile5 } from "fs/promises";
18308
- import path8 from "path";
18420
+ import path10 from "path";
18309
18421
  function missingGitignoreEntries(existing, entries) {
18310
18422
  const present = new Set(
18311
18423
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -18313,7 +18425,7 @@ function missingGitignoreEntries(existing, entries) {
18313
18425
  return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
18314
18426
  }
18315
18427
  async function ensureGitignore(dir, entries) {
18316
- const file = path8.join(dir, ".gitignore");
18428
+ const file = path10.join(dir, ".gitignore");
18317
18429
  let existing;
18318
18430
  try {
18319
18431
  existing = await readFile5(file, "utf8");
@@ -18374,8 +18486,8 @@ async function loadTranscriptBestEffort(ref) {
18374
18486
  async function stageCaptions(outDir, transcript) {
18375
18487
  const text = transcript?.trim();
18376
18488
  if (!text || text === "[]") return {};
18377
- const compositionPath = path9.join(outDir, "tiktok-captions-composition");
18378
- await cp(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
18489
+ const compositionPath = path11.join(outDir, "tiktok-captions-composition");
18490
+ await cp2(SHIPPED_CAPTIONS_DIR, compositionPath, { recursive: true });
18379
18491
  return { compositionPath };
18380
18492
  }
18381
18493
  function patchCompositionMeta(metaJson, dims) {
@@ -18392,10 +18504,10 @@ function patchCompositionHtml(html, dims) {
18392
18504
  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`);
18393
18505
  }
18394
18506
  async function stampCompositionDims(compositionDir, dims) {
18395
- const metaPath = path9.join(compositionDir, "meta.json");
18507
+ const metaPath = path11.join(compositionDir, "meta.json");
18396
18508
  const rawMeta = await readFile6(metaPath, "utf8");
18397
18509
  await writeFile2(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
18398
- const htmlPath = path9.join(compositionDir, "index.html");
18510
+ const htmlPath = path11.join(compositionDir, "index.html");
18399
18511
  const rawHtml = await readFile6(htmlPath, "utf8");
18400
18512
  await writeFile2(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
18401
18513
  }
@@ -18535,6 +18647,10 @@ var scaffoldVideoCommand = defineCommand90({
18535
18647
  args: {
18536
18648
  file: { type: "positional", required: true, description: "Path to the reference video" },
18537
18649
  out: { type: "string", description: "Output canvas path (default <video-dir>/<name>.video.canvas.json)" },
18650
+ slug: {
18651
+ type: "string",
18652
+ description: "Creative slug \u2014 writes the canvas to src/creatives/<slug>/<slug>.canvas.json (repo convention)"
18653
+ },
18538
18654
  frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
18539
18655
  ambient: {
18540
18656
  type: "boolean",
@@ -18561,11 +18677,19 @@ var scaffoldVideoCommand = defineCommand90({
18561
18677
  }
18562
18678
  },
18563
18679
  async run({ args }) {
18564
- const videoPath = path9.resolve(String(args.file));
18565
- const base = path9.basename(videoPath, path9.extname(videoPath));
18566
- const outPath = args.out ? path9.resolve(String(args.out)) : path9.join(path9.dirname(videoPath), `${base}.video.canvas.json`);
18567
- const outDir = path9.dirname(outPath);
18568
- const blueprintPath = path9.join(outDir, "prompt.json");
18680
+ const videoPath = path11.resolve(String(args.file));
18681
+ const base = path11.basename(videoPath, path11.extname(videoPath));
18682
+ const slug = args.slug ? String(args.slug) : void 0;
18683
+ if (slug && !isValidScaffoldSlug(slug)) {
18684
+ process.stderr.write(
18685
+ `${JSON.stringify({ ok: false, error: { code: "invalid_slug", message: "--slug must be lowercase kebab (a-z, 0-9, hyphens), max 100 chars" } }, null, 2)}
18686
+ `
18687
+ );
18688
+ process.exit(2);
18689
+ }
18690
+ 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`);
18691
+ const outDir = path11.dirname(outPath);
18692
+ const blueprintPath = path11.join(outDir, "prompt.json");
18569
18693
  const frames = args.frames === "reuse" ? "reuse" : "generate";
18570
18694
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
18571
18695
  if (Number.isFinite(maxScenes)) {
@@ -18584,7 +18708,7 @@ var scaffoldVideoCommand = defineCommand90({
18584
18708
  shotCuts
18585
18709
  });
18586
18710
  const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
18587
- await mkdir(outDir, { recursive: true });
18711
+ await mkdir2(outDir, { recursive: true });
18588
18712
  const annotated = annotateBlueprintWithElements(blueprint, elements);
18589
18713
  await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
18590
18714
  `, "utf8");
@@ -18605,10 +18729,10 @@ var scaffoldVideoCommand = defineCommand90({
18605
18729
  `
18606
18730
  );
18607
18731
  }
18608
- const compositionDest = path9.join(outDir, "video-overlay-composition");
18609
- await cp(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
18732
+ const compositionDest = path11.join(outDir, "video-overlay-composition");
18733
+ await cp2(SHIPPED_COMPOSITION_DIR, compositionDest, { recursive: true });
18610
18734
  await stampCompositionDims(compositionDest, outDims);
18611
- const indexPath = path9.join(compositionDest, "index.html");
18735
+ const indexPath = path11.join(compositionDest, "index.html");
18612
18736
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
18613
18737
  const indexHtml = await readFile6(indexPath, "utf8");
18614
18738
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
@@ -18624,9 +18748,9 @@ var scaffoldVideoCommand = defineCommand90({
18624
18748
  const opts = {
18625
18749
  imageModel,
18626
18750
  videoModel,
18627
- overlayCompositionPath: path9.relative(outDir, compositionDest),
18628
- captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
18629
- blueprintPath: path9.relative(outDir, blueprintPath),
18751
+ overlayCompositionPath: path11.relative(outDir, compositionDest),
18752
+ captionsCompositionPath: captions.compositionPath ? path11.relative(outDir, captions.compositionPath) : void 0,
18753
+ blueprintPath: path11.relative(outDir, blueprintPath),
18630
18754
  frames,
18631
18755
  ambient: Boolean(args.ambient),
18632
18756
  ...args.aspect ? { aspect: String(args.aspect) } : {},
@@ -18684,7 +18808,7 @@ var scaffoldVideoCommand = defineCommand90({
18684
18808
  run_estimated_credits: validation.estimatedCredits
18685
18809
  },
18686
18810
  checklist: {
18687
- edit_prompt: `Edit ${path9.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.`,
18811
+ 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.`,
18688
18812
  recurring_elements_to_supply: report.elements,
18689
18813
  voices_to_confirm: report.dialogue.map((d) => ({
18690
18814
  scene: d.scene,
@@ -18711,7 +18835,7 @@ var scaffoldVideoCommand = defineCommand90({
18711
18835
 
18712
18836
  // src/commands/canvas/set-prompt.ts
18713
18837
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
18714
- import path10 from "path";
18838
+ import path12 from "path";
18715
18839
  import { defineCommand as defineCommand91 } from "citty";
18716
18840
  function setNodePrompt(canvas, nodeId, text) {
18717
18841
  const nodes = canvas?.nodes;
@@ -18739,7 +18863,7 @@ var setPromptCommand = defineCommand91({
18739
18863
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
18740
18864
  },
18741
18865
  async run({ args }) {
18742
- const filePath = path10.resolve(String(args.file));
18866
+ const filePath = path12.resolve(String(args.file));
18743
18867
  let canvas;
18744
18868
  try {
18745
18869
  canvas = JSON.parse(await readFile7(filePath, "utf8"));
@@ -18749,7 +18873,7 @@ var setPromptCommand = defineCommand91({
18749
18873
  process.exit(2);
18750
18874
  }
18751
18875
  let text;
18752
- if (args["text-file"]) text = await readFile7(path10.resolve(String(args["text-file"])), "utf8");
18876
+ if (args["text-file"]) text = await readFile7(path12.resolve(String(args["text-file"])), "utf8");
18753
18877
  else if (args.text !== void 0) text = String(args.text);
18754
18878
  else {
18755
18879
  process.stderr.write(
@@ -18770,7 +18894,7 @@ var setPromptCommand = defineCommand91({
18770
18894
  process.exit(2);
18771
18895
  return;
18772
18896
  }
18773
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
18897
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path12.dirname(filePath)), defaultRegistry());
18774
18898
  if (!validation.ok) {
18775
18899
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
18776
18900
  `);
@@ -18786,7 +18910,7 @@ var setPromptCommand = defineCommand91({
18786
18910
 
18787
18911
  // src/commands/canvas/validate.ts
18788
18912
  import { readFile as readFile8 } from "fs/promises";
18789
- import path11 from "path";
18913
+ import path13 from "path";
18790
18914
  import { defineCommand as defineCommand92 } from "citty";
18791
18915
  var validateCommand = defineCommand92({
18792
18916
  meta: {
@@ -18795,7 +18919,7 @@ var validateCommand = defineCommand92({
18795
18919
  },
18796
18920
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
18797
18921
  async run({ args }) {
18798
- const filePath = path11.resolve(String(args.file));
18922
+ const filePath = path13.resolve(String(args.file));
18799
18923
  const raw = await readFile8(filePath, "utf8");
18800
18924
  let parsed;
18801
18925
  try {
@@ -18806,7 +18930,7 @@ var validateCommand = defineCommand92({
18806
18930
  `);
18807
18931
  process.exit(2);
18808
18932
  }
18809
- parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
18933
+ parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
18810
18934
  const result = await validateCanvasDeep(parsed, defaultRegistry());
18811
18935
  if (!result.ok) {
18812
18936
  process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
@@ -18943,6 +19067,16 @@ registerSchema({
18943
19067
  type: "string",
18944
19068
  description: "Optional URL of the original reference ad",
18945
19069
  required: false
19070
+ },
19071
+ slug: {
19072
+ type: "string",
19073
+ description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
19074
+ required: false
19075
+ },
19076
+ runId: {
19077
+ type: "string",
19078
+ description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
19079
+ required: false
18946
19080
  }
18947
19081
  }
18948
19082
  });
@@ -18952,6 +19086,13 @@ function detectCreativeContentType(filePath) {
18952
19086
  unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
18953
19087
  });
18954
19088
  }
19089
+ function chatIdFromEnv() {
19090
+ try {
19091
+ return getEnv().BAKER_CHAT_ID || void 0;
19092
+ } catch {
19093
+ return void 0;
19094
+ }
19095
+ }
18955
19096
  function parseOptionalUrl(value) {
18956
19097
  if (value === void 0 || value.trim() === "") {
18957
19098
  return void 0;
@@ -18982,7 +19123,11 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
18982
19123
  return publishImageAsCreative(deps, {
18983
19124
  imageId: upload.imageId,
18984
19125
  title,
18985
- sourceReferenceUrl
19126
+ sourceReferenceUrl,
19127
+ slug: args.slug,
19128
+ runId: args.runId,
19129
+ // Attribute the publish to the driving chat (injected by the bridge).
19130
+ chatId: chatIdFromEnv()
18986
19131
  });
18987
19132
  }
18988
19133
  var publishCommand = defineCommand94({
@@ -18998,6 +19143,16 @@ var publishCommand = defineCommand94({
18998
19143
  type: "string",
18999
19144
  description: "Optional URL of the original reference ad",
19000
19145
  required: false
19146
+ },
19147
+ slug: {
19148
+ type: "string",
19149
+ description: "Creative slug (src/creatives/<slug>/) \u2014 attaches the image to that creative's row",
19150
+ required: false
19151
+ },
19152
+ runId: {
19153
+ type: "string",
19154
+ description: "Canvas run id (r_\u2026) of the approved generation to pin as published",
19155
+ required: false
19001
19156
  }
19002
19157
  },
19003
19158
  run: async ({ args }) => {
@@ -19016,7 +19171,9 @@ var publishCommand = defineCommand94({
19016
19171
  file,
19017
19172
  title,
19018
19173
  context: args.context,
19019
- sourceReferenceUrl: args.sourceReferenceUrl
19174
+ sourceReferenceUrl: args.sourceReferenceUrl,
19175
+ slug: args.slug,
19176
+ runId: args.runId
19020
19177
  });
19021
19178
  writeJson({ ok: true, data });
19022
19179
  } catch (err) {
@@ -19914,9 +20071,9 @@ async function readImageBuffer(pathOrUrl) {
19914
20071
  }
19915
20072
  return readFile10(pathOrUrl);
19916
20073
  }
19917
- async function isDirectory(path12) {
20074
+ async function isDirectory(path14) {
19918
20075
  try {
19919
- const s = await stat2(path12);
20076
+ const s = await stat2(path14);
19920
20077
  return s.isDirectory();
19921
20078
  } catch {
19922
20079
  return false;
@@ -23978,338 +24135,11 @@ var schemaCommand = defineCommand147({
23978
24135
  }
23979
24136
  });
23980
24137
 
23981
- // src/commands/tags/index.ts
23982
- import { defineCommand as defineCommand148 } from "citty";
23983
-
23984
- // src/commands/tags/shared.ts
23985
- function failValidation3(message) {
23986
- writeJson({ ok: false, error: { code: "VALIDATION_ERROR", message } });
23987
- process.exit(1);
23988
- }
23989
- function failApi3(err) {
23990
- if (err instanceof ApiError) {
23991
- writeJson({ ok: false, error: { code: err.code, message: err.message } });
23992
- process.exit(1);
23993
- }
23994
- if (err instanceof Error) {
23995
- writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: err.message } });
23996
- process.exit(1);
23997
- }
23998
- writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
23999
- process.exit(1);
24000
- }
24001
- function parseTagType(value) {
24002
- const parsed = tagTypeSchema.safeParse(value);
24003
- if (!parsed.success) {
24004
- failValidation3(`Unknown tag type "${value}". Valid types: ${TAG_TYPES.join(", ")}.`);
24005
- }
24006
- return parsed.data;
24007
- }
24008
- function toArray(value) {
24009
- if (value === void 0 || typeof value === "boolean") {
24010
- return [];
24011
- }
24012
- return Array.isArray(value) ? value : [value];
24013
- }
24014
- function parseSetArgs(value) {
24015
- const config = {};
24016
- for (const entry of toArray(value)) {
24017
- const eq = entry.indexOf("=");
24018
- if (eq <= 0) {
24019
- failValidation3(`--set expects key=value, got "${entry}".`);
24020
- }
24021
- config[entry.slice(0, eq)] = entry.slice(eq + 1);
24022
- }
24023
- return config;
24024
- }
24025
- function parseListArg(value) {
24026
- return toArray(value).flatMap(
24027
- (entry) => entry.split(",").map((item) => item.trim()).filter((item) => item !== "")
24028
- );
24029
- }
24030
- function rejectSecretSets(type, config) {
24031
- const secretFields = TAG_SECRET_FIELDS[type];
24032
- const offending = Object.keys(config).filter((key) => secretFields.includes(key));
24033
- if (offending.length > 0) {
24034
- failValidation3(
24035
- `${offending.join(", ")} ${offending.length === 1 ? "is a secret field" : "are secret fields"} \u2014 never pass secret values on the command line. Re-run with --request-secret ${offending[0]} and the user will provide it via the secure tag form in the chat.`
24036
- );
24037
- }
24038
- }
24039
- function validateRequestSecrets(type, fields) {
24040
- const requestable = TAG_REQUESTABLE_SECRET_FIELDS[type];
24041
- const invalid = fields.filter((field) => !requestable.includes(field));
24042
- if (invalid.length > 0) {
24043
- failValidation3(
24044
- `Cannot request ${invalid.join(", ")} for a ${type} tag. Requestable secret fields: ${requestable.length > 0 ? requestable.join(", ") : "(none \u2014 this type has no secret fields)"}.`
24045
- );
24046
- }
24047
- }
24048
- function renderEffectiveEntry(entry) {
24049
- const parts = [entry.ref, entry.type];
24050
- if (entry.identifier !== void 0) {
24051
- parts.push(entry.identifier);
24052
- }
24053
- if (entry.staged !== void 0) {
24054
- parts.push(`[staged: ${entry.staged}]`);
24055
- }
24056
- const secretBits = [
24057
- ...entry.secretsSet.map((field) => `${field} \u2713 set`),
24058
- ...entry.secretsPending.map((field) => `${field} \u23F3 pending`)
24059
- ];
24060
- if (secretBits.length > 0) {
24061
- parts.push(`[secrets: ${secretBits.join(", ")}]`);
24062
- }
24063
- return parts.join(" ");
24064
- }
24065
-
24066
- // src/commands/tags/index.ts
24067
- registerSchema({
24068
- command: "tags.list",
24069
- description: "Effective marketing tags for this chat: production tags overlaid with the ops staged in this chat's draft. The printed refs (tag ids or tag_temp_*) are exactly what flow side-effect tagIds should reference.",
24070
- args: {
24071
- json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
24072
- }
24073
- });
24074
- registerSchema({
24075
- command: "tags.add",
24076
- description: "Stage creation of a marketing tag (applies when the chat publishes). Set every non-secret field with --set; request secret fields (API keys, tokens, OAuth connections) with --request-secret \u2014 the user provides them via the secure tag form in the chat, never through the CLI.",
24077
- args: {
24078
- type: {
24079
- type: "positional",
24080
- description: "Tag type (see `baker tags list` output / meta, googleAnalytics, clarity, \u2026)",
24081
- required: true
24082
- },
24083
- set: { type: "string", description: "Repeatable key=value for non-secret config fields", required: false },
24084
- "request-secret": {
24085
- type: "string",
24086
- description: "Repeatable secret field name to request from the user",
24087
- required: false
24088
- }
24089
- }
24090
- });
24091
- registerSchema({
24092
- command: "tags.update",
24093
- description: "Stage an update to a tag by ref (real tag id, or tag_temp_* to amend a create staged in this chat). --set patches fields, --clear removes them, --request-secret asks the user for secret values.",
24094
- args: {
24095
- ref: { type: "positional", description: "Tag ref from `baker tags list`", required: true },
24096
- set: { type: "string", description: "Repeatable key=value for non-secret config fields", required: false },
24097
- clear: { type: "string", description: "Repeatable field name to clear", required: false },
24098
- "request-secret": {
24099
- type: "string",
24100
- description: "Repeatable secret field name to request from the user",
24101
- required: false
24102
- }
24103
- }
24104
- });
24105
- registerSchema({
24106
- command: "tags.remove",
24107
- description: "Stage deletion of a tag by ref (applies on publish). Removing a tag_temp_* ref drops the staged create instead.",
24108
- args: { ref: { type: "positional", description: "Tag ref from `baker tags list`", required: true } }
24109
- });
24110
- async function listTags(json) {
24111
- try {
24112
- const chatId = requireChatId();
24113
- const response = await apiPost("/api/tags/list", { chatId });
24114
- if (json) {
24115
- writeJson({ ok: true, data: response });
24116
- return;
24117
- }
24118
- if (response.tags.length === 0) {
24119
- process.stdout.write("No tags configured. Stage one with `baker tags add <type> --set key=value`.\n");
24120
- return;
24121
- }
24122
- process.stdout.write(`${response.tags.map(renderEffectiveEntry).join("\n")}
24123
- `);
24124
- } catch (err) {
24125
- failApi3(err);
24126
- }
24127
- }
24128
- var listCommand7 = defineCommand148({
24129
- meta: {
24130
- name: "list",
24131
- description: "Effective tags for this chat (production + staged). Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
24132
- },
24133
- args: { json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" } },
24134
- run: async ({ args }) => {
24135
- await listTags(args.json === true);
24136
- }
24137
- });
24138
- async function stage(body) {
24139
- try {
24140
- const response = await apiPost("/api/tags/draft/stage", body);
24141
- writeJson({ ok: true, data: response });
24142
- } catch (err) {
24143
- failApi3(err);
24144
- }
24145
- }
24146
- var addCommand2 = defineCommand148({
24147
- meta: {
24148
- name: "add",
24149
- description: "Stage a new tag (applies on publish). Secret fields are never passed here \u2014 use --request-secret and the user fills them in the chat's secure tag form. Example: baker tags add meta --set pixelId=123456 --request-secret accessToken"
24150
- },
24151
- args: {
24152
- type: {
24153
- type: "positional",
24154
- description: "Tag type (meta, googleAnalytics, googleAds, clarity, \u2026)",
24155
- required: true
24156
- },
24157
- set: { type: "string", description: "key=value for a non-secret config field (repeatable)" },
24158
- "request-secret": { type: "string", description: "Secret field name the user should provide (repeatable)" }
24159
- },
24160
- run: async ({ args }) => {
24161
- const type = parseTagType(args.type);
24162
- const config = parseSetArgs(args.set);
24163
- const requestSecrets = parseListArg(args["request-secret"]);
24164
- rejectSecretSets(type, config);
24165
- validateRequestSecrets(type, requestSecrets);
24166
- const chatId = requireChatId();
24167
- await stage({
24168
- kind: "create",
24169
- chatId,
24170
- type,
24171
- config,
24172
- ...requestSecrets.length > 0 ? { requestSecrets } : {}
24173
- });
24174
- }
24175
- });
24176
- var updateCommand3 = defineCommand148({
24177
- meta: {
24178
- name: "update",
24179
- description: "Stage an update to a tag. A tag_temp_* ref amends the create staged in this chat. Example: baker tags update <ref> --set pixelId=999 --clear testEventCode"
24180
- },
24181
- args: {
24182
- ref: { type: "positional", description: "Tag ref from `baker tags list`", required: true },
24183
- set: { type: "string", description: "key=value patch for a non-secret config field (repeatable)" },
24184
- clear: { type: "string", description: "Field name to clear (repeatable)" },
24185
- "request-secret": { type: "string", description: "Secret field name the user should provide (repeatable)" }
24186
- },
24187
- run: async ({ args }) => {
24188
- const config = parseSetArgs(args.set);
24189
- const clearFields = parseListArg(args.clear);
24190
- const requestSecrets = parseListArg(args["request-secret"]);
24191
- if (Object.keys(config).length === 0 && clearFields.length === 0 && requestSecrets.length === 0) {
24192
- failValidation3("Nothing to update \u2014 pass --set, --clear, or --request-secret.");
24193
- }
24194
- const chatId = requireChatId();
24195
- await stage({
24196
- kind: "update",
24197
- chatId,
24198
- ref: args.ref,
24199
- ...Object.keys(config).length > 0 ? { config } : {},
24200
- ...clearFields.length > 0 ? { clearFields } : {},
24201
- ...requestSecrets.length > 0 ? { requestSecrets } : {}
24202
- });
24203
- }
24204
- });
24205
- var removeCommand5 = defineCommand148({
24206
- meta: {
24207
- name: "remove",
24208
- description: "Stage deletion of a tag (applies on publish). Removing a tag_temp_* ref drops the staged create instead. Example: baker tags remove <ref>"
24209
- },
24210
- args: { ref: { type: "positional", description: "Tag ref from `baker tags list`", required: true } },
24211
- run: async ({ args }) => {
24212
- const chatId = requireChatId();
24213
- await stage({ kind: "delete", chatId, ref: args.ref });
24214
- }
24215
- });
24216
- async function listDraft3() {
24217
- try {
24218
- const chatId = requireChatId();
24219
- const response = await apiPost("/api/tags/draft", { chatId });
24220
- writeJson({ ok: true, data: response });
24221
- } catch (err) {
24222
- failApi3(err);
24223
- }
24224
- }
24225
- var draftListCommand = defineCommand148({
24226
- meta: { name: "list", description: "Review the tag ops staged in this chat. Example: baker tags draft" },
24227
- run: async () => {
24228
- await listDraft3();
24229
- }
24230
- });
24231
- var draftRemoveCommand = defineCommand148({
24232
- meta: {
24233
- name: "remove",
24234
- description: "Drop one staged tag op by ref. Example: baker tags draft remove tag_temp_abc123"
24235
- },
24236
- args: { ref: { type: "positional", description: "Staged op ref", required: true } },
24237
- run: async ({ args }) => {
24238
- try {
24239
- const chatId = requireChatId();
24240
- const response = await apiPost("/api/tags/draft/remove", {
24241
- chatId,
24242
- ref: args.ref
24243
- });
24244
- writeJson({ ok: true, data: response });
24245
- } catch (err) {
24246
- failApi3(err);
24247
- }
24248
- }
24249
- });
24250
- var draftClearCommand = defineCommand148({
24251
- meta: {
24252
- name: "clear",
24253
- description: "Drop ALL tag ops staged in this chat \u2014 nothing will apply on publish. Example: baker tags draft clear"
24254
- },
24255
- run: async () => {
24256
- try {
24257
- const chatId = requireChatId();
24258
- const response = await apiPost("/api/tags/draft/clear", { chatId });
24259
- writeJson({ ok: true, data: response });
24260
- } catch (err) {
24261
- failApi3(err);
24262
- }
24263
- }
24264
- });
24265
- var draftCommand3 = defineCommand148({
24266
- meta: {
24267
- name: "draft",
24268
- description: "Review and edit the tag ops staged in this chat BEFORE publish. Subcommands: list (default), remove, clear. Ops never touch production tags until the chat is published."
24269
- },
24270
- subCommands: {
24271
- list: draftListCommand,
24272
- remove: draftRemoveCommand,
24273
- clear: draftClearCommand
24274
- },
24275
- run: async () => {
24276
- await listDraft3();
24277
- }
24278
- });
24279
- var tagsCommand3 = defineCommand148({
24280
- meta: {
24281
- name: "tags",
24282
- description: `Manage the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) as per-chat STAGED changes \u2014 nothing touches production until the chat is published.
24283
-
24284
- Secrets: secret fields (accessToken, apiSecret, authorizationToken, apiKey, conversionToken, oauthProviderId) are NEVER typed into chat or passed to this CLI. Stage with --request-secret <field>, then invoke the request_tag_input tool (baker_ui) so the user fills them in the dashboard's secure tag form.
24285
-
24286
- 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.
24287
-
24288
- Examples:
24289
- baker tags list # production + staged, with secret status
24290
- baker tags add clarity --set projectId=abcde12345 # client-only tag, no secrets needed
24291
- baker tags add meta --set pixelId=123 --request-secret accessToken
24292
- baker tags update <ref> --set pixelId=999 --clear testEventCode
24293
- baker tags remove <ref> # stage deletion (temp ref = drop the create)
24294
- baker tags draft # review staged ops before finishing`
24295
- },
24296
- subCommands: {
24297
- list: listCommand7,
24298
- add: addCommand2,
24299
- update: updateCommand3,
24300
- remove: removeCommand5,
24301
- draft: draftCommand3
24302
- },
24303
- run: async () => {
24304
- await listTags(false);
24305
- }
24306
- });
24307
-
24308
24138
  // src/commands/testimonials/index.ts
24309
- import { defineCommand as defineCommand152 } from "citty";
24139
+ import { defineCommand as defineCommand151 } from "citty";
24310
24140
 
24311
24141
  // src/commands/testimonials/get.ts
24312
- import { defineCommand as defineCommand149 } from "citty";
24142
+ import { defineCommand as defineCommand148 } from "citty";
24313
24143
  registerSchema({
24314
24144
  command: "testimonials.get",
24315
24145
  description: "Get a single testimonial by ID",
@@ -24317,7 +24147,7 @@ registerSchema({
24317
24147
  id: { type: "string", description: "Testimonial ID", required: true }
24318
24148
  }
24319
24149
  });
24320
- var getCommand4 = defineCommand149({
24150
+ var getCommand4 = defineCommand148({
24321
24151
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
24322
24152
  args: {
24323
24153
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -24354,7 +24184,7 @@ var getCommand4 = defineCommand149({
24354
24184
  });
24355
24185
 
24356
24186
  // src/commands/testimonials/list.ts
24357
- import { defineCommand as defineCommand150 } from "citty";
24187
+ import { defineCommand as defineCommand149 } from "citty";
24358
24188
  registerSchema({
24359
24189
  command: "testimonials.list",
24360
24190
  description: "List testimonials with optional filters.",
@@ -24384,7 +24214,7 @@ registerSchema({
24384
24214
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
24385
24215
  }
24386
24216
  });
24387
- var listCommand8 = defineCommand150({
24217
+ var listCommand7 = defineCommand149({
24388
24218
  meta: {
24389
24219
  name: "list",
24390
24220
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -24433,7 +24263,7 @@ var listCommand8 = defineCommand150({
24433
24263
  });
24434
24264
 
24435
24265
  // src/commands/testimonials/search.ts
24436
- import { defineCommand as defineCommand151 } from "citty";
24266
+ import { defineCommand as defineCommand150 } from "citty";
24437
24267
  registerSchema({
24438
24268
  command: "testimonials.search",
24439
24269
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -24464,7 +24294,7 @@ registerSchema({
24464
24294
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
24465
24295
  }
24466
24296
  });
24467
- var searchCommand2 = defineCommand151({
24297
+ var searchCommand2 = defineCommand150({
24468
24298
  meta: {
24469
24299
  name: "search",
24470
24300
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -24535,10 +24365,10 @@ var searchCommand2 = defineCommand151({
24535
24365
  });
24536
24366
 
24537
24367
  // src/commands/testimonials/tags.ts
24538
- var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
24368
+ var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
24539
24369
 
24540
24370
  // src/commands/testimonials/index.ts
24541
- var testimonialsCommand = defineCommand152({
24371
+ var testimonialsCommand = defineCommand151({
24542
24372
  meta: {
24543
24373
  name: "testimonials",
24544
24374
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -24553,16 +24383,16 @@ Examples:
24553
24383
  subCommands: {
24554
24384
  get: getCommand4,
24555
24385
  search: searchCommand2,
24556
- list: listCommand8,
24557
- tags: tagsCommand4
24386
+ list: listCommand7,
24387
+ tags: tagsCommand3
24558
24388
  }
24559
24389
  });
24560
24390
 
24561
24391
  // src/commands/videos/index.ts
24562
- import { defineCommand as defineCommand157 } from "citty";
24392
+ import { defineCommand as defineCommand156 } from "citty";
24563
24393
 
24564
24394
  // src/commands/videos/delete.ts
24565
- import { defineCommand as defineCommand153 } from "citty";
24395
+ import { defineCommand as defineCommand152 } from "citty";
24566
24396
  registerSchema({
24567
24397
  command: "videos.delete",
24568
24398
  description: "Delete a video by ID",
@@ -24576,7 +24406,7 @@ registerSchema({
24576
24406
  }
24577
24407
  }
24578
24408
  });
24579
- var deleteCommand3 = defineCommand153({
24409
+ var deleteCommand3 = defineCommand152({
24580
24410
  meta: {
24581
24411
  name: "delete",
24582
24412
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -24617,7 +24447,7 @@ var deleteCommand3 = defineCommand153({
24617
24447
  });
24618
24448
 
24619
24449
  // src/commands/videos/get.ts
24620
- import { defineCommand as defineCommand154 } from "citty";
24450
+ import { defineCommand as defineCommand153 } from "citty";
24621
24451
  registerSchema({
24622
24452
  command: "videos.get",
24623
24453
  description: "Get a single video by ID",
@@ -24625,7 +24455,7 @@ registerSchema({
24625
24455
  id: { type: "string", description: "Video ID", required: true }
24626
24456
  }
24627
24457
  });
24628
- var getCommand5 = defineCommand154({
24458
+ var getCommand5 = defineCommand153({
24629
24459
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
24630
24460
  args: {
24631
24461
  id: { type: "positional", description: "Video ID", required: false },
@@ -24662,7 +24492,7 @@ var getCommand5 = defineCommand154({
24662
24492
  });
24663
24493
 
24664
24494
  // src/commands/videos/search.ts
24665
- import { defineCommand as defineCommand155 } from "citty";
24495
+ import { defineCommand as defineCommand154 } from "citty";
24666
24496
  registerSchema({
24667
24497
  command: "videos.search",
24668
24498
  description: "Search videos by text query. Only returns ready videos.",
@@ -24672,7 +24502,7 @@ registerSchema({
24672
24502
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
24673
24503
  }
24674
24504
  });
24675
- var searchCommand3 = defineCommand155({
24505
+ var searchCommand3 = defineCommand154({
24676
24506
  meta: {
24677
24507
  name: "search",
24678
24508
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -24719,12 +24549,12 @@ var searchCommand3 = defineCommand155({
24719
24549
  });
24720
24550
 
24721
24551
  // src/commands/videos/tags.ts
24722
- var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
24552
+ var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
24723
24553
 
24724
24554
  // src/commands/videos/upload.ts
24725
24555
  import { readFile as readFile12, stat as stat3 } from "fs/promises";
24726
24556
  import { extname as extname3 } from "path";
24727
- import { defineCommand as defineCommand156 } from "citty";
24557
+ import { defineCommand as defineCommand155 } from "citty";
24728
24558
  var MIME_MAP = {
24729
24559
  ".mp4": "video/mp4",
24730
24560
  ".mov": "video/quicktime",
@@ -24758,7 +24588,7 @@ function detectContentType(filePath) {
24758
24588
  }
24759
24589
  return mime;
24760
24590
  }
24761
- var uploadCommand2 = defineCommand156({
24591
+ var uploadCommand2 = defineCommand155({
24762
24592
  meta: {
24763
24593
  name: "upload",
24764
24594
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -24812,7 +24642,7 @@ var uploadCommand2 = defineCommand156({
24812
24642
  });
24813
24643
 
24814
24644
  // src/commands/videos/index.ts
24815
- var videosCommand = defineCommand157({
24645
+ var videosCommand = defineCommand156({
24816
24646
  meta: {
24817
24647
  name: "videos",
24818
24648
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -24830,15 +24660,15 @@ Examples:
24830
24660
  search: searchCommand3,
24831
24661
  upload: uploadCommand2,
24832
24662
  delete: deleteCommand3,
24833
- tags: tagsCommand5
24663
+ tags: tagsCommand4
24834
24664
  }
24835
24665
  });
24836
24666
 
24837
24667
  // src/commands/winning-ads/index.ts
24838
- import { defineCommand as defineCommand160 } from "citty";
24668
+ import { defineCommand as defineCommand159 } from "citty";
24839
24669
 
24840
24670
  // src/commands/winning-ads/advertisers.ts
24841
- import { defineCommand as defineCommand158 } from "citty";
24671
+ import { defineCommand as defineCommand157 } from "citty";
24842
24672
  registerSchema({
24843
24673
  command: "winning-ads.advertisers",
24844
24674
  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).",
@@ -24851,7 +24681,7 @@ registerSchema({
24851
24681
  function identity(record) {
24852
24682
  return record;
24853
24683
  }
24854
- var advertisersCommand2 = defineCommand158({
24684
+ var advertisersCommand2 = defineCommand157({
24855
24685
  meta: {
24856
24686
  name: "advertisers",
24857
24687
  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'
@@ -24902,7 +24732,7 @@ var advertisersCommand2 = defineCommand158({
24902
24732
  });
24903
24733
 
24904
24734
  // src/commands/winning-ads/search.ts
24905
- import { defineCommand as defineCommand159 } from "citty";
24735
+ import { defineCommand as defineCommand158 } from "citty";
24906
24736
  registerSchema({
24907
24737
  command: "winning-ads.search",
24908
24738
  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.",
@@ -25010,7 +24840,7 @@ function buildSearchBody(args) {
25010
24840
  }
25011
24841
  return body;
25012
24842
  }
25013
- var searchCommand4 = defineCommand159({
24843
+ var searchCommand4 = defineCommand158({
25014
24844
  meta: {
25015
24845
  name: "search",
25016
24846
  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"
@@ -25122,7 +24952,7 @@ var searchCommand4 = defineCommand159({
25122
24952
  });
25123
24953
 
25124
24954
  // src/commands/winning-ads/index.ts
25125
- var winningAdsCommand = defineCommand160({
24955
+ var winningAdsCommand = defineCommand159({
25126
24956
  meta: {
25127
24957
  name: "winning-ads",
25128
24958
  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.
@@ -25162,11 +24992,11 @@ function getCliVersion() {
25162
24992
  }
25163
24993
 
25164
24994
  // src/cli.ts
25165
- var main = defineCommand161({
24995
+ var main = defineCommand160({
25166
24996
  meta: {
25167
24997
  name: "baker",
25168
24998
  version: getCliVersion(),
25169
- description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, marketing tags, and ad platform data in Baker.
24999
+ description: `AI-agent CLI for finding and managing images, videos, testimonials, action items, scheduled actions, and ad platform data in Baker.
25170
25000
 
25171
25001
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
25172
25002
  Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
@@ -25186,7 +25016,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
25186
25016
  videos: videosCommand,
25187
25017
  testimonials: testimonialsCommand,
25188
25018
  canvas: canvasCommand,
25189
- tags: tagsCommand3,
25190
25019
  "winning-ads": winningAdsCommand,
25191
25020
  mcp: mcpCommand,
25192
25021
  schema: schemaCommand