@koda-sl/baker-cli 0.155.0 → 0.156.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-UFBKUMN2.js → chunk-JOPBGFXC.js} +2 -2
- package/dist/{chunk-FBUVCOH6.js → chunk-R4PG6VCS.js} +71 -44
- package/dist/chunk-R4PG6VCS.js.map +1 -0
- package/dist/cli.js +76 -27
- package/dist/cli.js.map +1 -1
- package/dist/{output-R534QTMO.js → output-KLK2GZXR.js} +2 -2
- package/dist/{shared-MUWU7BK5.js → shared-AXAXNKGE.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-FBUVCOH6.js.map +0 -1
- /package/dist/{chunk-UFBKUMN2.js.map → chunk-JOPBGFXC.js.map} +0 -0
- /package/dist/{output-R534QTMO.js.map → output-KLK2GZXR.js.map} +0 -0
- /package/dist/{shared-MUWU7BK5.js.map → shared-AXAXNKGE.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handleConnectionError,
|
|
3
3
|
writeAdsJson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-R4PG6VCS.js";
|
|
5
5
|
import {
|
|
6
6
|
ApiError
|
|
7
7
|
} from "./chunk-LVCBCJWF.js";
|
|
@@ -94,4 +94,4 @@ export {
|
|
|
94
94
|
csvOrJson,
|
|
95
95
|
resolveEffectiveStatus
|
|
96
96
|
};
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-JOPBGFXC.js.map
|
|
@@ -1,10 +1,74 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ApiError,
|
|
2
3
|
apiGet
|
|
3
4
|
} from "./chunk-LVCBCJWF.js";
|
|
4
5
|
import {
|
|
5
6
|
getEnv
|
|
6
7
|
} from "./chunk-RK67WL4O.js";
|
|
7
8
|
|
|
9
|
+
// src/error-handler.ts
|
|
10
|
+
var REQUEST_CONNECTION_PLATFORM = {
|
|
11
|
+
google_ads: "google-ads",
|
|
12
|
+
ga4: "google-analytics",
|
|
13
|
+
gsc: "google-search-console",
|
|
14
|
+
linkedin_ads: "linkedin"
|
|
15
|
+
};
|
|
16
|
+
var PLATFORM_NAME = {
|
|
17
|
+
google_ads: "Google Ads",
|
|
18
|
+
ga4: "Google Analytics 4",
|
|
19
|
+
gsc: "Google Search Console",
|
|
20
|
+
x_ads: "X Ads",
|
|
21
|
+
meta_ads: "Meta Ads",
|
|
22
|
+
linkedin_ads: "LinkedIn Ads"
|
|
23
|
+
};
|
|
24
|
+
function connectionFixExplanation(platform) {
|
|
25
|
+
const name = PLATFORM_NAME[platform];
|
|
26
|
+
const slug = REQUEST_CONNECTION_PLATFORM[platform];
|
|
27
|
+
if (slug === void 0) {
|
|
28
|
+
return `${name} is not connected for this company, and it cannot be connected from the chat yet. Tell the user to connect it in the dashboard under Brain \u2192 Integrations \u2192 Tools \u2192 ${name}. Do not fail the whole job: say what stays unavailable and carry on with the rest.`;
|
|
29
|
+
}
|
|
30
|
+
return `${name} is not connected for this company (or no account has been picked). Do NOT send the user to Settings and do NOT end the turn here \u2014 call the \`request_connection\` tool with { platform: "${slug}", reason } and they connect and pick their accounts from inside the chat. If that tool is not available to you, tell them exactly where to do it: dashboard \u2192 Brain \u2192 Integrations \u2192 Tools \u2192 ${name}. Either way, carry on with the rest of the task and say what stays unavailable until it is connected.`;
|
|
31
|
+
}
|
|
32
|
+
function handleConnectionError(platform, originalMessage) {
|
|
33
|
+
const platformName = PLATFORM_NAME[platform];
|
|
34
|
+
const alternative = {
|
|
35
|
+
google_ads: "keywords-for-site or research advertisers",
|
|
36
|
+
ga4: "lighthouse for page performance",
|
|
37
|
+
gsc: "keywords-for-site or research keyword-gap",
|
|
38
|
+
x_ads: "research advertisers",
|
|
39
|
+
meta_ads: "research advertisers or research keyword-ideas",
|
|
40
|
+
linkedin_ads: "research advertisers (LinkedIn Ad Library) or research keyword-ideas"
|
|
41
|
+
}[platform];
|
|
42
|
+
const code = {
|
|
43
|
+
google_ads: "NO_GOOGLE_ADS_CONNECTION",
|
|
44
|
+
ga4: "NO_GA4_CONNECTION",
|
|
45
|
+
gsc: "NO_GSC_CONNECTION",
|
|
46
|
+
x_ads: "NO_X_ADS_CONNECTION",
|
|
47
|
+
meta_ads: "NO_META_ADS_CONNECTION",
|
|
48
|
+
linkedin_ads: "NO_LINKEDIN_ADS_CONNECTION"
|
|
49
|
+
}[platform];
|
|
50
|
+
const envelope = {
|
|
51
|
+
ok: false,
|
|
52
|
+
error: {
|
|
53
|
+
code,
|
|
54
|
+
message: originalMessage || `No ${platformName} connection found for this company.`,
|
|
55
|
+
fix: {
|
|
56
|
+
action: REQUEST_CONNECTION_PLATFORM[platform] === void 0 ? "ask_user" : "request_connection",
|
|
57
|
+
explanation: `${connectionFixExplanation(platform)} (Optional fallback for estimated external insights: 'baker research ${alternative}'.)`
|
|
58
|
+
},
|
|
59
|
+
retryable: false
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
writeJsonEnvelope(envelope);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
function isNotConnectedError(code, message) {
|
|
66
|
+
if (code !== "NOT_FOUND" && code !== "UNAUTHORIZED") {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return /no .* connection found|not connected|no .* (selected|picked)|is not in .* connected/i.test(message);
|
|
70
|
+
}
|
|
71
|
+
|
|
8
72
|
// src/commands/ads/cache.ts
|
|
9
73
|
import { createHash } from "crypto";
|
|
10
74
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -75,48 +139,6 @@ function getManagerIdForCustomer(customerId) {
|
|
|
75
139
|
return void 0;
|
|
76
140
|
}
|
|
77
141
|
|
|
78
|
-
// src/error-handler.ts
|
|
79
|
-
function handleConnectionError(platform, originalMessage) {
|
|
80
|
-
const platformName = {
|
|
81
|
-
google_ads: "Google Ads",
|
|
82
|
-
ga4: "Google Analytics 4",
|
|
83
|
-
gsc: "Google Search Console",
|
|
84
|
-
x_ads: "X Ads",
|
|
85
|
-
meta_ads: "Meta Ads",
|
|
86
|
-
linkedin_ads: "LinkedIn Ads"
|
|
87
|
-
}[platform];
|
|
88
|
-
const alternative = {
|
|
89
|
-
google_ads: "keywords-for-site or research advertisers",
|
|
90
|
-
ga4: "lighthouse for page performance",
|
|
91
|
-
gsc: "keywords-for-site or research keyword-gap",
|
|
92
|
-
x_ads: "research advertisers",
|
|
93
|
-
meta_ads: "research advertisers or research keyword-ideas",
|
|
94
|
-
linkedin_ads: "research advertisers (LinkedIn Ad Library) or research keyword-ideas"
|
|
95
|
-
}[platform];
|
|
96
|
-
const code = {
|
|
97
|
-
google_ads: "NO_GOOGLE_ADS_CONNECTION",
|
|
98
|
-
ga4: "NO_GA4_CONNECTION",
|
|
99
|
-
gsc: "NO_GSC_CONNECTION",
|
|
100
|
-
x_ads: "NO_X_ADS_CONNECTION",
|
|
101
|
-
meta_ads: "NO_META_ADS_CONNECTION",
|
|
102
|
-
linkedin_ads: "NO_LINKEDIN_ADS_CONNECTION"
|
|
103
|
-
}[platform];
|
|
104
|
-
const envelope = {
|
|
105
|
-
ok: false,
|
|
106
|
-
error: {
|
|
107
|
-
code,
|
|
108
|
-
message: originalMessage || `No ${platformName} connection found for this company.`,
|
|
109
|
-
fix: {
|
|
110
|
-
action: "authenticate",
|
|
111
|
-
explanation: `AGENT INSTRUCTION: You cannot resolve this error programmatically. The user has not connected their ${platformName} account. Step 1: Inform the user that they must connect ${platformName} in their Baker dashboard settings for direct data queries. Step 2: Do not fail the overall audit or playbook. Document the missing connection, skip this specific check, and proceed with the rest of your tasks. (Optional fallback: use 'baker research ${alternative}' for estimated external insights).`
|
|
112
|
-
},
|
|
113
|
-
retryable: false
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
writeJsonEnvelope(envelope);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
142
|
// src/commands/ads/output.ts
|
|
121
143
|
function writeAdsJson(envelope) {
|
|
122
144
|
process.stdout.write(`${JSON.stringify(envelope, null, 2)}
|
|
@@ -236,7 +258,10 @@ ${list}`
|
|
|
236
258
|
}
|
|
237
259
|
});
|
|
238
260
|
process.exit(1);
|
|
239
|
-
} catch {
|
|
261
|
+
} catch (err) {
|
|
262
|
+
if (err instanceof ApiError && isNotConnectedError(err.code, err.message)) {
|
|
263
|
+
handleConnectionError("google_ads", err.message);
|
|
264
|
+
}
|
|
240
265
|
writeAdsJson({
|
|
241
266
|
ok: false,
|
|
242
267
|
error: {
|
|
@@ -254,11 +279,13 @@ export {
|
|
|
254
279
|
getQueryTtl,
|
|
255
280
|
buildQueryCacheKey,
|
|
256
281
|
getManagerIdForCustomer,
|
|
282
|
+
connectionFixExplanation,
|
|
257
283
|
handleConnectionError,
|
|
284
|
+
isNotConnectedError,
|
|
258
285
|
writeAdsJson,
|
|
259
286
|
writeJsonEnvelope,
|
|
260
287
|
toCsvRow,
|
|
261
288
|
writeAdsOutput,
|
|
262
289
|
resolveCustomerId
|
|
263
290
|
};
|
|
264
|
-
//# sourceMappingURL=chunk-
|
|
291
|
+
//# sourceMappingURL=chunk-R4PG6VCS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error-handler.ts","../src/commands/ads/cache.ts","../src/commands/ads/output.ts"],"sourcesContent":["import { writeJsonEnvelope } from \"./commands/ads/output.ts\";\n\ntype ConnectionPlatform = \"google_ads\" | \"ga4\" | \"gsc\" | \"x_ads\" | \"meta_ads\" | \"linkedin_ads\";\n\n/**\n * Platforms the agent can get connected without the user leaving the chat, via\n * the blocking `request_connection` tool, and the id that tool expects. Meta and\n * X Ads are absent on purpose — they are still coming soon, so the only honest\n * answer there is the dashboard.\n */\nconst REQUEST_CONNECTION_PLATFORM: Partial<Record<ConnectionPlatform, string>> = {\n google_ads: \"google-ads\",\n ga4: \"google-analytics\",\n gsc: \"google-search-console\",\n linkedin_ads: \"linkedin\",\n};\n\nconst PLATFORM_NAME: Record<ConnectionPlatform, string> = {\n google_ads: \"Google Ads\",\n ga4: \"Google Analytics 4\",\n gsc: \"Google Search Console\",\n x_ads: \"X Ads\",\n meta_ads: \"Meta Ads\",\n linkedin_ads: \"LinkedIn Ads\",\n};\n\n/**\n * How to tell the agent to get a platform connected. Never \"send them to\n * Settings\" for a platform `request_connection` covers — that ends the turn on a\n * wall the agent could have opened itself. The fallback line matters too: a\n * Session booted before the tool shipped does not have it, and the agent must\n * still be able to say where the connect button is instead of stalling.\n */\nexport function connectionFixExplanation(platform: ConnectionPlatform): string {\n const name = PLATFORM_NAME[platform];\n const slug = REQUEST_CONNECTION_PLATFORM[platform];\n if (slug === undefined) {\n return (\n `${name} is not connected for this company, and it cannot be connected from the chat yet. Tell the user to ` +\n `connect it in the dashboard under Brain → Integrations → Tools → ${name}. Do not fail the whole job: say ` +\n `what stays unavailable and carry on with the rest.`\n );\n }\n return (\n `${name} is not connected for this company (or no account has been picked). Do NOT send the user to Settings ` +\n `and do NOT end the turn here — call the \\`request_connection\\` tool with { platform: \"${slug}\", reason } and ` +\n `they connect and pick their accounts from inside the chat. If that tool is not available to you, tell them ` +\n `exactly where to do it: dashboard → Brain → Integrations → Tools → ${name}. Either way, carry on with the ` +\n `rest of the task and say what stays unavailable until it is connected.`\n );\n}\n\n/**\n * Shared error handler for \"No Connection\" scenarios.\n * Provides a structured error for AI agents with a suggested fix and alternative commands.\n */\nexport function handleConnectionError(platform: ConnectionPlatform, originalMessage?: string): never {\n const platformName = PLATFORM_NAME[platform];\n\n const alternative = {\n google_ads: \"keywords-for-site or research advertisers\",\n ga4: \"lighthouse for page performance\",\n gsc: \"keywords-for-site or research keyword-gap\",\n x_ads: \"research advertisers\",\n meta_ads: \"research advertisers or research keyword-ideas\",\n linkedin_ads: \"research advertisers (LinkedIn Ad Library) or research keyword-ideas\",\n }[platform];\n\n const code = {\n google_ads: \"NO_GOOGLE_ADS_CONNECTION\",\n ga4: \"NO_GA4_CONNECTION\",\n gsc: \"NO_GSC_CONNECTION\",\n x_ads: \"NO_X_ADS_CONNECTION\",\n meta_ads: \"NO_META_ADS_CONNECTION\",\n linkedin_ads: \"NO_LINKEDIN_ADS_CONNECTION\",\n }[platform];\n\n const envelope = {\n ok: false,\n error: {\n code,\n message: originalMessage || `No ${platformName} connection found for this company.`,\n fix: {\n action: REQUEST_CONNECTION_PLATFORM[platform] === undefined ? \"ask_user\" : \"request_connection\",\n explanation: `${connectionFixExplanation(platform)} (Optional fallback for estimated external insights: 'baker research ${alternative}'.)`,\n },\n retryable: false,\n },\n };\n\n writeJsonEnvelope(envelope);\n process.exit(1);\n}\n\n/**\n * Does this API failure mean \"the platform isn't connected\"? The read commands\n * surface the backend's own 404/403 verbatim, so the connect fix has to be\n * recognised from the code the client mapped it to plus the message.\n */\nexport function isNotConnectedError(code: string, message: string): boolean {\n if (code !== \"NOT_FOUND\" && code !== \"UNAUTHORIZED\") {\n return false;\n }\n // The last alternative is the write-path 403 (\"customer X is not in this\n // company's connected Google Ads accounts\") — a different sentence for the\n // same remedy: connect, and pick the account.\n return /no .* connection found|not connected|no .* (selected|picked)|is not in .* connected/i.test(message);\n}\n","import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { CacheEntry } from \"./types.ts\";\n\nconst CACHE_DIR = join(homedir(), \".baker\", \"cache\", \"ads\");\n\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n}\n\nfunction hashKey(key: string): string {\n return createHash(\"sha256\").update(key).digest(\"hex\").slice(0, 16);\n}\n\nfunction cachePath(category: string, key: string): string {\n const dir = join(CACHE_DIR, category);\n ensureDir(dir);\n return join(dir, `${hashKey(key)}.json`);\n}\n\nexport function cacheGet<T>(category: string, key: string): CacheEntry<T> | null {\n const path = cachePath(category, key);\n if (!existsSync(path)) {\n return null;\n }\n try {\n const raw = readFileSync(path, \"utf-8\");\n const entry = JSON.parse(raw) as CacheEntry<T>;\n if (entry.expiresAt < Date.now()) {\n rmSync(path, { force: true });\n return null;\n }\n return entry;\n } catch {\n rmSync(path, { force: true });\n return null;\n }\n}\n\nexport function cacheSet<T>(\n category: string,\n key: string,\n data: T,\n ttlMs: number,\n fields?: Record<string, string>,\n): void {\n const path = cachePath(category, key);\n const entry: CacheEntry<T> = {\n expiresAt: Date.now() + ttlMs,\n data,\n fields,\n };\n writeFileSync(path, JSON.stringify(entry), \"utf-8\");\n}\n\nconst HOUR = 60 * 60 * 1000;\nconst MINUTE = 60 * 1000;\n\nexport function getQueryTtl(query: string): number {\n const upper = query.toUpperCase();\n if (upper.includes(\"TODAY\")) {\n return 15 * MINUTE;\n }\n if (upper.includes(\"LAST_7_DAYS\") || upper.includes(\"LAST_14_DAYS\")) {\n return 1 * HOUR;\n }\n // Historical data (BETWEEN, LAST_30_DAYS, LAST_90_DAYS, etc.)\n return 6 * HOUR;\n}\n\nexport function buildQueryCacheKey(customerId: string, query: string): string {\n const today = new Date().toISOString().slice(0, 10);\n return `${customerId}:${today}:${query.trim().replace(/\\s+/g, \" \")}`;\n}\n\ninterface CachedAccount {\n id: string;\n access_type: \"direct\" | \"managed\";\n manager_id?: string;\n}\n\nexport function getManagerIdForCustomer(customerId: string): string | undefined {\n const cached = cacheGet<CachedAccount[]>(\"accounts\", \"list\");\n if (!cached) return undefined;\n const account = cached.data.find((a) => a.id === customerId);\n if (account?.access_type === \"managed\") return account.manager_id;\n return undefined;\n}\n","import { ApiError, apiGet } from \"../../client.ts\";\nimport { getEnv } from \"../../env.ts\";\nimport { handleConnectionError, isNotConnectedError } from \"../../error-handler.ts\";\nimport type { QueryContext } from \"../../geo-context.ts\";\nimport { cacheGet, cacheSet } from \"./cache.ts\";\nimport type { AdsErrorEnvelope, AdsFileSummary, AdsSuccessEnvelope } from \"./types.ts\";\n\ntype AdsOutput =\n | AdsSuccessEnvelope<unknown>\n | AdsErrorEnvelope\n | AdsFileSummary\n | { ok: true; data: unknown; query_context?: QueryContext; cached?: true; fields?: Record<string, string> }\n | { ok: false; error: { code: string; message: string } };\n\nexport function writeAdsJson(envelope: AdsOutput): void {\n process.stdout.write(`${JSON.stringify(envelope, null, 2)}\\n`);\n}\n\nexport function writeJsonEnvelope(envelope: Record<string, unknown>): void {\n process.stdout.write(`${JSON.stringify(envelope, null, 2)}\\n`);\n}\n\nexport function toCsvRow(values: string[]): string {\n return values\n .map((v) => {\n if (v.includes(\",\") || v.includes('\"') || v.includes(\"\\n\")) {\n return `\"${v.replace(/\"/g, '\"\"')}\"`;\n }\n return v;\n })\n .join(\",\");\n}\n\nfunction flattenRow(row: Record<string, unknown>): Record<string, string> {\n const flat: Record<string, string> = {};\n for (const [key, val] of Object.entries(row)) {\n flat[key] = typeof val === \"object\" && val !== null ? JSON.stringify(val) : String(val ?? \"\");\n }\n return flat;\n}\n\nfunction writeAdsCsv(data: Array<Record<string, unknown>>, fields?: string[]): void {\n if (data.length === 0) return;\n const cols = fields ?? Object.keys(data[0] ?? {});\n process.stdout.write(`${toCsvRow(cols)}\\n`);\n for (const row of data) {\n const flat = flattenRow(row);\n process.stdout.write(`${toCsvRow(cols.map((f) => flat[f] ?? \"\"))}\\n`);\n }\n}\n\nfunction writeAdsJsonl(data: Array<Record<string, unknown>>): void {\n for (const row of data) {\n process.stdout.write(`${JSON.stringify(row)}\\n`);\n }\n}\n\nfunction writeAdsMd(data: Array<Record<string, unknown>>, fields?: string[]): void {\n if (data.length === 0) return;\n const cols = fields ?? Object.keys(data[0] ?? {});\n process.stdout.write(`| ${cols.join(\" | \")} |\\n`);\n process.stdout.write(`| ${cols.map(() => \"---\").join(\" | \")} |\\n`);\n for (const row of data) {\n const flat = flattenRow(row);\n process.stdout.write(`| ${cols.map((f) => flat[f] ?? \"\").join(\" | \")} |\\n`);\n }\n}\n\nexport function writeAdsOutput(data: Array<Record<string, unknown>>, format: string, fields?: string[]): void {\n switch (format) {\n case \"csv\":\n writeAdsCsv(data, fields);\n break;\n case \"jsonl\":\n writeAdsJsonl(data);\n break;\n case \"md\":\n writeAdsMd(data, fields);\n break;\n default:\n writeAdsJson({ ok: true, data });\n }\n}\n\ninterface AccountInfo {\n id: string;\n name: string;\n access_type: \"direct\" | \"managed\";\n level: number;\n manager_id?: string;\n}\n\nasync function fetchAccounts(useCache = true): Promise<AccountInfo[]> {\n if (useCache) {\n const cached = cacheGet<AccountInfo[]>(\"accounts\", \"list\");\n if (cached) return cached.data;\n }\n const params = !useCache ? { \"skip-cache\": \"true\" } : undefined;\n const data = await apiGet<AccountInfo[]>(\"/api/ads/google/accounts\", params);\n if (useCache) {\n cacheSet(\"accounts\", \"list\", data, 60 * 60 * 1000);\n }\n return data;\n}\n\nexport async function resolveCustomerId(args: Record<string, unknown>): Promise<string> {\n const fromArgs = args[\"customer-id\"] as string | undefined;\n const customerId = fromArgs || getEnv().BAKER_GOOGLE_ADS_CUSTOMER_ID;\n\n if (customerId) {\n if (!/^\\d{10}$/.test(customerId)) {\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_CUSTOMER_ID\",\n message:\n \"Customer ID must be exactly 10 digits without dashes. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID.\",\n },\n });\n process.exit(1);\n }\n return customerId;\n }\n\n const useCache = !args[\"no-cache\"];\n\n try {\n const accounts = await fetchAccounts(useCache);\n const [single] = accounts;\n if (accounts.length === 1 && single) {\n process.stderr.write(`Using account \"${single.name}\" (${single.id})\\n`);\n return single.id;\n }\n if (accounts.length === 0) {\n handleConnectionError(\"google_ads\");\n }\n const list = accounts.map((a) => ` ${a.id} ${a.name}`).join(\"\\n\");\n writeAdsJson({\n ok: false,\n error: {\n code: \"MULTIPLE_ACCOUNTS\",\n message: `Multiple accounts found. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID:\\n${list}`,\n },\n });\n process.exit(1);\n } catch (err) {\n // \"No connection\" reaches here as a 404/403 from the accounts lookup. Reporting it as\n // an unusable customer id sends the agent hunting for an id that cannot exist yet.\n if (err instanceof ApiError && isNotConnectedError(err.code, err.message)) {\n handleConnectionError(\"google_ads\", err.message);\n }\n writeAdsJson({\n ok: false,\n error: {\n code: \"INVALID_CUSTOMER_ID\",\n message: \"Could not auto-detect account. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID.\",\n },\n });\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -45,20 +45,22 @@ import {
|
|
|
45
45
|
resolveAccountIdArg,
|
|
46
46
|
resolveEffectiveStatus,
|
|
47
47
|
todayIso
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-JOPBGFXC.js";
|
|
49
49
|
import {
|
|
50
50
|
buildQueryCacheKey,
|
|
51
51
|
cacheGet,
|
|
52
52
|
cacheSet,
|
|
53
|
+
connectionFixExplanation,
|
|
53
54
|
getManagerIdForCustomer,
|
|
54
55
|
getQueryTtl,
|
|
55
56
|
handleConnectionError,
|
|
57
|
+
isNotConnectedError,
|
|
56
58
|
resolveCustomerId,
|
|
57
59
|
toCsvRow,
|
|
58
60
|
writeAdsJson,
|
|
59
61
|
writeAdsOutput,
|
|
60
62
|
writeJsonEnvelope
|
|
61
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-R4PG6VCS.js";
|
|
62
64
|
import {
|
|
63
65
|
ApiError,
|
|
64
66
|
apiGet,
|
|
@@ -5825,12 +5827,23 @@ function getRetryDelay(code) {
|
|
|
5825
5827
|
if (code === "TIMEOUT") return 5e3;
|
|
5826
5828
|
return void 0;
|
|
5827
5829
|
}
|
|
5828
|
-
function parseApiError(errorMessage, originalQuery, customerId) {
|
|
5830
|
+
function parseApiError(errorMessage, originalQuery, customerId, apiCode) {
|
|
5829
5831
|
const ctx = {
|
|
5830
5832
|
originalQuery,
|
|
5831
5833
|
customerId,
|
|
5832
5834
|
apiErrorMessage: errorMessage
|
|
5833
5835
|
};
|
|
5836
|
+
if (apiCode && isNotConnectedError(apiCode, errorMessage)) {
|
|
5837
|
+
return {
|
|
5838
|
+
ok: false,
|
|
5839
|
+
error: {
|
|
5840
|
+
code: "NO_GOOGLE_ADS_CONNECTION",
|
|
5841
|
+
message: errorMessage,
|
|
5842
|
+
fix: { action: "request_connection", explanation: connectionFixExplanation("google_ads") },
|
|
5843
|
+
retryable: false
|
|
5844
|
+
}
|
|
5845
|
+
};
|
|
5846
|
+
}
|
|
5834
5847
|
for (const rule of CORRECTION_RULES) {
|
|
5835
5848
|
if (rule.matchApiError?.test(errorMessage)) {
|
|
5836
5849
|
const fix = rule.fix(ctx);
|
|
@@ -5970,7 +5983,7 @@ Examples:
|
|
|
5970
5983
|
writeJsonEnvelope({ ok: true, data, fields: fieldDescs, hints: window.hints });
|
|
5971
5984
|
} catch (err) {
|
|
5972
5985
|
if (err instanceof ApiError) {
|
|
5973
|
-
writeAdsJson(parseApiError(err.message, "", customerId));
|
|
5986
|
+
writeAdsJson(parseApiError(err.message, "", customerId, err.code));
|
|
5974
5987
|
process.exit(1);
|
|
5975
5988
|
}
|
|
5976
5989
|
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
@@ -6031,7 +6044,7 @@ Examples:
|
|
|
6031
6044
|
writeAdsJson({ ok: true, data });
|
|
6032
6045
|
} catch (err) {
|
|
6033
6046
|
if (err instanceof ApiError) {
|
|
6034
|
-
writeAdsJson(parseApiError(err.message, "", customerId));
|
|
6047
|
+
writeAdsJson(parseApiError(err.message, "", customerId, err.code));
|
|
6035
6048
|
process.exit(1);
|
|
6036
6049
|
}
|
|
6037
6050
|
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
@@ -6285,6 +6298,9 @@ function loadPatchArg(args) {
|
|
|
6285
6298
|
}
|
|
6286
6299
|
function handleGoogleError(err) {
|
|
6287
6300
|
if (err instanceof ApiError) {
|
|
6301
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
6302
|
+
handleConnectionError("google_ads", err.message);
|
|
6303
|
+
}
|
|
6288
6304
|
writeJsonEnvelope({ ok: false, error: { code: err.code ?? "API_ERROR", message: err.message } });
|
|
6289
6305
|
process.exit(1);
|
|
6290
6306
|
}
|
|
@@ -6723,6 +6739,9 @@ function buildDiscoverBody(customerId, args) {
|
|
|
6723
6739
|
}
|
|
6724
6740
|
function handleKeywordError(err) {
|
|
6725
6741
|
if (err instanceof ApiError) {
|
|
6742
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
6743
|
+
handleConnectionError("google_ads", err.message);
|
|
6744
|
+
}
|
|
6726
6745
|
const envelope = {
|
|
6727
6746
|
ok: false,
|
|
6728
6747
|
error: {
|
|
@@ -6866,6 +6885,26 @@ registerSchema({
|
|
|
6866
6885
|
output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
|
|
6867
6886
|
}
|
|
6868
6887
|
});
|
|
6888
|
+
function handleMetricsError(err) {
|
|
6889
|
+
if (err instanceof ApiError) {
|
|
6890
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
6891
|
+
handleConnectionError("google_ads", err.message);
|
|
6892
|
+
}
|
|
6893
|
+
const envelope = {
|
|
6894
|
+
ok: false,
|
|
6895
|
+
error: {
|
|
6896
|
+
code: err.code,
|
|
6897
|
+
message: err.message,
|
|
6898
|
+
fix: { action: "reject", explanation: err.message },
|
|
6899
|
+
retryable: err.code === "RATE_LIMITED"
|
|
6900
|
+
}
|
|
6901
|
+
};
|
|
6902
|
+
writeAdsJson(envelope);
|
|
6903
|
+
process.exit(1);
|
|
6904
|
+
}
|
|
6905
|
+
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
6906
|
+
process.exit(1);
|
|
6907
|
+
}
|
|
6869
6908
|
var metricsCommand = defineCommand26({
|
|
6870
6909
|
meta: {
|
|
6871
6910
|
name: "metrics",
|
|
@@ -6933,21 +6972,7 @@ Examples:
|
|
|
6933
6972
|
};
|
|
6934
6973
|
writeAdsJson({ ok: true, data, fields, query_context: queryContext });
|
|
6935
6974
|
} catch (err) {
|
|
6936
|
-
|
|
6937
|
-
const envelope = {
|
|
6938
|
-
ok: false,
|
|
6939
|
-
error: {
|
|
6940
|
-
code: err.code,
|
|
6941
|
-
message: err.message,
|
|
6942
|
-
fix: { action: "reject", explanation: err.message },
|
|
6943
|
-
retryable: err.code === "RATE_LIMITED"
|
|
6944
|
-
}
|
|
6945
|
-
};
|
|
6946
|
-
writeAdsJson(envelope);
|
|
6947
|
-
process.exit(1);
|
|
6948
|
-
}
|
|
6949
|
-
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
6950
|
-
process.exit(1);
|
|
6975
|
+
handleMetricsError(err);
|
|
6951
6976
|
}
|
|
6952
6977
|
}
|
|
6953
6978
|
});
|
|
@@ -7514,7 +7539,7 @@ async function validateArgs(args) {
|
|
|
7514
7539
|
}
|
|
7515
7540
|
function handleQueryError(err, finalQuery, customerId) {
|
|
7516
7541
|
if (err instanceof ApiError) {
|
|
7517
|
-
const envelope = parseApiError(err.message, finalQuery, customerId);
|
|
7542
|
+
const envelope = parseApiError(err.message, finalQuery, customerId, err.code);
|
|
7518
7543
|
envelope.error.gaqlExecuted = finalQuery;
|
|
7519
7544
|
writeAdsJson(envelope);
|
|
7520
7545
|
process.exit(1);
|
|
@@ -9119,6 +9144,9 @@ function handleLinkedinError(err) {
|
|
|
9119
9144
|
if (err.code === "NOT_FOUND") {
|
|
9120
9145
|
handleConnectionError("linkedin_ads", err.message);
|
|
9121
9146
|
}
|
|
9147
|
+
if (isNoAccountsSelectedError(err.code, err.message)) {
|
|
9148
|
+
handleConnectionError("linkedin_ads", err.message);
|
|
9149
|
+
}
|
|
9122
9150
|
const explanation = explainLinkedinError(err);
|
|
9123
9151
|
const envelope = {
|
|
9124
9152
|
ok: false,
|
|
@@ -9140,6 +9168,9 @@ function handleLinkedinError(err) {
|
|
|
9140
9168
|
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message } });
|
|
9141
9169
|
process.exit(1);
|
|
9142
9170
|
}
|
|
9171
|
+
function isNoAccountsSelectedError(code, message) {
|
|
9172
|
+
return code === "VALIDATION_ERROR" && /no linkedin ad accounts selected/i.test(message);
|
|
9173
|
+
}
|
|
9143
9174
|
function explainLinkedinError(err) {
|
|
9144
9175
|
const lower = err.message.toLowerCase();
|
|
9145
9176
|
if (err.code === "VALIDATION_ERROR" && lower.includes("granularity") && lower.includes("daily")) {
|
|
@@ -13511,8 +13542,8 @@ function duplicateCommand2(entity, label) {
|
|
|
13511
13542
|
run: async ({ args }) => {
|
|
13512
13543
|
const { apiPost: apiPost2 } = await import("./client-R5ZSVIK3.js");
|
|
13513
13544
|
const { requireChatId: requireChatId2 } = await import("./env-3JMYIH25.js");
|
|
13514
|
-
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-
|
|
13515
|
-
const { handleMetaError: handleMetaError2 } = await import("./shared-
|
|
13545
|
+
const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-KLK2GZXR.js");
|
|
13546
|
+
const { handleMetaError: handleMetaError2 } = await import("./shared-AXAXNKGE.js");
|
|
13516
13547
|
try {
|
|
13517
13548
|
const accountId = bareAccountId2(args);
|
|
13518
13549
|
const chatId = requireChatId2();
|
|
@@ -23679,7 +23710,10 @@ ${list}`
|
|
|
23679
23710
|
}
|
|
23680
23711
|
});
|
|
23681
23712
|
process.exit(1);
|
|
23682
|
-
} catch {
|
|
23713
|
+
} catch (err) {
|
|
23714
|
+
if (err instanceof ApiError && (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND")) {
|
|
23715
|
+
handleConnectionError("ga4", err.message);
|
|
23716
|
+
}
|
|
23683
23717
|
writeJsonEnvelope({
|
|
23684
23718
|
ok: false,
|
|
23685
23719
|
error: {
|
|
@@ -23742,6 +23776,9 @@ Examples:
|
|
|
23742
23776
|
writeJsonEnvelope(data);
|
|
23743
23777
|
} catch (err) {
|
|
23744
23778
|
if (err instanceof ApiError) {
|
|
23779
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
23780
|
+
handleConnectionError("ga4", err.message);
|
|
23781
|
+
}
|
|
23745
23782
|
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
23746
23783
|
process.exit(1);
|
|
23747
23784
|
}
|
|
@@ -23933,6 +23970,9 @@ function buildRequestBody(args, propertyId, useCache) {
|
|
|
23933
23970
|
}
|
|
23934
23971
|
function handleError(err) {
|
|
23935
23972
|
if (err instanceof ApiError) {
|
|
23973
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
23974
|
+
handleConnectionError("ga4", err.message);
|
|
23975
|
+
}
|
|
23936
23976
|
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
23937
23977
|
process.exit(1);
|
|
23938
23978
|
}
|
|
@@ -24119,7 +24159,10 @@ ${list}`
|
|
|
24119
24159
|
}
|
|
24120
24160
|
});
|
|
24121
24161
|
process.exit(1);
|
|
24122
|
-
} catch {
|
|
24162
|
+
} catch (err) {
|
|
24163
|
+
if (err instanceof ApiError && (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND")) {
|
|
24164
|
+
handleConnectionError("gsc", err.message);
|
|
24165
|
+
}
|
|
24123
24166
|
writeJsonEnvelope({
|
|
24124
24167
|
ok: false,
|
|
24125
24168
|
error: {
|
|
@@ -24221,6 +24264,9 @@ function buildRequestBody2(args, siteUrl, useCache) {
|
|
|
24221
24264
|
}
|
|
24222
24265
|
function handleError2(err) {
|
|
24223
24266
|
if (err instanceof ApiError) {
|
|
24267
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
24268
|
+
handleConnectionError("gsc", err.message);
|
|
24269
|
+
}
|
|
24224
24270
|
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
24225
24271
|
process.exit(1);
|
|
24226
24272
|
}
|
|
@@ -24357,6 +24403,9 @@ Examples:
|
|
|
24357
24403
|
writeJsonEnvelope({ ok: true, data });
|
|
24358
24404
|
} catch (err) {
|
|
24359
24405
|
if (err instanceof ApiError) {
|
|
24406
|
+
if (isNotConnectedError(err.code, err.message)) {
|
|
24407
|
+
handleConnectionError("gsc", err.message);
|
|
24408
|
+
}
|
|
24360
24409
|
writeJsonEnvelope({ ok: false, error: { code: err.code, message: err.message } });
|
|
24361
24410
|
process.exit(1);
|
|
24362
24411
|
}
|
|
@@ -30410,8 +30459,8 @@ function handleError3(err) {
|
|
|
30410
30459
|
message: err.message,
|
|
30411
30460
|
...err.code === "UNAUTHORIZED" ? {
|
|
30412
30461
|
fix: {
|
|
30413
|
-
action: "
|
|
30414
|
-
explanation: 'Tag Manager is not connected for this company yet, or no container has been picked. Do NOT send the user to Settings \u2014 call the `request_connection` tool with { platform: "google-tag-manager", reason } and they connect and pick the container from inside the chat. Carry on with the rest of the task meanwhile.'
|
|
30462
|
+
action: "request_connection",
|
|
30463
|
+
explanation: 'Tag Manager is not connected for this company yet, or no container has been picked. Do NOT send the user to Settings \u2014 call the `request_connection` tool with { platform: "google-tag-manager", reason } and they connect and pick the container from inside the chat. `request_tag_input` is NOT the route: that form manages the container snippet on the site, not what runs inside the container, and it cannot pick a container. If `request_connection` is not available to you, say so plainly and point them at dashboard \u2192 Brain \u2192 Integrations \u2192 Tools \u2192 Google Tag Manager, where they also pick the container. Carry on with the rest of the task meanwhile.'
|
|
30415
30464
|
}
|
|
30416
30465
|
} : {},
|
|
30417
30466
|
retryable: RETRYABLE_CODES.has(err.code)
|