@koda-sl/baker-cli 0.16.0 → 0.19.0-dev.2731a036

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 CHANGED
@@ -383,6 +383,260 @@ baker ads google keywords metrics --customer-id 1234567890 --keywords "running s
383
383
 
384
384
  ---
385
385
 
386
+ ### Google Ads Library (`baker ads google library`)
387
+
388
+ Manage and search the Google Ads Transparency Center. Track competitor advertisers, browse their ad creatives, and discover who's bidding on keywords.
389
+
390
+ **Typical workflow:** `search-advertiser` → `track` → `search-ads`
391
+
392
+ ---
393
+
394
+ ### `baker ads google library search-advertiser "query"`
395
+
396
+ Search for an advertiser on the Google Ads Transparency Center.
397
+
398
+ ```bash
399
+ baker ads google library search-advertiser "Nike"
400
+ baker ads google library search-advertiser "example.com"
401
+ ```
402
+
403
+ **Response:**
404
+
405
+ ```json
406
+ {
407
+ "ok": true,
408
+ "data": {
409
+ "results": [
410
+ { "advertiserId": "AR12345678901234567", "name": "Nike, Inc.", "region": "US", "format": "TEXT_IMAGE_VIDEO" }
411
+ ]
412
+ }
413
+ }
414
+ ```
415
+
416
+ **Flags:**
417
+
418
+ | Flag | Description |
419
+ |------------|--------------------------------|
420
+ | `--output` | Format: `json` \| `csv` \| `md` |
421
+
422
+ ---
423
+
424
+ ### `baker ads google library track <id> <name>`
425
+
426
+ Track a new Google advertiser and wait for the initial ad sync to complete. Polls every 5 seconds with a 10-minute timeout. Progress is written to stderr.
427
+
428
+ ```bash
429
+ baker ads google library track AR12345678901234567 "Nike, Inc."
430
+ baker ads google library track AR12345678901234567 "Nike, Inc." --json
431
+ ```
432
+
433
+ **Response (with `--json`):**
434
+
435
+ ```json
436
+ {
437
+ "ok": true,
438
+ "data": {
439
+ "advertiserId": "ar_abc123",
440
+ "accountId": "acc_def456",
441
+ "totalAdCount": 342,
442
+ "activeAdCount": 89
443
+ }
444
+ }
445
+ ```
446
+
447
+ **Flags:**
448
+
449
+ | Flag | Description |
450
+ |----------|----------------------|
451
+ | `--json` | Output in JSON format |
452
+
453
+ ---
454
+
455
+ ### `baker ads google library list-advertisers`
456
+
457
+ List all tracked Google advertisers and their accounts.
458
+
459
+ ```bash
460
+ baker ads google library list-advertisers
461
+ baker ads google library list-advertisers --output md
462
+ ```
463
+
464
+ **Flags:**
465
+
466
+ | Flag | Description |
467
+ |------------|--------------------------------|
468
+ | `--output` | Format: `json` \| `csv` \| `md` |
469
+
470
+ ---
471
+
472
+ ### `baker ads google library sync-status <accountId>`
473
+
474
+ Check the sync status and ad counts of a tracked account.
475
+
476
+ ```bash
477
+ baker ads google library sync-status acc_def456
478
+ ```
479
+
480
+ **Response:**
481
+
482
+ ```json
483
+ {
484
+ "ok": true,
485
+ "data": {
486
+ "syncStatus": null,
487
+ "totalAdCount": 342,
488
+ "activeAdCount": 89
489
+ }
490
+ }
491
+ ```
492
+
493
+ `syncStatus` is `null` when idle, `"syncing"` during a sync, or `"error"` if the last sync failed.
494
+
495
+ ---
496
+
497
+ ### `baker ads google library search-ads <accountId>`
498
+
499
+ Search and filter ads for a tracked account. Supports pagination.
500
+
501
+ ```bash
502
+ baker ads google library search-ads acc_def456
503
+ baker ads google library search-ads acc_def456 --search "summer sale" --isActive --mediaType image
504
+ baker ads google library search-ads acc_def456 --sort newest --limit 50
505
+ baker ads google library search-ads acc_def456 --cursor "eyJwYWdl..."
506
+ ```
507
+
508
+ **Response:**
509
+
510
+ ```json
511
+ {
512
+ "ok": true,
513
+ "data": {
514
+ "page": [
515
+ {
516
+ "_id": "abc123",
517
+ "platform": "google",
518
+ "externalId": "CR_1234567890",
519
+ "isActive": true,
520
+ "mediaType": "image",
521
+ "headline": "Summer Sale — 50% Off Everything",
522
+ "description": "Shop our biggest sale of the year. Free shipping on all orders.",
523
+ "destinationUrl": "https://example.com/summer-sale",
524
+ "bodyText": "Summer Sale — 50% Off Everything",
525
+ "pageName": "Example Store",
526
+ "impressionsMin": 100000,
527
+ "impressionsMax": 200000,
528
+ "startDate": "2025-06-01",
529
+ "endDate": "2025-06-30",
530
+ "firstSeenAt": 1717200000000,
531
+ "lastSeenAt": 1719792000000,
532
+ "publisherPlatforms": ["GOOGLE_ADS"],
533
+ "regionCodes": ["US", "GB"],
534
+ "variations": [
535
+ {
536
+ "headline": "Summer Sale — 50% Off",
537
+ "description": "Shop our biggest sale of the year.",
538
+ "destinationUrl": "https://example.com/summer-sale",
539
+ "imageUrl": "https://...",
540
+ "visibleUrl": "example.com"
541
+ }
542
+ ],
543
+ "regions": [
544
+ { "code": "US", "name": "United States" }
545
+ ],
546
+ "analysisStatus": "completed",
547
+ "aiAnalysis": {
548
+ "aiSummary": "Promotional display ad for a seasonal sale with urgency-driven CTA",
549
+ "hookAngle": "Discount/Price",
550
+ "offerType": "Percentage Discount",
551
+ "ctaStrategy": "Shop Now",
552
+ "funnelStage": "Bottom",
553
+ "targetAudience": "Price-sensitive shoppers",
554
+ "adFormat": "responsive_display",
555
+ "tags": ["sale", "discount", "ecommerce"],
556
+ "trustSignals": ["Free shipping"],
557
+ "keyMessages": ["50% off", "Free shipping"],
558
+ "competitiveAngle": "Price leadership",
559
+ "dominantColors": ["#FF5733", "#FFFFFF"],
560
+ "analyzedAt": 1719792000000
561
+ }
562
+ }
563
+ ],
564
+ "continueCursor": "eyJwYWdl...",
565
+ "isDone": false
566
+ }
567
+ }
568
+ ```
569
+
570
+ **Key response fields:**
571
+
572
+ | Field | Description |
573
+ |-------|-------------|
574
+ | `headline`, `description` | Top-level ad copy (first variation) |
575
+ | `variations[]` | All ad variations with copy, images, videos, and URLs |
576
+ | `regions[]` | Geographic targeting regions |
577
+ | `impressionsMin/Max` | Estimated impression range (Google Ads Transparency data) |
578
+ | `publisherPlatforms` | Where the ad ran (GOOGLE_ADS, YOUTUBE, etc.) |
579
+ | `analysisStatus` | AI analysis state: `pending`, `processing`, `completed`, `failed` |
580
+ | `aiAnalysis` | AI-generated creative analysis (only present when `analysisStatus` is `completed`) |
581
+ | `aiAnalysis.aiSummary` | One-line AI summary of the ad |
582
+ | `aiAnalysis.hookAngle` | Creative hook (Discount, Fear, Social Proof, etc.) |
583
+ | `aiAnalysis.funnelStage` | Funnel position: Top, Middle, Bottom |
584
+ | `aiAnalysis.tags` | AI-generated tags for filtering |
585
+
586
+ **Flags:**
587
+
588
+ | Flag | Description |
589
+ |---------------|------------------------------------------------|
590
+ | `--search` | Search term for ad text |
591
+ | `--isActive` | Filter by active ads only |
592
+ | `--mediaType` | Filter by media type: `image`, `video`, `text` |
593
+ | `--sort` | Sort: `newest` or `oldest` |
594
+ | `--limit` | Max results per page (default 20, max 100) |
595
+ | `--cursor` | Pagination cursor from previous response |
596
+ | `--output` | Format: `json` \| `csv` \| `md` |
597
+
598
+ ---
599
+
600
+ ### `baker ads google library sync <accountId>`
601
+
602
+ Trigger an immediate re-sync for a tracked account. Polls every 5 seconds until complete (10-minute timeout). Progress is written to stderr.
603
+
604
+ ```bash
605
+ baker ads google library sync acc_def456
606
+ ```
607
+
608
+ **Response:**
609
+
610
+ ```json
611
+ {
612
+ "ok": true,
613
+ "data": {
614
+ "totalAdCount": 350,
615
+ "activeAdCount": 92
616
+ }
617
+ }
618
+ ```
619
+
620
+ ---
621
+
622
+ ### `baker ads google library search-competitors "keyword"`
623
+
624
+ Search for competitors running Google ads for a keyword. Uses DataForSEO (same data as `baker research advertisers`).
625
+
626
+ ```bash
627
+ baker ads google library search-competitors "running shoes"
628
+ baker ads google library search-competitors "crm software" --location uk
629
+ ```
630
+
631
+ **Flags:**
632
+
633
+ | Flag | Description |
634
+ |--------------|----------------------------|
635
+ | `--location` | Location name or code |
636
+ | `--json` | Output in JSON format |
637
+
638
+ ---
639
+
386
640
  ### Caching
387
641
 
388
642
  Google Ads data is cached at two levels:
@@ -587,9 +841,55 @@ baker gsc sitemaps --site-url "https://example.com/"
587
841
 
588
842
  ### Competitive Intelligence (`baker research`)
589
843
 
590
- Market and competitor research powered by DataForSEO. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps, and landing page performance.
844
+ Market and competitor research powered by DataForSEO and AI-powered Google Search grounding. Shows who's competing for keywords, search intent classification, competitor keyword strategies, keyword gaps, landing page performance, and open-ended AI research.
845
+
846
+ All DataForSEO research responses include a `note` field indicating that data is estimated from third-party SERP scraping and should be used for directional insights, not precise measurement.
847
+
848
+ ---
849
+
850
+ ### `baker research web "question"`
851
+
852
+ Search the web with AI to answer any open-ended marketing question — competitors, ICP, pricing, pain points, market trends. Uses live internet data via Google Search.
853
+
854
+ ```bash
855
+ baker research web "Who are the main competitors of HubSpot CRM?"
856
+ baker research web "What are the top pain points for SMB CRM buyers?" --depth high
857
+ baker research web "Full competitive analysis of project management SaaS" --depth xhigh
858
+ baker research web "What is the pricing of monday.com?" --output md
859
+ ```
860
+
861
+ **Depth levels:**
862
+
863
+ | Depth | Model | Use case | Timeout |
864
+ |-------|-------|----------|---------|
865
+ | `medium` (default) | Gemini Flash + minimal thinking | Quick lookups | 3m |
866
+ | `high` | Gemini Flash + deep thinking | Thorough answers | 6m |
867
+ | `xhigh` | Gemini Deep Research | Exhaustive research (use sparingly) | 15m |
868
+
869
+ **Response:**
870
+
871
+ ```json
872
+ {
873
+ "ok": true,
874
+ "data": {
875
+ "answer": "## HubSpot CRM Competitors\n\n### 1. Salesforce\n...",
876
+ "sources": [
877
+ { "title": "HubSpot vs Salesforce", "url": "https://..." }
878
+ ]
879
+ },
880
+ "fields": {
881
+ "answer": "AI-generated research answer (markdown)",
882
+ "sources": "Array of {title, url} sources used for grounding"
883
+ }
884
+ }
885
+ ```
886
+
887
+ **Flags:**
591
888
 
592
- All research responses include a `note` field indicating that data is estimated from third-party SERP scraping and should be used for directional insights, not precise measurement.
889
+ | Flag | Description |
890
+ |------------|------------------------------------------------------|
891
+ | `--depth` | Research depth: medium (default), high, xhigh |
892
+ | `--output` | Format: json (default), md (raw markdown + sources) |
593
893
 
594
894
  ---
595
895
 
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import { videosCommand } from "./commands/videos/index.js";
11
11
  const main = defineCommand({
12
12
  meta: {
13
13
  name: "baker",
14
- version: "0.16.0",
14
+ version: "0.19.0",
15
15
  description: `AI-agent CLI for finding and managing images, videos, testimonials, and ad platform data in Baker.
16
16
 
17
17
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
package/dist/client.d.ts CHANGED
@@ -5,6 +5,8 @@ export declare class ApiError extends Error {
5
5
  }
6
6
  export declare function validateConvexId(id: string): void;
7
7
  export declare function apiGet<T>(path: string, params?: Record<string, string>): Promise<T>;
8
- export declare function apiPost<T>(path: string, body: unknown): Promise<T>;
8
+ export declare function apiPost<T>(path: string, body: unknown, opts?: {
9
+ timeoutMs?: number;
10
+ }): Promise<T>;
9
11
  export {};
10
12
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,GACV,cAAc,GACd,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,SAAS,CAAC;AAEd,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,SAAS,CAAC;gBAEJ,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;CAK7C;AAqBD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjD;AAsDD,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BzF;AAED,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBxE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AA6BA,KAAK,SAAS,GACV,cAAc,GACd,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,SAAS,CAAC;AAEd,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,SAAS,CAAC;gBAEJ,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM;CAK7C;AAqBD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIjD;AAsDD,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BzF;AAED,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAuBvG"}
package/dist/client.js CHANGED
@@ -1,4 +1,23 @@
1
1
  import { getEnv } from "./env.js";
2
+ const MAX_RATE_LIMIT_RETRIES = 3;
3
+ const MAX_TOTAL_WAIT_MS = 2 * 60 * 1000;
4
+ async function fetchWithRateLimitRetry(url, init) {
5
+ let totalWaited = 0;
6
+ for (let attempt = 0; attempt <= MAX_RATE_LIMIT_RETRIES; attempt++) {
7
+ const response = await fetch(url, init);
8
+ if (response.status !== 429 || attempt >= MAX_RATE_LIMIT_RETRIES) {
9
+ return response;
10
+ }
11
+ const retryAfterHeader = response.headers.get("Retry-After");
12
+ const waitMs = retryAfterHeader ? Number(retryAfterHeader) * 1000 : 2000 * 2 ** attempt;
13
+ if (totalWaited + waitMs > MAX_TOTAL_WAIT_MS) {
14
+ return response;
15
+ }
16
+ totalWaited += waitMs;
17
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
18
+ }
19
+ return fetch(url, init);
20
+ }
2
21
  export class ApiError extends Error {
3
22
  code;
4
23
  constructor(code, message) {
@@ -90,7 +109,7 @@ export async function apiGet(path, params) {
90
109
  }
91
110
  let response;
92
111
  try {
93
- response = await fetch(url.toString(), {
112
+ response = await fetchWithRateLimitRetry(url.toString(), {
94
113
  method: "GET",
95
114
  headers: {
96
115
  Authorization: `Bearer ${env.BAKER_API_KEY}`,
@@ -107,11 +126,12 @@ export async function apiGet(path, params) {
107
126
  }
108
127
  return handleResponse(response);
109
128
  }
110
- export async function apiPost(path, body) {
129
+ export async function apiPost(path, body, opts) {
111
130
  const env = getEnv();
131
+ const timeoutMs = opts?.timeoutMs ?? 60_000;
112
132
  let response;
113
133
  try {
114
- response = await fetch(new URL(path, env.BAKER_API_URL).toString(), {
134
+ response = await fetchWithRateLimitRetry(new URL(path, env.BAKER_API_URL).toString(), {
115
135
  method: "POST",
116
136
  headers: {
117
137
  Authorization: `Bearer ${env.BAKER_API_KEY}`,
@@ -119,12 +139,12 @@ export async function apiPost(path, body) {
119
139
  Accept: "application/json",
120
140
  },
121
141
  body: JSON.stringify(body),
122
- signal: AbortSignal.timeout(60_000),
142
+ signal: AbortSignal.timeout(timeoutMs),
123
143
  });
124
144
  }
125
145
  catch (err) {
126
146
  if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
127
- throw new ApiError("TIMEOUT", "Request timed out after 60 seconds");
147
+ throw new ApiError("TIMEOUT", `Request timed out after ${Math.round(timeoutMs / 1000)} seconds`);
128
148
  }
129
149
  throw new ApiError("NETWORK_ERROR", `Request failed: ${err instanceof Error ? err.message : "Unknown error"}`);
130
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,qDAsBxB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,qDAyBxB,CAAC"}
@@ -3,6 +3,7 @@ import { accountsCommand } from "./accounts.js";
3
3
  import { changesCommand } from "./changes.js";
4
4
  import { currencyCommand } from "./currency.js";
5
5
  import { keywordsCommand } from "./keywords/index.js";
6
+ import { library } from "./library/index.js";
6
7
  import { queryCommand } from "./query.js";
7
8
  export const googleCommand = defineCommand({
8
9
  meta: {
@@ -12,12 +13,14 @@ export const googleCommand = defineCommand({
12
13
  Start here:
13
14
  baker ads google accounts — list accessible accounts
14
15
  baker ads google query --list-presets — see available query templates
16
+ baker ads google library --help — manage and search the Google Ads Library
15
17
 
16
18
  Examples:
17
19
  baker ads google query "SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date DURING LAST_7_DAYS" --customer-id 1234567890
18
20
  baker ads google query --preset campaign-performance --customer-id 1234567890
19
21
  baker ads google currency --customer-id 1234567890
20
- baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"`,
22
+ baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"
23
+ baker ads google library list-advertisers — list tracked Google advertisers`,
21
24
  },
22
25
  subCommands: {
23
26
  accounts: accountsCommand,
@@ -25,6 +28,7 @@ Examples:
25
28
  changes: changesCommand,
26
29
  query: queryCommand,
27
30
  keywords: keywordsCommand,
31
+ library: library,
28
32
  },
29
33
  });
30
34
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;;;;;;;;;;sFAUqE;KACnF;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,eAAe;KAC1B;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;;;;;;;;;;;;iFAYgE;KAC9E;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,OAAO;KACjB;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const library: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/commands/ads/google/library/index.ts"],"names":[],"mappings":"AA0RA,eAAO,MAAM,OAAO,qDAclB,CAAC"}
@@ -0,0 +1,271 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet, apiPost } from "../../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../../output.js";
4
+ const listAdvertisers = defineCommand({
5
+ meta: {
6
+ name: "list-advertisers",
7
+ description: "List tracked Google advertisers and their accounts",
8
+ },
9
+ args: {
10
+ output: { type: "string", description: "Format: json|csv|md", default: "json" },
11
+ },
12
+ async run({ args }) {
13
+ const data = await apiGet("/api/ads/google/library/advertisers");
14
+ if (args.output !== "json") {
15
+ writeAdsOutput(data, args.output);
16
+ }
17
+ else {
18
+ writeAdsJson({ ok: true, data });
19
+ }
20
+ },
21
+ });
22
+ const syncStatus = defineCommand({
23
+ meta: {
24
+ name: "sync-status",
25
+ description: "Check the sync status and ad counts of a Google account",
26
+ },
27
+ args: {
28
+ accountId: {
29
+ type: "positional",
30
+ description: "Account ID to check",
31
+ required: true,
32
+ },
33
+ output: { type: "string", description: "Format: json", default: "json" },
34
+ },
35
+ async run({ args }) {
36
+ const data = await apiGet("/api/ads/google/library/account-status", {
37
+ accountId: args.accountId,
38
+ });
39
+ writeAdsJson({ ok: true, data });
40
+ },
41
+ });
42
+ const searchAds = defineCommand({
43
+ meta: {
44
+ name: "search-ads",
45
+ description: "Search and filter Google ads for an account",
46
+ },
47
+ args: {
48
+ accountId: {
49
+ type: "positional",
50
+ description: "Account ID to search in",
51
+ required: true,
52
+ },
53
+ search: {
54
+ type: "string",
55
+ description: "Search term for ad text",
56
+ },
57
+ isActive: {
58
+ type: "boolean",
59
+ description: "Filter by active ads only",
60
+ },
61
+ mediaType: {
62
+ type: "string",
63
+ description: "Filter by media type (image, video, text)",
64
+ },
65
+ sort: {
66
+ type: "string",
67
+ description: "Sort by newest or oldest",
68
+ },
69
+ limit: {
70
+ type: "string",
71
+ description: "Maximum number of ads to return (default 20)",
72
+ },
73
+ cursor: {
74
+ type: "string",
75
+ description: "Pagination cursor",
76
+ },
77
+ output: { type: "string", description: "Format: json|csv|md", default: "json" },
78
+ },
79
+ async run({ args }) {
80
+ const data = await apiPost("/api/ads/google/library/ads/search", {
81
+ accountId: args.accountId,
82
+ search: args.search,
83
+ isActive: args.isActive,
84
+ mediaType: args.mediaType,
85
+ sort: args.sort,
86
+ numItems: args.limit ? Number.parseInt(args.limit, 10) : undefined,
87
+ cursor: args.cursor,
88
+ });
89
+ if (args.output !== "json" && Array.isArray(data.page)) {
90
+ writeAdsOutput(data.page, args.output);
91
+ }
92
+ else {
93
+ writeAdsJson({ ok: true, data });
94
+ }
95
+ },
96
+ });
97
+ const searchAdvertiser = defineCommand({
98
+ meta: {
99
+ name: "search-advertiser",
100
+ description: "Search for an advertiser on the Google Ads Transparency Center",
101
+ },
102
+ args: {
103
+ query: {
104
+ type: "positional",
105
+ description: "Company name or domain to search for",
106
+ required: true,
107
+ },
108
+ output: { type: "string", description: "Format: json|csv|md", default: "json" },
109
+ },
110
+ async run({ args }) {
111
+ const data = await apiPost("/api/ads/google/library/search-advertiser", {
112
+ query: args.query,
113
+ });
114
+ if (args.output !== "json" && Array.isArray(data.results)) {
115
+ writeAdsOutput(data.results, args.output);
116
+ }
117
+ else {
118
+ writeAdsJson({ ok: true, data });
119
+ }
120
+ },
121
+ });
122
+ function sleep(ms) {
123
+ return new Promise((resolve) => setTimeout(resolve, ms));
124
+ }
125
+ const track = defineCommand({
126
+ meta: {
127
+ name: "track",
128
+ description: "Track a new Google advertiser (from search results). Waits for initial sync to complete before returning.",
129
+ },
130
+ args: {
131
+ id: {
132
+ type: "positional",
133
+ description: "Google Advertiser ID (e.g. AR123...)",
134
+ required: true,
135
+ },
136
+ name: {
137
+ type: "positional",
138
+ description: "Display name for the advertiser",
139
+ required: true,
140
+ },
141
+ json: {
142
+ type: "boolean",
143
+ description: "Output in JSON format",
144
+ },
145
+ },
146
+ async run({ args }) {
147
+ const data = await apiPost("/api/ads/google/library/track", {
148
+ id: args.id,
149
+ name: args.name,
150
+ });
151
+ process.stderr.write(`Tracking "${args.name}" (${args.id}). Syncing ads...\n`);
152
+ const deadline = Date.now() + 600_000;
153
+ while (Date.now() < deadline) {
154
+ await sleep(5_000);
155
+ const status = await apiGet("/api/ads/google/library/account-status", {
156
+ accountId: data.accountId,
157
+ });
158
+ if (!status.syncStatus) {
159
+ process.stderr.write(`Sync complete. ${status.totalAdCount ?? 0} ads (${status.activeAdCount ?? 0} active)\n`);
160
+ if (args.json) {
161
+ writeAdsJson({ ok: true, data: { ...data, ...status } });
162
+ }
163
+ return;
164
+ }
165
+ if (status.syncStatus === "error") {
166
+ process.stderr.write("Sync failed.\n");
167
+ writeAdsJson({ ok: false, error: { code: "SYNC_ERROR", message: "Initial sync failed" } });
168
+ process.exit(1);
169
+ }
170
+ process.stderr.write(` syncing...\n`);
171
+ }
172
+ process.stderr.write("Sync timed out after 10 minutes.\n");
173
+ writeAdsJson({
174
+ ok: false,
175
+ error: { code: "TIMEOUT", message: "Sync did not complete within 10 minutes" },
176
+ });
177
+ process.exit(1);
178
+ },
179
+ });
180
+ const sync = defineCommand({
181
+ meta: {
182
+ name: "sync",
183
+ description: "Trigger an immediate sync for a Google account. Waits for completion before returning.",
184
+ },
185
+ args: {
186
+ accountId: {
187
+ type: "positional",
188
+ description: "Account ID to sync",
189
+ required: true,
190
+ },
191
+ output: { type: "string", description: "Format: json", default: "json" },
192
+ },
193
+ async run({ args }) {
194
+ await apiPost("/api/ads/google/library/sync", {
195
+ accountId: args.accountId,
196
+ });
197
+ process.stderr.write("Sync started. Polling...\n");
198
+ const deadline = Date.now() + 600_000;
199
+ while (Date.now() < deadline) {
200
+ await sleep(5_000);
201
+ const status = await apiGet("/api/ads/google/library/account-status", {
202
+ accountId: args.accountId,
203
+ });
204
+ if (!status.syncStatus) {
205
+ process.stderr.write(`Sync complete. ${status.totalAdCount ?? 0} ads (${status.activeAdCount ?? 0} active)\n`);
206
+ if (args.output === "json") {
207
+ writeAdsJson({ ok: true, data: status });
208
+ }
209
+ return;
210
+ }
211
+ if (status.syncStatus === "error") {
212
+ process.stderr.write("Sync failed.\n");
213
+ writeAdsJson({ ok: false, error: { code: "SYNC_ERROR", message: "Sync failed" } });
214
+ process.exit(1);
215
+ }
216
+ process.stderr.write(" syncing...\n");
217
+ }
218
+ process.stderr.write("Sync timed out after 10 minutes.\n");
219
+ writeAdsJson({ ok: false, error: { code: "TIMEOUT", message: "Sync did not complete within 10 minutes" } });
220
+ process.exit(1);
221
+ },
222
+ });
223
+ const searchCompetitors = defineCommand({
224
+ meta: {
225
+ name: "search-competitors",
226
+ description: "Search for competitors running Google ads for a keyword (DataForSEO)",
227
+ },
228
+ args: {
229
+ keyword: {
230
+ type: "positional",
231
+ description: "Keyword to search for",
232
+ required: true,
233
+ },
234
+ location: {
235
+ type: "string",
236
+ description: "Location (name or code)",
237
+ },
238
+ json: {
239
+ type: "boolean",
240
+ description: "Output in JSON format",
241
+ },
242
+ },
243
+ async run({ args }) {
244
+ const data = await apiPost("/api/research/advertisers", {
245
+ keyword: args.keyword,
246
+ location: args.location,
247
+ });
248
+ if (args.json) {
249
+ writeAdsJson({ ok: true, data });
250
+ }
251
+ else {
252
+ writeAdsOutput(data, "md");
253
+ }
254
+ },
255
+ });
256
+ export const library = defineCommand({
257
+ meta: {
258
+ name: "library",
259
+ description: "Manage and search the Google Ads Library",
260
+ },
261
+ subCommands: {
262
+ "list-advertisers": listAdvertisers,
263
+ "sync-status": syncStatus,
264
+ "search-ads": searchAds,
265
+ "search-advertiser": searchAdvertiser,
266
+ "search-competitors": searchCompetitors,
267
+ track: track,
268
+ sync: sync,
269
+ },
270
+ });
271
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/commands/ads/google/library/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,eAAe,qDAoC1B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,eAAe,qDAqC1B,CAAC"}
@@ -8,12 +8,14 @@ import { keywordsForSiteCommand } from "./keywords-for-site.js";
8
8
  import { languagesCommand } from "./languages.js";
9
9
  import { lighthouseCommand } from "./lighthouse.js";
10
10
  import { relevantPagesCommand } from "./relevant-pages.js";
11
+ import { webCommand } from "./web.js";
11
12
  export const researchCommand = defineCommand({
12
13
  meta: {
13
14
  name: "research",
14
- description: `Competitive intelligence commands powered by DataForSEO. Shows market/competitor data — who's bidding on keywords, search intent, competitor keyword lists, keyword gaps, and landing page performance.
15
+ description: `Competitive intelligence and AI-powered research commands.
15
16
 
16
17
  Commands:
18
+ web — Search the web with AI (ask any question)
17
19
  advertisers — Who's bidding on a keyword?
18
20
  autocomplete — Google Autocomplete suggestions
19
21
  intent — Google Search intent classification
@@ -25,15 +27,15 @@ Commands:
25
27
  languages — List supported language codes
26
28
 
27
29
  Examples:
30
+ baker research web "Who are the main competitors of HubSpot?"
31
+ baker research web "What is the ICP for CRM buyers?" --depth high
28
32
  baker research advertisers "running shoes"
29
- baker research autocomplete "running shoes"
30
33
  baker research intent "buy running shoes,best running shoes 2026"
31
34
  baker research keywords-for-site "competitor.com"
32
- baker research keyword-gap "them.com" "us.com"
33
- baker research relevant-pages "competitor.com"
34
- baker research lighthouse "https://example.com/landing"`,
35
+ baker research keyword-gap "them.com" "us.com"`,
35
36
  },
36
37
  subCommands: {
38
+ web: webCommand,
37
39
  advertisers: advertisersCommand,
38
40
  autocomplete: autocompleteCommand,
39
41
  countries: countriesCommand,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;0DAoByC;KACvD;IACD,WAAW,EAAE;QACX,WAAW,EAAE,kBAAkB;QAC/B,YAAY,EAAE,mBAAmB;QACjC,SAAS,EAAE,gBAAgB;QAC3B,MAAM,EAAE,aAAa;QACrB,mBAAmB,EAAE,sBAAsB;QAC3C,aAAa,EAAE,iBAAiB;QAChC,SAAS,EAAE,gBAAgB;QAC3B,UAAU,EAAE,iBAAiB;QAC7B,gBAAgB,EAAE,oBAAoB;KACvC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;iDAoBgC;KAC9C;IACD,WAAW,EAAE;QACX,GAAG,EAAE,UAAU;QACf,WAAW,EAAE,kBAAkB;QAC/B,YAAY,EAAE,mBAAmB;QACjC,SAAS,EAAE,gBAAgB;QAC3B,MAAM,EAAE,aAAa;QACrB,mBAAmB,EAAE,sBAAsB;QAC3C,aAAa,EAAE,iBAAiB;QAChC,SAAS,EAAE,gBAAgB;QAC3B,UAAU,EAAE,iBAAiB;QAC7B,gBAAgB,EAAE,oBAAoB;KACvC;CACF,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare const webCommand: import("citty").CommandDef<{
2
+ readonly question: {
3
+ readonly type: "positional";
4
+ readonly description: "The research question";
5
+ readonly required: true;
6
+ };
7
+ readonly depth: {
8
+ readonly type: "string";
9
+ readonly description: "Research depth: medium|high|xhigh (default: medium)";
10
+ readonly required: false;
11
+ };
12
+ readonly output: {
13
+ readonly type: "string";
14
+ readonly description: "Format: json|md (default: json)";
15
+ readonly required: false;
16
+ readonly default: "json";
17
+ };
18
+ }>;
19
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../../src/commands/research/web.ts"],"names":[],"mappings":"AAsEA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;EA6DrB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet, apiPost } from "../../client.js";
3
+ import { registerSchema } from "../../schemas.js";
4
+ import { handleResearchError, writeResearchJson } from "./output.js";
5
+ registerSchema({
6
+ command: "research.web",
7
+ description: "Search the web with AI to answer marketing questions — competitors, ICP, pricing, pain points, market trends. Three depth levels: medium (quick, default), high (thorough), xhigh (exhaustive deep research).",
8
+ args: {
9
+ question: {
10
+ type: "string",
11
+ description: "The research question to answer using live web data",
12
+ required: true,
13
+ },
14
+ depth: {
15
+ type: "string",
16
+ description: "Research depth: medium (quick), high (thorough), xhigh (exhaustive). Default: medium",
17
+ required: false,
18
+ enum: ["medium", "high", "xhigh"],
19
+ },
20
+ },
21
+ });
22
+ const TIMEOUT_MS = {
23
+ medium: 180_000,
24
+ high: 360_000,
25
+ xhigh: 900_000,
26
+ };
27
+ const FIELDS = {
28
+ answer: "AI-generated research answer (markdown)",
29
+ sources: "Array of {title, url} sources used for grounding",
30
+ };
31
+ function sleep(ms) {
32
+ return new Promise((resolve) => setTimeout(resolve, ms));
33
+ }
34
+ async function runDeepResearch(question) {
35
+ const { interactionId } = await apiPost("/api/research/deep-research/start", { question });
36
+ process.stderr.write(`Deep research started (${interactionId}). Polling...\n`);
37
+ const deadline = Date.now() + TIMEOUT_MS.xhigh;
38
+ while (Date.now() < deadline) {
39
+ await sleep(10_000);
40
+ const poll = await apiGet("/api/research/deep-research/poll", {
41
+ id: interactionId,
42
+ });
43
+ if (poll.status === "completed" && poll.result) {
44
+ return poll.result;
45
+ }
46
+ if (poll.status === "failed" || poll.status === "cancelled") {
47
+ throw new Error(`Deep research ${poll.status}`);
48
+ }
49
+ process.stderr.write(` status: ${poll.status}\n`);
50
+ }
51
+ throw new Error("Deep research timed out");
52
+ }
53
+ export const webCommand = defineCommand({
54
+ meta: {
55
+ name: "web",
56
+ description: `Search the web with AI to answer any open-ended marketing question. Uses live internet data via Google Search.
57
+
58
+ Depth levels:
59
+ medium — Quick lookup using Gemini Flash with minimal thinking (default)
60
+ high — Thorough answer using Gemini Flash with deep thinking
61
+ xhigh — Exhaustive deep research using Gemini Deep Research (slow, use sparingly)
62
+
63
+ Examples:
64
+ baker research web "Who are the main competitors of HubSpot CRM?"
65
+ baker research web "What are the top pain points for SMB CRM buyers?" --depth high
66
+ baker research web "Full competitive analysis of project management SaaS" --depth xhigh`,
67
+ },
68
+ args: {
69
+ question: { type: "positional", description: "The research question", required: true },
70
+ depth: { type: "string", description: "Research depth: medium|high|xhigh (default: medium)", required: false },
71
+ output: { type: "string", description: "Format: json|md (default: json)", required: false, default: "json" },
72
+ },
73
+ run: async ({ args }) => {
74
+ const question = args.question;
75
+ if (question.length < 5) {
76
+ writeResearchJson({
77
+ ok: false,
78
+ error: { code: "VALIDATION_ERROR", message: "Question must be at least 5 characters" },
79
+ });
80
+ process.exit(1);
81
+ }
82
+ const depth = (args.depth || "medium");
83
+ if (!["medium", "high", "xhigh"].includes(depth)) {
84
+ writeResearchJson({
85
+ ok: false,
86
+ error: { code: "VALIDATION_ERROR", message: "Depth must be one of: medium, high, xhigh" },
87
+ });
88
+ process.exit(1);
89
+ }
90
+ try {
91
+ const data = depth === "xhigh"
92
+ ? await runDeepResearch(question)
93
+ : await apiPost("/api/research/explore", { question, depth }, { timeoutMs: TIMEOUT_MS[depth] });
94
+ const format = args.output || "json";
95
+ if (format === "md") {
96
+ process.stdout.write(`${data.answer}\n`);
97
+ if (data.sources.length > 0) {
98
+ process.stdout.write("\n## Sources\n");
99
+ for (const s of data.sources) {
100
+ process.stdout.write(`- [${s.title}](${s.url})\n`);
101
+ }
102
+ }
103
+ return;
104
+ }
105
+ writeResearchJson({ ok: true, data, fields: FIELDS });
106
+ }
107
+ catch (err) {
108
+ handleResearchError(err);
109
+ }
110
+ },
111
+ });
112
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../../src/commands/research/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErE,cAAc,CAAC;IACb,OAAO,EAAE,cAAc;IACvB,WAAW,EACT,+MAA+M;IACjN,IAAI,EAAE;QACJ,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,qDAAqD;YAClE,QAAQ,EAAE,IAAI;SACf;QACD,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,sFAAsF;YACnG,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;SAClC;KACF;CACF,CAAC,CAAC;AAIH,MAAM,UAAU,GAA0B;IACxC,MAAM,EAAE,OAAO;IACf,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,OAAO;CACf,CAAC;AAOF,MAAM,MAAM,GAA2B;IACrC,MAAM,EAAE,yCAAyC;IACjD,OAAO,EAAE,kDAAkD;CAC5D,CAAC;AAEF,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,OAAO,CAA4B,mCAAmC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEtH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,aAAa,iBAAiB,CAAC,CAAC;IAE/E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC;IAC/C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAyC,kCAAkC,EAAE;YACpG,EAAE,EAAE,aAAa;SAClB,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE;QACJ,IAAI,EAAE,KAAK;QACX,WAAW,EAAE;;;;;;;;;;0FAUyE;KACvF;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qDAAqD,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC9G,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iCAAiC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE;KAC7G;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAkB,CAAC;QACzC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,iBAAiB,CAAC;gBAChB,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,wCAAwC,EAAE;aACvF,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,CAAE,IAAI,CAAC,KAAgB,IAAI,QAAQ,CAAU,CAAC;QAC5D,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,iBAAiB,CAAC;gBAChB,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,2CAA2C,EAAE;aAC1F,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GACR,KAAK,KAAK,OAAO;gBACf,CAAC,CAAC,MAAM,eAAe,CAAC,QAAQ,CAAC;gBACjC,CAAC,CAAC,MAAM,OAAO,CAAY,uBAAuB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAE/G,MAAM,MAAM,GAAI,IAAI,CAAC,MAAiB,IAAI,MAAM,CAAC;YACjD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;gBACzC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;oBACvC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;wBAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;oBACrD,CAAC;gBACH,CAAC;gBACD,OAAO;YACT,CAAC;YACD,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koda-sl/baker-cli",
3
- "version": "0.16.0",
3
+ "version": "0.19.0-dev.2731a036",
4
4
  "description": "AI-agent-first CLI for interacting with Baker",
5
5
  "type": "module",
6
6
  "bin": {