@koda-sl/baker-cli 0.121.0-dev.36aef87f5 → 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,241 +1924,142 @@ var imagesIngestResponseSchema = z4.object({
1916
1924
  contentHash: z4.string()
1917
1925
  });
1918
1926
 
1919
- // ../api/src/tags.ts
1920
- import { z as z5 } from "zod";
1921
- var TAG_TYPES = [
1922
- "meta",
1923
- "amplitude",
1924
- "googleAds",
1925
- "tiktok",
1926
- "vwo",
1927
- "hotjar",
1928
- "clarity",
1929
- "pinterest",
1930
- "code",
1931
- "googleAnalytics",
1932
- "googleTagManager",
1933
- "hubspot",
1934
- "linkedinInsightTag",
1935
- "onetrust",
1936
- "posthog",
1937
- "datafast",
1938
- "recaptcha",
1939
- "twitterAds"
1940
- ];
1941
- var tagTypeSchema = z5.enum(TAG_TYPES);
1942
- var tagDraftOpKindSchema = z5.enum(["create", "update", "delete"]);
1943
- var tagDraftOpViewSchema = z5.object({
1944
- /** `tag_temp_*` for staged creates; the real tag id for update/delete ops. */
1945
- ref: z5.string(),
1946
- kind: tagDraftOpKindSchema,
1947
- type: tagTypeSchema,
1948
- /** Present on update/delete ops — the real tag this op targets. */
1949
- tagId: z5.string().optional(),
1950
- /** Non-secret config (create: full; update: the staged patch). Secrets are structurally absent. */
1951
- config: z5.record(z5.string(), z5.string()),
1952
- /** Update only — fields the op explicitly clears. */
1953
- clearFields: z5.array(z5.string()).optional(),
1954
- /** Names of secret fields already provided via the dashboard secure form. Never values. */
1955
- secretsSet: z5.array(z5.string()),
1956
- /** Names of secret fields still awaiting user input. */
1957
- secretsPending: z5.array(z5.string()),
1958
- summary: z5.string(),
1959
- stagedAt: z5.number()
1960
- });
1961
- var tagsEffectiveEntrySchema = z5.object({
1962
- /** Real tag id, or `tag_temp_*` for staged creates. Use as flow side-effect `tagIds` value. */
1963
- ref: z5.string(),
1964
- tagId: z5.string().optional(),
1965
- type: tagTypeSchema,
1966
- /** Value of the type's identifying field, when set. */
1967
- identifier: z5.string().optional(),
1968
- /** Redacted config; for staged updates, production config with the patch merged. */
1969
- config: z5.record(z5.string(), z5.string()),
1970
- /** Absent = live production tag with no staged changes in this chat. */
1971
- staged: tagDraftOpKindSchema.optional(),
1972
- secretsSet: z5.array(z5.string()),
1973
- secretsPending: z5.array(z5.string())
1974
- });
1975
- var tagsListRequestSchema = z5.object({ chatId: z5.string() });
1976
- var tagsListResponseSchema = z5.object({ tags: z5.array(tagsEffectiveEntrySchema) });
1977
- var tagsDraftListRequestSchema = z5.object({ chatId: z5.string() });
1978
- var tagsDraftListResponseSchema = z5.object({
1979
- status: z5.enum(["active", "publishing", "applied", "discarded", "none"]),
1980
- ops: z5.array(tagDraftOpViewSchema)
1981
- });
1982
- var tagInputRequestSchema = z5.object({
1983
- // Every tag change is a tab in the approval form: create/edit show the full
1984
- // body; delete shows a confirm. No tag change bypasses this approval.
1985
- mode: z5.enum(["create", "edit", "delete"]),
1986
- tagType: tagTypeSchema,
1987
- /** Edit/delete mode — the real tag id or `tag_temp_*` ref being changed. */
1988
- ref: z5.string().optional(),
1989
- /** Non-secret values the agent proposes to prefill. Secret keys are stripped at every boundary. */
1990
- prefilledConfig: z5.record(z5.string(), z5.string()).optional(),
1991
- /** Secret field names the agent asks the user to provide. */
1992
- requestedSecretFields: z5.array(z5.string()).optional(),
1993
- /** Short message shown above the form explaining why the input is needed. */
1994
- message: z5.string().optional()
1995
- });
1996
- var tagChangeToolInputSchema = z5.object({
1997
- changes: z5.array(tagInputRequestSchema).min(1).max(8)
1998
- });
1999
- var tagInputResultSchema = z5.discriminatedUnion("status", [
2000
- z5.object({
2001
- status: z5.literal("submitted"),
2002
- ref: z5.string(),
2003
- type: tagTypeSchema,
2004
- /** Identifying field name → value (non-secret), when the type has one. */
2005
- identifier: z5.record(z5.string(), z5.string()).optional(),
2006
- secretFieldsSet: z5.array(z5.string()),
2007
- note: z5.string().optional()
2008
- }),
2009
- z5.object({
2010
- status: z5.literal("declined"),
2011
- reason: z5.string().optional()
2012
- })
2013
- ]);
2014
- var tagChangeToolResultSchema = z5.object({
2015
- results: z5.array(tagInputResultSchema)
2016
- });
2017
-
2018
1927
  // ../api/src/testimonials.ts
2019
- import { z as z6 } from "zod";
2020
- var testimonialSourceTypeSchema = z6.enum(["google", "trustpilot"]);
2021
- var testimonialStatusSchema = z6.enum(["pending", "processing", "ready", "error"]);
2022
- var testimonialSentimentSchema = z6.enum(["positive", "neutral", "negative"]);
2023
- var testimonialDocSchema = z6.object({
2024
- _id: z6.string(),
2025
- _creationTime: z6.number(),
2026
- companyId: z6.string(),
2027
- 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(),
2028
1937
  sourceType: testimonialSourceTypeSchema,
2029
- reviewText: z6.string(),
2030
- reviewTitle: z6.string().optional(),
2031
- searchText: z6.string().optional(),
2032
- reviewerName: z6.string().optional(),
2033
- reviewerImageUrl: z6.string().optional(),
2034
- reviewerImageId: z6.string().optional(),
2035
- reviewerLocation: z6.string().optional(),
2036
- rating: z6.number().optional(),
2037
- reviewDate: z6.number().optional(),
2038
- ownerAnswer: z6.string().optional(),
2039
- mediaUrls: z6.array(z6.string()).optional(),
2040
- imageIds: z6.array(z6.string()).optional(),
2041
- videoIds: z6.array(z6.string()).optional(),
2042
- sourceUrl: z6.string().optional(),
2043
- rawData: z6.unknown().optional(),
2044
- tags: z6.array(z6.string()),
2045
- highlight: z6.string().optional(),
2046
- language: z6.string().optional(),
2047
- 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(),
2048
1957
  sentiment: testimonialSentimentSchema.optional(),
2049
- textEmbedding: z6.array(z6.number()).optional(),
2050
- externalId: z6.string().optional(),
2051
- contentHash: z6.string().optional(),
1958
+ textEmbedding: z5.array(z5.number()).optional(),
1959
+ externalId: z5.string().optional(),
1960
+ contentHash: z5.string().optional(),
2052
1961
  status: testimonialStatusSchema,
2053
- errorMessage: z6.string().optional(),
2054
- createdAt: z6.number(),
2055
- updatedAt: z6.number()
1962
+ errorMessage: z5.string().optional(),
1963
+ createdAt: z5.number(),
1964
+ updatedAt: z5.number()
2056
1965
  });
2057
- var testimonialsListRequestSchema = z6.object({
1966
+ var testimonialsListRequestSchema = z5.object({
2058
1967
  source: testimonialSourceTypeSchema.optional(),
2059
- rating_min: z6.coerce.number().int().min(1).max(5).optional(),
2060
- rating_max: z6.coerce.number().int().min(1).max(5).optional(),
2061
- 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(),
2062
1971
  status: testimonialStatusSchema.optional(),
2063
1972
  sentiment: testimonialSentimentSchema.optional(),
2064
- language: z6.string().min(2).max(5).optional(),
2065
- limit: z6.coerce.number().int().positive().max(200).optional()
2066
- });
2067
- var testimonialsListResponseSchema = z6.array(testimonialDocSchema);
2068
- var testimonialsGetRequestSchema = z6.object({ id: z6.string().min(1, "Missing id parameter") });
2069
- var testimonialsSearchRequestSchema = z6.object({
2070
- query: z6.string().min(1),
2071
- 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(),
2072
1981
  source: testimonialSourceTypeSchema.optional(),
2073
- rating_min: z6.coerce.number().int().min(1).max(5).optional(),
2074
- rating_max: z6.coerce.number().int().min(1).max(5).optional(),
2075
- 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(),
2076
1985
  status: testimonialStatusSchema.optional(),
2077
1986
  sentiment: testimonialSentimentSchema.optional(),
2078
- language: z6.string().min(2).max(5).optional()
1987
+ language: z5.string().min(2).max(5).optional()
2079
1988
  }).refine(
2080
1989
  (data) => data.rating_min === void 0 || data.rating_max === void 0 || data.rating_min <= data.rating_max,
2081
1990
  { message: "rating_min must be less than or equal to rating_max" }
2082
1991
  );
2083
- var testimonialsSearchResponseSchema = z6.array(testimonialDocSchema);
2084
- var testimonialsOutscraperWebhookResponseSchema = z6.object({
2085
- ok: z6.literal(true),
2086
- 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()
2087
1996
  });
2088
1997
 
2089
1998
  // ../api/src/videos.ts
2090
- import { z as z7 } from "zod";
2091
- var videoStatusSchema = z7.enum(["uploading", "uploaded", "processing", "ready", "error"]);
2092
- var videoTranscriptSegmentSchema = z7.object({
2093
- text: z7.string(),
2094
- startSecond: z7.number(),
2095
- endSecond: z7.number()
2096
- });
2097
- var videoSceneSchema = z7.object({
2098
- title: z7.string(),
2099
- description: z7.string(),
2100
- startSecond: z7.number(),
2101
- endSecond: z7.number(),
2102
- thumbnailTime: z7.number()
2103
- });
2104
- var videoDocSchema = z7.object({
2105
- _id: z7.string(),
2106
- _creationTime: z7.number(),
2107
- companyId: z7.string(),
2108
- muxAssetId: z7.string(),
2109
- muxPlaybackId: z7.string(),
2110
- muxUploadId: z7.string(),
2111
- name: z7.string(),
2112
- description: z7.string(),
2113
- tags: z7.array(z7.string()),
2114
- source: z7.string(),
2115
- externalId: z7.string().optional(),
2116
- sourceId: z7.string().optional(),
2117
- width: z7.number().optional(),
2118
- height: z7.number().optional(),
2119
- aspectRatio: z7.number().optional(),
2120
- duration: z7.number().optional(),
2121
- transcript: z7.string().optional(),
2122
- transcriptSegments: z7.array(videoTranscriptSegmentSchema).optional(),
2123
- scenes: z7.array(videoSceneSchema).optional(),
2124
- descriptionEmbedding: z7.array(z7.number()).optional(),
2125
- 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(),
2126
2035
  status: videoStatusSchema,
2127
- errorMessage: z7.string().optional(),
2128
- createdAt: z7.number(),
2129
- updatedAt: z7.number(),
2130
- thumbnailUrl: z7.string()
2131
- });
2132
- var videosWebhookResponseSchema = z7.object({ ok: z7.literal(true) });
2133
- var videosGetRequestSchema = z7.object({ id: z7.string().min(1, "Missing id parameter") });
2134
- var videosSearchRequestSchema = z7.object({
2135
- query: z7.string().min(1),
2136
- limit: z7.coerce.number().int().positive().max(100).optional(),
2137
- tags: z7.array(z7.string()).optional()
2138
- });
2139
- var videoSearchResultSchema = z7.object({
2140
- _id: z7.string(),
2141
- thumbnailUrl: z7.string(),
2142
- name: z7.string(),
2143
- description: z7.string(),
2144
- tags: z7.array(z7.string()),
2145
- status: z7.string(),
2146
- duration: z7.number().optional(),
2147
- muxPlaybackId: z7.string(),
2148
- createdAt: z7.number()
2149
- });
2150
- var videosSearchResponseSchema = z7.array(videoSearchResultSchema);
2151
- var videosUploadResponseSchema = z7.object({ uploadUrl: z7.string(), videoId: z7.string() });
2152
- var videosDeleteRequestSchema = z7.object({ id: z7.string().min(1, "Missing video ID") });
2153
- 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) });
2154
2063
 
2155
2064
  // src/commands/actions/complete.ts
2156
2065
  import { defineCommand as defineCommand2 } from "citty";
@@ -3963,37 +3872,37 @@ var GEO_TARGET_CONSTANT_REGEX = /^geoTargetConstants\/\d+$/;
3963
3872
  var LANGUAGE_CONSTANT_REGEX = /^languageConstants\/\d+$/;
3964
3873
 
3965
3874
  // ../api/src/ads-google/ops.ts
3966
- import { z as z8 } from "zod";
3967
- var tempRefSchema2 = z8.string().regex(TEMP_REF_REGEX2, "expected a g_temp_* reference");
3968
- var refSchema = z8.union([
3969
- z8.string().regex(RESOURCE_NAME_REGEX, "expected a customers/\u2026/\u2026/\u2026 resource name"),
3970
- 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"),
3971
3880
  tempRefSchema2
3972
3881
  ]);
3973
3882
  var targetRefSchema = refSchema;
3974
- var microsSchema = z8.number().int().positive("expected a positive micros amount");
3975
- var httpsUrlSchema2 = z8.string().url().refine((u) => u.startsWith("https://"), "final URLs must be https");
3976
- var customerIdSchema = z8.string().regex(NUMERIC_ID_REGEX2, "customerId must be the bare numeric customer id");
3977
- var stageableStatusSchema2 = z8.enum(STAGEABLE_CREATE_STATUSES2);
3978
- var matchTypeSchema = z8.enum(KEYWORD_MATCH_TYPES);
3979
- 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");
3980
- var budgetCreateSchema = z8.object({
3981
- 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),
3982
3891
  amountMicros: microsSchema,
3983
- deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
3984
- explicitlyShared: z8.boolean().default(false)
3892
+ deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).default("STANDARD"),
3893
+ explicitlyShared: z7.boolean().default(false)
3985
3894
  });
3986
- var budgetUpdateSchema = z8.object({
3987
- 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(),
3988
3897
  amountMicros: microsSchema.optional(),
3989
- deliveryMethod: z8.enum(BUDGET_DELIVERY_METHODS).optional()
3898
+ deliveryMethod: z7.enum(BUDGET_DELIVERY_METHODS).optional()
3990
3899
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
3991
- var biddingConfigSchema = z8.object({
3992
- type: z8.enum(BIDDING_STRATEGY_TYPES),
3900
+ var biddingConfigSchema = z7.object({
3901
+ type: z7.enum(BIDDING_STRATEGY_TYPES),
3993
3902
  targetCpaMicros: microsSchema.optional(),
3994
- targetRoas: z8.number().positive().optional(),
3903
+ targetRoas: z7.number().positive().optional(),
3995
3904
  cpcBidCeilingMicros: microsSchema.optional(),
3996
- enhancedCpcEnabled: z8.boolean().optional()
3905
+ enhancedCpcEnabled: z7.boolean().optional()
3997
3906
  }).superRefine((p, ctx) => {
3998
3907
  if (p.type === "TARGET_CPA" && p.targetCpaMicros === void 0) {
3999
3908
  ctx.addIssue({ code: "custom", path: ["targetCpaMicros"], message: "TARGET_CPA needs targetCpaMicros" });
@@ -4002,17 +3911,17 @@ var biddingConfigSchema = z8.object({
4002
3911
  ctx.addIssue({ code: "custom", path: ["targetRoas"], message: "TARGET_ROAS needs targetRoas" });
4003
3912
  }
4004
3913
  });
4005
- var networkSettingsSchema = z8.object({
4006
- targetGoogleSearch: z8.boolean().optional(),
4007
- targetSearchNetwork: z8.boolean().optional(),
4008
- targetContentNetwork: z8.boolean().optional(),
4009
- 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()
4010
3919
  });
4011
- var dateSchema = z8.string().regex(/^\d{4}-\d{2}-\d{2}$/, "expected a YYYY-MM-DD date");
4012
- var campaignCreateSchema2 = z8.object({
4013
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.campaign.nameMax),
4014
- channelType: z8.enum(ADVERTISING_CHANNEL_TYPES),
4015
- 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(),
4016
3925
  budget: refSchema,
4017
3926
  /** Inline standard bidding, or a portfolio strategy ref via biddingStrategy. */
4018
3927
  bidding: biddingConfigSchema.optional(),
@@ -4021,7 +3930,7 @@ var campaignCreateSchema2 = z8.object({
4021
3930
  startDate: dateSchema.optional(),
4022
3931
  endDate: dateSchema.optional(),
4023
3932
  /** Advisory Google Ads UI objective — drives warnings, not sent to the API. */
4024
- objective: z8.enum(CAMPAIGN_OBJECTIVES).optional(),
3933
+ objective: z7.enum(CAMPAIGN_OBJECTIVES).optional(),
4025
3934
  status: stageableStatusSchema2.default("PAUSED")
4026
3935
  }).superRefine((p, ctx) => {
4027
3936
  if (!p.bidding && !p.biddingStrategy) {
@@ -4045,129 +3954,129 @@ var campaignCreateSchema2 = z8.object({
4045
3954
  ctx.addIssue({ code: "custom", path: ["endDate"], message: "endDate must be after startDate" });
4046
3955
  }
4047
3956
  });
4048
- var campaignUpdateSchema2 = z8.object({
4049
- 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(),
4050
3959
  budget: refSchema.optional(),
4051
3960
  bidding: biddingConfigSchema.optional(),
4052
3961
  networkSettings: networkSettingsSchema.optional(),
4053
3962
  startDate: dateSchema.optional(),
4054
3963
  endDate: dateSchema.optional(),
4055
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3964
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4056
3965
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4057
- var adGroupCreateSchema = z8.object({
4058
- 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),
4059
3968
  campaign: refSchema,
4060
- type: z8.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
3969
+ type: z7.enum(AD_GROUP_TYPES).default("SEARCH_STANDARD"),
4061
3970
  cpcBidMicros: microsSchema.optional(),
4062
3971
  status: stageableStatusSchema2.default("PAUSED")
4063
3972
  });
4064
- var adGroupUpdateSchema = z8.object({
4065
- 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(),
4066
3975
  cpcBidMicros: microsSchema.optional(),
4067
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3976
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4068
3977
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4069
- var keywordAddSchema = z8.object({
3978
+ var keywordAddSchema = z7.object({
4070
3979
  adGroup: refSchema,
4071
3980
  text: keywordTextSchema,
4072
3981
  matchType: matchTypeSchema,
4073
3982
  cpcBidMicros: microsSchema.optional(),
4074
- finalUrls: z8.array(httpsUrlSchema2).optional(),
3983
+ finalUrls: z7.array(httpsUrlSchema2).optional(),
4075
3984
  status: stageableStatusSchema2.default("ENABLED")
4076
3985
  });
4077
- var keywordUpdateSchema = z8.object({
3986
+ var keywordUpdateSchema = z7.object({
4078
3987
  cpcBidMicros: microsSchema.optional(),
4079
- finalUrls: z8.array(httpsUrlSchema2).optional(),
4080
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
3988
+ finalUrls: z7.array(httpsUrlSchema2).optional(),
3989
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional()
4081
3990
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4082
- var negativeKeywordAddSchema = z8.object({
4083
- level: z8.enum(["adGroup", "campaign"]),
3991
+ var negativeKeywordAddSchema = z7.object({
3992
+ level: z7.enum(["adGroup", "campaign"]),
4084
3993
  parent: refSchema,
4085
3994
  text: keywordTextSchema,
4086
3995
  matchType: matchTypeSchema
4087
3996
  });
4088
- var sharedSetCreateSchema = z8.object({
4089
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.sharedSet.nameMax),
4090
- 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")
4091
4000
  });
4092
- var sharedSetMemberAddSchema = z8.object({
4001
+ var sharedSetMemberAddSchema = z7.object({
4093
4002
  sharedSet: refSchema,
4094
4003
  text: keywordTextSchema,
4095
4004
  matchType: matchTypeSchema
4096
4005
  });
4097
- var campaignSharedSetAttachSchema = z8.object({
4006
+ var campaignSharedSetAttachSchema = z7.object({
4098
4007
  campaign: refSchema,
4099
4008
  sharedSet: refSchema
4100
4009
  });
4101
- var adTextAssetSchema = z8.object({
4102
- text: z8.string().min(1),
4103
- pinnedField: z8.enum(PINNED_FIELDS).optional()
4010
+ var adTextAssetSchema = z7.object({
4011
+ text: z7.string().min(1),
4012
+ pinnedField: z7.enum(PINNED_FIELDS).optional()
4104
4013
  });
4105
- var responsiveSearchAdSchema = z8.object({
4106
- format: z8.literal("responsiveSearch"),
4107
- headlines: z8.array(
4014
+ var responsiveSearchAdSchema = z7.object({
4015
+ format: z7.literal("responsiveSearch"),
4016
+ headlines: z7.array(
4108
4017
  adTextAssetSchema.refine(
4109
4018
  (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.headlineTextMax,
4110
4019
  "headline exceeds 30 chars"
4111
4020
  )
4112
4021
  ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.headlinesMax),
4113
- descriptions: z8.array(
4022
+ descriptions: z7.array(
4114
4023
  adTextAssetSchema.refine(
4115
4024
  (a) => a.text.length <= GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionTextMax,
4116
4025
  "description exceeds 90 chars"
4117
4026
  )
4118
4027
  ).min(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMin).max(GOOGLE_ADS_LIMITS.responsiveSearchAd.descriptionsMax),
4119
- path1: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4120
- path2: z8.string().max(GOOGLE_ADS_LIMITS.responsiveSearchAd.pathMax).optional(),
4121
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4122
- });
4123
- var responsiveDisplayAdSchema = z8.object({
4124
- format: z8.literal("responsiveDisplay"),
4125
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.headlineTextMax) })).min(1).max(5),
4126
- longHeadline: z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.longHeadlineTextMax) }),
4127
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(GOOGLE_ADS_LIMITS.responsiveDisplayAd.descriptionTextMax) })).min(1).max(5),
4128
- 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),
4129
4038
  // A Responsive Display Ad's images are fields on the ad's own content (never campaign-level
4130
4039
  // asset links). Google requires ≥1 landscape marketing image (1.91:1) AND ≥1 square marketing
4131
4040
  // image (1:1) to serve; the logo images are optional.
4132
- marketingImageAssets: z8.array(refSchema).optional(),
4133
- squareMarketingImageAssets: z8.array(refSchema).optional(),
4134
- logoImageAssets: z8.array(refSchema).optional(),
4135
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4136
- });
4137
- var callAdSchema = z8.object({
4138
- format: z8.literal("call"),
4139
- countryCode: z8.string().length(2),
4140
- phoneNumber: z8.string().min(3),
4141
- headline1: z8.string().min(1).max(30),
4142
- headline2: z8.string().min(1).max(30),
4143
- description1: z8.string().min(1).max(90),
4144
- description2: z8.string().min(1).max(90),
4145
- businessName: z8.string().min(1).max(25),
4146
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4147
- });
4148
- var appAdSchema = z8.object({
4149
- format: z8.literal("app"),
4150
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(30) })).min(1),
4151
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1)
4152
- });
4153
- var videoAdSchema = z8.object({
4154
- 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"),
4155
4064
  // A raw YouTube id is not a publishable Google Ads reference — the video must be staged as
4156
4065
  // its own `google.asset.create` (type: youtubeVideo) first, then referenced here by asset ref.
4157
- videoAssets: z8.array(refSchema).min(1),
4158
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4159
- });
4160
- var demandGenAdSchema = z8.object({
4161
- format: z8.literal("demandGen"),
4162
- headlines: z8.array(z8.object({ text: z8.string().min(1).max(40) })).min(1).max(5),
4163
- descriptions: z8.array(z8.object({ text: z8.string().min(1).max(90) })).min(1).max(5),
4164
- businessName: z8.string().min(1).max(25),
4165
- finalUrls: z8.array(httpsUrlSchema2).min(1),
4166
- imageAssets: z8.array(refSchema).optional(),
4167
- squareImageAssets: z8.array(refSchema).optional(),
4168
- logoImageAssets: z8.array(refSchema).optional()
4169
- });
4170
- 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", [
4171
4080
  responsiveSearchAdSchema,
4172
4081
  responsiveDisplayAdSchema,
4173
4082
  callAdSchema,
@@ -4175,45 +4084,45 @@ var adContentSchema = z8.discriminatedUnion("format", [
4175
4084
  videoAdSchema,
4176
4085
  demandGenAdSchema
4177
4086
  ]);
4178
- var adCreateSchema = z8.object({
4087
+ var adCreateSchema = z7.object({
4179
4088
  adGroup: refSchema,
4180
4089
  status: stageableStatusSchema2.default("PAUSED"),
4181
4090
  content: adContentSchema
4182
4091
  });
4183
- var adUpdateSchema = z8.object({
4184
- status: z8.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4092
+ var adUpdateSchema = z7.object({
4093
+ status: z7.enum(["ENABLED", "PAUSED", "REMOVED"]).optional(),
4185
4094
  /** Whole-content replacement for RSA-like formats; re-validated against adContentSchema. */
4186
- content: z8.record(z8.string(), z8.unknown()).optional()
4095
+ content: z7.record(z7.string(), z7.unknown()).optional()
4187
4096
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4188
- var textAssetSchema = z8.object({ type: z8.literal("text"), text: z8.string().min(1) });
4189
- var imageAssetSchema = z8.object({
4190
- type: z8.literal("image"),
4191
- imageId: z8.string().min(1),
4192
- name: z8.string().optional()
4193
- });
4194
- var youtubeVideoAssetSchema = z8.object({
4195
- type: z8.literal("youtubeVideo"),
4196
- youtubeVideoId: z8.string().min(1),
4197
- name: z8.string().optional()
4198
- });
4199
- var sitelinkAssetSchema = z8.object({
4200
- type: z8.literal("sitelink"),
4201
- linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax),
4202
- description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4203
- description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4204
- finalUrls: z8.array(httpsUrlSchema2).min(1)
4205
- });
4206
- var calloutAssetSchema = z8.object({
4207
- type: z8.literal("callout"),
4208
- calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax)
4209
- });
4210
- var structuredSnippetAssetSchema = z8.object({
4211
- type: z8.literal("structuredSnippet"),
4212
- header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax),
4213
- values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax)
4214
- });
4215
- var callToActionAssetSchema = z8.object({ type: z8.literal("callToAction"), callToAction: z8.string().min(1) });
4216
- 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", [
4217
4126
  textAssetSchema,
4218
4127
  imageAssetSchema,
4219
4128
  youtubeVideoAssetSchema,
@@ -4222,136 +4131,136 @@ var assetCreateSchema = z8.discriminatedUnion("type", [
4222
4131
  structuredSnippetAssetSchema,
4223
4132
  callToActionAssetSchema
4224
4133
  ]);
4225
- var assetUpdateSchema = z8.object({
4226
- name: z8.string().min(1).optional(),
4227
- linkText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.sitelinkLinkTextMax).optional(),
4228
- description1: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4229
- description2: z8.string().max(GOOGLE_ADS_LIMITS.asset.sitelinkDescriptionMax).optional(),
4230
- finalUrls: z8.array(httpsUrlSchema2).min(1).optional(),
4231
- calloutText: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.calloutTextMax).optional(),
4232
- header: z8.string().min(1).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetHeaderMax).optional(),
4233
- values: z8.array(z8.string().min(1)).min(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMin).max(GOOGLE_ADS_LIMITS.asset.structuredSnippetValuesMax).optional(),
4234
- callToAction: z8.string().min(1).optional(),
4235
- 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()
4236
4145
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4237
- var assetLinkAttachSchema = z8.object({
4238
- level: z8.enum(["campaign", "adGroup", "customer"]),
4146
+ var assetLinkAttachSchema = z7.object({
4147
+ level: z7.enum(["campaign", "adGroup", "customer"]),
4239
4148
  parent: refSchema.optional(),
4240
4149
  asset: refSchema,
4241
- fieldType: z8.enum(ASSET_FIELD_TYPES)
4150
+ fieldType: z7.enum(ASSET_FIELD_TYPES)
4242
4151
  }).superRefine((value, ctx) => {
4243
4152
  if (value.level !== "customer" && !value.parent) {
4244
4153
  ctx.addIssue({
4245
- code: z8.ZodIssueCode.custom,
4154
+ code: z7.ZodIssueCode.custom,
4246
4155
  path: ["parent"],
4247
4156
  message: `parent is required for a ${value.level}-level asset link (--parent-ref)`
4248
4157
  });
4249
4158
  }
4250
4159
  });
4251
- var assetGroupCreateSchema = z8.object({
4160
+ var assetGroupCreateSchema = z7.object({
4252
4161
  campaign: refSchema,
4253
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax),
4254
- finalUrls: z8.array(httpsUrlSchema2).min(1),
4255
- 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),
4256
- 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),
4257
- 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),
4258
- businessName: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.businessNameMax),
4259
- imageAssets: z8.array(refSchema).optional(),
4260
- squareImageAssets: z8.array(refSchema).optional(),
4261
- logoAssets: z8.array(refSchema).optional(),
4262
- status: z8.enum(["ENABLED", "PAUSED"]).default("PAUSED")
4263
- });
4264
- var assetGroupUpdateSchema = z8.object({
4265
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.assetGroup.nameMax).optional(),
4266
- finalUrls: z8.array(httpsUrlSchema2).min(1).optional(),
4267
- 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()
4268
4177
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4269
- var audienceCreateSchema2 = z8.object({
4270
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.audience.nameMax),
4271
- type: z8.enum(USER_LIST_TYPES).default("BASIC"),
4272
- 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(),
4273
4182
  /** Customer-match members (crm-based) — file-first for large lists. */
4274
- members: z8.array(z8.record(z8.string(), z8.string())).optional(),
4275
- sourceFileRef: z8.string().optional()
4183
+ members: z7.array(z7.record(z7.string(), z7.string())).optional(),
4184
+ sourceFileRef: z7.string().optional()
4276
4185
  });
4277
- var audienceCriterionAttachSchema = z8.object({
4278
- level: z8.enum(["campaign", "adGroup"]),
4186
+ var audienceCriterionAttachSchema = z7.object({
4187
+ level: z7.enum(["campaign", "adGroup"]),
4279
4188
  parent: refSchema,
4280
4189
  userList: refSchema,
4281
- negative: z8.boolean().default(false)
4190
+ negative: z7.boolean().default(false)
4282
4191
  });
4283
- var conversionActionCreateSchema = z8.object({
4284
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax),
4285
- type: z8.enum(CONVERSION_ACTION_TYPES).default("WEBPAGE"),
4286
- category: z8.enum(CONVERSION_ACTION_CATEGORIES).default("DEFAULT"),
4287
- 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"),
4288
4197
  defaultValueMicros: microsSchema.optional(),
4289
- defaultCurrencyCode: z8.string().length(3).optional(),
4290
- clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4291
- viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4292
- status: z8.enum(["ENABLED", "PAUSED"]).default("ENABLED")
4293
- });
4294
- var conversionActionUpdateSchema = z8.object({
4295
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.conversionAction.nameMax).optional(),
4296
- category: z8.enum(CONVERSION_ACTION_CATEGORIES).optional(),
4297
- 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(),
4298
4207
  defaultValueMicros: microsSchema.optional(),
4299
- defaultCurrencyCode: z8.string().length(3).optional(),
4300
- clickThroughLookbackWindowDays: z8.number().int().positive().optional(),
4301
- viewThroughLookbackWindowDays: z8.number().int().positive().optional(),
4302
- 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()
4303
4212
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4304
- var biddingStrategyCreateSchema = z8.object({
4305
- 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),
4306
4215
  config: biddingConfigSchema
4307
4216
  }).superRefine((p, ctx) => {
4308
4217
  if (p.config.type === "MANUAL_CPC") {
4309
4218
  ctx.addIssue({ code: "custom", path: ["config", "type"], message: "portfolio strategies cannot be Manual CPC" });
4310
4219
  }
4311
4220
  });
4312
- var biddingStrategyUpdateSchema = z8.object({
4313
- 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(),
4314
4223
  config: biddingConfigSchema.optional()
4315
4224
  }).refine((p) => Object.values(p).some((v) => v !== void 0), "update needs at least one field");
4316
- var labelCreateSchema = z8.object({
4317
- name: z8.string().min(1).max(GOOGLE_ADS_LIMITS.label.nameMax),
4318
- backgroundColor: z8.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
4319
- 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()
4320
4229
  });
4321
- var labelAttachSchema = z8.object({
4322
- level: z8.enum(["campaign", "adGroup", "ad"]),
4230
+ var labelAttachSchema = z7.object({
4231
+ level: z7.enum(["campaign", "adGroup", "ad"]),
4323
4232
  parent: refSchema,
4324
4233
  label: refSchema
4325
4234
  });
4326
- var locationCriterionSchema = z8.object({
4327
- criterionType: z8.literal("location"),
4328
- geoTargetConstant: z8.union([z8.string().regex(GEO_TARGET_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4329
- });
4330
- var languageCriterionSchema = z8.object({
4331
- criterionType: z8.literal("language"),
4332
- languageConstant: z8.union([z8.string().regex(LANGUAGE_CONSTANT_REGEX), z8.string().regex(NUMERIC_ID_REGEX2)])
4333
- });
4334
- var adScheduleCriterionSchema = z8.object({
4335
- criterionType: z8.literal("adSchedule"),
4336
- dayOfWeek: z8.enum(DAYS_OF_WEEK),
4337
- startHour: z8.number().int().min(0).max(23),
4338
- startMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO"),
4339
- endHour: z8.number().int().min(0).max(24),
4340
- endMinute: z8.enum(["ZERO", "FIFTEEN", "THIRTY", "FORTY_FIVE"]).default("ZERO")
4341
- });
4342
- var deviceCriterionSchema = z8.object({
4343
- criterionType: z8.literal("device"),
4344
- 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),
4345
4254
  // Google's `CampaignCriterion.bid_modifier`: "The modifier must be in the range 0.1 - 10.0. Use 0
4346
4255
  // to opt out of a Device type." So 0 (exclude the device) and 0.1–10.0 are valid; the (0, 0.1) gap is not.
4347
- bidModifier: 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, {
4348
4257
  message: "bid modifier must be 0 (exclude the device) or between 0.1 and 10.0"
4349
4258
  })
4350
4259
  });
4351
- var campaignCriterionAddSchema = z8.object({
4260
+ var campaignCriterionAddSchema = z7.object({
4352
4261
  campaign: refSchema,
4353
- negative: z8.boolean().default(false),
4354
- criterion: z8.discriminatedUnion("criterionType", [
4262
+ negative: z7.boolean().default(false),
4263
+ criterion: z7.discriminatedUnion("criterionType", [
4355
4264
  locationCriterionSchema,
4356
4265
  languageCriterionSchema,
4357
4266
  adScheduleCriterionSchema,
@@ -4361,7 +4270,7 @@ var campaignCriterionAddSchema = z8.object({
4361
4270
  const c = val.criterion;
4362
4271
  if (c.criterionType === "adSchedule" && c.endHour === 24 && c.endMinute !== "ZERO") {
4363
4272
  ctx.addIssue({
4364
- code: z8.ZodIssueCode.custom,
4273
+ code: z7.ZodIssueCode.custom,
4365
4274
  message: "endHour 24 (midnight) cannot have a non-zero endMinute",
4366
4275
  path: ["criterion", "endMinute"]
4367
4276
  });
@@ -4413,17 +4322,17 @@ var GOOGLE_DRAFT_OP_KINDS = [
4413
4322
  "google.campaignCriterion.add",
4414
4323
  "google.campaignCriterion.remove"
4415
4324
  ];
4416
- var googleDraftOpKindSchema = z8.enum(GOOGLE_DRAFT_OP_KINDS);
4325
+ var googleDraftOpKindSchema = z7.enum(GOOGLE_DRAFT_OP_KINDS);
4417
4326
  function createOp2(kind, payload) {
4418
- return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, payload });
4327
+ return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, payload });
4419
4328
  }
4420
4329
  function updateOp2(kind, payload) {
4421
- 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 });
4422
4331
  }
4423
4332
  function targetOp(kind) {
4424
- return z8.object({ kind: z8.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4333
+ return z7.object({ kind: z7.literal(kind), customerId: customerIdSchema, target: targetRefSchema });
4425
4334
  }
4426
- var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4335
+ var googleDraftOpInputSchema = z7.discriminatedUnion("kind", [
4427
4336
  createOp2("google.budget.create", budgetCreateSchema),
4428
4337
  updateOp2("google.budget.update", budgetUpdateSchema),
4429
4338
  createOp2("google.campaign.create", campaignCreateSchema2),
@@ -4471,132 +4380,132 @@ var googleDraftOpInputSchema = z8.discriminatedUnion("kind", [
4471
4380
  ]);
4472
4381
 
4473
4382
  // ../api/src/ads-google/wire.ts
4474
- import { z as z9 } from "zod";
4475
- var googleWriteModeSchema = z9.enum(["live", "simulated"]);
4476
- var googleDraftOpResultSchema = z9.object({
4477
- status: z9.enum(["applied", "simulated", "failed", "skipped"]),
4478
- resourceName: z9.string().optional(),
4479
- error: z9.string().optional(),
4480
- skippedBecause: z9.string().optional(),
4481
- executedAt: z9.number().optional()
4482
- });
4483
- var googleDraftStageRequestSchema = z9.object({
4484
- 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(),
4485
4394
  op: googleDraftOpInputSchema
4486
4395
  });
4487
- var googleDraftStageResponseSchema = z9.object({
4488
- staged: z9.literal(true),
4489
- ref: z9.string(),
4396
+ var googleDraftStageResponseSchema = z8.object({
4397
+ staged: z8.literal(true),
4398
+ ref: z8.string(),
4490
4399
  kind: googleDraftOpKindSchema,
4491
4400
  mode: googleWriteModeSchema,
4492
- dependsOn: z9.array(z9.string()),
4493
- summary: z9.string(),
4494
- warnings: z9.array(z9.string()),
4401
+ dependsOn: z8.array(z8.string()),
4402
+ summary: z8.string(),
4403
+ warnings: z8.array(z8.string()),
4495
4404
  /** True when the op amended an already-staged op in place instead of appending a new one. */
4496
- amended: z9.boolean().optional()
4405
+ amended: z8.boolean().optional()
4497
4406
  });
4498
- var googleDraftAmendRequestSchema = z9.object({
4499
- chatId: z9.string(),
4500
- ref: z9.string(),
4501
- 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())
4502
4411
  });
4503
- var googleDraftShowRequestSchema = z9.object({
4504
- chatId: z9.string(),
4505
- ref: z9.string()
4412
+ var googleDraftShowRequestSchema = z8.object({
4413
+ chatId: z8.string(),
4414
+ ref: z8.string()
4506
4415
  });
4507
4416
  var GOOGLE_DRAFT_BATCH_MAX = 500;
4508
- var googleDraftStageBatchRequestSchema = z9.object({
4509
- chatId: z9.string(),
4510
- 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)
4511
4420
  });
4512
- var googleDraftStageBatchResponseSchema = z9.object({
4513
- staged: z9.literal(true),
4421
+ var googleDraftStageBatchResponseSchema = z8.object({
4422
+ staged: z8.literal(true),
4514
4423
  mode: googleWriteModeSchema,
4515
- count: z9.number(),
4516
- ops: z9.array(
4517
- z9.object({
4518
- ref: z9.string(),
4424
+ count: z8.number(),
4425
+ ops: z8.array(
4426
+ z8.object({
4427
+ ref: z8.string(),
4519
4428
  kind: googleDraftOpKindSchema,
4520
- dependsOn: z9.array(z9.string()),
4521
- summary: z9.string(),
4522
- warnings: z9.array(z9.string())
4429
+ dependsOn: z8.array(z8.string()),
4430
+ summary: z8.string(),
4431
+ warnings: z8.array(z8.string())
4523
4432
  })
4524
4433
  )
4525
4434
  });
4526
- var googleDraftOpViewSchema = z9.object({
4527
- ref: z9.string(),
4435
+ var googleDraftOpViewSchema = z8.object({
4436
+ ref: z8.string(),
4528
4437
  kind: googleDraftOpKindSchema,
4529
- customerId: z9.string(),
4530
- target: z9.string().optional(),
4531
- dependsOn: z9.array(z9.string()),
4532
- summary: z9.string(),
4533
- 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(),
4534
4443
  result: googleDraftOpResultSchema.optional()
4535
4444
  });
4536
- var googleDraftShowResponseSchema = z9.object({
4445
+ var googleDraftShowResponseSchema = z8.object({
4537
4446
  op: googleDraftOpViewSchema.extend({
4538
- payload: z9.unknown().optional(),
4539
- warnings: z9.array(z9.string()).optional(),
4540
- annotations: z9.unknown().optional()
4447
+ payload: z8.unknown().optional(),
4448
+ warnings: z8.array(z8.string()).optional(),
4449
+ annotations: z8.unknown().optional()
4541
4450
  })
4542
4451
  });
4543
- var googleDraftListRequestSchema = z9.object({
4544
- chatId: z9.string()
4452
+ var googleDraftListRequestSchema = z8.object({
4453
+ chatId: z8.string()
4545
4454
  });
4546
- var googleDraftAdvisorySchema = z9.object({
4547
- scope: z9.enum(["campaign", "adGroup"]),
4548
- message: z9.string()
4455
+ var googleDraftAdvisorySchema = z8.object({
4456
+ scope: z8.enum(["campaign", "adGroup"]),
4457
+ message: z8.string()
4549
4458
  });
4550
- var googleDraftStatusCollectionSchema = z9.object({
4551
- label: z9.string(),
4552
- added: z9.number(),
4553
- removed: z9.number(),
4554
- existing: z9.number()
4459
+ var googleDraftStatusCollectionSchema = z8.object({
4460
+ label: z8.string(),
4461
+ added: z8.number(),
4462
+ removed: z8.number(),
4463
+ existing: z8.number()
4555
4464
  });
4556
- var googleDraftChangeOperationSchema = z9.enum(["create", "update", "pause", "resume", "remove"]);
4557
- var googleDraftStatusNodeSchema = z9.lazy(
4558
- () => z9.object({
4559
- entity: z9.string(),
4560
- 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(),
4561
4470
  operation: googleDraftChangeOperationSchema.optional(),
4562
- existing: z9.boolean(),
4563
- collections: z9.array(googleDraftStatusCollectionSchema),
4564
- children: z9.array(googleDraftStatusNodeSchema),
4565
- 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()
4566
4475
  })
4567
4476
  );
4568
- var googleDraftListResponseSchema = z9.object({
4569
- status: z9.enum(["active", "publishing", "applied", "discarded", "none"]),
4477
+ var googleDraftListResponseSchema = z8.object({
4478
+ status: z8.enum(["active", "publishing", "applied", "discarded", "none"]),
4570
4479
  mode: googleWriteModeSchema,
4571
- count: z9.number(),
4572
- ops: z9.array(googleDraftOpViewSchema),
4480
+ count: z8.number(),
4481
+ ops: z8.array(googleDraftOpViewSchema),
4573
4482
  /** Grouped campaign ▸ ad group ▸ ad tree for the readable CLI status view. */
4574
- tree: z9.array(googleDraftStatusNodeSchema).optional(),
4483
+ tree: z8.array(googleDraftStatusNodeSchema).optional(),
4575
4484
  /** Non-blocking completeness advisories for the whole draft. */
4576
- advisories: z9.array(googleDraftAdvisorySchema).optional()
4485
+ advisories: z8.array(googleDraftAdvisorySchema).optional()
4577
4486
  });
4578
- var googleDraftRemoveRequestSchema = z9.object({
4579
- chatId: z9.string(),
4580
- ref: z9.string()
4487
+ var googleDraftRemoveRequestSchema = z8.object({
4488
+ chatId: z8.string(),
4489
+ ref: z8.string()
4581
4490
  });
4582
- var googleDraftRemoveResponseSchema = z9.object({
4491
+ var googleDraftRemoveResponseSchema = z8.object({
4583
4492
  /** The requested ref plus any dependents removed by cascade. */
4584
- removed: z9.array(z9.string())
4493
+ removed: z8.array(z8.string())
4585
4494
  });
4586
- var googleDraftClearRequestSchema = z9.object({
4587
- chatId: z9.string()
4495
+ var googleDraftClearRequestSchema = z8.object({
4496
+ chatId: z8.string()
4588
4497
  });
4589
- var googleDraftClearResponseSchema = z9.object({
4590
- cleared: z9.number()
4498
+ var googleDraftClearResponseSchema = z8.object({
4499
+ cleared: z8.number()
4591
4500
  });
4592
- var googleFieldErrorSchema = z9.object({
4593
- path: z9.string(),
4594
- message: z9.string()
4501
+ var googleFieldErrorSchema = z8.object({
4502
+ path: z8.string(),
4503
+ message: z8.string()
4595
4504
  });
4596
- var googleDraftErrorResponseSchema = z9.object({
4597
- code: z9.string(),
4598
- error: z9.string(),
4599
- fields: z9.array(googleFieldErrorSchema).optional()
4505
+ var googleDraftErrorResponseSchema = z8.object({
4506
+ code: z8.string(),
4507
+ error: z8.string(),
4508
+ fields: z8.array(googleFieldErrorSchema).optional()
4600
4509
  });
4601
4510
 
4602
4511
  // src/commands/ads/google/draft-status.ts
@@ -4761,11 +4670,11 @@ function rawTextEntries(value) {
4761
4670
  const values = Array.isArray(value) ? value : typeof value === "string" ? [value] : [];
4762
4671
  return values.filter((v) => typeof v === "string").flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
4763
4672
  }
4764
- function rawFileEntries(path12) {
4765
- if (typeof path12 !== "string" || path12.length === 0) {
4673
+ function rawFileEntries(path14) {
4674
+ if (typeof path14 !== "string" || path14.length === 0) {
4766
4675
  return [];
4767
4676
  }
4768
- 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("#"));
4769
4678
  }
4770
4679
  function keywordEntries(args) {
4771
4680
  const defaultMatch = typeof args["match-type"] === "string" ? args["match-type"].toUpperCase() : void 0;
@@ -4788,19 +4697,19 @@ function keywordEntries(args) {
4788
4697
  }
4789
4698
  return entries;
4790
4699
  }
4791
- function loadJsonFileArg(path12) {
4792
- if (typeof path12 !== "string" || path12.length === 0) {
4700
+ function loadJsonFileArg(path14) {
4701
+ if (typeof path14 !== "string" || path14.length === 0) {
4793
4702
  return {};
4794
4703
  }
4795
4704
  try {
4796
- const parsed = JSON.parse(readFileSync2(path12, "utf8"));
4705
+ const parsed = JSON.parse(readFileSync2(path14, "utf8"));
4797
4706
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4798
- failWriteValidation(`${path12} must contain a JSON object`);
4707
+ failWriteValidation(`${path14} must contain a JSON object`);
4799
4708
  }
4800
4709
  return parsed;
4801
4710
  } catch (err) {
4802
4711
  if (err instanceof SyntaxError) {
4803
- failWriteValidation(`${path12} is not valid JSON: ${err.message}`);
4712
+ failWriteValidation(`${path14} is not valid JSON: ${err.message}`);
4804
4713
  }
4805
4714
  throw err;
4806
4715
  }
@@ -4911,10 +4820,10 @@ async function stageUpdate(kind, customerId, target, payload) {
4911
4820
  async function stageTarget(kind, customerId, target) {
4912
4821
  await stageGoogleOp({ kind, customerId, target });
4913
4822
  }
4914
- async function draftAction(path12, body) {
4823
+ async function draftAction(path14, body) {
4915
4824
  try {
4916
4825
  const chatId = requireChatId();
4917
- const response = await apiPost(path12, { chatId, ...body });
4826
+ const response = await apiPost(path14, { chatId, ...body });
4918
4827
  writeJsonEnvelope(response);
4919
4828
  } catch (err) {
4920
4829
  handleGoogleError(err);
@@ -8669,19 +8578,19 @@ function failWriteValidation2(message) {
8669
8578
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
8670
8579
  process.exit(1);
8671
8580
  }
8672
- function loadJsonFileArg2(path12) {
8673
- if (typeof path12 !== "string" || path12.length === 0) {
8581
+ function loadJsonFileArg2(path14) {
8582
+ if (typeof path14 !== "string" || path14.length === 0) {
8674
8583
  return {};
8675
8584
  }
8676
8585
  try {
8677
- const parsed = JSON.parse(readFileSync6(path12, "utf8"));
8586
+ const parsed = JSON.parse(readFileSync6(path14, "utf8"));
8678
8587
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
8679
- failWriteValidation2(`${path12} must contain a JSON object`);
8588
+ failWriteValidation2(`${path14} must contain a JSON object`);
8680
8589
  }
8681
8590
  return parsed;
8682
8591
  } catch (err) {
8683
8592
  if (err instanceof SyntaxError) {
8684
- failWriteValidation2(`${path12} is not valid JSON: ${err.message}`);
8593
+ failWriteValidation2(`${path14} is not valid JSON: ${err.message}`);
8685
8594
  }
8686
8595
  throw err;
8687
8596
  }
@@ -8766,15 +8675,15 @@ function parseLocaleFlag(value) {
8766
8675
  }
8767
8676
  return { language: match[1], country: match[2].toUpperCase() };
8768
8677
  }
8769
- function loadTargetingFileArg(path12) {
8770
- if (typeof path12 !== "string" || path12.length === 0) {
8678
+ function loadTargetingFileArg(path14) {
8679
+ if (typeof path14 !== "string" || path14.length === 0) {
8771
8680
  return void 0;
8772
8681
  }
8773
- const parsed = loadJsonFileArg2(path12);
8682
+ const parsed = loadJsonFileArg2(path14);
8774
8683
  const criteria = parsed.targetingCriteria ?? parsed;
8775
8684
  if (!criteria.include) {
8776
8685
  failWriteValidation2(
8777
- `${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)`
8778
8687
  );
8779
8688
  }
8780
8689
  return criteria;
@@ -8809,14 +8718,14 @@ function parseCsvLine(line) {
8809
8718
  cells.push(current);
8810
8719
  return cells.map((cell) => cell.trim());
8811
8720
  }
8812
- function parseListFileArg(path12, maxRows) {
8813
- if (typeof path12 !== "string" || path12.length === 0) {
8721
+ function parseListFileArg(path14, maxRows) {
8722
+ if (typeof path14 !== "string" || path14.length === 0) {
8814
8723
  return void 0;
8815
8724
  }
8816
- const raw = readFileSync6(path12, "utf8");
8725
+ const raw = readFileSync6(path14, "utf8");
8817
8726
  const lines = raw.split(/\r?\n/).filter((line) => line.trim().length > 0);
8818
8727
  if (lines.length < 2) {
8819
- failWriteValidation2(`${path12} needs a header row and at least one data row`);
8728
+ failWriteValidation2(`${path14} needs a header row and at least one data row`);
8820
8729
  }
8821
8730
  const columns = parseCsvLine(lines[0]).map((column) => column.trim());
8822
8731
  const rows = [];
@@ -8835,7 +8744,7 @@ function parseListFileArg(path12, maxRows) {
8835
8744
  }
8836
8745
  }
8837
8746
  if (rows.length > maxRows) {
8838
- failWriteValidation2(`${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.`);
8839
8748
  }
8840
8749
  return { columns, rows };
8841
8750
  }
@@ -9480,7 +9389,7 @@ var leadFormsCreateCommand = defineCommand38({
9480
9389
  Required: name, headline (\u226460), privacyPolicyUrl, questions[] (\u226412; playbook: \u22644 for completion).
9481
9390
  Each question is a predefined profile field ({ name, predefinedField: "EMAIL" }) or a custom question ({ name, questionType: "MULTIPLE_CHOICE", options: [...] }; \u22643 custom).
9482
9391
  Best-practice fields the preview will nudge for if missing: 1-3 qualifying questions, consents[] (disclosure checkboxes), thankYou.message + thankYou.landingUrl|appointmentUrl.
9483
- Also supported: locale, formImageId|formImageUrn, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
9392
+ Also supported: locale, formImageId|formImageUrn, privacyPolicyText, hiddenFields[], legalDisclaimer, thankYou.cta. Example: baker ads linkedin lead-forms create --file form.json`
9484
9393
  },
9485
9394
  args: {
9486
9395
  ...accountArgs,
@@ -10904,72 +10813,72 @@ var NUMERIC_ID_REGEX3 = /^\d+$/;
10904
10813
  var IMAGE_HASH_REGEX = /^[A-Fa-f0-9]{16,}$/;
10905
10814
 
10906
10815
  // ../api/src/ads-meta/ops.ts
10907
- import { z as z10 } from "zod";
10908
- var tempRefSchema3 = z10.string().regex(TEMP_REF_REGEX3, "expected a meta_temp_* reference");
10909
- var parentRefSchema2 = z10.union([z10.string().regex(NUMERIC_ID_REGEX3, "expected a numeric id"), tempRefSchema3]);
10910
- var moneySchema2 = z10.object({
10911
- 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"),
10912
- currencyCode: z10.string().length(3).optional()
10913
- });
10914
- var httpsUrlSchema3 = z10.string().url().refine((u) => u.startsWith("https://"), "destination URLs must be https");
10915
- var bakerMediaIdSchema2 = z10.string().min(1);
10916
- var stageableStatusSchema3 = z10.enum(STAGEABLE_CREATE_STATUSES3);
10917
- 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);
10918
10827
  function currencyMinimums2(currencyCode) {
10919
10828
  return CURRENCY_MINIMUMS2[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM2;
10920
10829
  }
10921
- function validateDailyBudgetFloor(money, ctx, path12) {
10830
+ function validateDailyBudgetFloor(money, ctx, path14) {
10922
10831
  if (money?.currencyCode) {
10923
10832
  const min = currencyMinimums2(money.currencyCode).dailyBudgetMin;
10924
10833
  if (Number(money.amount) < min) {
10925
- ctx.addIssue({ code: "custom", path: path12, message: `below the ${min} ${money.currencyCode} daily minimum` });
10834
+ ctx.addIssue({ code: "custom", path: path14, message: `below the ${min} ${money.currencyCode} daily minimum` });
10926
10835
  }
10927
10836
  }
10928
10837
  }
10929
- var geoLocationsSchema = z10.object({
10930
- countries: z10.array(z10.string().length(2)).optional(),
10931
- regions: z10.array(z10.object({ key: z10.string() })).optional(),
10932
- cities: z10.array(z10.object({ key: z10.string(), radius: z10.number().optional(), distance_unit: z10.string().optional() })).optional(),
10933
- zips: z10.array(z10.object({ key: z10.string() })).optional(),
10934
- location_types: z10.array(z10.string()).optional()
10935
- }).catchall(z10.unknown());
10936
- var idNameSchema = z10.object({ id: z10.string(), name: z10.string().optional() });
10937
- 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({
10938
10847
  geo_locations: geoLocationsSchema.optional(),
10939
10848
  excluded_geo_locations: geoLocationsSchema.optional(),
10940
- age_min: z10.number().int().min(13).max(65).optional(),
10941
- age_max: z10.number().int().min(13).max(65).optional(),
10942
- genders: z10.array(z10.union([z10.literal(1), z10.literal(2)])).optional(),
10943
- locales: z10.array(z10.number().int()).optional(),
10944
- interests: z10.array(idNameSchema).optional(),
10945
- behaviors: z10.array(idNameSchema).optional(),
10946
- custom_audiences: z10.array(z10.object({ id: parentRefSchema2 })).optional(),
10947
- excluded_custom_audiences: z10.array(z10.object({ id: parentRefSchema2 })).optional(),
10948
- flexible_spec: z10.array(z10.record(z10.string(), z10.unknown())).optional(),
10949
- exclusions: z10.record(z10.string(), z10.unknown()).optional(),
10950
- publisher_platforms: z10.array(z10.string()).optional(),
10951
- facebook_positions: z10.array(z10.string()).optional(),
10952
- instagram_positions: z10.array(z10.string()).optional(),
10953
- audience_network_positions: z10.array(z10.string()).optional(),
10954
- messenger_positions: z10.array(z10.string()).optional(),
10955
- device_platforms: z10.array(z10.string()).optional(),
10956
- targeting_automation: z10.object({ advantage_audience: z10.union([z10.literal(0), z10.literal(1)]) }).partial().optional()
10957
- }).catchall(z10.unknown());
10958
- var specialAdCategoriesSchema = z10.array(z10.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
10959
- var campaignCreateSchema3 = z10.object({
10960
- name: z10.string().min(1).max(META_LIMITS.campaign.nameMax),
10961
- 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),
10962
10871
  status: stageableStatusSchema3.default("PAUSED"),
10963
10872
  special_ad_categories: specialAdCategoriesSchema,
10964
- special_ad_category_country: z10.array(z10.string().length(2)).optional(),
10965
- buying_type: z10.enum(BUYING_TYPES).default("AUCTION"),
10966
- 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(),
10967
10876
  /** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */
10968
10877
  dailyBudget: moneySchema2.optional(),
10969
10878
  lifetimeBudget: moneySchema2.optional(),
10970
10879
  spendCap: moneySchema2.optional(),
10971
- start_time: z10.number().int().positive().optional(),
10972
- stop_time: z10.number().int().positive().optional()
10880
+ start_time: z9.number().int().positive().optional(),
10881
+ stop_time: z9.number().int().positive().optional()
10973
10882
  }).superRefine((p, ctx) => {
10974
10883
  if (p.dailyBudget && p.lifetimeBudget) {
10975
10884
  ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
@@ -10979,15 +10888,15 @@ var campaignCreateSchema3 = z10.object({
10979
10888
  ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
10980
10889
  }
10981
10890
  });
10982
- var campaignUpdateSchema3 = z10.object({
10983
- 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(),
10984
10893
  status: updateStatusSchema.optional(),
10985
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
10894
+ bid_strategy: z9.enum(BID_STRATEGIES).optional(),
10986
10895
  dailyBudget: moneySchema2.optional(),
10987
10896
  lifetimeBudget: moneySchema2.optional(),
10988
10897
  spendCap: moneySchema2.optional(),
10989
- start_time: z10.number().int().positive().optional(),
10990
- stop_time: z10.number().int().positive().optional()
10898
+ start_time: z9.number().int().positive().optional(),
10899
+ stop_time: z9.number().int().positive().optional()
10991
10900
  }).superRefine((p, ctx) => {
10992
10901
  if (!Object.values(p).some((val) => val !== void 0)) {
10993
10902
  ctx.addIssue({ code: "custom", message: "update needs at least one field" });
@@ -10997,38 +10906,38 @@ var campaignUpdateSchema3 = z10.object({
10997
10906
  }
10998
10907
  validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
10999
10908
  });
11000
- var promotedObjectSchema = z10.object({
10909
+ var promotedObjectSchema = z9.object({
11001
10910
  page_id: parentRefSchema2.optional(),
11002
- pixel_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11003
- custom_event_type: z10.enum(CUSTOM_EVENT_TYPES).optional(),
11004
- application_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11005
- object_store_url: z10.string().url().optional(),
11006
- product_catalog_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11007
- product_set_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11008
- whatsapp_phone_number: z10.string().optional(),
11009
- 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()
11010
10919
  }).partial();
11011
- var attributionSpecSchema = z10.array(
11012
- z10.object({
11013
- event_type: z10.enum(ATTRIBUTION_EVENT_TYPES),
11014
- 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)])
11015
10924
  })
11016
10925
  );
11017
10926
  var adSetFields = {
11018
- name: z10.string().min(1).max(META_LIMITS.adSet.nameMax),
10927
+ name: z9.string().min(1).max(META_LIMITS.adSet.nameMax),
11019
10928
  campaign_id: parentRefSchema2,
11020
10929
  status: stageableStatusSchema3.default("PAUSED"),
11021
10930
  dailyBudget: moneySchema2.optional(),
11022
10931
  lifetimeBudget: moneySchema2.optional(),
11023
10932
  bidAmount: moneySchema2.optional(),
11024
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
11025
- billing_event: z10.enum(BILLING_EVENTS),
11026
- optimization_goal: z10.enum(OPTIMIZATION_GOALS),
11027
- 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(),
11028
10937
  promoted_object: promotedObjectSchema.optional(),
11029
10938
  attribution_spec: attributionSpecSchema.optional(),
11030
- start_time: z10.number().int().positive().optional(),
11031
- end_time: z10.number().int().positive().optional(),
10939
+ start_time: z9.number().int().positive().optional(),
10940
+ end_time: z9.number().int().positive().optional(),
11032
10941
  targeting: metaTargetingSchema
11033
10942
  };
11034
10943
  function validateAdSetBudgetAndBid(p, ctx) {
@@ -11046,22 +10955,22 @@ function validateAdSetBudgetAndBid(p, ctx) {
11046
10955
  ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
11047
10956
  }
11048
10957
  }
11049
- var adSetCreateSchema = z10.object(adSetFields).superRefine((p, ctx) => {
10958
+ var adSetCreateSchema = z9.object(adSetFields).superRefine((p, ctx) => {
11050
10959
  validateAdSetBudgetAndBid(p, ctx);
11051
10960
  });
11052
- var adSetUpdateSchema = z10.object({
10961
+ var adSetUpdateSchema = z9.object({
11053
10962
  name: adSetFields.name.optional(),
11054
10963
  status: updateStatusSchema.optional(),
11055
10964
  dailyBudget: moneySchema2.optional(),
11056
10965
  lifetimeBudget: moneySchema2.optional(),
11057
10966
  bidAmount: moneySchema2.optional(),
11058
- bid_strategy: z10.enum(BID_STRATEGIES).optional(),
11059
- optimization_goal: z10.enum(OPTIMIZATION_GOALS).optional(),
11060
- 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(),
11061
10970
  promoted_object: promotedObjectSchema.optional(),
11062
10971
  attribution_spec: attributionSpecSchema.optional(),
11063
- start_time: z10.number().int().positive().optional(),
11064
- end_time: z10.number().int().positive().optional(),
10972
+ start_time: z9.number().int().positive().optional(),
10973
+ end_time: z9.number().int().positive().optional(),
11065
10974
  targeting: metaTargetingSchema.optional()
11066
10975
  }).superRefine((p, ctx) => {
11067
10976
  if (!Object.values(p).some((val) => val !== void 0)) {
@@ -11069,38 +10978,38 @@ var adSetUpdateSchema = z10.object({
11069
10978
  }
11070
10979
  validateAdSetBudgetAndBid(p, ctx);
11071
10980
  });
11072
- var messageSchema = z10.string().min(1).max(META_LIMITS.creative.messageHardMax);
11073
- var headlineSchema2 = z10.string().min(1).max(META_LIMITS.creative.headlineMax);
11074
- var descriptionSchema = z10.string().min(1).max(META_LIMITS.creative.descriptionMax);
11075
- var callToActionSchema = z10.object({
11076
- 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),
11077
10986
  /** Overrides the base link for the CTA button; defaults to the ad's link. */
11078
10987
  link: httpsUrlSchema3.optional()
11079
10988
  });
11080
- var creativeEnhancementsSchema = z10.object({
11081
- standardEnhancements: z10.enum(ENROLL_STATUSES).optional(),
11082
- 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()
11083
10992
  });
11084
10993
  var creativeSharedFields = {
11085
- name: z10.string().max(META_LIMITS.creative.nameMax).optional(),
10994
+ name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
11086
10995
  /** Facebook Page id backing the ad's identity. */
11087
10996
  page_id: parentRefSchema2,
11088
10997
  /** Instagram account id for IG placements (aka instagram_actor_id on read). */
11089
- instagram_user_id: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
10998
+ instagram_user_id: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
11090
10999
  /** URL tracking parameters appended to the destination, e.g. "utm_source=fb&utm_campaign=x". */
11091
- url_tags: z10.string().max(1e3).optional(),
11000
+ url_tags: z9.string().max(1e3).optional(),
11092
11001
  enhancements: creativeEnhancementsSchema.optional()
11093
11002
  };
11094
11003
  var imageMediaFields = {
11095
- imageHash: z10.string().regex(IMAGE_HASH_REGEX).optional(),
11004
+ imageHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
11096
11005
  imageRef: tempRefSchema3.optional()
11097
11006
  };
11098
11007
  var videoMediaFields = {
11099
- videoId: z10.string().regex(NUMERIC_ID_REGEX3).optional(),
11008
+ videoId: z9.string().regex(NUMERIC_ID_REGEX3).optional(),
11100
11009
  videoRef: tempRefSchema3.optional(),
11101
11010
  /** Thumbnail for a video creative — image hash, ref, or public url. */
11102
- thumbnailHash: z10.string().regex(IMAGE_HASH_REGEX).optional(),
11103
- imageUrl: z10.string().url().optional()
11011
+ thumbnailHash: z9.string().regex(IMAGE_HASH_REGEX).optional(),
11012
+ imageUrl: z9.string().url().optional()
11104
11013
  };
11105
11014
  function countImageRefs(p) {
11106
11015
  return [p.imageHash, p.imageRef].filter(Boolean).length;
@@ -11108,8 +11017,8 @@ function countImageRefs(p) {
11108
11017
  function countVideoRefs(p) {
11109
11018
  return [p.videoId, p.videoRef].filter(Boolean).length;
11110
11019
  }
11111
- var singleCreativeSchema = z10.object({
11112
- creativeType: z10.literal("single"),
11020
+ var singleCreativeSchema = z9.object({
11021
+ creativeType: z9.literal("single"),
11113
11022
  ...creativeSharedFields,
11114
11023
  /** Primary text. */
11115
11024
  message: messageSchema,
@@ -11118,7 +11027,7 @@ var singleCreativeSchema = z10.object({
11118
11027
  headline: headlineSchema2.optional(),
11119
11028
  description: descriptionSchema.optional(),
11120
11029
  /** Display URL / caption shown under the headline. */
11121
- caption: z10.string().max(255).optional(),
11030
+ caption: z9.string().max(255).optional(),
11122
11031
  call_to_action: callToActionSchema.optional(),
11123
11032
  ...imageMediaFields,
11124
11033
  ...videoMediaFields
@@ -11142,10 +11051,10 @@ var singleCreativeSchema = z10.object({
11142
11051
  });
11143
11052
  }
11144
11053
  });
11145
- var carouselCardSchema = z10.object({
11054
+ var carouselCardSchema = z9.object({
11146
11055
  link: httpsUrlSchema3,
11147
- headline: z10.string().max(META_LIMITS.creative.headlineMax).optional(),
11148
- 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(),
11149
11058
  call_to_action: callToActionSchema.optional(),
11150
11059
  ...imageMediaFields,
11151
11060
  ...videoMediaFields
@@ -11165,35 +11074,35 @@ var carouselCardSchema = z10.object({
11165
11074
  ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
11166
11075
  }
11167
11076
  });
11168
- var carouselCreativeSchema2 = z10.object({
11169
- creativeType: z10.literal("carousel"),
11077
+ var carouselCreativeSchema2 = z9.object({
11078
+ creativeType: z9.literal("carousel"),
11170
11079
  ...creativeSharedFields,
11171
11080
  message: messageSchema,
11172
11081
  /** Optional "see more" card destination applied when a card has no own link. */
11173
11082
  link: httpsUrlSchema3.optional(),
11174
11083
  call_to_action: callToActionSchema.optional(),
11175
- cards: 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)
11176
11085
  });
11177
- var dynamicImageSchema = z10.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
11178
- 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({
11179
11088
  videoId: videoMediaFields.videoId,
11180
11089
  videoRef: videoMediaFields.videoRef,
11181
11090
  thumbnailHash: videoMediaFields.thumbnailHash
11182
11091
  }).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
11183
11092
  var DYN = META_LIMITS.creative;
11184
- var dynamicCreativeSchema = z10.object({
11185
- creativeType: z10.literal("dynamic"),
11093
+ var dynamicCreativeSchema = z9.object({
11094
+ creativeType: z9.literal("dynamic"),
11186
11095
  ...creativeSharedFields,
11187
- bodies: z10.array(z10.object({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
11188
- titles: z10.array(z10.object({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
11189
- descriptions: z10.array(z10.object({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
11190
- images: z10.array(dynamicImageSchema).optional(),
11191
- videos: z10.array(dynamicVideoSchema).optional(),
11192
- ad_formats: z10.array(z10.enum(AD_FORMATS2)).min(1),
11193
- call_to_action_types: z10.array(z10.enum(CTA_TYPES2)).optional(),
11194
- 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),
11195
11104
  /** Multi-language / placement customization — structural passthrough for v1. */
11196
- 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()
11197
11106
  }).superRefine((p, ctx) => {
11198
11107
  if (!(p.images?.length || p.videos?.length)) {
11199
11108
  ctx.addIssue({
@@ -11203,57 +11112,57 @@ var dynamicCreativeSchema = z10.object({
11203
11112
  });
11204
11113
  }
11205
11114
  });
11206
- var existingPostCreativeSchema = z10.object({
11207
- creativeType: z10.literal("existing_post"),
11115
+ var existingPostCreativeSchema = z9.object({
11116
+ creativeType: z9.literal("existing_post"),
11208
11117
  name: creativeSharedFields.name,
11209
11118
  /** "<page_id>_<post_id>" object story id of the post to promote. */
11210
- object_story_id: z10.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
11119
+ object_story_id: z9.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"'),
11211
11120
  instagram_user_id: creativeSharedFields.instagram_user_id,
11212
11121
  url_tags: creativeSharedFields.url_tags,
11213
11122
  enhancements: creativeSharedFields.enhancements
11214
11123
  });
11215
- var creativeContentSchema2 = z10.discriminatedUnion("creativeType", [
11124
+ var creativeContentSchema2 = z9.discriminatedUnion("creativeType", [
11216
11125
  singleCreativeSchema,
11217
11126
  carouselCreativeSchema2,
11218
11127
  dynamicCreativeSchema,
11219
11128
  existingPostCreativeSchema
11220
11129
  ]);
11221
11130
  var adCreativeCreateSchema = creativeContentSchema2;
11222
- var adCreativeUpdateSchema = z10.object({
11223
- name: z10.string().max(META_LIMITS.creative.nameMax).optional(),
11131
+ var adCreativeUpdateSchema = z9.object({
11132
+ name: z9.string().max(META_LIMITS.creative.nameMax).optional(),
11224
11133
  status: updateStatusSchema.optional(),
11225
11134
  /** Content patch — only honored when the target is a staged meta_temp_* creative. */
11226
- content: z10.record(z10.string(), z10.unknown()).optional()
11135
+ content: z9.record(z9.string(), z9.unknown()).optional()
11227
11136
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11228
- var adCreateSchema2 = z10.object({
11229
- 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),
11230
11139
  adset_id: parentRefSchema2,
11231
11140
  status: stageableStatusSchema3.default("PAUSED"),
11232
- creative: z10.object({ creative_id: parentRefSchema2 }),
11141
+ creative: z9.object({ creative_id: parentRefSchema2 }),
11233
11142
  /** Conversion pixel / offline event set / view tags — structural passthrough. */
11234
- tracking_specs: z10.array(z10.record(z10.string(), z10.unknown())).optional()
11143
+ tracking_specs: z9.array(z9.record(z9.string(), z9.unknown())).optional()
11235
11144
  });
11236
- var adUpdateSchema2 = z10.object({
11237
- 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(),
11238
11147
  status: updateStatusSchema.optional(),
11239
11148
  /** Swapping the creative is the Meta way to "edit" an ad's creative. */
11240
- creative: z10.object({ creative_id: parentRefSchema2 }).optional(),
11241
- 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()
11242
11151
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11243
- var lookalikeSpecSchema = z10.object({
11244
- origin: z10.array(z10.object({ id: parentRefSchema2 })).min(1),
11245
- ratio: z10.number().min(0.01).max(0.2).optional(),
11246
- country: z10.string().length(2).optional()
11247
- });
11248
- var customAudienceCreateSchema = z10.object({
11249
- name: z10.string().min(1).max(META_LIMITS.audience.nameMax),
11250
- subtype: z10.enum(CUSTOM_AUDIENCE_SUBTYPES),
11251
- description: z10.string().max(500).optional(),
11252
- customer_file_source: z10.string().optional(),
11253
- 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(),
11254
11163
  lookalike_spec: lookalikeSpecSchema.optional(),
11255
11164
  /** Website/engagement rule — structural passthrough validated by Meta. */
11256
- rule: z10.record(z10.string(), z10.unknown()).optional()
11165
+ rule: z9.record(z9.string(), z9.unknown()).optional()
11257
11166
  }).superRefine((p, ctx) => {
11258
11167
  if (p.subtype === "LOOKALIKE" && !p.lookalike_spec) {
11259
11168
  ctx.addIssue({ code: "custom", path: ["lookalike_spec"], message: "LOOKALIKE audiences need a lookalike_spec" });
@@ -11262,16 +11171,16 @@ var customAudienceCreateSchema = z10.object({
11262
11171
  ctx.addIssue({ code: "custom", path: ["rule"], message: `${p.subtype} audiences need a rule (use --file)` });
11263
11172
  }
11264
11173
  });
11265
- var customAudienceUpdateSchema = z10.object({
11266
- name: z10.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
11267
- 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()
11268
11177
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
11269
- var mediaUploadSchema = z10.object({
11270
- kind: z10.enum(MEDIA_KINDS),
11178
+ var mediaUploadSchema = z9.object({
11179
+ kind: z9.enum(MEDIA_KINDS),
11271
11180
  bakerImageId: bakerMediaIdSchema2.optional(),
11272
11181
  bakerVideoId: bakerMediaIdSchema2.optional(),
11273
11182
  /** Optional display name / filename hint. */
11274
- name: z10.string().max(255).optional()
11183
+ name: z9.string().max(255).optional()
11275
11184
  }).superRefine((p, ctx) => {
11276
11185
  if (p.kind === "image" && !p.bakerImageId) {
11277
11186
  ctx.addIssue({ code: "custom", path: ["bakerImageId"], message: "image uploads need a bakerImageId" });
@@ -11293,16 +11202,16 @@ var META_DRAFT_OP_KINDS = [
11293
11202
  "customAudience.update",
11294
11203
  "media.upload"
11295
11204
  ];
11296
- var metaDraftOpKindSchema = z10.enum(META_DRAFT_OP_KINDS);
11297
- var accountIdSchema2 = z10.string().regex(NUMERIC_ID_REGEX3, "accountId must be the bare numeric ad account id");
11298
- 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]);
11299
11208
  function createOp3(kind, payload) {
11300
- return z10.object({ kind: z10.literal(kind), accountId: accountIdSchema2, payload });
11209
+ return z9.object({ kind: z9.literal(kind), accountId: accountIdSchema2, payload });
11301
11210
  }
11302
11211
  function updateOp3(kind, payload) {
11303
- 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 });
11304
11213
  }
11305
- var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
11214
+ var metaDraftOpInputSchema = z9.discriminatedUnion("kind", [
11306
11215
  createOp3("campaign.create", campaignCreateSchema3),
11307
11216
  updateOp3("campaign.update", campaignUpdateSchema3),
11308
11217
  createOp3("adSet.create", adSetCreateSchema),
@@ -11317,89 +11226,89 @@ var metaDraftOpInputSchema = z10.discriminatedUnion("kind", [
11317
11226
  ]);
11318
11227
 
11319
11228
  // ../api/src/ads-meta/wire.ts
11320
- import { z as z11 } from "zod";
11321
- var metaWriteModeSchema = z11.enum(["live", "simulated"]);
11322
- var metaDraftOpResultSchema = z11.object({
11323
- 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"]),
11324
11233
  /** The resulting Meta node id (campaign/adset/creative/ad/audience) or simulated id. */
11325
- id: z11.string().optional(),
11234
+ id: z10.string().optional(),
11326
11235
  /** For media.upload ops: the resulting image hash. */
11327
- hash: z11.string().optional(),
11328
- error: z11.string().optional(),
11329
- skippedBecause: z11.string().optional(),
11330
- executedAt: z11.number().optional()
11236
+ hash: z10.string().optional(),
11237
+ error: z10.string().optional(),
11238
+ skippedBecause: z10.string().optional(),
11239
+ executedAt: z10.number().optional()
11331
11240
  });
11332
- var metaDraftStageRequestSchema = z11.object({
11333
- chatId: z11.string(),
11241
+ var metaDraftStageRequestSchema = z10.object({
11242
+ chatId: z10.string(),
11334
11243
  op: metaDraftOpInputSchema
11335
11244
  });
11336
- var metaDraftStageResponseSchema = z11.object({
11337
- staged: z11.literal(true),
11338
- ref: z11.string(),
11245
+ var metaDraftStageResponseSchema = z10.object({
11246
+ staged: z10.literal(true),
11247
+ ref: z10.string(),
11339
11248
  kind: metaDraftOpKindSchema,
11340
11249
  mode: metaWriteModeSchema,
11341
- dependsOn: z11.array(z11.string()),
11342
- summary: z11.string(),
11343
- warnings: z11.array(z11.string()),
11250
+ dependsOn: z10.array(z10.string()),
11251
+ summary: z10.string(),
11252
+ warnings: z10.array(z10.string()),
11344
11253
  /** True when the op amended an already-staged op in place instead of appending a new one. */
11345
- amended: z11.boolean().optional()
11346
- });
11347
- var metaDraftDuplicateRequestSchema = z11.object({
11348
- chatId: z11.string(),
11349
- accountId: z11.string(),
11350
- entity: z11.enum(["campaign", "adSet", "ad"]),
11351
- sourceId: z11.string(),
11352
- 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(),
11353
11262
  /** Pause the original after the copy publishes. */
11354
- replace: z11.boolean().optional()
11263
+ replace: z10.boolean().optional()
11355
11264
  });
11356
- var metaDraftOpViewSchema = z11.object({
11357
- ref: z11.string(),
11265
+ var metaDraftOpViewSchema = z10.object({
11266
+ ref: z10.string(),
11358
11267
  kind: metaDraftOpKindSchema,
11359
- accountId: z11.string(),
11360
- target: z11.string().optional(),
11361
- dependsOn: z11.array(z11.string()),
11362
- summary: z11.string(),
11363
- 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(),
11364
11273
  result: metaDraftOpResultSchema.optional()
11365
11274
  });
11366
- var metaDraftListRequestSchema = z11.object({
11367
- chatId: z11.string()
11275
+ var metaDraftListRequestSchema = z10.object({
11276
+ chatId: z10.string()
11368
11277
  });
11369
- var metaDraftAdvisorySchema = z11.object({
11370
- ref: z11.string(),
11371
- message: z11.string()
11278
+ var metaDraftAdvisorySchema = z10.object({
11279
+ ref: z10.string(),
11280
+ message: z10.string()
11372
11281
  });
11373
- var metaDraftListResponseSchema = z11.object({
11374
- status: z11.enum(["active", "publishing", "applied", "discarded", "none"]),
11282
+ var metaDraftListResponseSchema = z10.object({
11283
+ status: z10.enum(["active", "publishing", "applied", "discarded", "none"]),
11375
11284
  mode: metaWriteModeSchema,
11376
- count: z11.number(),
11377
- ops: z11.array(metaDraftOpViewSchema),
11285
+ count: z10.number(),
11286
+ ops: z10.array(metaDraftOpViewSchema),
11378
11287
  /** Non-blocking cross-op quality advisories — "good campaign, not just valid". */
11379
- advisories: z11.array(metaDraftAdvisorySchema)
11288
+ advisories: z10.array(metaDraftAdvisorySchema)
11380
11289
  });
11381
- var metaDraftRemoveRequestSchema = z11.object({
11382
- chatId: z11.string(),
11383
- ref: z11.string()
11290
+ var metaDraftRemoveRequestSchema = z10.object({
11291
+ chatId: z10.string(),
11292
+ ref: z10.string()
11384
11293
  });
11385
- var metaDraftRemoveResponseSchema = z11.object({
11294
+ var metaDraftRemoveResponseSchema = z10.object({
11386
11295
  /** The requested ref plus any dependents removed by cascade. */
11387
- removed: z11.array(z11.string())
11296
+ removed: z10.array(z10.string())
11388
11297
  });
11389
- var metaDraftClearRequestSchema = z11.object({
11390
- chatId: z11.string()
11298
+ var metaDraftClearRequestSchema = z10.object({
11299
+ chatId: z10.string()
11391
11300
  });
11392
- var metaDraftClearResponseSchema = z11.object({
11393
- cleared: z11.number()
11301
+ var metaDraftClearResponseSchema = z10.object({
11302
+ cleared: z10.number()
11394
11303
  });
11395
- var metaFieldErrorSchema = z11.object({
11396
- path: z11.string(),
11397
- message: z11.string()
11304
+ var metaFieldErrorSchema = z10.object({
11305
+ path: z10.string(),
11306
+ message: z10.string()
11398
11307
  });
11399
- var metaDraftErrorResponseSchema = z11.object({
11400
- code: z11.string(),
11401
- error: z11.string(),
11402
- fields: z11.array(metaFieldErrorSchema).optional()
11308
+ var metaDraftErrorResponseSchema = z10.object({
11309
+ code: z10.string(),
11310
+ error: z10.string(),
11311
+ fields: z10.array(metaFieldErrorSchema).optional()
11403
11312
  });
11404
11313
 
11405
11314
  // src/commands/ads/meta/write-shared.ts
@@ -11410,19 +11319,19 @@ function failWriteValidation3(message) {
11410
11319
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
11411
11320
  process.exit(1);
11412
11321
  }
11413
- function loadJsonFileArg3(path12) {
11414
- if (typeof path12 !== "string" || path12.length === 0) {
11322
+ function loadJsonFileArg3(path14) {
11323
+ if (typeof path14 !== "string" || path14.length === 0) {
11415
11324
  return {};
11416
11325
  }
11417
11326
  try {
11418
- const parsed = JSON.parse(readFileSync8(path12, "utf8"));
11327
+ const parsed = JSON.parse(readFileSync8(path14, "utf8"));
11419
11328
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
11420
- failWriteValidation3(`${path12} must contain a JSON object`);
11329
+ failWriteValidation3(`${path14} must contain a JSON object`);
11421
11330
  }
11422
11331
  return parsed;
11423
11332
  } catch (err) {
11424
11333
  if (err instanceof SyntaxError) {
11425
- failWriteValidation3(`${path12} is not valid JSON: ${err.message}`);
11334
+ failWriteValidation3(`${path14} is not valid JSON: ${err.message}`);
11426
11335
  }
11427
11336
  throw err;
11428
11337
  }
@@ -14485,7 +14394,7 @@ async function probeDuration(filePath) {
14485
14394
 
14486
14395
  // src/commands/canvas/run.ts
14487
14396
  import { readFile as readFile2 } from "fs/promises";
14488
- import path4 from "path";
14397
+ import path5 from "path";
14489
14398
  import { defineCommand as defineCommand88 } from "citty";
14490
14399
 
14491
14400
  // src/commands/canvas/placeholders.ts
@@ -14529,9 +14438,102 @@ function isResolvableRelative(value) {
14529
14438
  return typeof value === "string" && value.length > 0 && !value.includes("[TODO") && !path2.isAbsolute(value);
14530
14439
  }
14531
14440
 
14441
+ // src/commands/canvas/run-record.ts
14442
+ import path3 from "path";
14443
+ var MAX_RUN_NODES = 200;
14444
+ var MAX_OUTPUTS_PER_NODE = 10;
14445
+ var MAX_FINAL_OUTPUTS = 10;
14446
+ var MAX_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
+
14532
14534
  // src/commands/canvas/run-retention.ts
14533
14535
  import { rm } from "fs/promises";
14534
- import path3 from "path";
14536
+ import path4 from "path";
14535
14537
  function runDirsToPrune(entries, keep, currentRunId) {
14536
14538
  const runs = entries.filter((e) => /^r_[0-9A-Za-z]+$/.test(e) && e !== currentRunId).sort();
14537
14539
  if (keep <= 0) return runs;
@@ -14548,7 +14550,7 @@ async function pruneOldRuns(outputsDir, keep, currentRunId, log) {
14548
14550
  const toPrune = runDirsToPrune(entries, keep, currentRunId);
14549
14551
  if (toPrune.length === 0) return;
14550
14552
  for (const dir of toPrune) {
14551
- await rm(path3.join(outputsDir, dir), { recursive: true, force: true }).catch(
14553
+ await rm(path4.join(outputsDir, dir), { recursive: true, force: true }).catch(
14552
14554
  (e) => log(`[prune ] could not remove ${dir}: ${e.message}`)
14553
14555
  );
14554
14556
  }
@@ -14575,10 +14577,22 @@ var runCommand = defineCommand88({
14575
14577
  "keep-runs": {
14576
14578
  type: "string",
14577
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)"
14578
14592
  }
14579
14593
  },
14580
14594
  async run({ args }) {
14581
- const filePath = path4.resolve(String(args.file));
14595
+ const filePath = path5.resolve(String(args.file));
14582
14596
  const raw = await readFile2(filePath, "utf8");
14583
14597
  let parsed;
14584
14598
  try {
@@ -14589,7 +14603,7 @@ var runCommand = defineCommand88({
14589
14603
  `);
14590
14604
  process.exit(2);
14591
14605
  }
14592
- parsed = resolveRelativeCanvasPaths(parsed, path4.dirname(filePath));
14606
+ parsed = resolveRelativeCanvasPaths(parsed, path5.dirname(filePath));
14593
14607
  const pending = unsuppliedPlaceholderAssets(parsed);
14594
14608
  if (pending.length > 0) {
14595
14609
  process.stderr.write(
@@ -14609,16 +14623,26 @@ var runCommand = defineCommand88({
14609
14623
  );
14610
14624
  process.exit(2);
14611
14625
  }
14626
+ const remoteCache = args["remote-cache"] !== void 0 ? String(args["remote-cache"]) !== "off" : void 0;
14612
14627
  const engine = createEngineFromEnv({
14613
14628
  cacheDir: args["cache-dir"] ? String(args["cache-dir"]) : void 0,
14614
14629
  outputsDir: args["outputs-dir"] ? String(args["outputs-dir"]) : void 0,
14615
14630
  log: (line) => process.stdout.write(`${line}
14616
- `)
14631
+ `),
14632
+ remoteCache
14617
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();
14618
14642
  try {
14619
14643
  const policy = args["cache-policy"] ?? "read_write";
14620
14644
  const result = await engine.run(parsed, {
14621
- run_id: args["run-id"] ? String(args["run-id"]) : void 0,
14645
+ run_id: runId,
14622
14646
  cache_policy: policy,
14623
14647
  concurrency: resolveConcurrency(
14624
14648
  // --concurrency wins; --parallel is the discoverable alias for the same bound.
@@ -14626,9 +14650,10 @@ var runCommand = defineCommand88({
14626
14650
  process.env.BAKER_CANVAS_CONCURRENCY
14627
14651
  )
14628
14652
  });
14653
+ if (record) await record(buildRunRecord(result, recordMeta));
14629
14654
  const keepRuns = args["keep-runs"] !== void 0 ? Number(args["keep-runs"]) : void 0;
14630
14655
  if (keepRuns !== void 0 && Number.isFinite(keepRuns)) {
14631
- 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");
14632
14657
  await pruneOldRuns(outputsDir, keepRuns, result.run_id, (line) => process.stdout.write(`${line}
14633
14658
  `));
14634
14659
  }
@@ -14656,6 +14681,7 @@ var runCommand = defineCommand88({
14656
14681
  }
14657
14682
  if (e instanceof LayerExecutionError) {
14658
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));
14659
14685
  process.stderr.write(
14660
14686
  `${JSON.stringify({ ok: false, error: { code: "runtime", message: e.message, failures } }, null, 2)}
14661
14687
  `
@@ -14663,40 +14689,54 @@ var runCommand = defineCommand88({
14663
14689
  process.exit(1);
14664
14690
  }
14665
14691
  const msg = e instanceof Error ? e.message : String(e);
14692
+ if (record) await record(buildFailedRunRecord(runId, msg, recordMeta));
14666
14693
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "runtime", message: msg } }, null, 2)}
14667
14694
  `);
14668
14695
  process.exit(1);
14669
14696
  }
14670
14697
  }
14671
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
+ }
14672
14712
 
14673
14713
  // src/commands/canvas/scaffold-static-ad.ts
14674
- import { readFile as readFile3, writeFile } from "fs/promises";
14675
- import path6 from "path";
14714
+ import { access, cp, mkdir, readFile as readFile3, writeFile } from "fs/promises";
14715
+ import path8 from "path";
14676
14716
  import { defineCommand as defineCommand89 } from "citty";
14677
14717
 
14678
14718
  // src/engine/scaffold/staticAd.ts
14679
- import { z as z12 } from "zod";
14719
+ import { z as z11 } from "zod";
14680
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"]);
14681
14721
  var DEFAULT_ASPECT_RATIO = "9:16";
14682
- var Blueprint = z12.object({
14683
- meta: z12.object({ estimated_aspect_ratio: z12.string().optional() }).loose().optional(),
14684
- 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()
14685
14725
  }).loose();
14686
- var ElementLocator = z12.object({
14687
- collection: z12.enum(["subjects", "people", "brands_logos"]),
14688
- index: z12.number().int().nonnegative()
14726
+ var ElementLocator = z11.object({
14727
+ collection: z11.enum(["subjects", "people", "brands_logos"]),
14728
+ index: z11.number().int().nonnegative()
14689
14729
  }).loose();
14690
- var MainElement = z12.object({
14730
+ var MainElement = z11.object({
14691
14731
  // logo | product | person | animal | badge | other
14692
- type: z12.string(),
14693
- label: z12.string().optional(),
14694
- description: z12.string().optional(),
14695
- expression: z12.string().nullable().optional(),
14696
- 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(),
14697
14737
  locator: ElementLocator.optional()
14698
14738
  }).loose();
14699
- var MainElements = z12.array(MainElement);
14739
+ var MainElements = z11.array(MainElement);
14700
14740
  function sanitizeId(raw, fallback) {
14701
14741
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
14702
14742
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -14858,18 +14898,106 @@ function staticAdReport(input, elementsInput, opts) {
14858
14898
  };
14859
14899
  }
14860
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
+
14861
14960
  // src/commands/canvas/scaffold-static-ad-paths.ts
14862
- import path5 from "path";
14863
- function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd()) {
14961
+ import path7 from "path";
14962
+ function resolveScaffoldStaticAdPaths(rawFile, out, cwd = process.cwd(), slug) {
14864
14963
  const file = rawFile.trim();
14865
14964
  const imageIsUrl = /^https?:\/\//i.test(file);
14866
- const imageSource = imageIsUrl ? file : path5.resolve(cwd, file);
14867
- const outPath = out ? path5.resolve(cwd, out) : imageIsUrl ? path5.join(cwd, "static-ad.canvas.json") : path5.join(path5.dirname(imageSource), "static-ad.canvas.json");
14868
- const blueprintPath = path5.join(path5.dirname(outPath), "prompt.json");
14869
- 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);
14870
14977
  }
14871
14978
 
14872
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
+ }
14873
15001
  function resolveModel(kind, preferred) {
14874
15002
  const ids = Object.keys(MODEL_REGISTRY[kind]);
14875
15003
  return ids.includes(preferred) ? preferred : ids[0] ?? preferred;
@@ -15029,6 +15157,16 @@ var scaffoldStaticAdCommand = defineCommand89({
15029
15157
  file: { type: "positional", required: true, description: "Path or http(s) URL to the source/inspiration image" },
15030
15158
  context: { type: "string", description: "Known provenance (advertiser, category, market) to ground the describe" },
15031
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" },
15032
15170
  "describe-model": { type: "string", description: "Override the image_describe model id" },
15033
15171
  "select-model": { type: "string", description: "Override the text_generate model id for element selection" },
15034
15172
  "layout-model": { type: "string", description: "Override the text_generate model id for the layout pass" },
@@ -15037,10 +15175,21 @@ var scaffoldStaticAdCommand = defineCommand89({
15037
15175
  "skip-font": { type: "boolean", description: "Skip the brand-font \u2192 type-specimen slot" }
15038
15176
  },
15039
15177
  async run({ args }) {
15040
- 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(
15041
15187
  String(args.file),
15042
- args.out ? String(args.out) : void 0
15188
+ args.out ? String(args.out) : void 0,
15189
+ process.cwd(),
15190
+ slug
15043
15191
  );
15192
+ await mkdir(path8.dirname(outPath), { recursive: true });
15044
15193
  const { describeModel, selectModel, layoutModel, genModel } = resolveModels(args);
15045
15194
  const describeCanvas = buildDescribeCanvas(
15046
15195
  imageSource,
@@ -15057,11 +15206,21 @@ var scaffoldStaticAdCommand = defineCommand89({
15057
15206
  }
15058
15207
  await writeFile(blueprintPath, `${JSON.stringify(annotated, null, 2)}
15059
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
+ }
15060
15219
  const opts = {
15061
15220
  genModel,
15062
- imagePath: imageSource,
15063
- imageIsUrl,
15064
- blueprintPath,
15221
+ imagePath: canvasImagePath,
15222
+ imageIsUrl: canvasImageIsUrl,
15223
+ blueprintPath: canvasBlueprintPath,
15065
15224
  aspectRatio: args.aspect ? String(args.aspect) : void 0,
15066
15225
  includeFont: !args["skip-font"]
15067
15226
  };
@@ -15083,12 +15242,31 @@ var scaffoldStaticAdCommand = defineCommand89({
15083
15242
  }
15084
15243
  await writeFile(outPath, `${JSON.stringify(canvas, null, 2)}
15085
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
+ }
15086
15262
  process.stdout.write(
15087
15263
  `${JSON.stringify(
15088
15264
  {
15089
15265
  ok: true,
15090
15266
  canvas_path: outPath,
15091
15267
  prompt_path: blueprintPath,
15268
+ definition_path: definitionPath ?? void 0,
15269
+ source_reference: sourceRelPath ?? void 0,
15092
15270
  output: canvas.output,
15093
15271
  models: { describe: describeModel, select: selectModel, layout: layoutModel, gen: opts.genModel },
15094
15272
  aspect_ratio: report.aspect_ratio,
@@ -15099,7 +15277,7 @@ var scaffoldStaticAdCommand = defineCommand89({
15099
15277
  run_estimated_credits: validation.estimatedCredits
15100
15278
  },
15101
15279
  checklist: {
15102
- 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.`,
15103
15281
  assets_to_supply: report.elements,
15104
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)",
15105
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."
@@ -15114,8 +15292,8 @@ var scaffoldStaticAdCommand = defineCommand89({
15114
15292
  });
15115
15293
 
15116
15294
  // src/commands/canvas/scaffold-video.ts
15117
- import { cp, mkdir, readFile as readFile6, writeFile as writeFile2 } from "fs/promises";
15118
- 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";
15119
15297
  import { defineCommand as defineCommand90 } from "citty";
15120
15298
 
15121
15299
  // src/engine/nodes/local/lib/sceneDetect.ts
@@ -15232,7 +15410,7 @@ import { toCardinal as nwKo } from "n2words/ko-KR";
15232
15410
  import { toCardinal as nwNl } from "n2words/nl-NL";
15233
15411
  import { toCardinal as nwPl } from "n2words/pl-PL";
15234
15412
  import { toCardinal as nwPt } from "n2words/pt-PT";
15235
- import { z as z13 } from "zod";
15413
+ import { z as z12 } from "zod";
15236
15414
 
15237
15415
  // src/engine/scaffold/lib/shoot-modes.ts
15238
15416
  var SHOOT_MODES = [
@@ -15545,71 +15723,71 @@ function trimArgs(durationS, offsetS = 0, dims) {
15545
15723
  "{{out.video}}"
15546
15724
  ];
15547
15725
  }
15548
- var FrameAsset = z13.object({ url: z13.string().optional() }).loose().optional();
15549
- var DialogueLine = z13.object({
15550
- speaker: z13.string().optional(),
15551
- 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(),
15552
15730
  // Absolute seconds on the source timeline (the deconstruct emits both).
15553
- start_s: z13.number().optional(),
15554
- end_s: z13.number().optional(),
15555
- delivery: z13.string().optional(),
15556
- 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(),
15557
15735
  // DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element
15558
15736
  // presence alone can't answer that — a founder pictured in a polaroid close-up is
15559
15737
  // "present" yet the line is voiceover, and treating it as on-camera produced a
15560
15738
  // native Seedance lip-sync clip of a still photograph. `false` pins the line to
15561
15739
  // the VO path; absent keeps the presence-based decision (old blueprints).
15562
- on_camera: z13.boolean().optional()
15740
+ on_camera: z12.boolean().optional()
15563
15741
  }).loose();
15564
- var Sfx = z13.object({
15565
- at_s: z13.number().optional(),
15566
- duration_s: z13.number().optional(),
15567
- sound_effect_prompt: z13.string().optional(),
15568
- 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()
15569
15747
  }).loose();
15570
- var CompositionRegion = z13.object({
15748
+ var CompositionRegion = z12.object({
15571
15749
  // full | top | bottom | left | right | inset
15572
- panel: z13.string().optional(),
15750
+ panel: z12.string().optional(),
15573
15751
  // 9-grid anchor for an `inset` presenter box.
15574
- position: z13.string().optional(),
15575
- is_presenter: z13.boolean().optional(),
15752
+ position: z12.string().optional(),
15753
+ is_presenter: z12.boolean().optional(),
15576
15754
  // The cast id shown/speaking in this region (routes lip-sync + element refs).
15577
- cast_ref: z13.string().optional(),
15755
+ cast_ref: z12.string().optional(),
15578
15756
  // What the region's content IS: camera | screen_capture | static_graphic |
15579
15757
  // generated. Authoritative for routing when present (regex-over-prose fallback
15580
15758
  // otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the
15581
15759
  // overlay layer, never AI-generated.
15582
- kind: z13.string().optional(),
15760
+ kind: z12.string().optional(),
15583
15761
  // Opaque id naming the SPECIFIC on-screen document/note/app-state this
15584
15762
  // screen_capture region shows. Two scenes share it only when they show the SAME
15585
15763
  // recording continuing (scrolling/typing/waiting within it) — a genuinely
15586
15764
  // DIFFERENT document/note/recording (a source video splicing two screen captures)
15587
15765
  // gets a different id. Breaks a persistent-layout run into separate surface stubs
15588
15766
  // instead of asking the operator for one screenshot that can't cover both.
15589
- surface_id: z13.string().optional(),
15767
+ surface_id: z12.string().optional(),
15590
15768
  // Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style
15591
15769
  // presenter bubble inside a screen recording) — video-in-video the reproduction
15592
15770
  // must re-composite, not paint into the surface.
15593
- nested: z13.array(z13.object({}).loose()).optional(),
15594
- summary: z13.string().optional(),
15595
- frame_prompt: z13.string().optional(),
15596
- 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()
15597
15775
  }).loose();
15598
- var SceneComposition = z13.object({
15776
+ var SceneComposition = z12.object({
15599
15777
  // full_frame (default) | split_screen | pip | keyed_overlay
15600
- layout: z13.string().optional(),
15778
+ layout: z12.string().optional(),
15601
15779
  // split_screen only: vertical (top/bottom) | horizontal (left/right).
15602
- split_axis: z13.string().optional(),
15603
- regions: z13.array(CompositionRegion).optional()
15780
+ split_axis: z12.string().optional(),
15781
+ regions: z12.array(CompositionRegion).optional()
15604
15782
  }).loose();
15605
- var CameraMotion = z13.object({ movement: z13.string().optional(), detail: z13.string().optional() }).loose();
15606
- var TranscriptWord = z13.object({ text: z13.string().optional() }).loose();
15607
- var Scene = z13.object({
15608
- start_s: z13.number().optional(),
15609
- end_s: z13.number().optional(),
15610
- duration_s: z13.number().optional(),
15611
- summary: z13.string().optional(),
15612
- 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(),
15613
15791
  // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).
15614
15792
  // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold
15615
15793
  // builds one clip per region and stacks/overlays them into the scene picture.
@@ -15617,82 +15795,82 @@ var Scene = z13.object({
15617
15795
  // The capture "look" for this scene — selected from the ad-native shoot-mode
15618
15796
  // grammar (see lib/shoot-modes.ts). When absent the scaffold auto-derives a
15619
15797
  // UGC/product mode; a human can override per scene by setting this.
15620
- shoot_mode: z13.string().optional(),
15798
+ shoot_mode: z12.string().optional(),
15621
15799
  // Diegetic ambient the clip's native audio should carry (no music). When
15622
15800
  // absent the scene falls back to its shoot mode's default ambience.
15623
- ambient: z13.string().optional(),
15801
+ ambient: z12.string().optional(),
15624
15802
  camera_motion: CameraMotion.optional(),
15625
- start_frame_prompt: z13.string().optional(),
15626
- end_frame_prompt: z13.string().optional(),
15627
- 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(),
15628
15806
  // The scene's role in the ad's persuasion arc (DECON-supplied); drives the
15629
15807
  // script re-craft checklist. Inferred from position when absent.
15630
- narrative_role: z13.string().optional(),
15808
+ narrative_role: z12.string().optional(),
15631
15809
  // DECON-supplied on the HOOK scene: the engineered physical/emotional state that
15632
15810
  // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected
15633
15811
  // into the hook's start-frame description so the generator renders that state,
15634
15812
  // not a calm influencer (CCA-11).
15635
- 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(),
15636
15814
  // DECON-supplied per-scene location (so a gym hook isn't flattened to "home").
15637
- scene_setting: z13.string().optional(),
15815
+ scene_setting: z12.string().optional(),
15638
15816
  // How this scene cuts to the next (DECON-supplied). A recognized non-cut type
15639
15817
  // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the
15640
15818
  // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is
15641
15819
  // ignored (nothing follows it).
15642
- transition_out: z13.object({ type: z13.string().optional(), description: z13.string().optional() }).loose().optional(),
15643
- dialogue: z13.array(DialogueLine).optional(),
15644
- sfx: z13.array(Sfx).optional(),
15645
- overlays: z13.array(z13.unknown()).optional(),
15646
- 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(),
15647
15825
  // DECON-supplied: how much the picture itself moves within the shot. Gates the
15648
15826
  // flash-hold optimization — a sub-2s b-roll flash with REAL subject motion
15649
15827
  // (pouring, spreading, hands working) must stay a real clip; freezing it turns
15650
15828
  // a montage into a slideshow. Absent (old blueprints) keeps the cheap still.
15651
- motion_level: z13.enum(["static", "subtle", "dynamic"]).optional(),
15652
- transcript_slice: z13.array(TranscriptWord).optional(),
15829
+ motion_level: z12.enum(["static", "subtle", "dynamic"]).optional(),
15830
+ transcript_slice: z12.array(TranscriptWord).optional(),
15653
15831
  start_frame_asset: FrameAsset,
15654
15832
  end_frame_asset: FrameAsset,
15655
15833
  // DECON-supplied: true when this scene is a length-split CONTINUATION of the
15656
15834
  // previous one (the SAME physical shot, broken up only because it exceeded the
15657
15835
  // clip ceiling). The scaffold then shares the splice keyframe — this scene's
15658
15836
  // start frame IS the previous scene's end frame — so the join is seamless.
15659
- continues_previous: z13.boolean().optional()
15837
+ continues_previous: z12.boolean().optional()
15660
15838
  }).loose();
15661
- var VideoBlueprint = z13.object({
15662
- source: z13.object({ aspect_ratio: z13.string().optional(), duration_s: z13.number().optional() }).loose().optional(),
15663
- global: z13.object({
15664
- music: z13.object({
15665
- present: z13.boolean().optional(),
15666
- 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(),
15667
15845
  // Absolute second the music enters in the reference (the bed often
15668
15846
  // kicks in mid-ad, after the hook). We start the regenerated track here
15669
15847
  // instead of at 0 so the timing matches.
15670
- starts_at_s: z13.number().optional(),
15848
+ starts_at_s: z12.number().optional(),
15671
15849
  // Populated by the deconstruct when AudD (Shazam-style) recognizes the
15672
15850
  // reference track. We never reuse it — only style the regenerated bed.
15673
- 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()
15674
15852
  }).loose().optional(),
15675
- cast: z13.array(
15676
- z13.object({
15677
- id: z13.string().optional(),
15678
- description: z13.string().optional(),
15853
+ cast: z12.array(
15854
+ z12.object({
15855
+ id: z12.string().optional(),
15856
+ description: z12.string().optional(),
15679
15857
  // The deconstruct's note on the target-market localization (e.g. "native
15680
15858
  // French speaker") — read to derive the spoken-track language code.
15681
- market_localization_note: z13.string().optional()
15859
+ market_localization_note: z12.string().optional()
15682
15860
  }).loose()
15683
15861
  ).optional(),
15684
- voiceover: z13.object({
15862
+ voiceover: z12.object({
15685
15863
  // on_camera | mixed → mouths are on screen (lip-sync candidates);
15686
15864
  // voiceover | none → narration over the picture (no lip-sync).
15687
- mode: z13.string().optional(),
15688
- voice_description: z13.string().optional(),
15689
- persona: z13.string().optional()
15865
+ mode: z12.string().optional(),
15866
+ voice_description: z12.string().optional(),
15867
+ persona: z12.string().optional()
15690
15868
  }).loose().optional(),
15691
15869
  // Visual palette — read only to colour a clean brand-card/CTA plate (the
15692
15870
  // first hex is the dominant brand colour); never to drive frame generation.
15693
- 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()
15694
15872
  }).loose().optional(),
15695
- scenes: z13.array(Scene).min(1)
15873
+ scenes: z12.array(Scene).min(1)
15696
15874
  }).loose();
15697
15875
  function injectHookPhysicality(blueprint) {
15698
15876
  for (const scene of blueprint.scenes) {
@@ -15702,26 +15880,26 @@ function injectHookPhysicality(blueprint) {
15702
15880
  scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper \u2014 render it explicitly, not a calm pose: ${why}.`;
15703
15881
  }
15704
15882
  }
15705
- var AppearsItem = z13.union([z13.number(), z13.object({ scene: z13.number(), edge: z13.string().optional() }).loose()]);
15706
- 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({
15707
15885
  // person | animal | product | logo | badge | other
15708
- type: z13.string(),
15709
- label: z13.string().optional(),
15710
- description: z13.string().optional(),
15711
- 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(),
15712
15890
  // When the element maps to a global cast entry, its stable id (for annotation).
15713
- cast_id: z13.string().nullable().optional(),
15891
+ cast_id: z12.string().nullable().optional(),
15714
15892
  // The label of another element that is the SAME individual as this one, shown
15715
15893
  // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a
15716
15894
  // pink shirt and believer in a white shirt). Each look gets its own reference
15717
15895
  // slot, but the face/identity must stay identical across them.
15718
- same_as: z13.string().nullable().optional(),
15896
+ same_as: z12.string().nullable().optional(),
15719
15897
  // Scenes the element appears in. Either a bare list of scene indices (both
15720
15898
  // edges) or per-{scene,edge} entries. Both forms are accepted and merged.
15721
- scenes: z13.array(z13.number()).optional(),
15722
- appears_in: z13.array(AppearsItem).optional()
15899
+ scenes: z12.array(z12.number()).optional(),
15900
+ appears_in: z12.array(AppearsItem).optional()
15723
15901
  }).loose();
15724
- var RecurringElements = z13.array(RecurringElement);
15902
+ var RecurringElements = z12.array(RecurringElement);
15725
15903
  function sanitizeId2(raw, fallback) {
15726
15904
  const id = raw.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
15727
15905
  return /^[a-z]/.test(id) ? id : `${fallback}_${id}`.replace(/_+$/g, "") || fallback;
@@ -16139,7 +16317,7 @@ function scrubFloatSentences(text, floatDescs) {
16139
16317
  return kept;
16140
16318
  }
16141
16319
  function sceneFloatDescs(scene) {
16142
- const floats = z13.array(FloatingElement).safeParse(scene.floating_elements ?? []);
16320
+ const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
16143
16321
  if (!floats.success) return [];
16144
16322
  return floats.data.map((f) => f.description?.trim() ?? "").filter(Boolean);
16145
16323
  }
@@ -17479,25 +17657,25 @@ function buildSfxMusic(blueprint, nodes) {
17479
17657
  }
17480
17658
  return tracks;
17481
17659
  }
17482
- var OverlayStyle = z13.object({ color_hex: z13.string().optional(), background: z13.string().optional(), size: z13.string().optional() }).loose();
17483
- var Overlay = z13.object({
17484
- text: z13.string().optional(),
17485
- appears_at_s: z13.number().optional(),
17486
- duration_s: z13.number().optional(),
17487
- position: z13.string().optional(),
17488
- role: z13.string().optional(),
17489
- animation: z13.string().optional(),
17490
- 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(),
17491
17669
  style: OverlayStyle.optional()
17492
17670
  }).loose();
17493
- var FloatingElement = z13.object({
17494
- kind: z13.string().optional(),
17495
- description: z13.string().optional(),
17496
- brand_name: z13.string().nullish(),
17497
- what_it_represents: z13.string().optional(),
17498
- appears_at_s: z13.number().optional(),
17499
- duration_s: z13.number().optional(),
17500
- 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()
17501
17679
  }).loose();
17502
17680
  function escapeHtml(s) {
17503
17681
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -17529,7 +17707,7 @@ function positionClass(position) {
17529
17707
  function collectCaptions(blueprint) {
17530
17708
  return blueprint.scenes.flatMap((scene) => {
17531
17709
  const sceneStart = scene.start_s ?? 0;
17532
- const overlays = z13.array(Overlay).safeParse(scene.overlays ?? []);
17710
+ const overlays = z12.array(Overlay).safeParse(scene.overlays ?? []);
17533
17711
  return overlays.success ? overlays.data.filter((ov) => Boolean(ov.text?.trim())).map((ov) => {
17534
17712
  const at = ov.appears_at_s ?? sceneStart;
17535
17713
  return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };
@@ -17609,7 +17787,7 @@ function collectFloatWindows(blueprint, uiRouted) {
17609
17787
  const windows = /* @__PURE__ */ new Map();
17610
17788
  blueprint.scenes.forEach((scene, i) => {
17611
17789
  const sceneStart = scene.start_s ?? 0;
17612
- const floats = z13.array(FloatingElement).safeParse(scene.floating_elements ?? []);
17790
+ const floats = z12.array(FloatingElement).safeParse(scene.floating_elements ?? []);
17613
17791
  if (!floats.success) return;
17614
17792
  for (const fe of floats.data) {
17615
17793
  const at = fe.appears_at_s ?? sceneStart;
@@ -17995,8 +18173,8 @@ function buildMotionBoard(blueprint) {
17995
18173
  const end_s = scene.end_s ?? start_s + sceneDurationS(scene);
17996
18174
  cursor = end_s;
17997
18175
  const spoken = sceneSpokenText(scene);
17998
- const overlays = z13.array(Overlay).safeParse(scene.overlays ?? []);
17999
- 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 ?? []);
18000
18178
  const graphics = [
18001
18179
  ...(overlays.success ? overlays.data : []).filter((ov) => ov.text?.trim()).map((ov) => ({
18002
18180
  kind: "text",
@@ -18223,23 +18401,23 @@ function videoReport(input, elementsInput) {
18223
18401
 
18224
18402
  // src/commands/canvas/composition-path.ts
18225
18403
  import { existsSync as existsSync3 } from "fs";
18226
- import path7 from "path";
18404
+ import path9 from "path";
18227
18405
  function resolveShippedCanvasDir(name, startDir, exists = existsSync3, maxDepth = 8) {
18228
- const rel = path7.join("canvas", name);
18406
+ const rel = path9.join("canvas", name);
18229
18407
  let dir = startDir;
18230
18408
  for (let i = 0; i < maxDepth; i++) {
18231
- const candidate = path7.join(dir, rel);
18232
- if (exists(path7.join(candidate, "meta.json"))) return candidate;
18233
- 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);
18234
18412
  if (parent === dir) break;
18235
18413
  dir = parent;
18236
18414
  }
18237
- return path7.resolve(startDir, "../../../", rel);
18415
+ return path9.resolve(startDir, "../../../", rel);
18238
18416
  }
18239
18417
 
18240
18418
  // src/commands/canvas/gitignore.ts
18241
18419
  import { appendFile, readFile as readFile5 } from "fs/promises";
18242
- import path8 from "path";
18420
+ import path10 from "path";
18243
18421
  function missingGitignoreEntries(existing, entries) {
18244
18422
  const present = new Set(
18245
18423
  existing.split("\n").map((l) => l.trim().replace(/\/+$/, "")).filter((l) => l.length > 0 && !l.startsWith("#"))
@@ -18247,7 +18425,7 @@ function missingGitignoreEntries(existing, entries) {
18247
18425
  return entries.filter((e) => !present.has(e.trim().replace(/\/+$/, "")));
18248
18426
  }
18249
18427
  async function ensureGitignore(dir, entries) {
18250
- const file = path8.join(dir, ".gitignore");
18428
+ const file = path10.join(dir, ".gitignore");
18251
18429
  let existing;
18252
18430
  try {
18253
18431
  existing = await readFile5(file, "utf8");
@@ -18308,8 +18486,8 @@ async function loadTranscriptBestEffort(ref) {
18308
18486
  async function stageCaptions(outDir, transcript) {
18309
18487
  const text = transcript?.trim();
18310
18488
  if (!text || text === "[]") return {};
18311
- const compositionPath = path9.join(outDir, "tiktok-captions-composition");
18312
- 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 });
18313
18491
  return { compositionPath };
18314
18492
  }
18315
18493
  function patchCompositionMeta(metaJson, dims) {
@@ -18326,10 +18504,10 @@ function patchCompositionHtml(html, dims) {
18326
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`);
18327
18505
  }
18328
18506
  async function stampCompositionDims(compositionDir, dims) {
18329
- const metaPath = path9.join(compositionDir, "meta.json");
18507
+ const metaPath = path11.join(compositionDir, "meta.json");
18330
18508
  const rawMeta = await readFile6(metaPath, "utf8");
18331
18509
  await writeFile2(metaPath, patchCompositionMeta(rawMeta, dims), "utf8");
18332
- const htmlPath = path9.join(compositionDir, "index.html");
18510
+ const htmlPath = path11.join(compositionDir, "index.html");
18333
18511
  const rawHtml = await readFile6(htmlPath, "utf8");
18334
18512
  await writeFile2(htmlPath, patchCompositionHtml(rawHtml, dims), "utf8");
18335
18513
  }
@@ -18469,6 +18647,10 @@ var scaffoldVideoCommand = defineCommand90({
18469
18647
  args: {
18470
18648
  file: { type: "positional", required: true, description: "Path to the reference video" },
18471
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
+ },
18472
18654
  frames: { type: "string", description: '"generate" (default, anchored regen) or "reuse" (wire real frames in)' },
18473
18655
  ambient: {
18474
18656
  type: "boolean",
@@ -18495,11 +18677,19 @@ var scaffoldVideoCommand = defineCommand90({
18495
18677
  }
18496
18678
  },
18497
18679
  async run({ args }) {
18498
- const videoPath = path9.resolve(String(args.file));
18499
- const base = path9.basename(videoPath, path9.extname(videoPath));
18500
- const outPath = args.out ? path9.resolve(String(args.out)) : path9.join(path9.dirname(videoPath), `${base}.video.canvas.json`);
18501
- const outDir = path9.dirname(outPath);
18502
- 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");
18503
18693
  const frames = args.frames === "reuse" ? "reuse" : "generate";
18504
18694
  const maxScenes = args["max-scenes"] ? Number(args["max-scenes"]) : void 0;
18505
18695
  if (Number.isFinite(maxScenes)) {
@@ -18518,7 +18708,7 @@ var scaffoldVideoCommand = defineCommand90({
18518
18708
  shotCuts
18519
18709
  });
18520
18710
  const { blueprint, elements, transcript, creditsSpent } = await runAnalysisPasses(deconstructCanvas, selectModel);
18521
- await mkdir(outDir, { recursive: true });
18711
+ await mkdir2(outDir, { recursive: true });
18522
18712
  const annotated = annotateBlueprintWithElements(blueprint, elements);
18523
18713
  await writeFile2(blueprintPath, `${JSON.stringify(annotated, null, 2)}
18524
18714
  `, "utf8");
@@ -18539,10 +18729,10 @@ var scaffoldVideoCommand = defineCommand90({
18539
18729
  `
18540
18730
  );
18541
18731
  }
18542
- const compositionDest = path9.join(outDir, "video-overlay-composition");
18543
- 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 });
18544
18734
  await stampCompositionDims(compositionDest, outDims);
18545
- const indexPath = path9.join(compositionDest, "index.html");
18735
+ const indexPath = path11.join(compositionDest, "index.html");
18546
18736
  const overlayHtml = buildOverlayHtml(blueprint, { captionsActive: Boolean(transcript) });
18547
18737
  const indexHtml = await readFile6(indexPath, "utf8");
18548
18738
  const injected = indexHtml.replace("<!--OVERLAYS-->", () => overlayHtml);
@@ -18558,9 +18748,9 @@ var scaffoldVideoCommand = defineCommand90({
18558
18748
  const opts = {
18559
18749
  imageModel,
18560
18750
  videoModel,
18561
- overlayCompositionPath: path9.relative(outDir, compositionDest),
18562
- captionsCompositionPath: captions.compositionPath ? path9.relative(outDir, captions.compositionPath) : void 0,
18563
- 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),
18564
18754
  frames,
18565
18755
  ambient: Boolean(args.ambient),
18566
18756
  ...args.aspect ? { aspect: String(args.aspect) } : {},
@@ -18618,7 +18808,7 @@ var scaffoldVideoCommand = defineCommand90({
18618
18808
  run_estimated_credits: validation.estimatedCredits
18619
18809
  },
18620
18810
  checklist: {
18621
- 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.`,
18622
18812
  recurring_elements_to_supply: report.elements,
18623
18813
  voices_to_confirm: report.dialogue.map((d) => ({
18624
18814
  scene: d.scene,
@@ -18645,7 +18835,7 @@ var scaffoldVideoCommand = defineCommand90({
18645
18835
 
18646
18836
  // src/commands/canvas/set-prompt.ts
18647
18837
  import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
18648
- import path10 from "path";
18838
+ import path12 from "path";
18649
18839
  import { defineCommand as defineCommand91 } from "citty";
18650
18840
  function setNodePrompt(canvas, nodeId, text) {
18651
18841
  const nodes = canvas?.nodes;
@@ -18673,7 +18863,7 @@ var setPromptCommand = defineCommand91({
18673
18863
  "text-file": { type: "string", description: "Read the new prompt from a UTF-8 file (preserves accents/newlines)" }
18674
18864
  },
18675
18865
  async run({ args }) {
18676
- const filePath = path10.resolve(String(args.file));
18866
+ const filePath = path12.resolve(String(args.file));
18677
18867
  let canvas;
18678
18868
  try {
18679
18869
  canvas = JSON.parse(await readFile7(filePath, "utf8"));
@@ -18683,7 +18873,7 @@ var setPromptCommand = defineCommand91({
18683
18873
  process.exit(2);
18684
18874
  }
18685
18875
  let text;
18686
- 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");
18687
18877
  else if (args.text !== void 0) text = String(args.text);
18688
18878
  else {
18689
18879
  process.stderr.write(
@@ -18704,7 +18894,7 @@ var setPromptCommand = defineCommand91({
18704
18894
  process.exit(2);
18705
18895
  return;
18706
18896
  }
18707
- const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path10.dirname(filePath)), defaultRegistry());
18897
+ const validation = await validateCanvasDeep(resolveRelativeCanvasPaths(updated, path12.dirname(filePath)), defaultRegistry());
18708
18898
  if (!validation.ok) {
18709
18899
  process.stderr.write(`${JSON.stringify({ ok: false, error: { code: "validation", issues: validation.issues } }, null, 2)}
18710
18900
  `);
@@ -18720,7 +18910,7 @@ var setPromptCommand = defineCommand91({
18720
18910
 
18721
18911
  // src/commands/canvas/validate.ts
18722
18912
  import { readFile as readFile8 } from "fs/promises";
18723
- import path11 from "path";
18913
+ import path13 from "path";
18724
18914
  import { defineCommand as defineCommand92 } from "citty";
18725
18915
  var validateCommand = defineCommand92({
18726
18916
  meta: {
@@ -18729,7 +18919,7 @@ var validateCommand = defineCommand92({
18729
18919
  },
18730
18920
  args: { file: { type: "positional", required: true, description: "Path to canvas JSON" } },
18731
18921
  async run({ args }) {
18732
- const filePath = path11.resolve(String(args.file));
18922
+ const filePath = path13.resolve(String(args.file));
18733
18923
  const raw = await readFile8(filePath, "utf8");
18734
18924
  let parsed;
18735
18925
  try {
@@ -18740,7 +18930,7 @@ var validateCommand = defineCommand92({
18740
18930
  `);
18741
18931
  process.exit(2);
18742
18932
  }
18743
- parsed = resolveRelativeCanvasPaths(parsed, path11.dirname(filePath));
18933
+ parsed = resolveRelativeCanvasPaths(parsed, path13.dirname(filePath));
18744
18934
  const result = await validateCanvasDeep(parsed, defaultRegistry());
18745
18935
  if (!result.ok) {
18746
18936
  process.stderr.write(`${JSON.stringify({ ok: false, issues: result.issues }, null, 2)}
@@ -18877,6 +19067,16 @@ registerSchema({
18877
19067
  type: "string",
18878
19068
  description: "Optional URL of the original reference ad",
18879
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
18880
19080
  }
18881
19081
  }
18882
19082
  });
@@ -18886,6 +19086,13 @@ function detectCreativeContentType(filePath) {
18886
19086
  unsupportedMessage: "Unsupported creative image extension. Use PNG, JPG, or WebP."
18887
19087
  });
18888
19088
  }
19089
+ function chatIdFromEnv() {
19090
+ try {
19091
+ return getEnv().BAKER_CHAT_ID || void 0;
19092
+ } catch {
19093
+ return void 0;
19094
+ }
19095
+ }
18889
19096
  function parseOptionalUrl(value) {
18890
19097
  if (value === void 0 || value.trim() === "") {
18891
19098
  return void 0;
@@ -18916,7 +19123,11 @@ async function publishCreative(args, deps = defaultImageApiDeps) {
18916
19123
  return publishImageAsCreative(deps, {
18917
19124
  imageId: upload.imageId,
18918
19125
  title,
18919
- 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()
18920
19131
  });
18921
19132
  }
18922
19133
  var publishCommand = defineCommand94({
@@ -18932,6 +19143,16 @@ var publishCommand = defineCommand94({
18932
19143
  type: "string",
18933
19144
  description: "Optional URL of the original reference ad",
18934
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
18935
19156
  }
18936
19157
  },
18937
19158
  run: async ({ args }) => {
@@ -18950,7 +19171,9 @@ var publishCommand = defineCommand94({
18950
19171
  file,
18951
19172
  title,
18952
19173
  context: args.context,
18953
- sourceReferenceUrl: args.sourceReferenceUrl
19174
+ sourceReferenceUrl: args.sourceReferenceUrl,
19175
+ slug: args.slug,
19176
+ runId: args.runId
18954
19177
  });
18955
19178
  writeJson({ ok: true, data });
18956
19179
  } catch (err) {
@@ -19848,9 +20071,9 @@ async function readImageBuffer(pathOrUrl) {
19848
20071
  }
19849
20072
  return readFile10(pathOrUrl);
19850
20073
  }
19851
- async function isDirectory(path12) {
20074
+ async function isDirectory(path14) {
19852
20075
  try {
19853
- const s = await stat2(path12);
20076
+ const s = await stat2(path14);
19854
20077
  return s.isDirectory();
19855
20078
  } catch {
19856
20079
  return false;
@@ -23912,121 +24135,11 @@ var schemaCommand = defineCommand147({
23912
24135
  }
23913
24136
  });
23914
24137
 
23915
- // src/commands/tags/index.ts
23916
- import { defineCommand as defineCommand148 } from "citty";
23917
-
23918
- // src/commands/tags/shared.ts
23919
- function failApi3(err) {
23920
- if (err instanceof ApiError) {
23921
- writeJson({ ok: false, error: { code: err.code, message: err.message } });
23922
- process.exit(1);
23923
- }
23924
- if (err instanceof Error) {
23925
- writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: err.message } });
23926
- process.exit(1);
23927
- }
23928
- writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
23929
- process.exit(1);
23930
- }
23931
- function renderEffectiveEntry(entry) {
23932
- const parts = [entry.ref, entry.type];
23933
- if (entry.identifier !== void 0) {
23934
- parts.push(entry.identifier);
23935
- }
23936
- if (entry.staged !== void 0) {
23937
- parts.push(`[staged: ${entry.staged}]`);
23938
- }
23939
- const secretBits = [
23940
- ...entry.secretsSet.map((field) => `${field} \u2713 set`),
23941
- ...entry.secretsPending.map((field) => `${field} \u23F3 pending`)
23942
- ];
23943
- if (secretBits.length > 0) {
23944
- parts.push(`[secrets: ${secretBits.join(", ")}]`);
23945
- }
23946
- return parts.join(" ");
23947
- }
23948
-
23949
- // src/commands/tags/index.ts
23950
- registerSchema({
23951
- command: "tags.list",
23952
- description: "Effective marketing tags for this chat: production tags overlaid with the changes staged in this chat. The printed refs (tag ids or tag_temp_*) are exactly what flow side-effect tagIds should reference. Read-only \u2014 every tag change (create, edit, delete) goes through the request_tag_input approval tool.",
23953
- args: {
23954
- json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list", required: false }
23955
- }
23956
- });
23957
- async function listTags(json) {
23958
- try {
23959
- const chatId = requireChatId();
23960
- const response = await apiPost("/api/tags/list", { chatId });
23961
- if (json) {
23962
- writeJson({ ok: true, data: response });
23963
- return;
23964
- }
23965
- if (response.tags.length === 0) {
23966
- process.stdout.write("No tags configured. Propose one with the request_tag_input tool (baker_ui).\n");
23967
- return;
23968
- }
23969
- process.stdout.write(`${response.tags.map(renderEffectiveEntry).join("\n")}
23970
- `);
23971
- } catch (err) {
23972
- failApi3(err);
23973
- }
23974
- }
23975
- var listCommand7 = defineCommand148({
23976
- meta: {
23977
- name: "list",
23978
- description: "Effective tags for this chat (production + staged). Refs printed here are what flow side-effect tagIds should use. Example: baker tags list"
23979
- },
23980
- args: { json: { type: "boolean", description: "Print the raw JSON envelope instead of the readable list" } },
23981
- run: async ({ args }) => {
23982
- await listTags(args.json === true);
23983
- }
23984
- });
23985
- async function listDraft3() {
23986
- try {
23987
- const chatId = requireChatId();
23988
- const response = await apiPost("/api/tags/draft", { chatId });
23989
- writeJson({ ok: true, data: response });
23990
- } catch (err) {
23991
- failApi3(err);
23992
- }
23993
- }
23994
- var draftCommand3 = defineCommand148({
23995
- meta: {
23996
- name: "draft",
23997
- description: "Review the tag changes staged in this chat (read-only). Staged changes were approved via request_tag_input and apply when the chat is published; to amend or drop one, propose a follow-up change through the same tool (a delete on a tag_temp_* ref drops the staged create)."
23998
- },
23999
- run: async () => {
24000
- await listDraft3();
24001
- }
24002
- });
24003
- var tagsCommand3 = defineCommand148({
24004
- meta: {
24005
- name: "tags",
24006
- description: `Read the client's marketing/analytics tags (Meta pixel, GA4, Google Ads, GTM, Clarity, Hotjar, \u2026) \u2014 production tags plus the changes staged in this chat.
24007
-
24008
- This command is READ-ONLY. Every tag change \u2014 create, edit, or delete \u2014 goes through the request_tag_input tool (baker_ui MCP server): propose one or more changes (each becomes a tab in one approval form), pre-fill the non-secret fields you know, and the user reviews, fills secrets, and approves or skips each. Secret values (accessToken, apiSecret, authorizationToken, apiKey, conversionToken, OAuth connections) never pass through the CLI or the chat.
24009
-
24010
- Refs: \`baker tags list\` prints each tag's ref \u2014 a real tag id, or tag_temp_* for creates staged in this chat. Use these refs as flow side-effect tagIds; they keep resolving after publish.
24011
-
24012
- Examples:
24013
- baker tags list # production + staged, with secret status
24014
- baker tags draft # review the staged changes awaiting publish`
24015
- },
24016
- subCommands: {
24017
- list: listCommand7,
24018
- draft: draftCommand3
24019
- },
24020
- run: async () => {
24021
- await listTags(false);
24022
- }
24023
- });
24024
-
24025
24138
  // src/commands/testimonials/index.ts
24026
- import { defineCommand as defineCommand152 } from "citty";
24139
+ import { defineCommand as defineCommand151 } from "citty";
24027
24140
 
24028
24141
  // src/commands/testimonials/get.ts
24029
- import { defineCommand as defineCommand149 } from "citty";
24142
+ import { defineCommand as defineCommand148 } from "citty";
24030
24143
  registerSchema({
24031
24144
  command: "testimonials.get",
24032
24145
  description: "Get a single testimonial by ID",
@@ -24034,7 +24147,7 @@ registerSchema({
24034
24147
  id: { type: "string", description: "Testimonial ID", required: true }
24035
24148
  }
24036
24149
  });
24037
- var getCommand4 = defineCommand149({
24150
+ var getCommand4 = defineCommand148({
24038
24151
  meta: { name: "get", description: "Get a single testimonial by ID. Example: baker testimonials get j571abc123" },
24039
24152
  args: {
24040
24153
  id: { type: "positional", description: "Testimonial ID", required: false },
@@ -24071,7 +24184,7 @@ var getCommand4 = defineCommand149({
24071
24184
  });
24072
24185
 
24073
24186
  // src/commands/testimonials/list.ts
24074
- import { defineCommand as defineCommand150 } from "citty";
24187
+ import { defineCommand as defineCommand149 } from "citty";
24075
24188
  registerSchema({
24076
24189
  command: "testimonials.list",
24077
24190
  description: "List testimonials with optional filters.",
@@ -24101,7 +24214,7 @@ registerSchema({
24101
24214
  limit: { type: "number", description: "Max results (default 50)", required: false, default: 50 }
24102
24215
  }
24103
24216
  });
24104
- var listCommand8 = defineCommand150({
24217
+ var listCommand7 = defineCommand149({
24105
24218
  meta: {
24106
24219
  name: "list",
24107
24220
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
@@ -24150,7 +24263,7 @@ var listCommand8 = defineCommand150({
24150
24263
  });
24151
24264
 
24152
24265
  // src/commands/testimonials/search.ts
24153
- import { defineCommand as defineCommand151 } from "citty";
24266
+ import { defineCommand as defineCommand150 } from "citty";
24154
24267
  registerSchema({
24155
24268
  command: "testimonials.search",
24156
24269
  description: "Search testimonials by text query. Uses hybrid BM25 + vector + reranking.",
@@ -24181,7 +24294,7 @@ registerSchema({
24181
24294
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
24182
24295
  }
24183
24296
  });
24184
- var searchCommand2 = defineCommand151({
24297
+ var searchCommand2 = defineCommand150({
24185
24298
  meta: {
24186
24299
  name: "search",
24187
24300
  description: "Semantic search testimonials by text query. Uses hybrid BM25 + vector + reranking. Example: baker testimonials search 'great service' --rating-min 4"
@@ -24252,10 +24365,10 @@ var searchCommand2 = defineCommand151({
24252
24365
  });
24253
24366
 
24254
24367
  // src/commands/testimonials/tags.ts
24255
- var tagsCommand4 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
24368
+ var tagsCommand3 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
24256
24369
 
24257
24370
  // src/commands/testimonials/index.ts
24258
- var testimonialsCommand = defineCommand152({
24371
+ var testimonialsCommand = defineCommand151({
24259
24372
  meta: {
24260
24373
  name: "testimonials",
24261
24374
  description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
@@ -24270,16 +24383,16 @@ Examples:
24270
24383
  subCommands: {
24271
24384
  get: getCommand4,
24272
24385
  search: searchCommand2,
24273
- list: listCommand8,
24274
- tags: tagsCommand4
24386
+ list: listCommand7,
24387
+ tags: tagsCommand3
24275
24388
  }
24276
24389
  });
24277
24390
 
24278
24391
  // src/commands/videos/index.ts
24279
- import { defineCommand as defineCommand157 } from "citty";
24392
+ import { defineCommand as defineCommand156 } from "citty";
24280
24393
 
24281
24394
  // src/commands/videos/delete.ts
24282
- import { defineCommand as defineCommand153 } from "citty";
24395
+ import { defineCommand as defineCommand152 } from "citty";
24283
24396
  registerSchema({
24284
24397
  command: "videos.delete",
24285
24398
  description: "Delete a video by ID",
@@ -24293,7 +24406,7 @@ registerSchema({
24293
24406
  }
24294
24407
  }
24295
24408
  });
24296
- var deleteCommand3 = defineCommand153({
24409
+ var deleteCommand3 = defineCommand152({
24297
24410
  meta: {
24298
24411
  name: "delete",
24299
24412
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -24334,7 +24447,7 @@ var deleteCommand3 = defineCommand153({
24334
24447
  });
24335
24448
 
24336
24449
  // src/commands/videos/get.ts
24337
- import { defineCommand as defineCommand154 } from "citty";
24450
+ import { defineCommand as defineCommand153 } from "citty";
24338
24451
  registerSchema({
24339
24452
  command: "videos.get",
24340
24453
  description: "Get a single video by ID",
@@ -24342,7 +24455,7 @@ registerSchema({
24342
24455
  id: { type: "string", description: "Video ID", required: true }
24343
24456
  }
24344
24457
  });
24345
- var getCommand5 = defineCommand154({
24458
+ var getCommand5 = defineCommand153({
24346
24459
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
24347
24460
  args: {
24348
24461
  id: { type: "positional", description: "Video ID", required: false },
@@ -24379,7 +24492,7 @@ var getCommand5 = defineCommand154({
24379
24492
  });
24380
24493
 
24381
24494
  // src/commands/videos/search.ts
24382
- import { defineCommand as defineCommand155 } from "citty";
24495
+ import { defineCommand as defineCommand154 } from "citty";
24383
24496
  registerSchema({
24384
24497
  command: "videos.search",
24385
24498
  description: "Search videos by text query. Only returns ready videos.",
@@ -24389,7 +24502,7 @@ registerSchema({
24389
24502
  tags: { type: "string", description: "Comma-separated tags to filter by", required: false }
24390
24503
  }
24391
24504
  });
24392
- var searchCommand3 = defineCommand155({
24505
+ var searchCommand3 = defineCommand154({
24393
24506
  meta: {
24394
24507
  name: "search",
24395
24508
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -24436,12 +24549,12 @@ var searchCommand3 = defineCommand155({
24436
24549
  });
24437
24550
 
24438
24551
  // src/commands/videos/tags.ts
24439
- var tagsCommand5 = makeTagsCommand("videos", "video", "/api/videos/tags");
24552
+ var tagsCommand4 = makeTagsCommand("videos", "video", "/api/videos/tags");
24440
24553
 
24441
24554
  // src/commands/videos/upload.ts
24442
24555
  import { readFile as readFile12, stat as stat3 } from "fs/promises";
24443
24556
  import { extname as extname3 } from "path";
24444
- import { defineCommand as defineCommand156 } from "citty";
24557
+ import { defineCommand as defineCommand155 } from "citty";
24445
24558
  var MIME_MAP = {
24446
24559
  ".mp4": "video/mp4",
24447
24560
  ".mov": "video/quicktime",
@@ -24475,7 +24588,7 @@ function detectContentType(filePath) {
24475
24588
  }
24476
24589
  return mime;
24477
24590
  }
24478
- var uploadCommand2 = defineCommand156({
24591
+ var uploadCommand2 = defineCommand155({
24479
24592
  meta: {
24480
24593
  name: "upload",
24481
24594
  description: "Upload a video file to Baker via Mux direct upload. Auto-detects content type. Example: baker videos upload ./demo.mp4"
@@ -24529,7 +24642,7 @@ var uploadCommand2 = defineCommand156({
24529
24642
  });
24530
24643
 
24531
24644
  // src/commands/videos/index.ts
24532
- var videosCommand = defineCommand157({
24645
+ var videosCommand = defineCommand156({
24533
24646
  meta: {
24534
24647
  name: "videos",
24535
24648
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, delete, tags.
@@ -24547,15 +24660,15 @@ Examples:
24547
24660
  search: searchCommand3,
24548
24661
  upload: uploadCommand2,
24549
24662
  delete: deleteCommand3,
24550
- tags: tagsCommand5
24663
+ tags: tagsCommand4
24551
24664
  }
24552
24665
  });
24553
24666
 
24554
24667
  // src/commands/winning-ads/index.ts
24555
- import { defineCommand as defineCommand160 } from "citty";
24668
+ import { defineCommand as defineCommand159 } from "citty";
24556
24669
 
24557
24670
  // src/commands/winning-ads/advertisers.ts
24558
- import { defineCommand as defineCommand158 } from "citty";
24671
+ import { defineCommand as defineCommand157 } from "citty";
24559
24672
  registerSchema({
24560
24673
  command: "winning-ads.advertisers",
24561
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).",
@@ -24568,7 +24681,7 @@ registerSchema({
24568
24681
  function identity(record) {
24569
24682
  return record;
24570
24683
  }
24571
- var advertisersCommand2 = defineCommand158({
24684
+ var advertisersCommand2 = defineCommand157({
24572
24685
  meta: {
24573
24686
  name: "advertisers",
24574
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'
@@ -24619,7 +24732,7 @@ var advertisersCommand2 = defineCommand158({
24619
24732
  });
24620
24733
 
24621
24734
  // src/commands/winning-ads/search.ts
24622
- import { defineCommand as defineCommand159 } from "citty";
24735
+ import { defineCommand as defineCommand158 } from "citty";
24623
24736
  registerSchema({
24624
24737
  command: "winning-ads.search",
24625
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.",
@@ -24727,7 +24840,7 @@ function buildSearchBody(args) {
24727
24840
  }
24728
24841
  return body;
24729
24842
  }
24730
- var searchCommand4 = defineCommand159({
24843
+ var searchCommand4 = defineCommand158({
24731
24844
  meta: {
24732
24845
  name: "search",
24733
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"
@@ -24839,7 +24952,7 @@ var searchCommand4 = defineCommand159({
24839
24952
  });
24840
24953
 
24841
24954
  // src/commands/winning-ads/index.ts
24842
- var winningAdsCommand = defineCommand160({
24955
+ var winningAdsCommand = defineCommand159({
24843
24956
  meta: {
24844
24957
  name: "winning-ads",
24845
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.
@@ -24879,11 +24992,11 @@ function getCliVersion() {
24879
24992
  }
24880
24993
 
24881
24994
  // src/cli.ts
24882
- var main = defineCommand161({
24995
+ var main = defineCommand160({
24883
24996
  meta: {
24884
24997
  name: "baker",
24885
24998
  version: getCliVersion(),
24886
- 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.
24887
25000
 
24888
25001
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
24889
25002
  Chat: Set BAKER_CHAT_ID for action and scheduled-action commands that stage changes against a chat.
@@ -24903,7 +25016,6 @@ Introspection: Run 'baker schema <command>' to inspect argument schemas.`
24903
25016
  videos: videosCommand,
24904
25017
  testimonials: testimonialsCommand,
24905
25018
  canvas: canvasCommand,
24906
- tags: tagsCommand3,
24907
25019
  "winning-ads": winningAdsCommand,
24908
25020
  mcp: mcpCommand,
24909
25021
  schema: schemaCommand