@koda-sl/baker-cli 0.412.0 → 0.414.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/README.md +17 -0
- package/dist/cli.js +394 -73
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
|
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([
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
60437
|
-
pause: z49.strictObject({ sourceId:
|
|
60438
|
-
resume: z49.strictObject({ sourceId:
|
|
60439
|
-
remove: z49.strictObject({ sourceId:
|
|
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
|
|
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 =
|
|
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:
|
|
97546
|
+
description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
|
|
97498
97547
|
required: false,
|
|
97499
|
-
enum: [
|
|
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: {
|
|
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:
|
|
97688
|
+
description: `Filter by source: ${testimonialSourceTypeSchema.options.join("|")}`,
|
|
97636
97689
|
required: false,
|
|
97637
|
-
enum: [
|
|
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: {
|
|
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 =
|
|
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
|
|
98092
|
+
import { defineCommand as defineCommand273 } from "citty";
|
|
97772
98093
|
|
|
97773
98094
|
// src/commands/videos/delete.ts
|
|
97774
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
99050
|
+
import { defineCommand as defineCommand284 } from "citty";
|
|
98730
99051
|
|
|
98731
99052
|
// src/commands/winning-ads/advertisers.ts
|
|
98732
|
-
import { defineCommand as
|
|
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
|
|
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 =
|
|
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
|
-
|
|
99158
|
+
reportError4(err);
|
|
98838
99159
|
}
|
|
98839
99160
|
}
|
|
98840
99161
|
});
|
|
98841
99162
|
|
|
98842
99163
|
// src/commands/winning-ads/content.ts
|
|
98843
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
99220
|
+
reportError4(err);
|
|
98900
99221
|
}
|
|
98901
99222
|
}
|
|
98902
99223
|
});
|
|
98903
99224
|
|
|
98904
99225
|
// src/commands/winning-ads/feed.ts
|
|
98905
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
99357
|
+
reportError4(err);
|
|
99037
99358
|
}
|
|
99038
99359
|
}
|
|
99039
99360
|
});
|
|
99040
99361
|
|
|
99041
99362
|
// src/commands/winning-ads/follow.ts
|
|
99042
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
99419
|
+
reportError4(err);
|
|
99099
99420
|
}
|
|
99100
99421
|
}
|
|
99101
99422
|
});
|
|
99102
99423
|
|
|
99103
99424
|
// src/commands/winning-ads/follow-competitors.ts
|
|
99104
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
99527
|
+
reportError4(err);
|
|
99207
99528
|
}
|
|
99208
99529
|
}
|
|
99209
99530
|
});
|
|
99210
99531
|
|
|
99211
99532
|
// src/commands/winning-ads/following.ts
|
|
99212
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
99617
|
+
reportError4(err);
|
|
99297
99618
|
}
|
|
99298
99619
|
}
|
|
99299
99620
|
});
|
|
99300
99621
|
|
|
99301
99622
|
// src/commands/winning-ads/search.ts
|
|
99302
|
-
import { defineCommand as
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
100127
|
+
reportError4(err);
|
|
99807
100128
|
}
|
|
99808
100129
|
}
|
|
99809
100130
|
});
|
|
99810
100131
|
|
|
99811
100132
|
// src/commands/winning-ads/winners.ts
|
|
99812
|
-
import { defineCommand as
|
|
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 =
|
|
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
|
-
|
|
100187
|
+
reportError4(err);
|
|
99867
100188
|
}
|
|
99868
100189
|
}
|
|
99869
100190
|
});
|
|
99870
100191
|
|
|
99871
100192
|
// src/commands/winning-ads/index.ts
|
|
99872
|
-
var winningAdsCommand =
|
|
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 =
|
|
100261
|
+
var main = defineCommand285({
|
|
99941
100262
|
meta: {
|
|
99942
100263
|
name: "baker",
|
|
99943
100264
|
version: getCliVersion(),
|