@koda-sl/baker-cli 0.5.0 → 0.9.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.
Files changed (144) hide show
  1. package/README.md +655 -162
  2. package/dist/cli.js +9 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/ads/cache.d.ts +8 -0
  5. package/dist/commands/ads/cache.d.ts.map +1 -0
  6. package/dist/commands/ads/cache.js +79 -0
  7. package/dist/commands/ads/cache.js.map +1 -0
  8. package/dist/commands/ads/cache.test.d.ts +2 -0
  9. package/dist/commands/ads/cache.test.d.ts.map +1 -0
  10. package/dist/commands/ads/cache.test.js +44 -0
  11. package/dist/commands/ads/cache.test.js.map +1 -0
  12. package/dist/commands/ads/field-descriptions.d.ts +2 -0
  13. package/dist/commands/ads/field-descriptions.d.ts.map +1 -0
  14. package/dist/commands/ads/field-descriptions.js +91 -0
  15. package/dist/commands/ads/field-descriptions.js.map +1 -0
  16. package/dist/commands/ads/google/accounts.d.ts +14 -0
  17. package/dist/commands/ads/google/accounts.d.ts.map +1 -0
  18. package/dist/commands/ads/google/accounts.js +72 -0
  19. package/dist/commands/ads/google/accounts.js.map +1 -0
  20. package/dist/commands/ads/google/changes.d.ts +29 -0
  21. package/dist/commands/ads/google/changes.d.ts.map +1 -0
  22. package/dist/commands/ads/google/changes.js +77 -0
  23. package/dist/commands/ads/google/changes.js.map +1 -0
  24. package/dist/commands/ads/google/correction-table.d.ts +3 -0
  25. package/dist/commands/ads/google/correction-table.d.ts.map +1 -0
  26. package/dist/commands/ads/google/correction-table.js +332 -0
  27. package/dist/commands/ads/google/correction-table.js.map +1 -0
  28. package/dist/commands/ads/google/currency.d.ts +13 -0
  29. package/dist/commands/ads/google/currency.d.ts.map +1 -0
  30. package/dist/commands/ads/google/currency.js +62 -0
  31. package/dist/commands/ads/google/currency.js.map +1 -0
  32. package/dist/commands/ads/google/error-parser.d.ts +3 -0
  33. package/dist/commands/ads/google/error-parser.d.ts.map +1 -0
  34. package/dist/commands/ads/google/error-parser.js +89 -0
  35. package/dist/commands/ads/google/error-parser.js.map +1 -0
  36. package/dist/commands/ads/google/error-parser.test.d.ts +2 -0
  37. package/dist/commands/ads/google/error-parser.test.d.ts.map +1 -0
  38. package/dist/commands/ads/google/error-parser.test.js +48 -0
  39. package/dist/commands/ads/google/error-parser.test.js.map +1 -0
  40. package/dist/commands/ads/google/index.d.ts +2 -0
  41. package/dist/commands/ads/google/index.d.ts.map +1 -0
  42. package/dist/commands/ads/google/index.js +30 -0
  43. package/dist/commands/ads/google/index.js.map +1 -0
  44. package/dist/commands/ads/google/keywords/discover.d.ts +49 -0
  45. package/dist/commands/ads/google/keywords/discover.d.ts.map +1 -0
  46. package/dist/commands/ads/google/keywords/discover.js +137 -0
  47. package/dist/commands/ads/google/keywords/discover.js.map +1 -0
  48. package/dist/commands/ads/google/keywords/index.d.ts +2 -0
  49. package/dist/commands/ads/google/keywords/index.d.ts.map +1 -0
  50. package/dist/commands/ads/google/keywords/index.js +18 -0
  51. package/dist/commands/ads/google/keywords/index.js.map +1 -0
  52. package/dist/commands/ads/google/keywords/metrics.d.ts +34 -0
  53. package/dist/commands/ads/google/keywords/metrics.d.ts.map +1 -0
  54. package/dist/commands/ads/google/keywords/metrics.js +109 -0
  55. package/dist/commands/ads/google/keywords/metrics.js.map +1 -0
  56. package/dist/commands/ads/google/preflight.d.ts +3 -0
  57. package/dist/commands/ads/google/preflight.d.ts.map +1 -0
  58. package/dist/commands/ads/google/preflight.js +115 -0
  59. package/dist/commands/ads/google/preflight.js.map +1 -0
  60. package/dist/commands/ads/google/preflight.test.d.ts +2 -0
  61. package/dist/commands/ads/google/preflight.test.d.ts.map +1 -0
  62. package/dist/commands/ads/google/preflight.test.js +50 -0
  63. package/dist/commands/ads/google/preflight.test.js.map +1 -0
  64. package/dist/commands/ads/google/presets.d.ts +12 -0
  65. package/dist/commands/ads/google/presets.d.ts.map +1 -0
  66. package/dist/commands/ads/google/presets.js +71 -0
  67. package/dist/commands/ads/google/presets.js.map +1 -0
  68. package/dist/commands/ads/google/presets.test.d.ts +2 -0
  69. package/dist/commands/ads/google/presets.test.d.ts.map +1 -0
  70. package/dist/commands/ads/google/presets.test.js +79 -0
  71. package/dist/commands/ads/google/presets.test.js.map +1 -0
  72. package/dist/commands/ads/google/query.d.ts +69 -0
  73. package/dist/commands/ads/google/query.d.ts.map +1 -0
  74. package/dist/commands/ads/google/query.js +305 -0
  75. package/dist/commands/ads/google/query.js.map +1 -0
  76. package/dist/commands/ads/index.d.ts +2 -0
  77. package/dist/commands/ads/index.d.ts.map +1 -0
  78. package/dist/commands/ads/index.js +19 -0
  79. package/dist/commands/ads/index.js.map +1 -0
  80. package/dist/commands/ads/output.d.ts +17 -0
  81. package/dist/commands/ads/output.d.ts.map +1 -0
  82. package/dist/commands/ads/output.js +78 -0
  83. package/dist/commands/ads/output.js.map +1 -0
  84. package/dist/commands/ads/output.test.d.ts +2 -0
  85. package/dist/commands/ads/output.test.d.ts.map +1 -0
  86. package/dist/commands/ads/output.test.js +100 -0
  87. package/dist/commands/ads/output.test.js.map +1 -0
  88. package/dist/commands/ads/types.d.ts +69 -0
  89. package/dist/commands/ads/types.d.ts.map +1 -0
  90. package/dist/commands/ads/types.js +2 -0
  91. package/dist/commands/ads/types.js.map +1 -0
  92. package/dist/commands/research/advertisers.d.ts +29 -0
  93. package/dist/commands/research/advertisers.d.ts.map +1 -0
  94. package/dist/commands/research/advertisers.js +71 -0
  95. package/dist/commands/research/advertisers.js.map +1 -0
  96. package/dist/commands/research/index.d.ts +2 -0
  97. package/dist/commands/research/index.d.ts.map +1 -0
  98. package/dist/commands/research/index.js +34 -0
  99. package/dist/commands/research/index.js.map +1 -0
  100. package/dist/commands/research/intent.d.ts +19 -0
  101. package/dist/commands/research/intent.d.ts.map +1 -0
  102. package/dist/commands/research/intent.js +67 -0
  103. package/dist/commands/research/intent.js.map +1 -0
  104. package/dist/commands/research/keyword-gap.d.ts +44 -0
  105. package/dist/commands/research/keyword-gap.d.ts.map +1 -0
  106. package/dist/commands/research/keyword-gap.js +92 -0
  107. package/dist/commands/research/keyword-gap.js.map +1 -0
  108. package/dist/commands/research/keywords-for-site.d.ts +39 -0
  109. package/dist/commands/research/keywords-for-site.d.ts.map +1 -0
  110. package/dist/commands/research/keywords-for-site.js +79 -0
  111. package/dist/commands/research/keywords-for-site.js.map +1 -0
  112. package/dist/commands/research/lighthouse.d.ts +19 -0
  113. package/dist/commands/research/lighthouse.d.ts.map +1 -0
  114. package/dist/commands/research/lighthouse.js +50 -0
  115. package/dist/commands/research/lighthouse.js.map +1 -0
  116. package/dist/commands/research/output.d.ts +26 -0
  117. package/dist/commands/research/output.d.ts.map +1 -0
  118. package/dist/commands/research/output.js +80 -0
  119. package/dist/commands/research/output.js.map +1 -0
  120. package/dist/commands/testimonials/get.d.ts +30 -0
  121. package/dist/commands/testimonials/get.d.ts.map +1 -0
  122. package/dist/commands/testimonials/get.js +42 -0
  123. package/dist/commands/testimonials/get.js.map +1 -0
  124. package/dist/commands/testimonials/index.d.ts +2 -0
  125. package/dist/commands/testimonials/index.d.ts.map +1 -0
  126. package/dist/commands/testimonials/index.js +22 -0
  127. package/dist/commands/testimonials/index.js.map +1 -0
  128. package/dist/commands/testimonials/list.d.ts +60 -0
  129. package/dist/commands/testimonials/list.d.ts.map +1 -0
  130. package/dist/commands/testimonials/list.js +69 -0
  131. package/dist/commands/testimonials/list.js.map +1 -0
  132. package/dist/commands/testimonials/search.d.ts +40 -0
  133. package/dist/commands/testimonials/search.d.ts.map +1 -0
  134. package/dist/commands/testimonials/search.js +59 -0
  135. package/dist/commands/testimonials/search.js.map +1 -0
  136. package/dist/env.d.ts +1 -0
  137. package/dist/env.d.ts.map +1 -1
  138. package/dist/env.js +5 -1
  139. package/dist/env.js.map +1 -1
  140. package/dist/output.d.ts +1 -0
  141. package/dist/output.d.ts.map +1 -1
  142. package/dist/output.js +37 -0
  143. package/dist/output.js.map +1 -1
  144. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,22 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import { defineCommand, runMain } from "citty";
3
+ import { adsCommand } from "./commands/ads/index.js";
3
4
  import { imagesCommand } from "./commands/images/index.js";
5
+ import { researchCommand } from "./commands/research/index.js";
4
6
  import { schemaCommand } from "./commands/schema.js";
7
+ import { testimonialsCommand } from "./commands/testimonials/index.js";
5
8
  import { videosCommand } from "./commands/videos/index.js";
6
9
  const main = defineCommand({
7
10
  meta: {
8
11
  name: "baker",
9
- version: "0.5.0",
10
- description: `AI-agent CLI for finding and managing images and videos in Baker.
12
+ version: "0.9.0",
13
+ description: `AI-agent CLI for finding and managing images, videos, testimonials, and ad platform data in Baker.
11
14
 
12
15
  Auth: Set BAKER_API_KEY (starts with bk_) and BAKER_API_URL environment variables.
13
16
  Output: All commands return JSON envelopes: { ok: true, data: ... } or { ok: false, error: { code, message } }.
14
- Formats: Use --output json|files|md to control output format. Default: json.
17
+ Formats: Use --output json|csv|jsonl|files|md to control output format. Default: json.
15
18
  Introspection: Run 'baker schema <command>' to inspect argument schemas.`,
16
19
  },
17
20
  subCommands: {
21
+ ads: adsCommand,
22
+ research: researchCommand,
18
23
  images: imagesCommand,
19
24
  videos: videosCommand,
25
+ testimonials: testimonialsCommand,
20
26
  schema: schemaCommand,
21
27
  },
22
28
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE;;;;;yEAKwD;KACtE;IACD,WAAW,EAAE;QACX,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE;;;;;yEAKwD;KACtE;IACD,WAAW,EAAE;QACX,GAAG,EAAE,UAAU;QACf,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,aAAa;QACrB,YAAY,EAAE,mBAAmB;QACjC,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CacheEntry } from "./types.ts";
2
+ export declare function cacheGet<T>(category: string, key: string): CacheEntry<T> | null;
3
+ export declare function cacheSet<T>(category: string, key: string, data: T, ttlMs: number, fields?: Record<string, string>): void;
4
+ export declare function cacheClear(): void;
5
+ export declare function getQueryTtl(query: string): number;
6
+ export declare function buildQueryCacheKey(customerId: string, query: string): string;
7
+ export declare function getManagerIdForCustomer(customerId: string): string | undefined;
8
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoB7C,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAiB/E;AAED,wBAAgB,QAAQ,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,IAAI,CAQN;AAED,wBAAgB,UAAU,IAAI,IAAI,CAKjC;AAKD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG5E;AAQD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM9E"}
@@ -0,0 +1,79 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ const CACHE_DIR = join(homedir(), ".baker", "cache", "ads");
6
+ function ensureDir(dir) {
7
+ if (!existsSync(dir)) {
8
+ mkdirSync(dir, { recursive: true });
9
+ }
10
+ }
11
+ function hashKey(key) {
12
+ return createHash("sha256").update(key).digest("hex").slice(0, 16);
13
+ }
14
+ function cachePath(category, key) {
15
+ const dir = join(CACHE_DIR, category);
16
+ ensureDir(dir);
17
+ return join(dir, `${hashKey(key)}.json`);
18
+ }
19
+ export function cacheGet(category, key) {
20
+ const path = cachePath(category, key);
21
+ if (!existsSync(path)) {
22
+ return null;
23
+ }
24
+ try {
25
+ const raw = readFileSync(path, "utf-8");
26
+ const entry = JSON.parse(raw);
27
+ if (entry.expiresAt < Date.now()) {
28
+ rmSync(path, { force: true });
29
+ return null;
30
+ }
31
+ return entry;
32
+ }
33
+ catch {
34
+ rmSync(path, { force: true });
35
+ return null;
36
+ }
37
+ }
38
+ export function cacheSet(category, key, data, ttlMs, fields) {
39
+ const path = cachePath(category, key);
40
+ const entry = {
41
+ expiresAt: Date.now() + ttlMs,
42
+ data,
43
+ fields,
44
+ };
45
+ writeFileSync(path, JSON.stringify(entry), "utf-8");
46
+ }
47
+ export function cacheClear() {
48
+ if (!existsSync(CACHE_DIR)) {
49
+ return;
50
+ }
51
+ rmSync(CACHE_DIR, { recursive: true, force: true });
52
+ }
53
+ const HOUR = 60 * 60 * 1000;
54
+ const MINUTE = 60 * 1000;
55
+ export function getQueryTtl(query) {
56
+ const upper = query.toUpperCase();
57
+ if (upper.includes("TODAY")) {
58
+ return 15 * MINUTE;
59
+ }
60
+ if (upper.includes("LAST_7_DAYS") || upper.includes("LAST_14_DAYS")) {
61
+ return 1 * HOUR;
62
+ }
63
+ // Historical data (BETWEEN, LAST_30_DAYS, LAST_90_DAYS, etc.)
64
+ return 6 * HOUR;
65
+ }
66
+ export function buildQueryCacheKey(customerId, query) {
67
+ const today = new Date().toISOString().slice(0, 10);
68
+ return `${customerId}:${today}:${query.trim().replace(/\s+/g, " ")}`;
69
+ }
70
+ export function getManagerIdForCustomer(customerId) {
71
+ const cached = cacheGet("accounts", "list");
72
+ if (!cached)
73
+ return undefined;
74
+ const account = cached.data.find((a) => a.id === customerId);
75
+ if (account?.access_type === "managed")
76
+ return account.manager_id;
77
+ return undefined;
78
+ }
79
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/commands/ads/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { buildQueryCacheKey, getQueryTtl } from "./cache.js";
3
+ describe("getQueryTtl", () => {
4
+ it("returns 15 minutes for queries containing TODAY", () => {
5
+ expect(getQueryTtl("SELECT * WHERE segments.date DURING TODAY")).toBe(900_000);
6
+ });
7
+ it("returns 1 hour for LAST_7_DAYS queries", () => {
8
+ expect(getQueryTtl("SELECT * WHERE segments.date DURING LAST_7_DAYS")).toBe(3_600_000);
9
+ });
10
+ it("returns 1 hour for LAST_14_DAYS queries", () => {
11
+ expect(getQueryTtl("SELECT * WHERE segments.date DURING LAST_14_DAYS")).toBe(3_600_000);
12
+ });
13
+ it("returns 6 hours for historical date ranges", () => {
14
+ expect(getQueryTtl("SELECT * WHERE segments.date DURING LAST_30_DAYS")).toBe(21_600_000);
15
+ });
16
+ it("is case insensitive", () => {
17
+ expect(getQueryTtl("segments.date during today")).toBe(900_000);
18
+ expect(getQueryTtl("during last_7_days")).toBe(3_600_000);
19
+ });
20
+ });
21
+ describe("buildQueryCacheKey", () => {
22
+ it("includes the customer ID", () => {
23
+ const key = buildQueryCacheKey("123-456", "SELECT campaign.id FROM campaign");
24
+ expect(key).toContain("123-456");
25
+ });
26
+ it("includes today's date", () => {
27
+ vi.useFakeTimers();
28
+ vi.setSystemTime(new Date("2026-03-15T12:00:00Z"));
29
+ const key = buildQueryCacheKey("cust1", "SELECT 1");
30
+ expect(key).toContain("2026-03-15");
31
+ vi.useRealTimers();
32
+ });
33
+ it("normalizes whitespace in the query", () => {
34
+ const key1 = buildQueryCacheKey("cust1", "SELECT campaign.id FROM campaign");
35
+ const key2 = buildQueryCacheKey("cust1", "SELECT campaign.id FROM campaign");
36
+ expect(key1).toBe(key2);
37
+ });
38
+ it("trims leading and trailing whitespace", () => {
39
+ const key1 = buildQueryCacheKey("cust1", " SELECT 1 ");
40
+ const key2 = buildQueryCacheKey("cust1", "SELECT 1");
41
+ expect(key1).toBe(key2);
42
+ });
43
+ });
44
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../../src/commands/ads/cache.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,WAAW,CAAC,2CAA2C,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,WAAW,CAAC,iDAAiD,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,WAAW,CAAC,kDAAkD,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,WAAW,CAAC,kDAAkD,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChE,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,GAAG,GAAG,kBAAkB,CAAC,SAAS,EAAE,kCAAkC,CAAC,CAAC;QAC9E,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,EAAE,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAEnD,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAEpC,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,EAAE,sCAAsC,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;QAC7E,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getFieldDescriptions(fields: string[]): Record<string, string>;
2
+ //# sourceMappingURL=field-descriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-descriptions.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/field-descriptions.ts"],"names":[],"mappings":"AA8FA,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS7E"}
@@ -0,0 +1,91 @@
1
+ const FIELD_DESCRIPTIONS = {
2
+ // Customer
3
+ "customer.id": "Google Ads account ID",
4
+ "customer.descriptive_name": "Account display name",
5
+ "customer.currency_code": "Account currency (e.g. USD, EUR)",
6
+ "customer.time_zone": "Account timezone (e.g. America/New_York)",
7
+ // Campaign
8
+ "campaign.id": "Unique campaign identifier",
9
+ "campaign.name": "Campaign display name",
10
+ "campaign.status": "ENABLED, PAUSED, or REMOVED",
11
+ "campaign.advertising_channel_type": "Campaign type: SEARCH, DISPLAY, SHOPPING, VIDEO, PERFORMANCE_MAX, DEMAND_GEN",
12
+ "campaign.bidding_strategy_type": "Bidding strategy (TARGET_CPA, TARGET_ROAS, MAXIMIZE_CONVERSIONS, etc.)",
13
+ "campaign.start_date": "Campaign start date (YYYY-MM-DD)",
14
+ "campaign.end_date": "Campaign end date (YYYY-MM-DD), blank if ongoing",
15
+ // Campaign budget
16
+ "campaign_budget.amount_micros": "Daily budget in micros (÷ 1,000,000 for actual currency)",
17
+ // Ad group
18
+ "ad_group.id": "Unique ad group identifier",
19
+ "ad_group.name": "Ad group display name",
20
+ "ad_group.status": "ENABLED, PAUSED, or REMOVED",
21
+ "ad_group.type": "Ad group type (SEARCH_STANDARD, DISPLAY_STANDARD, etc.)",
22
+ // Ad group ad
23
+ "ad_group_ad.ad.id": "Unique ad identifier",
24
+ "ad_group_ad.ad.final_urls": "Landing page URLs (array)",
25
+ "ad_group_ad.ad.type": "Ad format (RESPONSIVE_SEARCH_AD, etc.)",
26
+ "ad_group_ad.status": "ENABLED, PAUSED, or REMOVED",
27
+ "ad_group_ad.ad.responsive_search_ad.headlines": "Ad headline variations (array)",
28
+ "ad_group_ad.ad.responsive_search_ad.descriptions": "Ad description variations (array)",
29
+ // Keywords
30
+ "ad_group_criterion.keyword.text": "The keyword text",
31
+ "ad_group_criterion.keyword.match_type": "EXACT, PHRASE, or BROAD",
32
+ "ad_group_criterion.quality_info.quality_score": "Quality score 1-10 (higher is better)",
33
+ // Search terms
34
+ "search_term_view.search_term": "Actual user search query that triggered the ad",
35
+ "search_term_view.status": "Whether the search term is added, excluded, or none",
36
+ // Metrics
37
+ "metrics.impressions": "Times ads were shown (integer)",
38
+ "metrics.clicks": "Total clicks (integer)",
39
+ "metrics.cost_micros": "Total cost in micros (÷ 1,000,000 for actual currency). Use 'currency' command for account currency.",
40
+ "metrics.cost": "Total cost in actual currency (already converted from micros)",
41
+ "metrics.conversions": "Conversion count (can be fractional from attribution models)",
42
+ "metrics.conversions_value": "Revenue from conversions in actual currency",
43
+ "metrics.all_conversions": "All conversions including view-through",
44
+ "metrics.all_conversions_value": "Total attributed revenue including view-through",
45
+ "metrics.ctr": "Click-through rate as decimal (0.05 = 5%)",
46
+ "metrics.average_cpc": "Average cost per click in micros (÷ 1,000,000)",
47
+ "metrics.average_cpm": "Average cost per 1000 impressions in micros (÷ 1,000,000)",
48
+ "metrics.search_impression_share": "Impression share as decimal (0.0–1.0)",
49
+ "metrics.interaction_rate": "Interaction rate as decimal",
50
+ "metrics.video_views": "Total video views (integer)",
51
+ "metrics.video_view_rate": "Video view rate as decimal",
52
+ // Segments
53
+ "segments.date": "Date (YYYY-MM-DD format)",
54
+ "segments.device": "DESKTOP, MOBILE, TABLET, or OTHER",
55
+ "segments.day_of_week": "Day of week (MONDAY, TUESDAY, etc.)",
56
+ "segments.ad_network_type": "Network: SEARCH, SEARCH_PARTNERS, CONTENT, YOUTUBE_SEARCH, etc.",
57
+ "segments.product_title": "Shopping product title",
58
+ "segments.product_item_id": "Shopping product ID",
59
+ "segments.product_brand": "Shopping product brand",
60
+ "segments.product_type_l1": "Shopping product type (level 1)",
61
+ // Assets
62
+ "asset.type": "Asset type: IMAGE, YOUTUBE_VIDEO, TEXT, LEAD_FORM, etc.",
63
+ "asset.text_asset.text": "Text asset content",
64
+ "asset.image_asset.full_size.url": "Full-size image URL",
65
+ "asset.youtube_video_asset.youtube_video_id": "YouTube video ID",
66
+ "asset.youtube_video_asset.youtube_video_title": "YouTube video title",
67
+ "asset_group.name": "Asset group display name",
68
+ "asset_group_asset.field_type": "Where the asset is used (HEADLINE, DESCRIPTION, LOGO, etc.)",
69
+ "asset_group_asset.performance_label": "Performance rating: BEST, GOOD, LOW, LEARNING",
70
+ // Change events
71
+ "change_event.change_date_time": "When the change occurred (ISO 8601)",
72
+ "change_event.change_resource_type": "What was changed: CAMPAIGN, AD_GROUP, AD, etc.",
73
+ "change_event.resource_change_operation": "CREATE, UPDATE, or REMOVE",
74
+ "change_event.user_email": "Email of user who made the change",
75
+ // Landing pages
76
+ "landing_page_view.unexpanded_final_url": "Landing page URL",
77
+ // Geo
78
+ "geo_target_constant.name": "Geographic location name",
79
+ "geo_target_constant.resource_name": "Geo target resource identifier",
80
+ };
81
+ export function getFieldDescriptions(fields) {
82
+ const result = {};
83
+ for (const field of fields) {
84
+ const desc = FIELD_DESCRIPTIONS[field];
85
+ if (desc) {
86
+ result[field] = desc;
87
+ }
88
+ }
89
+ return result;
90
+ }
91
+ //# sourceMappingURL=field-descriptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-descriptions.js","sourceRoot":"","sources":["../../../src/commands/ads/field-descriptions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export declare const accountsCommand: import("citty").CommandDef<{
2
+ readonly "no-cache": {
3
+ readonly type: "boolean";
4
+ readonly description: "Skip cache";
5
+ readonly required: false;
6
+ };
7
+ readonly output: {
8
+ readonly type: "string";
9
+ readonly description: "Format: json|csv|md";
10
+ readonly required: false;
11
+ readonly default: "json";
12
+ };
13
+ }>;
14
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,eAAe;;;;;;;;;;;;EAsC1B,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { defineCommand } from "citty";
2
+ import { ApiError, apiGet } from "../../../client.js";
3
+ import { registerSchema } from "../../../schemas.js";
4
+ import { cacheGet, cacheSet } from "../cache.js";
5
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
6
+ registerSchema({
7
+ command: "ads.google.accounts",
8
+ description: "List all accessible Google Ads customer accounts. Returns accounts with id, name, access_type (direct or managed), level in the hierarchy, and optional manager_id for managed accounts. Run this first to find account IDs for other commands.",
9
+ args: {
10
+ "no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
11
+ },
12
+ });
13
+ function handleAccountsError(err) {
14
+ if (err instanceof ApiError) {
15
+ const isAuth = err.code === "UNAUTHORIZED";
16
+ const envelope = {
17
+ ok: false,
18
+ error: {
19
+ code: isAuth ? "AUTH_ERROR" : err.code,
20
+ message: err.message,
21
+ fix: {
22
+ action: isAuth ? "authenticate" : "reject",
23
+ explanation: isAuth ? "Connect Google Ads in dashboard settings first" : err.message,
24
+ },
25
+ retryable: false,
26
+ },
27
+ };
28
+ writeAdsJson(envelope);
29
+ process.exit(1);
30
+ }
31
+ writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
32
+ process.exit(1);
33
+ }
34
+ export const accountsCommand = defineCommand({
35
+ meta: {
36
+ name: "accounts",
37
+ description: `List accessible Google Ads accounts. Returns customer IDs needed for all other commands.
38
+
39
+ Examples:
40
+ baker ads google accounts`,
41
+ },
42
+ args: {
43
+ "no-cache": { type: "boolean", description: "Skip cache", required: false },
44
+ output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
45
+ },
46
+ run: async ({ args }) => {
47
+ const useCache = !args["no-cache"];
48
+ if (useCache) {
49
+ const cached = cacheGet("accounts", "list");
50
+ if (cached) {
51
+ writeAdsJson({ ok: true, data: cached.data, cached: true });
52
+ return;
53
+ }
54
+ }
55
+ try {
56
+ const data = await apiGet("/api/ads/google/accounts");
57
+ if (useCache) {
58
+ cacheSet("accounts", "list", data, 60 * 60 * 1000);
59
+ }
60
+ const format = args.output || "json";
61
+ if (format !== "json") {
62
+ writeAdsOutput(data, format);
63
+ return;
64
+ }
65
+ writeAdsJson({ ok: true, data });
66
+ }
67
+ catch (err) {
68
+ handleAccountsError(err);
69
+ }
70
+ },
71
+ });
72
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export declare const changesCommand: import("citty").CommandDef<{
2
+ readonly "customer-id": {
3
+ readonly type: "string";
4
+ readonly description: "Google Ads customer ID";
5
+ readonly required: false;
6
+ };
7
+ readonly days: {
8
+ readonly type: "string";
9
+ readonly description: "Lookback days (default 7)";
10
+ readonly required: false;
11
+ };
12
+ readonly "resource-type": {
13
+ readonly type: "string";
14
+ readonly description: "Filter by resource type";
15
+ readonly required: false;
16
+ };
17
+ readonly limit: {
18
+ readonly type: "string";
19
+ readonly description: "Max results (default 50)";
20
+ readonly required: false;
21
+ };
22
+ readonly output: {
23
+ readonly type: "string";
24
+ readonly description: "Format: json|csv|jsonl|md";
25
+ readonly required: false;
26
+ readonly default: "json";
27
+ };
28
+ }>;
29
+ //# sourceMappingURL=changes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/changes.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkDzB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { defineCommand } from "citty";
2
+ import { ApiError, apiPost } from "../../../client.js";
3
+ import { registerSchema } from "../../../schemas.js";
4
+ import { getManagerIdForCustomer } from "../cache.js";
5
+ import { getFieldDescriptions } from "../field-descriptions.js";
6
+ import { resolveCustomerId, writeAdsJson, writeAdsOutput } from "../output.js";
7
+ import { parseApiError } from "./error-parser.js";
8
+ registerSchema({
9
+ command: "ads.google.changes",
10
+ description: "Get recent change logs with performance impact. Shows what changed and how it affected metrics.",
11
+ args: {
12
+ "customer-id": {
13
+ type: "string",
14
+ description: "Google Ads customer ID (10 digits, no dashes). Falls back to BAKER_GOOGLE_ADS_CUSTOMER_ID env var.",
15
+ required: false,
16
+ },
17
+ days: { type: "string", description: "Lookback days (default: 7, max: 30)", required: false, default: 7 },
18
+ "resource-type": {
19
+ type: "string",
20
+ description: "Filter by type: CAMPAIGN, AD_GROUP, AD_GROUP_AD, AD_GROUP_CRITERION",
21
+ required: false,
22
+ },
23
+ limit: { type: "string", description: "Max change events (default: 50, max: 100)", required: false, default: 50 },
24
+ output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" },
25
+ },
26
+ });
27
+ export const changesCommand = defineCommand({
28
+ meta: {
29
+ name: "changes",
30
+ description: `Get recent changes in a Google Ads account with performance data.
31
+
32
+ Examples:
33
+ baker ads google changes --customer-id 1234567890
34
+ baker ads google changes --customer-id 1234567890 --days 14 --resource-type CAMPAIGN`,
35
+ },
36
+ args: {
37
+ "customer-id": { type: "string", description: "Google Ads customer ID", required: false },
38
+ days: { type: "string", description: "Lookback days (default 7)", required: false },
39
+ "resource-type": { type: "string", description: "Filter by resource type", required: false },
40
+ limit: { type: "string", description: "Max results (default 50)", required: false },
41
+ output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" },
42
+ },
43
+ run: async ({ args }) => {
44
+ const customerId = resolveCustomerId(args);
45
+ const body = {
46
+ customerId,
47
+ days: args.days ? Number(args.days) : 7,
48
+ limit: args.limit ? Number(args.limit) : 50,
49
+ };
50
+ const managerId = getManagerIdForCustomer(customerId);
51
+ if (managerId)
52
+ body.managerId = managerId;
53
+ if (args["resource-type"])
54
+ body.resourceType = args["resource-type"];
55
+ try {
56
+ const data = await apiPost("/api/ads/google/changes", body);
57
+ const format = args.output || "json";
58
+ if (format !== "json") {
59
+ writeAdsOutput(data, format);
60
+ return;
61
+ }
62
+ const first = data[0];
63
+ const fields = first ? Object.keys(first) : [];
64
+ const fieldDescs = getFieldDescriptions(fields);
65
+ writeAdsJson({ ok: true, data, fields: fieldDescs });
66
+ }
67
+ catch (err) {
68
+ if (err instanceof ApiError) {
69
+ writeAdsJson(parseApiError(err.message, "", customerId));
70
+ process.exit(1);
71
+ }
72
+ writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
73
+ process.exit(1);
74
+ }
75
+ },
76
+ });
77
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CorrectionRule } from "../types.ts";
2
+ export declare const CORRECTION_RULES: CorrectionRule[];
3
+ //# sourceMappingURL=correction-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correction-table.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/correction-table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,aAAa,CAAC;AAMrE,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA2W5C,CAAC"}