@ainyc/canonry 4.96.0 → 4.98.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/assets/agent-workspace/skills/canonry/references/canonry-cli.md +8 -3
- package/assets/assets/{BacklinksPage-BiuaXwM3.js → BacklinksPage-CuWs7I1D.js} +1 -1
- package/assets/assets/{ChartPrimitives-C7jCdApm.js → ChartPrimitives-bm37tprp.js} +1 -1
- package/assets/assets/ProjectPage-BksYe8FP.js +6 -0
- package/assets/assets/{RunRow-DLn-qaBh.js → RunRow-DzhQl87g.js} +1 -1
- package/assets/assets/{RunsPage-BArLwd1T.js → RunsPage-wOaewhbF.js} +1 -1
- package/assets/assets/{SettingsPage-BJmzcMsh.js → SettingsPage-CJdhhkkE.js} +1 -1
- package/assets/assets/{TrafficPage-DqG9hcNu.js → TrafficPage-BJBeN5Ph.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-yW5pdgrM.js → TrafficSourceDetailPage-D3PmH0B1.js} +1 -1
- package/assets/assets/{arrow-left-BUhA2bZu.js → arrow-left-BmITMI6O.js} +1 -1
- package/assets/assets/{extract-error-message-D2vzFSUQ.js → extract-error-message-BGwnyAfP.js} +1 -1
- package/assets/assets/index-BSX6r6ju.js +210 -0
- package/assets/assets/{index-DiykVUPr.css → index-BsZNCwg8.css} +1 -1
- package/assets/assets/{trash-2-C94CCTsF.js → trash-2-Bd2mkP_w.js} +1 -1
- package/assets/assets/{vendor-markdown-DK7fbRNb.js → vendor-markdown-6dwjPOKK.js} +1 -1
- package/assets/assets/{vendor-radix-B57xfQbP.js → vendor-radix-CQ77EO2y.js} +1 -1
- package/assets/assets/{vendor-recharts-ClRVR6aX.js → vendor-recharts-C9EZkgbP.js} +1 -1
- package/assets/assets/vendor-tanstack-Be8JdV5M.js +1 -0
- package/assets/index.html +6 -6
- package/dist/{chunk-IFB43PRW.js → chunk-3TH54726.js} +15 -7
- package/dist/{chunk-ROLTZPV7.js → chunk-7COFPNMH.js} +115 -11
- package/dist/{chunk-CEYDMSQO.js → chunk-CWFTMFEU.js} +58 -10
- package/dist/{chunk-CNTBEUVE.js → chunk-DJVUNURL.js} +140 -61
- package/dist/cli.js +19 -6
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-SJKUVFZ6.js → intelligence-service-QHBXW4KI.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/ProjectPage-BHo6vIlj.js +0 -6
- package/assets/assets/index-afT0D_K8.js +0 -210
- package/assets/assets/vendor-tanstack-Dq7p98wZ.js +0 -1
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
loadConfig,
|
|
10
10
|
loadConfigRaw,
|
|
11
11
|
saveConfigPatch
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3TH54726.js";
|
|
13
13
|
import {
|
|
14
14
|
CC_CACHE_DIR,
|
|
15
15
|
DUCKDB_SPEC,
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
siteAuditPages,
|
|
112
112
|
siteAuditSnapshots,
|
|
113
113
|
usageCounters
|
|
114
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-DJVUNURL.js";
|
|
115
115
|
import {
|
|
116
116
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
117
117
|
AGENT_PROVIDER_IDS,
|
|
@@ -171,7 +171,7 @@ import {
|
|
|
171
171
|
validationError,
|
|
172
172
|
winnabilityClassLabel,
|
|
173
173
|
withRetry
|
|
174
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-CWFTMFEU.js";
|
|
175
175
|
|
|
176
176
|
// src/telemetry.ts
|
|
177
177
|
import crypto from "crypto";
|
|
@@ -4377,8 +4377,8 @@ function removeOpenAiAdsConnection(config, projectName) {
|
|
|
4377
4377
|
|
|
4378
4378
|
// src/ads-sync.ts
|
|
4379
4379
|
var log4 = createLogger("AdsSync");
|
|
4380
|
-
var CAMPAIGN_INSIGHT_FIELDS = ["campaign.impressions", "campaign.clicks", "campaign.spend", "metadata.readable_time"];
|
|
4381
|
-
var AD_GROUP_INSIGHT_FIELDS = ["ad_group.impressions", "ad_group.clicks", "ad_group.spend", "metadata.readable_time"];
|
|
4380
|
+
var CAMPAIGN_INSIGHT_FIELDS = ["campaign.impressions", "campaign.clicks", "campaign.spend", "campaign.conversions", "metadata.readable_time"];
|
|
4381
|
+
var AD_GROUP_INSIGHT_FIELDS = ["ad_group.impressions", "ad_group.clicks", "ad_group.spend", "ad_group.conversions", "metadata.readable_time"];
|
|
4382
4382
|
function toInsightUpserts(level, entityId, rows) {
|
|
4383
4383
|
const upserts = [];
|
|
4384
4384
|
for (const row of rows) {
|
|
@@ -4392,7 +4392,8 @@ function toInsightUpserts(level, entityId, rows) {
|
|
|
4392
4392
|
date: row.readable_time,
|
|
4393
4393
|
impressions: row.impressions ?? 0,
|
|
4394
4394
|
clicks: row.clicks ?? 0,
|
|
4395
|
-
spendMicros: dollarsToMicros(row.spend ?? 0)
|
|
4395
|
+
spendMicros: dollarsToMicros(row.spend ?? 0),
|
|
4396
|
+
conversions: Math.round(row.conversions ?? 0)
|
|
4396
4397
|
});
|
|
4397
4398
|
}
|
|
4398
4399
|
return upserts;
|
|
@@ -4443,6 +4444,9 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
4443
4444
|
log4.error("campaign.failed", { runId, campaignId: campaign.id, error: err instanceof Error ? err.message : String(err) });
|
|
4444
4445
|
}
|
|
4445
4446
|
}
|
|
4447
|
+
const conversionTrackingConfigured = campaigns.some(
|
|
4448
|
+
(c) => (c.conversion_event_setting_ids?.length ?? 0) > 0
|
|
4449
|
+
);
|
|
4446
4450
|
const insertNow = (/* @__PURE__ */ new Date()).toISOString();
|
|
4447
4451
|
db.transaction((tx) => {
|
|
4448
4452
|
tx.delete(adsCampaigns).where(eq4(adsCampaigns.projectId, projectId)).run();
|
|
@@ -4505,6 +4509,7 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
4505
4509
|
impressions: upsert.impressions,
|
|
4506
4510
|
clicks: upsert.clicks,
|
|
4507
4511
|
spendMicros: upsert.spendMicros,
|
|
4512
|
+
conversions: upsert.conversions,
|
|
4508
4513
|
syncRunId: runId
|
|
4509
4514
|
}
|
|
4510
4515
|
}).run();
|
|
@@ -4515,6 +4520,7 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
4515
4520
|
currencyCode: account.currency_code,
|
|
4516
4521
|
timezone: account.timezone,
|
|
4517
4522
|
status: account.status,
|
|
4523
|
+
conversionTrackingConfigured,
|
|
4518
4524
|
lastSyncedAt: insertNow,
|
|
4519
4525
|
updatedAt: insertNow
|
|
4520
4526
|
}).where(eq4(adsConnections.projectId, projectId)).run();
|
|
@@ -6396,7 +6402,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
6396
6402
|
return result;
|
|
6397
6403
|
}
|
|
6398
6404
|
async function backfillInsightsCommand(project, opts) {
|
|
6399
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
6405
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-QHBXW4KI.js");
|
|
6400
6406
|
const config = loadConfig();
|
|
6401
6407
|
const db = createClient(config.database);
|
|
6402
6408
|
migrate(db);
|
|
@@ -7982,7 +7988,10 @@ import { Agent } from "@mariozechner/pi-agent-core";
|
|
|
7982
7988
|
import { registerBuiltInApiProviders } from "@mariozechner/pi-ai";
|
|
7983
7989
|
|
|
7984
7990
|
// src/agent/providers.ts
|
|
7985
|
-
import {
|
|
7991
|
+
import {
|
|
7992
|
+
getEnvApiKey,
|
|
7993
|
+
getModel
|
|
7994
|
+
} from "@mariozechner/pi-ai";
|
|
7986
7995
|
var PROVIDER_MODELS = {
|
|
7987
7996
|
[AgentProviderIds.claude]: {
|
|
7988
7997
|
[LlmCapabilities.agent]: "claude-opus-4-7",
|
|
@@ -8008,6 +8017,14 @@ var PROVIDER_MODELS = {
|
|
|
8008
8017
|
[LlmCapabilities.agent]: "glm-5.1",
|
|
8009
8018
|
[LlmCapabilities.analyze]: "glm-5-turbo",
|
|
8010
8019
|
[LlmCapabilities.classify]: "glm-5-turbo"
|
|
8020
|
+
},
|
|
8021
|
+
[AgentProviderIds.deepinfra]: {
|
|
8022
|
+
// DeepInfra `org/Model` slugs. GLM-5.2 drives the agent loop; the much
|
|
8023
|
+
// cheaper DeepSeek-V4-Flash fills analyze + classify. Resolved into a
|
|
8024
|
+
// custom openai-completions model, not pi-ai's catalog.
|
|
8025
|
+
[LlmCapabilities.agent]: "zai-org/GLM-5.2",
|
|
8026
|
+
[LlmCapabilities.analyze]: "deepseek-ai/DeepSeek-V4-Flash",
|
|
8027
|
+
[LlmCapabilities.classify]: "deepseek-ai/DeepSeek-V4-Flash"
|
|
8011
8028
|
}
|
|
8012
8029
|
};
|
|
8013
8030
|
var AGENT_PROVIDERS = {
|
|
@@ -8034,6 +8051,62 @@ var AGENT_PROVIDERS = {
|
|
|
8034
8051
|
label: "Z.ai (GLM)",
|
|
8035
8052
|
defaultModel: PROVIDER_MODELS[AgentProviderIds.zai][LlmCapabilities.agent],
|
|
8036
8053
|
autoDetectPriority: 3
|
|
8054
|
+
},
|
|
8055
|
+
[AgentProviderIds.deepinfra]: {
|
|
8056
|
+
// `piAiProvider` is the canonical id here (not a pi-ai vendor) — it's the
|
|
8057
|
+
// `model.provider` string the agent loop hands to `getApiKey`, which
|
|
8058
|
+
// `resolveAgentId` maps straight back to the deepinfra config/env key.
|
|
8059
|
+
piAiProvider: AgentProviderIds.deepinfra,
|
|
8060
|
+
label: "DeepInfra (GLM / DeepSeek)",
|
|
8061
|
+
defaultModel: PROVIDER_MODELS[AgentProviderIds.deepinfra][LlmCapabilities.agent],
|
|
8062
|
+
autoDetectPriority: 4,
|
|
8063
|
+
openaiCompatible: {
|
|
8064
|
+
baseUrl: "https://api.deepinfra.com/v1/openai",
|
|
8065
|
+
baseUrlEnvVar: "DEEPINFRA_BASE_URL",
|
|
8066
|
+
apiKeyEnvVar: "DEEPINFRA_TOKEN",
|
|
8067
|
+
// DeepInfra serves open-weight models (GLM, DeepSeek) behind an
|
|
8068
|
+
// OpenAI-compatible vLLM endpoint. pi-ai's `detectCompat` has no rule
|
|
8069
|
+
// for api.deepinfra.com, so it would apply the strict OpenAI profile;
|
|
8070
|
+
// we set the same open-model profile pi-ai uses for deepseek.com /
|
|
8071
|
+
// cerebras / z.ai. `developer` role and `reasoning_effort` are
|
|
8072
|
+
// OpenAI-platform-isms these models reject, `store` is response
|
|
8073
|
+
// persistence DeepInfra doesn't implement, and DeepInfra documents
|
|
8074
|
+
// `max_tokens` (not `max_completion_tokens`) on its OpenAI route.
|
|
8075
|
+
compat: {
|
|
8076
|
+
supportsStore: false,
|
|
8077
|
+
supportsDeveloperRole: false,
|
|
8078
|
+
supportsReasoningEffort: false,
|
|
8079
|
+
maxTokensField: "max_tokens"
|
|
8080
|
+
},
|
|
8081
|
+
// Best-effort metadata. Costs are USD/1M tokens (DeepInfra published
|
|
8082
|
+
// rates: GLM-5.2 ~$0.95 in / $0.18 cached / $3.00 out; DeepSeek-V4-Flash
|
|
8083
|
+
// ~$0.10 in / $0.20 out). contextWindow is DeepInfra's 1M (fp4) serving
|
|
8084
|
+
// window for both models; it's descriptive (see OpenAiCompatibleModelMeta),
|
|
8085
|
+
// so it documents the real window rather than gating compaction.
|
|
8086
|
+
knownModels: {
|
|
8087
|
+
"zai-org/GLM-5.2": {
|
|
8088
|
+
contextWindow: 1048576,
|
|
8089
|
+
maxTokens: 98304,
|
|
8090
|
+
reasoning: true,
|
|
8091
|
+
cost: { input: 0.95, output: 3, cacheRead: 0.18, cacheWrite: 0 }
|
|
8092
|
+
},
|
|
8093
|
+
"deepseek-ai/DeepSeek-V4-Flash": {
|
|
8094
|
+
contextWindow: 1048576,
|
|
8095
|
+
maxTokens: 32768,
|
|
8096
|
+
reasoning: false,
|
|
8097
|
+
cost: { input: 0.1, output: 0.2, cacheRead: 0, cacheWrite: 0 }
|
|
8098
|
+
}
|
|
8099
|
+
},
|
|
8100
|
+
// Fallback for arbitrary `--model` slugs we don't ship as tiers. cost is
|
|
8101
|
+
// 0, so an unknown slug isn't cost-tracked by pi-ai's `calculateCost`;
|
|
8102
|
+
// contextWindow stays conservative since we can't know the slug's window.
|
|
8103
|
+
defaultModelMeta: {
|
|
8104
|
+
contextWindow: 131072,
|
|
8105
|
+
maxTokens: 32768,
|
|
8106
|
+
reasoning: false,
|
|
8107
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
|
|
8108
|
+
}
|
|
8109
|
+
}
|
|
8037
8110
|
}
|
|
8038
8111
|
};
|
|
8039
8112
|
function agentProvidersByPriority() {
|
|
@@ -8055,6 +8128,9 @@ function resolveModelForProvider(provider, modelId) {
|
|
|
8055
8128
|
function resolveModelForCapability(provider, capability, modelIdOverride) {
|
|
8056
8129
|
const entry = AGENT_PROVIDERS[provider];
|
|
8057
8130
|
const id = modelIdOverride ?? PROVIDER_MODELS[provider][capability];
|
|
8131
|
+
if (entry.openaiCompatible) {
|
|
8132
|
+
return buildOpenAiCompatibleModel(entry, id);
|
|
8133
|
+
}
|
|
8058
8134
|
const model = getModel(entry.piAiProvider, id);
|
|
8059
8135
|
if (!model) {
|
|
8060
8136
|
throw new Error(
|
|
@@ -8063,6 +8139,27 @@ function resolveModelForCapability(provider, capability, modelIdOverride) {
|
|
|
8063
8139
|
}
|
|
8064
8140
|
return model;
|
|
8065
8141
|
}
|
|
8142
|
+
function buildOpenAiCompatibleModel(entry, id) {
|
|
8143
|
+
const host = entry.openaiCompatible;
|
|
8144
|
+
if (!host) {
|
|
8145
|
+
throw new Error(`buildOpenAiCompatibleModel called for non-custom provider '${entry.piAiProvider}'`);
|
|
8146
|
+
}
|
|
8147
|
+
const meta = host.knownModels[id] ?? host.defaultModelMeta;
|
|
8148
|
+
const baseUrl = (host.baseUrlEnvVar ? process.env[host.baseUrlEnvVar] : void 0) || host.baseUrl;
|
|
8149
|
+
return {
|
|
8150
|
+
id,
|
|
8151
|
+
name: id,
|
|
8152
|
+
api: "openai-completions",
|
|
8153
|
+
provider: entry.piAiProvider,
|
|
8154
|
+
baseUrl,
|
|
8155
|
+
reasoning: meta.reasoning,
|
|
8156
|
+
input: ["text"],
|
|
8157
|
+
cost: meta.cost,
|
|
8158
|
+
contextWindow: meta.contextWindow,
|
|
8159
|
+
maxTokens: meta.maxTokens,
|
|
8160
|
+
...host.compat ? { compat: host.compat } : {}
|
|
8161
|
+
};
|
|
8162
|
+
}
|
|
8066
8163
|
function validateAgentProviderRegistry() {
|
|
8067
8164
|
for (const provider of listAgentProviders()) {
|
|
8068
8165
|
for (const capability of LLM_CAPABILITIES) {
|
|
@@ -8086,10 +8183,14 @@ function resolveApiKeySource(providerOrPiAi, config) {
|
|
|
8086
8183
|
const entry = AGENT_PROVIDERS[id];
|
|
8087
8184
|
const fromConfig = config.providers?.[id]?.apiKey;
|
|
8088
8185
|
if (fromConfig) return { key: fromConfig, source: "config" };
|
|
8089
|
-
const fromEnv = getEnvApiKey(entry.piAiProvider);
|
|
8186
|
+
const fromEnv = entry.openaiCompatible ? process.env[entry.openaiCompatible.apiKeyEnvVar] : getEnvApiKey(entry.piAiProvider);
|
|
8090
8187
|
if (fromEnv) return { key: fromEnv, source: "env" };
|
|
8091
8188
|
return void 0;
|
|
8092
8189
|
}
|
|
8190
|
+
function agentProviderApiKeyEnvVar(id) {
|
|
8191
|
+
const entry = AGENT_PROVIDERS[id];
|
|
8192
|
+
return entry.openaiCompatible ? entry.openaiCompatible.apiKeyEnvVar : `${entry.piAiProvider.toUpperCase()}_API_KEY`;
|
|
8193
|
+
}
|
|
8093
8194
|
function resolveAgentId(providerOrPiAi) {
|
|
8094
8195
|
if (isAgentProviderId(providerOrPiAi)) return providerOrPiAi;
|
|
8095
8196
|
for (const id of AGENT_PROVIDER_IDS) {
|
|
@@ -8313,7 +8414,7 @@ ${skillBody}`;
|
|
|
8313
8414
|
}
|
|
8314
8415
|
function missingProviderMessage() {
|
|
8315
8416
|
const configHints = agentProvidersByPriority().join(", ");
|
|
8316
|
-
const envHints = agentProvidersByPriority().map(
|
|
8417
|
+
const envHints = agentProvidersByPriority().map(agentProviderApiKeyEnvVar).join(" / ");
|
|
8317
8418
|
return `No agent LLM provider configured. Add an API key for one of: ${configHints} in ~/.canonry/config.yaml, or export ${envHints}.`;
|
|
8318
8419
|
}
|
|
8319
8420
|
function detectAgentProvider(config) {
|
|
@@ -9267,7 +9368,7 @@ function pickExplainProvider(config, providerOverride) {
|
|
|
9267
9368
|
for (const provider of agentProvidersByPriority()) {
|
|
9268
9369
|
if (resolveApiKeyFor(provider, config)) return provider;
|
|
9269
9370
|
}
|
|
9270
|
-
const hints = agentProvidersByPriority().map(
|
|
9371
|
+
const hints = agentProvidersByPriority().map(agentProviderApiKeyEnvVar).join(" / ");
|
|
9271
9372
|
throw providerError(
|
|
9272
9373
|
`No LLM provider configured. Add an API key in ~/.canonry/config.yaml or set one of: ${hints}.`
|
|
9273
9374
|
);
|
|
@@ -10886,6 +10987,9 @@ async function createServer(opts) {
|
|
|
10886
10987
|
},
|
|
10887
10988
|
getGoogleAuthConfig: () => getGoogleAuthConfig(opts.config),
|
|
10888
10989
|
getPlacesConfig: () => getPlacesConfig(opts.config),
|
|
10990
|
+
// Resolved fresh each call so a key added at runtime (settings API) shows
|
|
10991
|
+
// up immediately in the `config.agent-providers` doctor check.
|
|
10992
|
+
getAgentProviderSummary: () => buildAgentProvidersResponse(opts.config).providers,
|
|
10889
10993
|
googleConnectionStore,
|
|
10890
10994
|
googleStateSecret,
|
|
10891
10995
|
publicUrl: opts.config.publicUrl,
|
|
@@ -1434,7 +1434,8 @@ var ProviderIds = {
|
|
|
1434
1434
|
perplexity: "perplexity",
|
|
1435
1435
|
local: "local",
|
|
1436
1436
|
cdpChatgpt: "cdp:chatgpt",
|
|
1437
|
-
zai: "zai"
|
|
1437
|
+
zai: "zai",
|
|
1438
|
+
deepinfra: "deepinfra"
|
|
1438
1439
|
};
|
|
1439
1440
|
var PROVIDER_IDS = Object.values(ProviderIds);
|
|
1440
1441
|
var SweepProviderIds = {
|
|
@@ -1450,7 +1451,8 @@ var AgentProviderIds = {
|
|
|
1450
1451
|
claude: ProviderIds.claude,
|
|
1451
1452
|
openai: ProviderIds.openai,
|
|
1452
1453
|
gemini: ProviderIds.gemini,
|
|
1453
|
-
zai: ProviderIds.zai
|
|
1454
|
+
zai: ProviderIds.zai,
|
|
1455
|
+
deepinfra: ProviderIds.deepinfra
|
|
1454
1456
|
};
|
|
1455
1457
|
var AGENT_PROVIDER_IDS = Object.values(AgentProviderIds);
|
|
1456
1458
|
function isAgentProviderId(value) {
|
|
@@ -3027,7 +3029,7 @@ function escapeRegExp(value) {
|
|
|
3027
3029
|
|
|
3028
3030
|
// ../contracts/src/agent.ts
|
|
3029
3031
|
import { z as z22 } from "zod";
|
|
3030
|
-
var agentProviderIdSchema = z22.enum(["claude", "openai", "gemini", "zai"]);
|
|
3032
|
+
var agentProviderIdSchema = z22.enum(["claude", "openai", "gemini", "zai", "deepinfra"]);
|
|
3031
3033
|
var agentProviderOptionDtoSchema = z22.object({
|
|
3032
3034
|
/** Stable identifier — what clients pass back as `provider` on the prompt endpoint. */
|
|
3033
3035
|
id: agentProviderIdSchema,
|
|
@@ -3850,6 +3852,23 @@ function citationStateToCited(state) {
|
|
|
3850
3852
|
|
|
3851
3853
|
// ../contracts/src/report.ts
|
|
3852
3854
|
import { z as z28 } from "zod";
|
|
3855
|
+
var REPORT_PERIOD_OPTIONS = [7, 14, 30, 90];
|
|
3856
|
+
var REPORT_DEFAULT_PERIOD_DAYS = 30;
|
|
3857
|
+
var reportPeriodSchema = z28.union([z28.literal(7), z28.literal(14), z28.literal(30), z28.literal(90)]).describe("Report window in days (7, 14, 30, or 90). Defaults to 30 when omitted.");
|
|
3858
|
+
function isReportPeriodDays(n) {
|
|
3859
|
+
return REPORT_PERIOD_OPTIONS.includes(n);
|
|
3860
|
+
}
|
|
3861
|
+
function parseReportPeriodDays(value) {
|
|
3862
|
+
if (value === void 0 || value === null || value === "") return REPORT_DEFAULT_PERIOD_DAYS;
|
|
3863
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
3864
|
+
if (!Number.isInteger(n) || !isReportPeriodDays(n)) {
|
|
3865
|
+
throw validationError(`"period" must be one of ${REPORT_PERIOD_OPTIONS.join(", ")}`);
|
|
3866
|
+
}
|
|
3867
|
+
return n;
|
|
3868
|
+
}
|
|
3869
|
+
function reportComparisonWindowDays(periodDays) {
|
|
3870
|
+
return Math.max(1, Math.floor(periodDays / 2));
|
|
3871
|
+
}
|
|
3853
3872
|
var providerLocationTreatmentSchema = z28.enum([
|
|
3854
3873
|
"prompt",
|
|
3855
3874
|
"request-param",
|
|
@@ -3907,7 +3926,14 @@ var reportMetaSchema = z28.object({
|
|
|
3907
3926
|
/** Earliest data point referenced by the report (ISO date). */
|
|
3908
3927
|
periodStart: z28.string().nullable(),
|
|
3909
3928
|
/** Latest data point referenced by the report (ISO date). */
|
|
3910
|
-
periodEnd: z28.string().nullable()
|
|
3929
|
+
periodEnd: z28.string().nullable(),
|
|
3930
|
+
/**
|
|
3931
|
+
* The selected report window, in days (one of `REPORT_PERIOD_OPTIONS`).
|
|
3932
|
+
* Every time-windowed section scopes to this many days; renderers read it to
|
|
3933
|
+
* label the window ("Last 30 days", "(30d)"). Defaults to
|
|
3934
|
+
* `REPORT_DEFAULT_PERIOD_DAYS` when no `period` is requested.
|
|
3935
|
+
*/
|
|
3936
|
+
periodDays: z28.number().int().positive()
|
|
3911
3937
|
});
|
|
3912
3938
|
var reportExecutiveSummarySchema = z28.object({
|
|
3913
3939
|
/**
|
|
@@ -4331,16 +4357,25 @@ var whatsChangedSectionSchema = z28.object({
|
|
|
4331
4357
|
/** Cited query count delta vs the prior completed run. Null when no prior run. */
|
|
4332
4358
|
citedQueryCount: reportRateDeltaSchema.nullable(),
|
|
4333
4359
|
/**
|
|
4334
|
-
* GSC clicks delta —
|
|
4335
|
-
* that. Null when GSC isn't connected
|
|
4360
|
+
* GSC clicks delta — the most recent `comparisonWindowDays` of `gsc.trend`
|
|
4361
|
+
* vs the `comparisonWindowDays` before that. Null when GSC isn't connected
|
|
4362
|
+
* or fewer than `comparisonWindowDays * 2` trend points exist.
|
|
4336
4363
|
*/
|
|
4337
4364
|
gscClicksDelta: reportRateDeltaSchema.nullable(),
|
|
4338
4365
|
/**
|
|
4339
|
-
* AI referral sessions delta —
|
|
4340
|
-
*
|
|
4341
|
-
* than
|
|
4366
|
+
* AI referral sessions delta — the most recent `comparisonWindowDays` of
|
|
4367
|
+
* `aiReferrals.trend` vs the `comparisonWindowDays` before that. Null when
|
|
4368
|
+
* AI referrals aren't tracked or fewer than `comparisonWindowDays * 2`
|
|
4369
|
+
* trend points exist.
|
|
4342
4370
|
*/
|
|
4343
4371
|
aiReferralsDelta: reportRateDeltaSchema.nullable(),
|
|
4372
|
+
/**
|
|
4373
|
+
* The period-over-period half-window in days used for `gscClicksDelta` and
|
|
4374
|
+
* `aiReferralsDelta` — `floor(meta.periodDays / 2)`. Renderers label those
|
|
4375
|
+
* deltas "vs prior {comparisonWindowDays} days" off this single value so the
|
|
4376
|
+
* SPA and HTML stay verbatim-identical.
|
|
4377
|
+
*/
|
|
4378
|
+
comparisonWindowDays: z28.number().int().positive(),
|
|
4344
4379
|
/**
|
|
4345
4380
|
* Per-provider citation rate movements (latest run vs prior run). Empty
|
|
4346
4381
|
* when no prior run. Sorted by |deltaAbs| desc — providers with the
|
|
@@ -5105,7 +5140,11 @@ var adsConnectionStatusDtoSchema = z31.object({
|
|
|
5105
5140
|
currencyCode: z31.string().nullable().optional(),
|
|
5106
5141
|
timezone: z31.string().nullable().optional(),
|
|
5107
5142
|
status: z31.string().nullable().optional(),
|
|
5108
|
-
lastSyncedAt: z31.string().nullable().optional()
|
|
5143
|
+
lastSyncedAt: z31.string().nullable().optional(),
|
|
5144
|
+
/** Whether the ad account has OpenAI conversion tracking (pixel or CAPI) configured,
|
|
5145
|
+
* detected from synced campaigns carrying conversion_event_setting_ids. Optional:
|
|
5146
|
+
* only present when connected. */
|
|
5147
|
+
conversionTrackingConfigured: z31.boolean().optional()
|
|
5109
5148
|
});
|
|
5110
5149
|
var adsDisconnectResponseSchema = z31.object({
|
|
5111
5150
|
disconnected: z31.boolean()
|
|
@@ -5163,6 +5202,10 @@ var adsInsightRowDtoSchema = z31.object({
|
|
|
5163
5202
|
impressions: z31.number().int(),
|
|
5164
5203
|
clicks: z31.number().int(),
|
|
5165
5204
|
spendMicros: z31.number().int(),
|
|
5205
|
+
/** Conversion count for the row. 0 when conversion tracking is not configured.
|
|
5206
|
+
* Conversion VALUE (for ROAS) is a deliberate follow-up: the upstream value
|
|
5207
|
+
* field is not yet captured against a live conversion-tracking account. */
|
|
5208
|
+
conversions: z31.number().int(),
|
|
5166
5209
|
/** clicks / impressions; null when impressions is 0. */
|
|
5167
5210
|
ctr: z31.number().nullable(),
|
|
5168
5211
|
/** spendMicros / clicks, rounded to integer micros; null when clicks is 0. */
|
|
@@ -5177,6 +5220,7 @@ var adsTotalsDtoSchema = z31.object({
|
|
|
5177
5220
|
impressions: z31.number().int(),
|
|
5178
5221
|
clicks: z31.number().int(),
|
|
5179
5222
|
spendMicros: z31.number().int(),
|
|
5223
|
+
conversions: z31.number().int(),
|
|
5180
5224
|
ctr: z31.number().nullable(),
|
|
5181
5225
|
cpcMicros: z31.number().int().nullable()
|
|
5182
5226
|
});
|
|
@@ -5554,6 +5598,10 @@ export {
|
|
|
5554
5598
|
citationVisibilityResponseSchema,
|
|
5555
5599
|
emptyCitationVisibility,
|
|
5556
5600
|
citationStateToCited,
|
|
5601
|
+
REPORT_PERIOD_OPTIONS,
|
|
5602
|
+
reportPeriodSchema,
|
|
5603
|
+
parseReportPeriodDays,
|
|
5604
|
+
reportComparisonWindowDays,
|
|
5557
5605
|
reportActionTone,
|
|
5558
5606
|
reportSeverityLabel,
|
|
5559
5607
|
reportHorizonLabel,
|