@koda-sl/baker-cli 0.412.0 → 0.413.0

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
@@ -21715,7 +21715,7 @@ var require_entry_node = __commonJS({
21715
21715
  });
21716
21716
 
21717
21717
  // src/cli.ts
21718
- import { defineCommand as defineCommand279, runMain } from "citty";
21718
+ import { defineCommand as defineCommand285, runMain } from "citty";
21719
21719
 
21720
21720
  // src/cache-flag.ts
21721
21721
  var NO_CACHE_ARG = {
@@ -26265,6 +26265,9 @@ var chatChangeTypeSchema = z13.enum([
26265
26265
  // A connected social account feeding the image and video libraries, keyed
26266
26266
  // on `platform:handle`. Immediate — see convex/mediaSources/mutations.ts.
26267
26267
  "media-source",
26268
+ // A review site listing feeding the testimonials library, keyed on the
26269
+ // source's id. Immediate — see convex/testimonials/mutations.ts.
26270
+ "testimonial-source",
26268
26271
  // A landing page saved to the reference library, keyed on the page.
26269
26272
  "landing-reference",
26270
26273
  // One Studio batch — the takes of one brief, as a set. See convex/lib/validators.ts.
@@ -28445,6 +28448,13 @@ var imageSourceSchema = z25.enum([
28445
28448
  "website",
28446
28449
  "google_testimonial",
28447
28450
  "trustpilot_testimonial",
28451
+ "yelp_testimonial",
28452
+ "tripadvisor_testimonial",
28453
+ "g2_testimonial",
28454
+ "capterra_testimonial",
28455
+ "amazon_testimonial",
28456
+ "app_store_testimonial",
28457
+ "google_play_testimonial",
28448
28458
  "instagram",
28449
28459
  "tiktok",
28450
28460
  "linkedin",
@@ -30262,7 +30272,17 @@ var tagChangeToolResultSchema = z33.object({
30262
30272
 
30263
30273
  // ../api/src/testimonials.ts
30264
30274
  import { z as z34 } from "zod";
30265
- var testimonialSourceTypeSchema = z34.enum(["google", "trustpilot"]);
30275
+ var testimonialSourceTypeSchema = z34.enum([
30276
+ "google",
30277
+ "trustpilot",
30278
+ "yelp",
30279
+ "tripadvisor",
30280
+ "g2",
30281
+ "capterra",
30282
+ "amazon",
30283
+ "app_store",
30284
+ "google_play"
30285
+ ]);
30266
30286
  var testimonialStatusSchema = z34.enum(["pending", "processing", "ready", "error"]);
30267
30287
  var testimonialSentimentSchema = z34.enum(["positive", "neutral", "negative"]);
30268
30288
  var testimonialDocSchema = z34.object({
@@ -30330,6 +30350,35 @@ var testimonialsOutscraperWebhookResponseSchema = z34.object({
30330
30350
  ok: z34.literal(true),
30331
30351
  note: z34.string().optional()
30332
30352
  });
30353
+ var testimonialSourceRefreshIntervalSchema = z34.enum(["never", "daily", "weekly", "monthly"]);
30354
+ var testimonialSourceSummarySchema = z34.object({
30355
+ id: z34.string(),
30356
+ platform: testimonialSourceTypeSchema,
30357
+ platformLabel: z34.string(),
30358
+ label: z34.string(),
30359
+ pageUrl: z34.string().optional(),
30360
+ status: z34.enum(["importing", "idle", "error"]),
30361
+ reviews: z34.number(),
30362
+ refreshInterval: z34.string(),
30363
+ lastSyncedAt: z34.number().optional(),
30364
+ error: z34.string().optional(),
30365
+ createdAt: z34.number()
30366
+ });
30367
+ var testimonialSourcesAddRequestSchema = z34.object({
30368
+ /** The review page's link; for Google Maps also the business name. */
30369
+ input: z34.string().trim().min(1, "Pass the review page's link, or a business name for Google Maps"),
30370
+ /** Needed only to force a site: a business name is Google, a link names its own site. */
30371
+ platform: testimonialSourceTypeSchema.optional(),
30372
+ /** Auto-sync cadence. Omitted = never, like the dashboard. */
30373
+ every: testimonialSourceRefreshIntervalSchema.optional()
30374
+ });
30375
+ var sourceIdSchema = z34.string().trim().min(1, "Pass a source id from `baker testimonials sources list`");
30376
+ var testimonialSourcesSyncRequestSchema = z34.object({ id: sourceIdSchema });
30377
+ var testimonialSourcesRemoveRequestSchema = z34.object({ id: sourceIdSchema });
30378
+ var testimonialSourcesScheduleRequestSchema = z34.object({
30379
+ id: sourceIdSchema,
30380
+ every: testimonialSourceRefreshIntervalSchema
30381
+ });
30333
30382
 
30334
30383
  // ../api/src/videos.ts
30335
30384
  import { z as z35 } from "zod";
@@ -60294,7 +60343,7 @@ var SOURCE_KINDS = ["webhook", "hubspot"];
60294
60343
  var SOURCE_STATUSES = ["learning", "counting", "paused"];
60295
60344
  var SOURCE_NAME_MAX = 80;
60296
60345
  var sourceNameSchema = z49.string().trim().min(1).max(SOURCE_NAME_MAX).refine((name) => validateEventName(name) === null, REJECTION_MESSAGES.invalid_name);
60297
- var sourceIdSchema = z49.string().min(1);
60346
+ var sourceIdSchema2 = z49.string().min(1);
60298
60347
  var sourceMappingSchema = z49.record(z49.string(), z49.string().min(1)).superRefine((mapping, ctx) => {
60299
60348
  for (const row2 of Object.keys(mapping)) {
60300
60349
  const problem = mappingRowProblem(row2);
@@ -60392,7 +60441,7 @@ var sourcesRequestSchema = z49.strictObject({
60392
60441
  }).optional(),
60393
60442
  /** Change what a HubSpot event watches. It counts from now on under the new trigger; the rows stay. The object cannot change: the rows read it. */
60394
60443
  setTrigger: z49.strictObject({
60395
- sourceId: sourceIdSchema,
60444
+ sourceId: sourceIdSchema2,
60396
60445
  trigger: hubspotTriggerInputSchema,
60397
60446
  contacts: hubspotDealContactsSchema.optional()
60398
60447
  }).optional(),
@@ -60400,7 +60449,7 @@ var sourcesRequestSchema = z49.strictObject({
60400
60449
  preview: hubspotPreviewRequestSchema.optional(),
60401
60450
  /** Change where a HubSpot-read source takes its amount from; no `amountProperty` clears it. Sugar over `map`. */
60402
60451
  setAmount: z49.strictObject({
60403
- sourceId: sourceIdSchema,
60452
+ sourceId: sourceIdSchema2,
60404
60453
  amountProperty: z49.string().trim().min(1).optional(),
60405
60454
  currency: currencyCodeSchema.optional()
60406
60455
  }).optional(),
@@ -60414,7 +60463,7 @@ var sourcesRequestSchema = z49.strictObject({
60414
60463
  * has a timestamp for, so nothing is invented. Dry unless `write`.
60415
60464
  */
60416
60465
  backfill: z49.strictObject({
60417
- sourceId: sourceIdSchema,
60466
+ sourceId: sourceIdSchema2,
60418
60467
  /** ISO instant, or Unix milliseconds. Bounded by the 400 days the store keeps. */
60419
60468
  since: z49.union([z49.string().trim().min(1), z49.number()]),
60420
60469
  /**
@@ -60433,10 +60482,10 @@ var sourcesRequestSchema = z49.strictObject({
60433
60482
  /** Without it, nothing is counted and the answer says what would be. */
60434
60483
  write: z49.boolean().optional()
60435
60484
  }).optional(),
60436
- map: z49.strictObject({ sourceId: sourceIdSchema, mapping: sourceMappingSchema }).optional(),
60437
- pause: z49.strictObject({ sourceId: sourceIdSchema }).optional(),
60438
- resume: z49.strictObject({ sourceId: sourceIdSchema }).optional(),
60439
- remove: z49.strictObject({ sourceId: sourceIdSchema }).optional()
60485
+ map: z49.strictObject({ sourceId: sourceIdSchema2, mapping: sourceMappingSchema }).optional(),
60486
+ pause: z49.strictObject({ sourceId: sourceIdSchema2 }).optional(),
60487
+ resume: z49.strictObject({ sourceId: sourceIdSchema2 }).optional(),
60488
+ remove: z49.strictObject({ sourceId: sourceIdSchema2 }).optional()
60440
60489
  });
60441
60490
  var sourceRefusalSchema = z49.strictObject({
60442
60491
  at: z49.number(),
@@ -97338,7 +97387,7 @@ Full guide: __tooling__/docs/tools/baker/tags.md`
97338
97387
  });
97339
97388
 
97340
97389
  // src/commands/testimonials/index.ts
97341
- import { defineCommand as defineCommand258 } from "citty";
97390
+ import { defineCommand as defineCommand264 } from "citty";
97342
97391
 
97343
97392
  // src/commands/testimonials/get.ts
97344
97393
  import { defineCommand as defineCommand255 } from "citty";
@@ -97402,7 +97451,7 @@ function resolveEmptyReason({
97402
97451
  }
97403
97452
  return sourceCount === 0 ? "no_corpus_connected" : "corpus_empty";
97404
97453
  }
97405
- var NO_CORPUS_EXIT = 'Testimonials are ingested from the client\'s Google/Trustpilot reviews \u2014 an agent cannot write one \u2014 so no rewording will find quotes. Stop searching and source proof another way: a result or case study the client already published, a named-customer logo (`baker images logo`), or a founder claim attributed as a claim. Otherwise ship without a testimonial block and file the gap: `baker actions create --name "Collect customer quotes for <page>" --priority medium --tags <slug>`. Never invent, paraphrase-into-existence, or pad with unrelated praise.';
97454
+ var NO_CORPUS_EXIT = "Testimonials are ingested from the client's public review pages \u2014 an agent cannot write one \u2014 so no rewording will find quotes. If the user named the client's own review page (Google Maps, Trustpilot, Yelp, Tripadvisor, G2, Capterra, Amazon, App Store, Google Play), add it with `baker testimonials sources add <link>` \u2014 its reviews arrive over the next minutes, not in this turn. Stop searching and source proof another way: a result or case study the client already published, a named-customer logo (`baker images logo`), or a founder claim attributed as a claim. Otherwise ship without a testimonial block and file the gap: `baker actions create --name \"Collect customer quotes for <page>\" --priority medium --tags <slug>`. Never invent, paraphrase-into-existence, or pad with unrelated praise.";
97406
97455
  function emptyReasonDetail(reason, sourceCount, activeFilters) {
97407
97456
  if (reason === "filtered_out") {
97408
97457
  return `No rows matched, and ${activeFilters.join(", ")} narrowed this read. The corpus was not checked \u2014 drop every filter to see whether the library itself is empty.`;
@@ -97494,9 +97543,9 @@ registerSchema({
97494
97543
  args: {
97495
97544
  source: {
97496
97545
  type: "string",
97497
- description: "Filter by source: google|trustpilot",
97546
+ description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
97498
97547
  required: false,
97499
- enum: ["google", "trustpilot"]
97548
+ enum: [...testimonialSourceTypeSchema.options]
97500
97549
  },
97501
97550
  "rating-min": { type: "number", description: "Minimum star rating (1-5)", required: false },
97502
97551
  "rating-max": { type: "number", description: "Maximum star rating (1-5)", required: false },
@@ -97549,7 +97598,11 @@ var listCommand22 = defineCommand256({
97549
97598
  description: "List testimonials with optional filters. Example: baker testimonials list --source google --sentiment positive"
97550
97599
  },
97551
97600
  args: {
97552
- source: { type: "string", description: "Filter by source: google|trustpilot", required: false },
97601
+ source: {
97602
+ type: "string",
97603
+ description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
97604
+ required: false
97605
+ },
97553
97606
  "rating-min": { type: "string", description: "Minimum star rating (1-5)", required: false },
97554
97607
  "rating-max": { type: "string", description: "Maximum star rating (1-5)", required: false },
97555
97608
  status: { type: "string", description: "Filter by status: pending|processing|ready|error", required: false },
@@ -97632,9 +97685,9 @@ registerSchema({
97632
97685
  limit: { type: "number", description: "Maximum results to return", required: false, default: 10 },
97633
97686
  source: {
97634
97687
  type: "string",
97635
- description: "Filter by source: google|trustpilot",
97688
+ description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
97636
97689
  required: false,
97637
- enum: ["google", "trustpilot"]
97690
+ enum: [...testimonialSourceTypeSchema.options]
97638
97691
  },
97639
97692
  "rating-min": { type: "number", description: "Minimum star rating (1-5)", required: false },
97640
97693
  "rating-max": { type: "number", description: "Maximum star rating (1-5)", required: false },
@@ -97690,7 +97743,11 @@ var searchCommand4 = defineCommand257({
97690
97743
  args: {
97691
97744
  query: { type: "positional", description: "Search query text", required: false },
97692
97745
  limit: { type: "string", description: "Max results (default 10)", required: false },
97693
- source: { type: "string", description: "Filter by source: google|trustpilot", required: false },
97746
+ source: {
97747
+ type: "string",
97748
+ description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
97749
+ required: false
97750
+ },
97694
97751
  "rating-min": { type: "string", description: "Minimum star rating (1-5)", required: false },
97695
97752
  "rating-max": { type: "string", description: "Maximum star rating (1-5)", required: false },
97696
97753
  status: { type: "string", description: "Filter by status: pending|processing|ready|error", required: false },
@@ -97742,14 +97799,276 @@ var searchCommand4 = defineCommand257({
97742
97799
  }
97743
97800
  });
97744
97801
 
97802
+ // src/commands/testimonials/sources/index.ts
97803
+ import { defineCommand as defineCommand263 } from "citty";
97804
+
97805
+ // src/commands/testimonials/sources/add.ts
97806
+ import { defineCommand as defineCommand258 } from "citty";
97807
+
97808
+ // src/commands/testimonials/sources/shared.ts
97809
+ function reportError3(err) {
97810
+ if (err instanceof ApiError) {
97811
+ writeJson({ ok: false, error: { code: err.code, message: err.message } });
97812
+ process.exit(1);
97813
+ }
97814
+ writeJson({ ok: false, error: { code: "INTERNAL_ERROR", message: "Unexpected error" } });
97815
+ process.exit(1);
97816
+ }
97817
+ function reportInvalid(issue) {
97818
+ writeJson({
97819
+ ok: false,
97820
+ error: {
97821
+ code: "VALIDATION_ERROR",
97822
+ message: issue ? `${issue.path.map(String).join(".") || "input"}: ${issue.message}` : "Invalid request"
97823
+ }
97824
+ });
97825
+ process.exit(1);
97826
+ }
97827
+ function compactSource2(source) {
97828
+ return {
97829
+ id: source.id,
97830
+ platform: source.platform,
97831
+ label: source.label,
97832
+ ...source.pageUrl ? { url: source.pageUrl } : {},
97833
+ status: source.status,
97834
+ reviews: source.reviews,
97835
+ autoSync: source.refreshInterval,
97836
+ ...source.lastSyncedAt ? { lastSyncedAt: new Date(source.lastSyncedAt).toISOString() } : {},
97837
+ ...source.error ? { error: source.error } : {}
97838
+ };
97839
+ }
97840
+
97841
+ // src/commands/testimonials/sources/add.ts
97842
+ var SITES = testimonialSourceTypeSchema.options.join("|");
97843
+ registerSchema({
97844
+ command: "testimonials.sources.add",
97845
+ description: "Add a review page as a testimonial source \u2014 Google Maps, Trustpilot, Yelp, Tripadvisor, G2, Capterra, Amazon, App Store or Google Play. Pass the page's link (it names its own site), or a business name for Google Maps. Its reviews (up to 700) are imported, tagged and made searchable in the background over the next minutes. Each imported review costs a little, so add only the client's own listings the user asked for. Applies immediately and shows on the chat as an already-applied change. Adding a listing that is already a source is a no-op that starts a fresh import.",
97846
+ args: {
97847
+ input: {
97848
+ type: "string",
97849
+ description: "The review page's link, or a business name (Google Maps only)",
97850
+ required: true
97851
+ },
97852
+ platform: {
97853
+ type: "string",
97854
+ description: `Only to force a site: ${SITES}. A bare domain with trustpilot is that company's Trustpilot page.`,
97855
+ required: false
97856
+ },
97857
+ every: {
97858
+ type: "string",
97859
+ description: `Auto-sync cadence: ${testimonialSourceRefreshIntervalSchema.options.join("|")} (default never)`,
97860
+ required: false
97861
+ }
97862
+ }
97863
+ });
97864
+ function addSourceHints(input, { created, source }) {
97865
+ const hints2 = [
97866
+ created ? `Added ${source.label} on ${source.platformLabel}. Its reviews are importing in the background \u2014 they become searchable with \`baker testimonials search\` as each one is analysed, usually within a few minutes. Don't wait on them in this turn; check with \`baker testimonials sources list\`.` : `${source.label} on ${source.platformLabel} was already a source; a fresh import was started if one wasn't running.`
97867
+ ];
97868
+ if (created && source.platform === "google" && !/^https?:\/\/|\.[a-z]{2,}\//i.test(input.trim())) {
97869
+ hints2.push(
97870
+ `Matched the name to ${source.label} on Google Maps (${source.pageUrl ?? "no link"}). If that is not the client's business, run \`baker testimonials sources remove ${source.id}\` at once and add the listing's Google Maps link instead.`
97871
+ );
97872
+ }
97873
+ if (source.refreshInterval === "never") {
97874
+ hints2.push(
97875
+ `Auto-sync is off. If the user wants new reviews to keep arriving: \`baker testimonials sources schedule ${source.id} --every monthly\`.`
97876
+ );
97877
+ }
97878
+ return hints2;
97879
+ }
97880
+ var addCommand4 = defineCommand258({
97881
+ meta: {
97882
+ name: "add",
97883
+ description: `Add a review page as a testimonial source. Start here with the page's link; for Google Maps a business name also works.
97884
+
97885
+ Examples:
97886
+ baker testimonials sources add https://www.yelp.com/biz/acme-bakery-madrid
97887
+ baker testimonials sources add https://www.g2.com/products/acme --every monthly
97888
+ baker testimonials sources add "Acme Bakery Madrid" # Google Maps, found by name
97889
+ baker testimonials sources add acme.com --platform trustpilot`
97890
+ },
97891
+ args: {
97892
+ input: { type: "positional", description: "Review page link, or a business name for Google Maps", required: true },
97893
+ platform: { type: "string", description: `Force a site: ${SITES}`, required: false },
97894
+ every: { type: "string", description: "Auto-sync: never|daily|weekly|monthly", required: false }
97895
+ },
97896
+ run: async ({ args: args8 }) => {
97897
+ const parsed = testimonialSourcesAddRequestSchema.safeParse({
97898
+ input: String(args8.input ?? ""),
97899
+ platform: args8.platform ? String(args8.platform).toLowerCase().replace(/[\s-]/g, "_") : void 0,
97900
+ every: args8.every ? String(args8.every).toLowerCase() : void 0
97901
+ });
97902
+ if (!parsed.success) reportInvalid(parsed.error.issues[0]);
97903
+ try {
97904
+ const data = await apiPost("/api/testimonials/sources/add", parsed.data, {
97905
+ timeoutMs: 12e4
97906
+ });
97907
+ const hints2 = addSourceHints(parsed.data.input, data);
97908
+ writeJson({ ok: true, data: { created: data.created, source: compactSource2(data.source) }, hints: hints2 });
97909
+ } catch (err) {
97910
+ reportError3(err);
97911
+ }
97912
+ }
97913
+ });
97914
+
97915
+ // src/commands/testimonials/sources/list.ts
97916
+ import { defineCommand as defineCommand259 } from "citty";
97917
+ registerSchema({
97918
+ command: "testimonials.sources.list",
97919
+ description: "List the review pages feeding the testimonials library: each one's id, site, import status and how many reviews it has brought in.",
97920
+ args: {}
97921
+ });
97922
+ function listSourceHints(sources) {
97923
+ if (sources.length === 0) {
97924
+ return [
97925
+ "No review sources yet. If the client has a public review page (Google Maps, Trustpilot, Yelp, Tripadvisor, G2, Capterra, Amazon, App Store, Google Play), add it with `baker testimonials sources add <link>`."
97926
+ ];
97927
+ }
97928
+ const hints2 = sources.filter((source) => source.status === "error").map(
97929
+ (source) => `${source.label} on ${source.platformLabel} did not import: ${source.error ?? "the last import failed"} Retry once with \`baker testimonials sources sync ${source.id}\`; if it fails again, tell the user in plain words and carry on with the other sources.`
97930
+ );
97931
+ if (sources.some((source) => source.status === "importing")) {
97932
+ hints2.push("Some sources are still importing \u2014 their review counts will grow over the next minutes.");
97933
+ }
97934
+ return hints2;
97935
+ }
97936
+ var listCommand23 = defineCommand259({
97937
+ meta: {
97938
+ name: "list",
97939
+ description: "List testimonial sources (id, site, import status, reviews imported).\n\nExample: baker testimonials sources list"
97940
+ },
97941
+ args: {},
97942
+ run: async () => {
97943
+ try {
97944
+ const sources = await apiGet("/api/testimonials/sources/list");
97945
+ const hints2 = listSourceHints(sources);
97946
+ writeJson({ ok: true, data: sources.map(compactSource2), hints: hints2.length > 0 ? hints2 : void 0 });
97947
+ } catch (err) {
97948
+ reportError3(err);
97949
+ }
97950
+ }
97951
+ });
97952
+
97953
+ // src/commands/testimonials/sources/remove.ts
97954
+ import { defineCommand as defineCommand260 } from "citty";
97955
+ registerSchema({
97956
+ command: "testimonials.sources.remove",
97957
+ description: "Remove a review source AND every testimonial it imported (and their pictures). Applies immediately and cannot be undone \u2014 only when the user asked for it.",
97958
+ args: { id: { type: "string", description: "Source id from `testimonials sources list`", required: true } }
97959
+ });
97960
+ var removeCommand8 = defineCommand260({
97961
+ meta: {
97962
+ name: "remove",
97963
+ description: "Remove a review source and all its testimonials (cannot be undone).\n\nExample: baker testimonials sources remove <source-id>"
97964
+ },
97965
+ args: { id: { type: "positional", description: "Source id from `testimonials sources list`", required: true } },
97966
+ run: async ({ args: args8 }) => {
97967
+ const parsed = testimonialSourcesRemoveRequestSchema.safeParse({ id: String(args8.id ?? "") });
97968
+ if (!parsed.success) reportInvalid(parsed.error.issues[0]);
97969
+ try {
97970
+ const data = await apiPost("/api/testimonials/sources/remove", parsed.data);
97971
+ writeJson({ ok: true, data });
97972
+ } catch (err) {
97973
+ reportError3(err);
97974
+ }
97975
+ }
97976
+ });
97977
+
97978
+ // src/commands/testimonials/sources/schedule.ts
97979
+ import { defineCommand as defineCommand261 } from "citty";
97980
+ var INTERVALS = testimonialSourceRefreshIntervalSchema.options.join("|");
97981
+ registerSchema({
97982
+ command: "testimonials.sources.schedule",
97983
+ description: "Set how often a review source imports its new reviews on its own.",
97984
+ args: {
97985
+ id: { type: "string", description: "Source id from `testimonials sources list`", required: true },
97986
+ every: { type: "string", description: `Auto-sync cadence: ${INTERVALS}`, required: true }
97987
+ }
97988
+ });
97989
+ var scheduleCommand2 = defineCommand261({
97990
+ meta: {
97991
+ name: "schedule",
97992
+ description: "Set a review source's auto-sync cadence.\n\nExample: baker testimonials sources schedule <source-id> --every monthly"
97993
+ },
97994
+ args: {
97995
+ id: { type: "positional", description: "Source id from `testimonials sources list`", required: true },
97996
+ every: { type: "string", description: INTERVALS, required: true }
97997
+ },
97998
+ run: async ({ args: args8 }) => {
97999
+ const parsed = testimonialSourcesScheduleRequestSchema.safeParse({
98000
+ id: String(args8.id ?? ""),
98001
+ every: String(args8.every ?? "").toLowerCase()
98002
+ });
98003
+ if (!parsed.success) reportInvalid(parsed.error.issues[0]);
98004
+ try {
98005
+ const data = await apiPost("/api/testimonials/sources/schedule", parsed.data);
98006
+ writeJson({ ok: true, data: { id: data.id, autoSync: parsed.data.every } });
98007
+ } catch (err) {
98008
+ reportError3(err);
98009
+ }
98010
+ }
98011
+ });
98012
+
98013
+ // src/commands/testimonials/sources/sync.ts
98014
+ import { defineCommand as defineCommand262 } from "citty";
98015
+ registerSchema({
98016
+ command: "testimonials.sources.sync",
98017
+ description: "Import a review source's new reviews now. Only reviews newer than the last import are read where the site allows it.",
98018
+ args: { id: { type: "string", description: "Source id from `testimonials sources list`", required: true } }
98019
+ });
98020
+ var syncCommand2 = defineCommand262({
98021
+ meta: {
98022
+ name: "sync",
98023
+ description: "Import a review source's new reviews now.\n\nExample: baker testimonials sources sync <source-id>"
98024
+ },
98025
+ args: { id: { type: "positional", description: "Source id from `testimonials sources list`", required: true } },
98026
+ run: async ({ args: args8 }) => {
98027
+ const parsed = testimonialSourcesSyncRequestSchema.safeParse({ id: String(args8.id ?? "") });
98028
+ if (!parsed.success) reportInvalid(parsed.error.issues[0]);
98029
+ try {
98030
+ const data = await apiPost("/api/testimonials/sources/sync", parsed.data);
98031
+ writeJson({
98032
+ ok: true,
98033
+ data,
98034
+ hints: data.started ? void 0 : ["An import was already running for this source; nothing new was started."]
98035
+ });
98036
+ } catch (err) {
98037
+ reportError3(err);
98038
+ }
98039
+ }
98040
+ });
98041
+
98042
+ // src/commands/testimonials/sources/index.ts
98043
+ var sourcesCommand2 = defineCommand263({
98044
+ meta: {
98045
+ name: "sources",
98046
+ description: `The review pages the testimonials come from: Google Maps, Trustpilot, Yelp, Tripadvisor, G2, Capterra, Amazon, App Store, Google Play. Subcommands: add, list, sync, schedule, remove.
98047
+
98048
+ Examples:
98049
+ baker testimonials sources add https://www.trustpilot.com/review/acme.com
98050
+ baker testimonials sources list
98051
+ baker testimonials sources sync <source-id>
98052
+ baker testimonials sources schedule <source-id> --every monthly
98053
+ baker testimonials sources remove <source-id>`
98054
+ },
98055
+ subCommands: {
98056
+ add: addCommand4,
98057
+ list: listCommand23,
98058
+ sync: syncCommand2,
98059
+ schedule: scheduleCommand2,
98060
+ remove: removeCommand8
98061
+ }
98062
+ });
98063
+
97745
98064
  // src/commands/testimonials/tags.ts
97746
98065
  var tagsCommand5 = makeTagsCommand("testimonials", "testimonial", "/api/testimonials/tags");
97747
98066
 
97748
98067
  // src/commands/testimonials/index.ts
97749
- var testimonialsCommand = defineCommand258({
98068
+ var testimonialsCommand = defineCommand264({
97750
98069
  meta: {
97751
98070
  name: "testimonials",
97752
- description: `Find and browse testimonials in Baker. Subcommands: search, get, list, tags.
98071
+ description: `Find and browse testimonials in Baker, and manage the review pages they come from. Subcommands: search, get, list, tags, sources.
97753
98072
 
97754
98073
  Examples:
97755
98074
  baker testimonials search "great customer service" --limit 5
@@ -97757,21 +98076,23 @@ Examples:
97757
98076
  baker testimonials get <testimonial-id>
97758
98077
  baker testimonials list --source google --sentiment positive
97759
98078
  baker testimonials tags
98079
+ baker testimonials sources add https://www.yelp.com/biz/acme-bakery-madrid
97760
98080
  Full guide: __tooling__/docs/tools/baker/testimonials.md`
97761
98081
  },
97762
98082
  subCommands: {
97763
98083
  get: getCommand6,
97764
98084
  search: searchCommand4,
97765
98085
  list: listCommand22,
97766
- tags: tagsCommand5
98086
+ tags: tagsCommand5,
98087
+ sources: sourcesCommand2
97767
98088
  }
97768
98089
  });
97769
98090
 
97770
98091
  // src/commands/videos/index.ts
97771
- import { defineCommand as defineCommand267 } from "citty";
98092
+ import { defineCommand as defineCommand273 } from "citty";
97772
98093
 
97773
98094
  // src/commands/videos/delete.ts
97774
- import { defineCommand as defineCommand259 } from "citty";
98095
+ import { defineCommand as defineCommand265 } from "citty";
97775
98096
  registerSchema({
97776
98097
  command: "videos.delete",
97777
98098
  description: "Delete a video by ID",
@@ -97785,7 +98106,7 @@ registerSchema({
97785
98106
  }
97786
98107
  }
97787
98108
  });
97788
- var deleteCommand4 = defineCommand259({
98109
+ var deleteCommand4 = defineCommand265({
97789
98110
  meta: {
97790
98111
  name: "delete",
97791
98112
  description: "Delete a video by ID. Use --dry-run to preview. Example: baker videos delete j571abc123 --dry-run"
@@ -97826,7 +98147,7 @@ var deleteCommand4 = defineCommand259({
97826
98147
  });
97827
98148
 
97828
98149
  // src/commands/videos/describe.ts
97829
- import { defineCommand as defineCommand260 } from "citty";
98150
+ import { defineCommand as defineCommand266 } from "citty";
97830
98151
  var DESCRIPTION_HELP2 = "What the clip actually shows, in the words someone would search for it by. This is what `baker videos search` retrieves on.";
97831
98152
  registerSchema({
97832
98153
  command: "videos.describe",
@@ -97843,7 +98164,7 @@ registerSchema({
97843
98164
  full: { type: "boolean", description: "Return the whole library row, not just what changed", required: false }
97844
98165
  }
97845
98166
  });
97846
- var describeCommand2 = defineCommand260({
98167
+ var describeCommand2 = defineCommand266({
97847
98168
  meta: {
97848
98169
  name: "describe",
97849
98170
  description: `Correct what the library says a video is. Only the fields you pass change; the rest keep their current values.
@@ -97905,7 +98226,7 @@ import { constants } from "fs";
97905
98226
  import { copyFile as copyFile2, mkdir as mkdir17, mkdtemp as mkdtemp3, rm as rm10 } from "fs/promises";
97906
98227
  import { tmpdir as tmpdir4 } from "os";
97907
98228
  import path56 from "path";
97908
- import { defineCommand as defineCommand261 } from "citty";
98229
+ import { defineCommand as defineCommand267 } from "citty";
97909
98230
 
97910
98231
  // src/commands/videos/videoPlatforms.ts
97911
98232
  var PLATFORM_DOMAINS = {
@@ -98043,7 +98364,7 @@ function positiveInt(value2) {
98043
98364
  const parsed = typeof value2 === "string" ? Number.parseInt(value2, 10) : Number.NaN;
98044
98365
  return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
98045
98366
  }
98046
- var fetchCommand2 = defineCommand261({
98367
+ var fetchCommand2 = defineCommand267({
98047
98368
  meta: {
98048
98369
  name: "fetch",
98049
98370
  description: "Download a video page to a local .mp4 without adding it to the library. Same downloader as `ingest` (proxy fallback, duration check).\n\nExample: baker videos fetch https://www.youtube.com/watch?v=abc123 --out ./clips"
@@ -98129,7 +98450,7 @@ async function placeInto(outDir, source, stem) {
98129
98450
  }
98130
98451
 
98131
98452
  // src/commands/videos/get.ts
98132
- import { defineCommand as defineCommand262 } from "citty";
98453
+ import { defineCommand as defineCommand268 } from "citty";
98133
98454
  registerSchema({
98134
98455
  command: "videos.get",
98135
98456
  description: "Get a single video by ID",
@@ -98137,7 +98458,7 @@ registerSchema({
98137
98458
  id: { type: "string", description: "Video ID", required: true }
98138
98459
  }
98139
98460
  });
98140
- var getCommand7 = defineCommand262({
98461
+ var getCommand7 = defineCommand268({
98141
98462
  meta: { name: "get", description: "Get a single video by ID. Example: baker videos get j571abc123" },
98142
98463
  args: {
98143
98464
  id: { type: "positional", description: "Video ID", required: false },
@@ -98174,7 +98495,7 @@ var getCommand7 = defineCommand262({
98174
98495
  });
98175
98496
 
98176
98497
  // src/commands/videos/group.ts
98177
- import { defineCommand as defineCommand263 } from "citty";
98498
+ import { defineCommand as defineCommand269 } from "citty";
98178
98499
  registerSchema({
98179
98500
  command: "videos.group",
98180
98501
  description: "List every clip and image that arrived in the same set as this video (carousel slides, one page)",
@@ -98183,7 +98504,7 @@ registerSchema({
98183
98504
  "group-key": { type: "string", description: "The set key directly, when you already have it", required: false }
98184
98505
  }
98185
98506
  });
98186
- var groupCommand2 = defineCommand263({
98507
+ var groupCommand2 = defineCommand269({
98187
98508
  meta: {
98188
98509
  name: "group",
98189
98510
  description: "List every asset that arrived in the same set as this clip \u2014 the other slides of the Instagram post it came from, stills included. A carousel is authored to be read in order, so a clip pulled out of one is usually missing half its meaning. Example: baker videos group <videoId>"
@@ -98206,7 +98527,7 @@ var groupCommand2 = defineCommand263({
98206
98527
  import { mkdtemp as mkdtemp4, rm as rm11, stat as stat12 } from "fs/promises";
98207
98528
  import { tmpdir as tmpdir5 } from "os";
98208
98529
  import path57 from "path";
98209
- import { defineCommand as defineCommand264 } from "citty";
98530
+ import { defineCommand as defineCommand270 } from "citty";
98210
98531
 
98211
98532
  // src/lib/streamUpload.ts
98212
98533
  import { createHash as createHash3 } from "crypto";
@@ -98259,7 +98580,7 @@ registerSchema({
98259
98580
  "dry-run": { type: "boolean", description: "Preview the operation without executing", required: false }
98260
98581
  }
98261
98582
  });
98262
- var ingestCommand2 = defineCommand264({
98583
+ var ingestCommand2 = defineCommand270({
98263
98584
  meta: {
98264
98585
  name: "ingest",
98265
98586
  description: "Add a video to the library from a URL. A direct file URL is handed straight to Baker, which fetches it. A page URL (YouTube, TikTok, Vimeo, Instagram) is downloaded here first, then uploaded \u2014 and a direct URL that Baker cannot fetch falls back to that same path automatically.\n\nExample: baker videos ingest https://www.youtube.com/watch?v=abc123"
@@ -98521,7 +98842,7 @@ async function uploadToAssetStore(filePath, sizeBytes) {
98521
98842
  }
98522
98843
 
98523
98844
  // src/commands/videos/search.ts
98524
- import { defineCommand as defineCommand265 } from "citty";
98845
+ import { defineCommand as defineCommand271 } from "citty";
98525
98846
  registerSchema({
98526
98847
  command: "videos.search",
98527
98848
  description: "Search videos by text query. Only returns ready videos.",
@@ -98547,7 +98868,7 @@ function searchHints(results) {
98547
98868
  }
98548
98869
  return hints2.length > 0 ? hints2 : void 0;
98549
98870
  }
98550
- var searchCommand5 = defineCommand265({
98871
+ var searchCommand5 = defineCommand271({
98551
98872
  meta: {
98552
98873
  name: "search",
98553
98874
  description: "Semantic search videos by text query. Uses hybrid BM25 + vector + reranking. Example: baker videos search 'product demo' --tags tutorial"
@@ -98599,7 +98920,7 @@ var tagsCommand6 = makeTagsCommand("videos", "video", "/api/videos/tags");
98599
98920
  // src/commands/videos/upload.ts
98600
98921
  import { stat as stat13 } from "fs/promises";
98601
98922
  import { basename as basename4 } from "path";
98602
- import { defineCommand as defineCommand266 } from "citty";
98923
+ import { defineCommand as defineCommand272 } from "citty";
98603
98924
  registerSchema({
98604
98925
  command: "videos.upload",
98605
98926
  description: "Upload a video to Baker \u2014 a local file (via Mux direct upload) or a remote http(s) URL.",
@@ -98626,7 +98947,7 @@ registerSchema({
98626
98947
  function isRemoteUrl3(value2) {
98627
98948
  return /^https?:\/\//i.test(value2);
98628
98949
  }
98629
- var uploadCommand2 = defineCommand266({
98950
+ var uploadCommand2 = defineCommand272({
98630
98951
  meta: {
98631
98952
  name: "upload",
98632
98953
  description: "Upload a video to Baker \u2014 accepts a local file path OR a remote http(s) URL.\n\nLocal: auto-detects content type and uploads via Mux direct upload.\nRemote: hands off to `videos ingest` (direct fetch, or download-then-upload for a YouTube/TikTok/Vimeo page).\n\nExamples:\n baker videos upload ./demo.mp4\n baker videos upload https://www.youtube.com/watch?v=abc123"
@@ -98695,7 +99016,7 @@ var uploadCommand2 = defineCommand266({
98695
99016
  });
98696
99017
 
98697
99018
  // src/commands/videos/index.ts
98698
- var videosCommand = defineCommand267({
99019
+ var videosCommand = defineCommand273({
98699
99020
  meta: {
98700
99021
  name: "videos",
98701
99022
  description: `Find and manage videos in Baker. Subcommands: search, get, upload, ingest, fetch, describe, delete, tags.
@@ -98726,10 +99047,10 @@ Full guide: __tooling__/docs/tools/baker/videos.md`
98726
99047
  });
98727
99048
 
98728
99049
  // src/commands/winning-ads/index.ts
98729
- import { defineCommand as defineCommand278 } from "citty";
99050
+ import { defineCommand as defineCommand284 } from "citty";
98730
99051
 
98731
99052
  // src/commands/winning-ads/advertisers.ts
98732
- import { defineCommand as defineCommand268 } from "citty";
99053
+ import { defineCommand as defineCommand274 } from "citty";
98733
99054
 
98734
99055
  // src/commands/winning-ads/shared.ts
98735
99056
  function splitList4(value2) {
@@ -98738,7 +99059,7 @@ function splitList4(value2) {
98738
99059
  }
98739
99060
  return value2.split(",").map((v) => v.trim()).filter(Boolean);
98740
99061
  }
98741
- function reportError3(err) {
99062
+ function reportError4(err) {
98742
99063
  if (err instanceof ApiError) {
98743
99064
  writeJson({ ok: false, error: { code: err.code, message: err.message } });
98744
99065
  process.exit(1);
@@ -98782,7 +99103,7 @@ function advertiserNormalizer(record, full) {
98782
99103
  last_synced_at: record.last_synced_at ?? null
98783
99104
  };
98784
99105
  }
98785
- var advertisersCommand2 = defineCommand268({
99106
+ var advertisersCommand2 = defineCommand274({
98786
99107
  meta: {
98787
99108
  name: "advertisers",
98788
99109
  description: 'List corpus advertisers by name or domain. Find your own advertiser for --exclude-advertiser, or a competitor for --advertiser-id / winners. Example: baker winning-ads advertisers "Deel" --output md'
@@ -98834,13 +99155,13 @@ var advertisersCommand2 = defineCommand268({
98834
99155
  advertiserNormalizer
98835
99156
  );
98836
99157
  } catch (err) {
98837
- reportError3(err);
99158
+ reportError4(err);
98838
99159
  }
98839
99160
  }
98840
99161
  });
98841
99162
 
98842
99163
  // src/commands/winning-ads/content.ts
98843
- import { defineCommand as defineCommand269 } from "citty";
99164
+ import { defineCommand as defineCommand275 } from "citty";
98844
99165
  registerSchema({
98845
99166
  command: "winning-ads.content",
98846
99167
  description: "Read what's INSIDE one winning ad: the spoken transcript, the on-screen text, and the ad copy. Use this after `search`/`winners`/`feed` return a shortlist \u2014 pass an ad_id to understand a reference before reproducing it. Static and carousel ads return the text drawn into the image with the job each piece does (headline, benefit, cta\u2026), the card it sits on, and their format_pattern. Add --full for how it is built (composition, colours, CTA, markers), how it persuades (awareness, mechanism, pains, desires, proof, objections), what it offers (offer type, price, guarantee, urgency), plus speech, pacing and soundtrack for video.",
@@ -98853,7 +99174,7 @@ registerSchema({
98853
99174
  }
98854
99175
  }
98855
99176
  });
98856
- var contentCommand = defineCommand269({
99177
+ var contentCommand = defineCommand275({
98857
99178
  meta: {
98858
99179
  name: "content",
98859
99180
  description: "Read the transcript + on-screen text + copy of one winning ad; --full adds its build, persuasion and offer. Example: baker winning-ads content adg_123 --platform meta --full --output md"
@@ -98896,13 +99217,13 @@ var contentCommand = defineCommand269({
98896
99217
  adContentNormalizer
98897
99218
  );
98898
99219
  } catch (err) {
98899
- reportError3(err);
99220
+ reportError4(err);
98900
99221
  }
98901
99222
  }
98902
99223
  });
98903
99224
 
98904
99225
  // src/commands/winning-ads/feed.ts
98905
- import { defineCommand as defineCommand270 } from "citty";
99226
+ import { defineCommand as defineCommand276 } from "citty";
98906
99227
  function buildFeedParams(input) {
98907
99228
  const params = {};
98908
99229
  const advertiser = splitList4(input.advertiser);
@@ -98954,7 +99275,7 @@ registerSchema({
98954
99275
  format: { type: "string", description: "Comma-separated formats to include (e.g. static,video)", required: false }
98955
99276
  }
98956
99277
  });
98957
- var feedCommand2 = defineCommand270({
99278
+ var feedCommand2 = defineCommand276({
98958
99279
  meta: {
98959
99280
  name: "feed",
98960
99281
  description: "Winners across every brand you follow (browse, then trim per advertiser). Example: baker winning-ads feed --per-advertiser 5 --output md"
@@ -99033,13 +99354,13 @@ var feedCommand2 = defineCommand270({
99033
99354
  `);
99034
99355
  }
99035
99356
  } catch (err) {
99036
- reportError3(err);
99357
+ reportError4(err);
99037
99358
  }
99038
99359
  }
99039
99360
  });
99040
99361
 
99041
99362
  // src/commands/winning-ads/follow.ts
99042
- import { defineCommand as defineCommand271 } from "citty";
99363
+ import { defineCommand as defineCommand277 } from "citty";
99043
99364
  var PLATFORMS = adLibraryPlatformSchema.options;
99044
99365
  registerSchema({
99045
99366
  command: "winning-ads.follow",
@@ -99054,7 +99375,7 @@ registerSchema({
99054
99375
  label: { type: "string", description: "Optional display label (defaults to the resolved name)", required: false }
99055
99376
  }
99056
99377
  });
99057
- var followCommand = defineCommand271({
99378
+ var followCommand = defineCommand277({
99058
99379
  meta: {
99059
99380
  name: "follow",
99060
99381
  description: 'Follow a brand to track ALL its ads \u2014 every platform and country. --platform is how we read your input, not a limit. A domain tracks every platform we can resolve. Example: baker winning-ads follow "deel.com" --platform meta'
@@ -99095,13 +99416,13 @@ var followCommand = defineCommand271({
99095
99416
  }
99096
99417
  writeJson({ ok: true, data, hints: hints2 });
99097
99418
  } catch (err) {
99098
- reportError3(err);
99419
+ reportError4(err);
99099
99420
  }
99100
99421
  }
99101
99422
  });
99102
99423
 
99103
99424
  // src/commands/winning-ads/follow-competitors.ts
99104
- import { defineCommand as defineCommand272 } from "citty";
99425
+ import { defineCommand as defineCommand278 } from "citty";
99105
99426
  var PLATFORMS2 = adLibraryPlatformSchema.options;
99106
99427
  var BATCH_TIMEOUT_MS = 3e5;
99107
99428
  function buildFollowBatchBody(input) {
@@ -99134,7 +99455,7 @@ registerSchema({
99134
99455
  }
99135
99456
  }
99136
99457
  });
99137
- var followCompetitorsCommand = defineCommand272({
99458
+ var followCompetitorsCommand = defineCommand278({
99138
99459
  meta: {
99139
99460
  name: "follow-competitors",
99140
99461
  description: 'Follow many brands at once by domain \u2014 add every competitor in one call. Example: baker winning-ads follow-competitors "deel.com,notion.so,hubspot.com"'
@@ -99203,13 +99524,13 @@ var followCompetitorsCommand = defineCommand272({
99203
99524
  }
99204
99525
  writeJson({ ok: true, data, hints: hints2.length > 0 ? hints2 : void 0 });
99205
99526
  } catch (err) {
99206
- reportError3(err);
99527
+ reportError4(err);
99207
99528
  }
99208
99529
  }
99209
99530
  });
99210
99531
 
99211
99532
  // src/commands/winning-ads/following.ts
99212
- import { defineCommand as defineCommand273 } from "citty";
99533
+ import { defineCommand as defineCommand279 } from "citty";
99213
99534
  registerSchema({
99214
99535
  command: "winning-ads.following",
99215
99536
  description: "List the brands you follow in your ad-dna library, with each one's status (ready vs still adding) and cached ad counts. A brand still adding has counts that are a lie in progress; one with `discovery_failed` has counts that are short because we couldn't finish looking, which is not the same as it running no ads.",
@@ -99263,7 +99584,7 @@ function followingNormalizer(record, full) {
99263
99584
  platforms: Array.isArray(record.platforms) ? record.platforms : []
99264
99585
  };
99265
99586
  }
99266
- var followingCommand = defineCommand273({
99587
+ var followingCommand = defineCommand279({
99267
99588
  meta: {
99268
99589
  name: "following",
99269
99590
  description: "List brands you follow, with status (ready / adding\u2026) and cached counts. A brand's counts are only final once it is ready. Example: baker winning-ads following --output md"
@@ -99293,13 +99614,13 @@ var followingCommand = defineCommand273({
99293
99614
  followingNormalizer
99294
99615
  );
99295
99616
  } catch (err) {
99296
- reportError3(err);
99617
+ reportError4(err);
99297
99618
  }
99298
99619
  }
99299
99620
  });
99300
99621
 
99301
99622
  // src/commands/winning-ads/search.ts
99302
- import { defineCommand as defineCommand274 } from "citty";
99623
+ import { defineCommand as defineCommand280 } from "citty";
99303
99624
  registerSchema({
99304
99625
  command: "winning-ads.search",
99305
99626
  description: "Search the ad-dna corpus of scored winning ads, the company's followed brands first. Returns a lean shortlist (advertiser, summary, scores, days_active/active/winner_category as proof, media_url, and visual/container/mechanism when known) to pick a reference to reproduce. Each search is a paid reranker + judge call: one strong search, at most one adjusted retry. A value outside a closed list (--platform, --format, --winner-category, --awareness, --format-pattern, --sort) is refused with error.fix.validValues.",
@@ -99485,7 +99806,7 @@ function reportSearchError(err) {
99485
99806
  writeJson({ ok: false, error: { code: err.code, message: err.message, fix } });
99486
99807
  process.exit(1);
99487
99808
  }
99488
- reportError3(err);
99809
+ reportError4(err);
99489
99810
  }
99490
99811
  var FLAG_FOR_FIELD = {
99491
99812
  limit: "--limit",
@@ -99577,7 +99898,7 @@ function writeSearchResult(data, opts) {
99577
99898
  writeOutput({ ok: true, data: rawResults, ...withHints2 }, opts.output, opts.fields, opts.full, winningAdNormalizer);
99578
99899
  }
99579
99900
  var SEARCH_TIMEOUT_MS = 12e4;
99580
- var searchCommand6 = defineCommand274({
99901
+ var searchCommand6 = defineCommand280({
99581
99902
  meta: {
99582
99903
  name: "search",
99583
99904
  description: "Search winning reference ads, the company's followed brands first. Start here: baker winning-ads search 'B2B SaaS before/after AI automation' --platform meta --format static --exclude-advertiser adv_123 --output md. A set of references for N concepts in one call: add --diverse --limit N. The best proven ad in one container from any category: --format-pattern comparison_table (no query needed; add --sort longest_running to order by staying power). Each search is a paid reranker + judge call: one strong search, at most one adjusted retry."
@@ -99703,7 +100024,7 @@ var searchCommand6 = defineCommand274({
99703
100024
  });
99704
100025
 
99705
100026
  // src/commands/winning-ads/seeds.ts
99706
- import { defineCommand as defineCommand275 } from "citty";
100027
+ import { defineCommand as defineCommand281 } from "citty";
99707
100028
  function leanRow(r) {
99708
100029
  return {
99709
100030
  key: r.key,
@@ -99731,7 +100052,7 @@ function makeSeedCommand(opts) {
99731
100052
  limit: { type: "number", description: "Max keys 1-100 (default 20)", required: false, default: 20 }
99732
100053
  }
99733
100054
  });
99734
- return defineCommand275({
100055
+ return defineCommand281({
99735
100056
  meta: { name: opts.name, description: opts.description },
99736
100057
  args: {
99737
100058
  platform: { type: "string", description: "Single platform to segment on", required: false },
@@ -99758,7 +100079,7 @@ function makeSeedCommand(opts) {
99758
100079
  }
99759
100080
  writeOutput({ ok: true, data: projected }, output);
99760
100081
  } catch (err) {
99761
- reportError3(err);
100082
+ reportError4(err);
99762
100083
  }
99763
100084
  }
99764
100085
  });
@@ -99780,7 +100101,7 @@ var formatsCommand = makeSeedCommand({
99780
100101
  });
99781
100102
 
99782
100103
  // src/commands/winning-ads/unfollow.ts
99783
- import { defineCommand as defineCommand276 } from "citty";
100104
+ import { defineCommand as defineCommand282 } from "citty";
99784
100105
  registerSchema({
99785
100106
  command: "winning-ads.unfollow",
99786
100107
  description: "Stop following a brand \u2014 removes it from your ad-dna library by advertiser id.",
@@ -99788,7 +100109,7 @@ registerSchema({
99788
100109
  advertiser: { type: "string", description: "Advertiser id to unfollow", required: true }
99789
100110
  }
99790
100111
  });
99791
- var unfollowCommand = defineCommand276({
100112
+ var unfollowCommand = defineCommand282({
99792
100113
  meta: {
99793
100114
  name: "unfollow",
99794
100115
  description: "Stop following a brand by advertiser id. Example: baker winning-ads unfollow adv_123"
@@ -99803,13 +100124,13 @@ var unfollowCommand = defineCommand276({
99803
100124
  });
99804
100125
  writeJson({ ok: true, data });
99805
100126
  } catch (err) {
99806
- reportError3(err);
100127
+ reportError4(err);
99807
100128
  }
99808
100129
  }
99809
100130
  });
99810
100131
 
99811
100132
  // src/commands/winning-ads/winners.ts
99812
- import { defineCommand as defineCommand277 } from "citty";
100133
+ import { defineCommand as defineCommand283 } from "citty";
99813
100134
  registerSchema({
99814
100135
  command: "winning-ads.winners",
99815
100136
  description: "Top winning ads for one advertiser id (from `advertisers` or `following`). Returns lean winner cards; add --full for DNA + longevity.",
@@ -99819,7 +100140,7 @@ registerSchema({
99819
100140
  platform: { type: "string", description: "Filter to a single platform: meta|linkedin|tiktok", required: false }
99820
100141
  }
99821
100142
  });
99822
- var winnersCommand = defineCommand277({
100143
+ var winnersCommand = defineCommand283({
99823
100144
  meta: {
99824
100145
  name: "winners",
99825
100146
  description: "Top winning ads for a specific advertiser id. Example: baker winning-ads winners adv_123 --top 15 --output md"
@@ -99863,13 +100184,13 @@ var winnersCommand = defineCommand277({
99863
100184
  winningAdNormalizer
99864
100185
  );
99865
100186
  } catch (err) {
99866
- reportError3(err);
100187
+ reportError4(err);
99867
100188
  }
99868
100189
  }
99869
100190
  });
99870
100191
 
99871
100192
  // src/commands/winning-ads/index.ts
99872
- var winningAdsCommand = defineCommand278({
100193
+ var winningAdsCommand = defineCommand284({
99873
100194
  meta: {
99874
100195
  name: "winning-ads",
99875
100196
  description: `Search the ad-dna corpus of scored "winning" ads for reference creatives to reproduce, and manage the brands your library tracks. Proxied through the Baker backend (BAKER_API_KEY) \u2014 no separate token needed.
@@ -99937,7 +100258,7 @@ function getCliVersion() {
99937
100258
  }
99938
100259
 
99939
100260
  // src/cli.ts
99940
- var main = defineCommand279({
100261
+ var main = defineCommand285({
99941
100262
  meta: {
99942
100263
  name: "baker",
99943
100264
  version: getCliVersion(),