@analitikisler/ai-tag-debugger 0.11.1 → 0.11.2
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/CHANGELOG.md +5 -0
- package/package.json +1 -1
- package/src/ask.js +8 -6
- package/src/audit.js +1 -1
- package/src/providers.js +10 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.2 (2026-10-16)
|
|
4
|
+
|
|
5
|
+
- Fix sentence requests (`aitd "check my GA tags"`) failing with a 400 "Invalid schema" error from the Anthropic API. The request schema now writes optional values in a form Anthropic, OpenAI and Gemini all accept.
|
|
6
|
+
- When `AI_GATEWAY_URL` is set, the first line of a run says so: `Using anthropic (claude-opus-5-5) via Cloudflare AI Gateway`.
|
|
7
|
+
|
|
3
8
|
## 0.11.1 (2026-10-16)
|
|
4
9
|
|
|
5
10
|
- Set `AI_GATEWAY_URL` (and `AI_GATEWAY_TOKEN` if the gateway has authentication on) to send Anthropic, OpenAI and Gemini calls through Cloudflare AI Gateway, for logs and cost tracking. Unset, nothing changes.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@analitikisler/ai-tag-debugger",
|
|
3
3
|
"mcpName": "io.github.analitikisler/ai-tag-debugger",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.2",
|
|
5
5
|
"description": "Open-source AI agent that QA-tests your website's analytics, ad and consent tracking (GA4, GTM, Google Ads, Meta, TikTok). Bring your own model (Claude, OpenAI, Gemini) or use it from your chat app over MCP.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
package/src/ask.js
CHANGED
|
@@ -7,19 +7,21 @@ const PLATFORM_KEYS = Object.keys(PLATFORMS);
|
|
|
7
7
|
// The same values as plan --topic (TOPICS in discover.js, kept in step by a test).
|
|
8
8
|
export const TOPIC_KEYS = ["custom-events", "ecommerce", "forms", "consent"];
|
|
9
9
|
|
|
10
|
+
// Optional values use anyOf with a null branch, not type: ["string", "null"]: the Anthropic API
|
|
11
|
+
// rejects an enum next to a type list, and anyOf works for OpenAI and Gemini too.
|
|
10
12
|
export const INTENT_SCHEMA = {
|
|
11
13
|
type: "object",
|
|
12
14
|
additionalProperties: false,
|
|
13
15
|
required: ["action", "site", "against", "platforms", "goal", "journey", "topic", "question"],
|
|
14
16
|
properties: {
|
|
15
17
|
action: { type: "string", enum: ["plan", "run", "report", "unclear"], description: "plan drafts what a site should track; run audits what the site sends; report re-reads an existing report; unclear when you cannot tell plan from run." },
|
|
16
|
-
site: { type:
|
|
17
|
-
against: { type:
|
|
18
|
+
site: { anyOf: [{ type: "string" }, { type: "null" }], description: "The site's domain or URL if the sentence names one." },
|
|
19
|
+
against: { anyOf: [{ type: "string", enum: ["plan", "latest"] }, { type: "null" }], description: "run only: compare with the saved plan, or with the latest run (\"what changed\", \"since the last run\", \"after the deploy\")." },
|
|
18
20
|
platforms: { type: "array", items: { type: "string", enum: PLATFORM_KEYS }, description: "Only the tracking platforms the sentence names; empty for all." },
|
|
19
|
-
goal: { type:
|
|
20
|
-
journey: { type:
|
|
21
|
-
topic: { type:
|
|
22
|
-
question: { type:
|
|
21
|
+
goal: { anyOf: [{ type: "string" }, { type: "null" }], description: "run only: a short user journey to try, in plain words, e.g. \"submit the contact form\"." },
|
|
22
|
+
journey: { anyOf: [{ type: "string", enum: ["purchase"] }, { type: "null" }], description: "run only: purchase when the sentence is about the purchase event or revenue." },
|
|
23
|
+
topic: { anyOf: [{ type: "string", enum: TOPIC_KEYS }, { type: "null" }], description: "plan only: limit the plan to one kind of event when the sentence asks about it." },
|
|
24
|
+
question: { anyOf: [{ type: "string" }, { type: "null" }], description: "One short question to ask back when the sentence is ambiguous; otherwise null." },
|
|
23
25
|
},
|
|
24
26
|
};
|
|
25
27
|
|
package/src/audit.js
CHANGED
|
@@ -102,7 +102,7 @@ export async function runAudit(opts) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
const provider = useAi ? await createProvider({ name: opts.provider ?? config.provider, model: opts.model ?? config.model, baseUrl: opts.baseUrl ?? config.base_url }) : null;
|
|
105
|
-
if (provider) log(`Using ${provider.name} (${provider.model})`);
|
|
105
|
+
if (provider) log(`Using ${provider.name} (${provider.model})${provider.via ? ` via ${provider.via}` : ""}`);
|
|
106
106
|
|
|
107
107
|
if (opts.saveSite) await mkdir(opts.saveSite, { recursive: true });
|
|
108
108
|
const runs = [];
|
package/src/providers.js
CHANGED
|
@@ -58,12 +58,19 @@ export async function createProvider(opts = {}, env = process.env) {
|
|
|
58
58
|
}
|
|
59
59
|
const model = opts.model ?? PROVIDERS[name].defaultModel;
|
|
60
60
|
const gateway = gatewayOptions(name, env);
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
const provider = await builtInProvider(name, model, gateway, opts.client, env);
|
|
62
|
+
// Shown in the "Using ..." line so a run says whether its calls went through the gateway.
|
|
63
|
+
if (gateway.baseURL && !opts.client) provider.via = "Cloudflare AI Gateway";
|
|
64
|
+
return provider;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function builtInProvider(name, model, gateway, client, env) {
|
|
68
|
+
if (name === "anthropic") return anthropicProvider(client ?? new (await import("@anthropic-ai/sdk")).default(gateway), model);
|
|
69
|
+
if (name === "openai") return openaiProvider(client ?? new (await import("openai")).default(gateway), model);
|
|
63
70
|
const { GoogleGenAI } = await import("@google/genai");
|
|
64
71
|
const apiKey = env.GEMINI_API_KEY ?? env.GOOGLE_API_KEY;
|
|
65
72
|
const httpOptions = gateway.baseURL ? { httpOptions: { baseUrl: gateway.baseURL, headers: gateway.defaultHeaders } } : {};
|
|
66
|
-
return geminiProvider(
|
|
73
|
+
return geminiProvider(client ?? new GoogleGenAI({ ...(apiKey ? { apiKey } : {}), ...httpOptions }), model);
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
// Cloudflare AI Gateway path for each provider, appended to AI_GATEWAY_URL.
|