@canonry/canonry 7.18.1 → 7.20.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/aero/references/agent-operations.md +14 -0
- package/assets/agent-workspace/skills/canonry/SKILL.md +14 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +33 -1
- package/assets/assets/AuditHistoryPanel-C0vj3liH.js +1 -0
- package/assets/assets/{BacklinksPage-BT3j4tQK.js → BacklinksPage-TnDsI9Wu.js} +1 -1
- package/assets/assets/{HistoryPage-BHV_3wbQ.js → HistoryPage-DEEC3g6M.js} +1 -1
- package/assets/assets/MeasurementPropertyPage-MT4tFOwx.js +4 -0
- package/assets/assets/ProjectPage-NI-bjpfN.js +8 -0
- package/assets/assets/{RunsPage-Cx5yMuzN.js → RunsPage-GIKqPu0J.js} +1 -1
- package/assets/assets/{SettingsPage-DrZ-eswp.js → SettingsPage-DLFwSj4J.js} +1 -1
- package/assets/assets/{SiteHealthSection-XOUI_75e.js → SiteHealthSection-CYG9IMh5.js} +3 -3
- package/assets/assets/{TrafficPage-DciX-fl5.js → TrafficPage-oOxDmxQq.js} +3 -3
- package/assets/assets/{TrafficSourceDetailPage-D1_lnRoS.js → TrafficSourceDetailPage-BGrwpVvM.js} +1 -1
- package/assets/assets/{extract-error-message-Cw5pcZtv.js → extract-error-message-DRDQFsgG.js} +1 -1
- package/assets/assets/{index-DIA9jvMi.js → index-B_2gPTCa.js} +36 -36
- package/assets/assets/{react-sigma_core.esm.min-Cc8jHlvQ.js → react-sigma_core.esm.min-DzDqz7hq.js} +1 -1
- package/assets/assets/v2-overview-adapter-BHzFliuj.js +1 -0
- package/assets/index.html +1 -1
- package/dist/{chunk-U7D7LNVJ.js → chunk-222NAFTY.js} +2 -2
- package/dist/{chunk-COQOQYRZ.js → chunk-46JZR2IV.js} +145 -31
- package/dist/{chunk-EAAM47H6.js → chunk-5IXQAOVK.js} +18 -3
- package/dist/{chunk-JUOFNJLV.js → chunk-6H2BC5EY.js} +3 -3
- package/dist/{chunk-PRL6UQ7L.js → chunk-KF7LRHGJ.js} +368 -211
- package/dist/{chunk-X2S7D3MN.js → chunk-MRKV43TV.js} +139 -7
- package/dist/{chunk-JMC7CEJB.js → chunk-NDQOCFJQ.js} +61 -43
- package/dist/cli.js +229 -45
- package/dist/{demo-server-XWRIXME5.js → demo-server-32PU7BM6.js} +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-332S7D7Y.js → intelligence-service-256DQBVR.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +13 -13
- package/assets/assets/AuditHistoryPanel-RAYlf3B4.js +0 -1
- package/assets/assets/MeasurementPropertyPage-9UFPKw-i.js +0 -1
- package/assets/assets/ProjectPage-C1_-qiHw.js +0 -8
- package/assets/assets/v2-overview-adapter-Ca5F20Kr.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
listAgentProviders,
|
|
22
22
|
notePrintedUpdateAvailable,
|
|
23
23
|
readCachedUpdateAvailable,
|
|
24
|
+
registeredProviderNames,
|
|
24
25
|
reparseStoredResult,
|
|
25
26
|
reparseStoredResult2,
|
|
26
27
|
reparseStoredResult3,
|
|
@@ -34,11 +35,11 @@ import {
|
|
|
34
35
|
trackCliCommandFinished,
|
|
35
36
|
trackEvent,
|
|
36
37
|
waitForServerRuntimeStartup
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-KF7LRHGJ.js";
|
|
38
39
|
import {
|
|
39
40
|
autoSyncSkills,
|
|
40
41
|
formatAutoSyncNotice
|
|
41
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-6H2BC5EY.js";
|
|
42
43
|
import {
|
|
43
44
|
configExists,
|
|
44
45
|
createApiClient,
|
|
@@ -54,14 +55,15 @@ import {
|
|
|
54
55
|
parseSkillsClient,
|
|
55
56
|
saveConfig,
|
|
56
57
|
saveConfigPatch,
|
|
57
|
-
shouldPrintServeSkillsNudge
|
|
58
|
-
|
|
58
|
+
shouldPrintServeSkillsNudge,
|
|
59
|
+
withBootstrapProviderDefaults
|
|
60
|
+
} from "./chunk-NDQOCFJQ.js";
|
|
59
61
|
import {
|
|
60
62
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
61
63
|
trustedProxiesProblem,
|
|
62
64
|
trustedProxyProblem
|
|
63
65
|
} from "./chunk-RB2F4D3Z.js";
|
|
64
|
-
import "./chunk-
|
|
66
|
+
import "./chunk-222NAFTY.js";
|
|
65
67
|
import {
|
|
66
68
|
CliError,
|
|
67
69
|
EXIT_SYSTEM_ERROR,
|
|
@@ -73,7 +75,7 @@ import {
|
|
|
73
75
|
runMeasurementDraftAction,
|
|
74
76
|
systemError,
|
|
75
77
|
usageError
|
|
76
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-5IXQAOVK.js";
|
|
77
79
|
import {
|
|
78
80
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
79
81
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -105,7 +107,7 @@ import {
|
|
|
105
107
|
rawEventSamples,
|
|
106
108
|
readMarketCompetitorNames,
|
|
107
109
|
runs
|
|
108
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-46JZR2IV.js";
|
|
109
111
|
import {
|
|
110
112
|
AdsDeliverySnapshotStatuses,
|
|
111
113
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -126,6 +128,7 @@ import {
|
|
|
126
128
|
OUTSTANDING_PROVIDER_BATCH_STATUSES,
|
|
127
129
|
ProviderBatchStatuses,
|
|
128
130
|
ProviderNames,
|
|
131
|
+
ProviderReloadErrorReasons,
|
|
129
132
|
READ_ONLY_SCOPE,
|
|
130
133
|
RatioUnits,
|
|
131
134
|
ResearchRunStatuses,
|
|
@@ -238,7 +241,7 @@ import {
|
|
|
238
241
|
visibilityCompareSelectionSchema,
|
|
239
242
|
visibilityReportRequestSchema,
|
|
240
243
|
winnabilityClassSchema
|
|
241
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-MRKV43TV.js";
|
|
242
245
|
|
|
243
246
|
// src/cli.ts
|
|
244
247
|
import { pathToFileURL } from "url";
|
|
@@ -256,11 +259,7 @@ function buildSetupState() {
|
|
|
256
259
|
const raw = loadConfigRaw();
|
|
257
260
|
if (raw) {
|
|
258
261
|
is_first_run = !raw.anonymousId;
|
|
259
|
-
|
|
260
|
-
provider_count = Object.values(raw.providers).filter(
|
|
261
|
-
(p) => Boolean(p?.apiKey) || Boolean(p?.baseUrl)
|
|
262
|
-
).length;
|
|
263
|
-
}
|
|
262
|
+
provider_count = registeredProviderNames(raw).length;
|
|
264
263
|
if (typeof raw.database === "string" && raw.database.length > 0) {
|
|
265
264
|
dbPath = raw.database;
|
|
266
265
|
}
|
|
@@ -788,7 +787,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
788
787
|
async function demoCommand(options) {
|
|
789
788
|
const { host, port } = parseDemoListenOptions(options);
|
|
790
789
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
791
|
-
const { createDemoServer } = await import("./demo-server-
|
|
790
|
+
const { createDemoServer } = await import("./demo-server-32PU7BM6.js");
|
|
792
791
|
const app = await createDemoServer({ trustProxy });
|
|
793
792
|
let stopping = false;
|
|
794
793
|
const stop = () => {
|
|
@@ -1202,7 +1201,7 @@ No DB writes performed. Re-run without --dry-run to apply.`);
|
|
|
1202
1201
|
}
|
|
1203
1202
|
}
|
|
1204
1203
|
async function backfillInsightsCommand(project2, opts) {
|
|
1205
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
1204
|
+
const { IntelligenceService } = await import("./intelligence-service-256DQBVR.js");
|
|
1206
1205
|
const config = loadConfig();
|
|
1207
1206
|
const db = createClient(config.database);
|
|
1208
1207
|
migrate(db);
|
|
@@ -12326,7 +12325,8 @@ function printMeasurementProperty(response) {
|
|
|
12326
12325
|
function shapedPage(response) {
|
|
12327
12326
|
if (response.answers !== void 0) return { shape: MeasurementEvidenceShapes.answers, ...response.answers };
|
|
12328
12327
|
if (response.evidence !== void 0) return { shape: MeasurementEvidenceShapes.sources, ...response.evidence };
|
|
12329
|
-
|
|
12328
|
+
if (response.otherQueries !== void 0) return { shape: MeasurementEvidenceShapes["other-queries"], ...response.otherQueries };
|
|
12329
|
+
throw systemError("The measurement property evidence response carried no evidence, answers or otherQueries page.");
|
|
12330
12330
|
}
|
|
12331
12331
|
async function showMeasurementPropertyEvidence(project2, opts) {
|
|
12332
12332
|
const response = await createApiClient().getMeasurementPropertyEvidence(project2, {
|
|
@@ -12373,15 +12373,24 @@ function printMeasurementPropertyEvidence(response) {
|
|
|
12373
12373
|
}
|
|
12374
12374
|
const page = shapedPage(response);
|
|
12375
12375
|
const answerShape = page.shape === MeasurementEvidenceShapes.answers;
|
|
12376
|
+
const otherQueriesShape = page.shape === MeasurementEvidenceShapes["other-queries"];
|
|
12376
12377
|
lines.push(`Measurement: ${response.measurement.state}${response.measurement.displayedRunId ? ` \xB7 run ${response.measurement.displayedRunId}` : ""}`);
|
|
12377
12378
|
if (page.items.length === 0) {
|
|
12378
|
-
lines.push(answerShape ? "No answers matched this Property in the displayed run." : "No source evidence matched this Property in the displayed run.");
|
|
12379
|
+
lines.push(answerShape ? "No answers matched this Property in the displayed run." : otherQueriesShape ? "No answer to another query cited this Property's pages in the displayed run." : "No source evidence matched this Property in the displayed run.");
|
|
12379
12380
|
console.log(lines.join("\n"));
|
|
12380
12381
|
return;
|
|
12381
12382
|
}
|
|
12382
|
-
lines.push(`${page.items.length} of ${page.totalEstimate ?? page.items.length} ${answerShape ? "answers" : "evidence rows"}`);
|
|
12383
|
+
lines.push(`${page.items.length} of ${page.totalEstimate ?? page.items.length} ${answerShape || otherQueriesShape ? "answers" : "evidence rows"}`);
|
|
12384
|
+
if (otherQueriesShape) lines.push("Cited on queries not assigned to this Property; not counted in its rates.");
|
|
12383
12385
|
lines.push("");
|
|
12384
|
-
if (page.shape === MeasurementEvidenceShapes
|
|
12386
|
+
if (page.shape === MeasurementEvidenceShapes["other-queries"]) {
|
|
12387
|
+
lines.push(`${"Engine".padEnd(12)}${"Question".padEnd(40)}${"Class".padEnd(11)}${"Assigned to".padEnd(24)}Pages`);
|
|
12388
|
+
for (const item of page.items) {
|
|
12389
|
+
lines.push(
|
|
12390
|
+
`${item.provider.padEnd(12)}${item.queryText.slice(0, 39).padEnd(40)}${item.queryClass.padEnd(11)}${item.assignedTargetKeys.join(", ").slice(0, 23).padEnd(24)}${item.sources.map((source) => source.sourceUrl).join(" ")}`
|
|
12391
|
+
);
|
|
12392
|
+
}
|
|
12393
|
+
} else if (page.shape === MeasurementEvidenceShapes.answers) {
|
|
12385
12394
|
lines.push(`${"Engine".padEnd(12)}${"Question".padEnd(40)}${"Mentioned".padEnd(15)}${"Cited".padEnd(8)}Sources`);
|
|
12386
12395
|
for (const item of page.items) {
|
|
12387
12396
|
lines.push(
|
|
@@ -15607,6 +15616,17 @@ async function showSettings(format) {
|
|
|
15607
15616
|
console.log("\nGoogle OAuth:\n");
|
|
15608
15617
|
console.log(` ${settings.google.configured ? "configured" : "not configured"}`);
|
|
15609
15618
|
}
|
|
15619
|
+
async function reloadProviders(format) {
|
|
15620
|
+
const result = await getClient25().reloadProviders();
|
|
15621
|
+
if (isMachineFormat(format)) {
|
|
15622
|
+
console.log(JSON.stringify(result, null, 2));
|
|
15623
|
+
return;
|
|
15624
|
+
}
|
|
15625
|
+
console.log("Saved provider configuration is now active on the server.");
|
|
15626
|
+
for (const provider of result.providers) {
|
|
15627
|
+
console.log(` ${provider.name}: ${provider.configured ? "configured" : "not configured"}`);
|
|
15628
|
+
}
|
|
15629
|
+
}
|
|
15610
15630
|
async function setGoogleAuth(opts) {
|
|
15611
15631
|
if (opts.target === "server") {
|
|
15612
15632
|
const result = await getClient25().updateGoogleSettings({
|
|
@@ -15640,6 +15660,11 @@ async function setGoogleAuth(opts) {
|
|
|
15640
15660
|
|
|
15641
15661
|
// src/cli-commands/settings.ts
|
|
15642
15662
|
var SETTINGS_CLI_COMMANDS = [
|
|
15663
|
+
{
|
|
15664
|
+
path: ["settings", "reload-providers"],
|
|
15665
|
+
usage: "canonry settings reload-providers [--format json]",
|
|
15666
|
+
run: async (input) => reloadProviders(input.format)
|
|
15667
|
+
},
|
|
15643
15668
|
{
|
|
15644
15669
|
path: ["settings", "provider"],
|
|
15645
15670
|
usage: "canonry settings provider <name> [--api-key <key>] [--base-url <url>] [--model <model>] [--max-concurrent <n>] [--max-per-minute <n>] [--max-per-day <n>] [--format json]",
|
|
@@ -15767,7 +15792,7 @@ Usage: canonry settings provider ${name} --api-key <key> [--model <model>] [--ma
|
|
|
15767
15792
|
},
|
|
15768
15793
|
{
|
|
15769
15794
|
path: ["settings"],
|
|
15770
|
-
usage: "canonry settings [provider|google] [args]",
|
|
15795
|
+
usage: "canonry settings [provider|reload-providers|google] [args]",
|
|
15771
15796
|
run: async (input) => {
|
|
15772
15797
|
const subcommand = input.positionals[0];
|
|
15773
15798
|
if (!subcommand) {
|
|
@@ -15776,8 +15801,8 @@ Usage: canonry settings provider ${name} --api-key <key> [--model <model>] [--ma
|
|
|
15776
15801
|
}
|
|
15777
15802
|
unknownSubcommand(subcommand, {
|
|
15778
15803
|
command: "settings",
|
|
15779
|
-
usage: "canonry settings [provider|google] [args]",
|
|
15780
|
-
available: ["provider", "google"]
|
|
15804
|
+
usage: "canonry settings [provider|reload-providers|google] [args]",
|
|
15805
|
+
available: ["provider", "reload-providers", "google"]
|
|
15781
15806
|
});
|
|
15782
15807
|
}
|
|
15783
15808
|
}
|
|
@@ -17291,14 +17316,72 @@ function persistedValue(value) {
|
|
|
17291
17316
|
}
|
|
17292
17317
|
return value;
|
|
17293
17318
|
}
|
|
17319
|
+
var PROVIDER_FREE_NEXT_STEPS = [
|
|
17320
|
+
"AI Visibility needs an answer-engine provider. Page Health does not.",
|
|
17321
|
+
"With the server running, the operator runs `canonry settings provider gemini --api-key <key>` (free key at https://aistudio.google.com/apikey). It takes effect immediately.",
|
|
17322
|
+
"Or the operator sets GEMINI_API_KEY and reruns `canonry bootstrap`. It reloads the matching running local server and confirms active providers; an offline server uses the saved settings at startup.",
|
|
17323
|
+
"A provider key is the operator's credential: never ask for it in chat."
|
|
17324
|
+
];
|
|
17325
|
+
var PROVIDER_CREDENTIAL_FIELDS = {
|
|
17326
|
+
[ProviderNames.gemini]: ["apiKey", "vertexProject", "vertexRegion", "vertexCredentials"],
|
|
17327
|
+
// A local key belongs to the server at its base URL.
|
|
17328
|
+
[ProviderNames.local]: ["baseUrl", "apiKey"]
|
|
17329
|
+
};
|
|
17330
|
+
var API_KEY_CREDENTIAL_FIELDS = ["apiKey"];
|
|
17331
|
+
function mergeEnvProvider(name, saved, fromEnv) {
|
|
17332
|
+
const credentialFields = PROVIDER_CREDENTIAL_FIELDS[name] ?? API_KEY_CREDENTIAL_FIELDS;
|
|
17333
|
+
const envFields = Object.entries(fromEnv);
|
|
17334
|
+
const envValues = new Map(envFields);
|
|
17335
|
+
const merged = {};
|
|
17336
|
+
for (const [field, value] of Object.entries(saved ?? {})) {
|
|
17337
|
+
if (envValues.get(field) !== void 0) merged[field] = envValues.get(field);
|
|
17338
|
+
else if (!credentialFields.includes(field)) merged[field] = value;
|
|
17339
|
+
}
|
|
17340
|
+
for (const [field, value] of envFields) {
|
|
17341
|
+
if (!(field in merged)) merged[field] = value;
|
|
17342
|
+
}
|
|
17343
|
+
return withBootstrapProviderDefaults(name, merged);
|
|
17344
|
+
}
|
|
17345
|
+
var ServerReloadStatuses = {
|
|
17346
|
+
reloaded: "reloaded",
|
|
17347
|
+
unchanged: "unchanged",
|
|
17348
|
+
unavailable: "unavailable",
|
|
17349
|
+
"not-local": "not-local",
|
|
17350
|
+
"not-matching": "not-matching",
|
|
17351
|
+
failed: "failed"
|
|
17352
|
+
};
|
|
17353
|
+
var NotMatchingReasons = {
|
|
17354
|
+
"other-install": "other-install",
|
|
17355
|
+
"reload-unsupported": "reload-unsupported"
|
|
17356
|
+
};
|
|
17357
|
+
function notMatchingReason(err) {
|
|
17358
|
+
const status = err.details?.httpStatus;
|
|
17359
|
+
if (status === 401 || status === 403) return NotMatchingReasons["other-install"];
|
|
17360
|
+
if (err.details?.reason === ProviderReloadErrorReasons["install-identity-mismatch"]) return NotMatchingReasons["other-install"];
|
|
17361
|
+
if (isEndpointMissing(err) || status === 501) return NotMatchingReasons["reload-unsupported"];
|
|
17362
|
+
return void 0;
|
|
17363
|
+
}
|
|
17364
|
+
function notMatchingLines(reason, serverUrl) {
|
|
17365
|
+
switch (reason) {
|
|
17366
|
+
case NotMatchingReasons["other-install"]:
|
|
17367
|
+
return [
|
|
17368
|
+
`The server at ${serverUrl} is not this install's server, so it was not reloaded.`,
|
|
17369
|
+
"To apply the saved providers, run `canonry settings reload-providers` against this install's server, or restart that server."
|
|
17370
|
+
];
|
|
17371
|
+
case NotMatchingReasons["reload-unsupported"]:
|
|
17372
|
+
return [
|
|
17373
|
+
`The server at ${serverUrl} cannot reload providers: it is too old or does not support reload.`,
|
|
17374
|
+
"Restart this install's server to apply the saved providers."
|
|
17375
|
+
];
|
|
17376
|
+
}
|
|
17377
|
+
}
|
|
17294
17378
|
async function bootstrapCommand(opts) {
|
|
17295
17379
|
const format = opts?.format ?? "text";
|
|
17296
|
-
const env = getBootstrapEnv(process.env);
|
|
17297
|
-
const providers = env.providers;
|
|
17298
17380
|
const configDir = getConfigDir();
|
|
17299
17381
|
const existing = configExists();
|
|
17300
17382
|
const existingConfig = existing ? loadConfig() : void 0;
|
|
17301
17383
|
const existingRaw = existing ? loadConfigRaw() : null;
|
|
17384
|
+
const env = getBootstrapEnv(process.env);
|
|
17302
17385
|
const databasePath = env.databasePath || existingRaw?.database || path8.join(configDir, "data.db");
|
|
17303
17386
|
let rawApiKey;
|
|
17304
17387
|
let generatedApiKey;
|
|
@@ -17311,12 +17394,9 @@ async function bootstrapCommand(opts) {
|
|
|
17311
17394
|
rawApiKey = generatedApiKey;
|
|
17312
17395
|
}
|
|
17313
17396
|
const mergedProviders = { ...existingConfig?.providers };
|
|
17314
|
-
|
|
17315
|
-
|
|
17316
|
-
|
|
17317
|
-
if (providers.perplexity) mergedProviders.perplexity = providers.perplexity;
|
|
17318
|
-
if (providers.muse) mergedProviders.muse = providers.muse;
|
|
17319
|
-
if (providers.local) mergedProviders.local = providers.local;
|
|
17397
|
+
for (const [name, fromEnv] of Object.entries(env.providers)) {
|
|
17398
|
+
if (fromEnv) mergedProviders[name] = mergeEnvProvider(name, mergedProviders[name], fromEnv);
|
|
17399
|
+
}
|
|
17320
17400
|
if (env.googleClientId && !env.googleClientSecret || !env.googleClientId && env.googleClientSecret) {
|
|
17321
17401
|
console.warn("Warning: GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must both be set to configure Google OAuth. Skipping Google auth config.");
|
|
17322
17402
|
}
|
|
@@ -17390,10 +17470,54 @@ async function bootstrapCommand(opts) {
|
|
|
17390
17470
|
providers: mergedProviders,
|
|
17391
17471
|
google: mergedGoogle
|
|
17392
17472
|
};
|
|
17393
|
-
const
|
|
17473
|
+
const providersChanged = !isDeepStrictEqual(persistedValue(existingRaw?.providers ?? {}), persistedValue(mergedProviders));
|
|
17474
|
+
const configChanged = !existingRaw || existingRaw.apiUrl !== apiUrl || existingRaw.database !== databasePath || existingRaw.apiKey !== rawApiKey || providersChanged || !isDeepStrictEqual(persistedValue(existingRaw.google), persistedValue(mergedGoogle));
|
|
17394
17475
|
if (configChanged) saveConfig(nextConfig);
|
|
17395
17476
|
const status = !existing ? "created" : configChanged || keyChanged ? "updated" : "unchanged";
|
|
17396
|
-
|
|
17477
|
+
const providerFree = registeredProviderNames(nextConfig).length === 0;
|
|
17478
|
+
const serverUrl = loadConfig().apiUrl;
|
|
17479
|
+
let serverReload;
|
|
17480
|
+
let reloadFailure;
|
|
17481
|
+
if (!isLoopbackBindHost(new URL(serverUrl).hostname)) {
|
|
17482
|
+
serverReload = { status: ServerReloadStatuses["not-local"] };
|
|
17483
|
+
} else if (!providersChanged) {
|
|
17484
|
+
serverReload = { status: ServerReloadStatuses.unchanged };
|
|
17485
|
+
} else {
|
|
17486
|
+
const signal = AbortSignal.timeout(4e3);
|
|
17487
|
+
try {
|
|
17488
|
+
const receipt = await createApiClient().reloadProviders({ configPath: getConfigPath(), databasePath }, signal);
|
|
17489
|
+
serverReload = {
|
|
17490
|
+
status: ServerReloadStatuses.reloaded,
|
|
17491
|
+
providers: receipt.providers.filter((provider) => provider.configured).map((provider) => provider.name)
|
|
17492
|
+
};
|
|
17493
|
+
} catch (err) {
|
|
17494
|
+
const reason = err instanceof CliError ? notMatchingReason(err) : void 0;
|
|
17495
|
+
if (err instanceof CliError && err.code === "CONNECTION_ERROR" && err.details?.connectionUnavailable === true && !signal.aborted) {
|
|
17496
|
+
serverReload = { status: ServerReloadStatuses.unavailable };
|
|
17497
|
+
} else if (err instanceof CliError && reason) {
|
|
17498
|
+
serverReload = { status: ServerReloadStatuses["not-matching"], reason, code: err.code };
|
|
17499
|
+
} else {
|
|
17500
|
+
reloadFailure = err instanceof CliError ? err : systemError("Provider configuration was saved, but server reload failed.");
|
|
17501
|
+
serverReload = { status: ServerReloadStatuses.failed, code: reloadFailure.code };
|
|
17502
|
+
}
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
const reloadSteps = (() => {
|
|
17506
|
+
switch (serverReload.status) {
|
|
17507
|
+
case ServerReloadStatuses.unavailable:
|
|
17508
|
+
return ["Start `canonry serve` to use the saved configuration."];
|
|
17509
|
+
case ServerReloadStatuses.failed:
|
|
17510
|
+
return ["Resolve the server reload error, then run `canonry settings reload-providers`."];
|
|
17511
|
+
case ServerReloadStatuses["not-matching"]:
|
|
17512
|
+
return [notMatchingLines(serverReload.reason, serverUrl).join(" ")];
|
|
17513
|
+
case ServerReloadStatuses.reloaded:
|
|
17514
|
+
case ServerReloadStatuses.unchanged:
|
|
17515
|
+
case ServerReloadStatuses["not-local"]:
|
|
17516
|
+
return [];
|
|
17517
|
+
}
|
|
17518
|
+
})();
|
|
17519
|
+
const nextSteps = [...providerFree ? PROVIDER_FREE_NEXT_STEPS : [], ...reloadSteps];
|
|
17520
|
+
if (isMachineFormat(format)) {
|
|
17397
17521
|
console.log(JSON.stringify({
|
|
17398
17522
|
bootstrapped: true,
|
|
17399
17523
|
status,
|
|
@@ -17403,18 +17527,44 @@ async function bootstrapCommand(opts) {
|
|
|
17403
17527
|
apiUrl,
|
|
17404
17528
|
providers: Object.keys(mergedProviders),
|
|
17405
17529
|
googleConfigured: !!mergedGoogle,
|
|
17406
|
-
generatedApiKey
|
|
17530
|
+
generatedApiKey,
|
|
17531
|
+
serverReload,
|
|
17532
|
+
nextSteps
|
|
17407
17533
|
}, null, 2));
|
|
17534
|
+
if (reloadFailure) throw reloadFailure;
|
|
17408
17535
|
return;
|
|
17409
17536
|
}
|
|
17410
17537
|
console.log(`Bootstrap ${status}. Config: ${getConfigPath()}`);
|
|
17411
17538
|
console.log(`SQLite database path: ${databasePath}`);
|
|
17412
|
-
|
|
17539
|
+
switch (serverReload.status) {
|
|
17540
|
+
case ServerReloadStatuses.reloaded:
|
|
17541
|
+
console.log(`Providers active on the running server: ${serverReload.providers.join(", ") || "none"}.`);
|
|
17542
|
+
break;
|
|
17543
|
+
case ServerReloadStatuses.unavailable:
|
|
17544
|
+
console.log("Start `canonry serve` to use the saved configuration.");
|
|
17545
|
+
break;
|
|
17546
|
+
case ServerReloadStatuses["not-local"]:
|
|
17547
|
+
console.log("Configuration saved locally. The configured remote server was not reloaded.");
|
|
17548
|
+
break;
|
|
17549
|
+
case ServerReloadStatuses["not-matching"]:
|
|
17550
|
+
for (const line of notMatchingLines(serverReload.reason, serverUrl)) console.log(line);
|
|
17551
|
+
break;
|
|
17552
|
+
case ServerReloadStatuses.unchanged:
|
|
17553
|
+
if (existing) console.log("Provider settings unchanged, so the server was not reloaded.");
|
|
17554
|
+
break;
|
|
17555
|
+
case ServerReloadStatuses.failed:
|
|
17556
|
+
break;
|
|
17557
|
+
}
|
|
17558
|
+
if (providerFree) {
|
|
17413
17559
|
console.log("Providers: none (Page Health works now; add one later to enable AI Visibility).");
|
|
17560
|
+
console.log(" To add one with the server running: canonry settings provider gemini --api-key <key>");
|
|
17561
|
+
console.log(" (free key at aistudio.google.com). Or set GEMINI_API_KEY and rerun `canonry bootstrap`;");
|
|
17562
|
+
console.log(" bootstrap reloads the matching running local server and confirms active providers.");
|
|
17414
17563
|
}
|
|
17415
17564
|
if (generatedApiKey) {
|
|
17416
17565
|
console.log(`API key (for the CLI, MCP, and agents): ${generatedApiKey}`);
|
|
17417
17566
|
}
|
|
17567
|
+
if (reloadFailure) throw reloadFailure;
|
|
17418
17568
|
}
|
|
17419
17569
|
|
|
17420
17570
|
// src/commands/daemon.ts
|
|
@@ -17746,7 +17896,9 @@ async function initCommand(opts) {
|
|
|
17746
17896
|
});
|
|
17747
17897
|
}
|
|
17748
17898
|
if (nonInteractive) {
|
|
17749
|
-
Object.
|
|
17899
|
+
for (const [name, entry] of Object.entries(envProviders)) {
|
|
17900
|
+
if (entry) providers[name] = withBootstrapProviderDefaults(name, entry);
|
|
17901
|
+
}
|
|
17750
17902
|
if (envGoogleConfigured) {
|
|
17751
17903
|
google = {
|
|
17752
17904
|
clientId: bootstrapEnv.googleClientId,
|
|
@@ -18374,9 +18526,7 @@ Canonry server running at ${url}`);
|
|
|
18374
18526
|
}, null, 2));
|
|
18375
18527
|
}
|
|
18376
18528
|
setTelemetrySource("cli-server");
|
|
18377
|
-
const providerNames =
|
|
18378
|
-
(k) => config.providers?.[k]?.apiKey || config.providers?.[k]?.baseUrl
|
|
18379
|
-
);
|
|
18529
|
+
const providerNames = registeredProviderNames(config);
|
|
18380
18530
|
trackEvent("serve.started", {
|
|
18381
18531
|
providerCount: providerNames.length,
|
|
18382
18532
|
providers: providerNames,
|
|
@@ -21747,7 +21897,7 @@ Usage: ${usage}`, {
|
|
|
21747
21897
|
|
|
21748
21898
|
// src/cli-commands/measurement-plan.ts
|
|
21749
21899
|
var QUERY_CLASSES = ["all", "branded", "non-brand"];
|
|
21750
|
-
var EVIDENCE_SHAPES = ["sources", "answers"];
|
|
21900
|
+
var EVIDENCE_SHAPES = ["sources", "answers", "other-queries"];
|
|
21751
21901
|
function queryClassOption(input) {
|
|
21752
21902
|
const value = getString(input.values, "query-class");
|
|
21753
21903
|
if (value === void 0) return void 0;
|
|
@@ -21979,7 +22129,7 @@ Usage: ${usage}`);
|
|
|
21979
22129
|
},
|
|
21980
22130
|
{
|
|
21981
22131
|
path: ["measurement-plan", "property-evidence"],
|
|
21982
|
-
usage: "canonry measurement-plan property-evidence <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--shape sources|answers] [--cursor <c>] [--limit N] [--format json|jsonl]",
|
|
22132
|
+
usage: "canonry measurement-plan property-evidence <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--shape sources|answers|other-queries] [--cursor <c>] [--limit N] [--format json|jsonl]",
|
|
21983
22133
|
options: { ...PROPERTY_SCOPE_OPTIONS, shape: stringOption(), cursor: stringOption(), limit: stringOption() },
|
|
21984
22134
|
run: (input) => {
|
|
21985
22135
|
const usage = "canonry measurement-plan property-evidence <project> --target-key <key>";
|
|
@@ -22060,14 +22210,48 @@ var NUDGE_EXEMPT_ROOTS = /* @__PURE__ */ new Set([
|
|
|
22060
22210
|
"status",
|
|
22061
22211
|
"unknown"
|
|
22062
22212
|
]);
|
|
22213
|
+
var PAGE_HEALTH_HANDOFF_COMMANDS = /* @__PURE__ */ new Set([
|
|
22214
|
+
"technical-aeo.run",
|
|
22215
|
+
"technical-aeo.score",
|
|
22216
|
+
"technical-aeo.crawl",
|
|
22217
|
+
"site-health.overview"
|
|
22218
|
+
]);
|
|
22219
|
+
var NO_PROVIDER_NOTICE_CODE = "NO_PROVIDER";
|
|
22220
|
+
var PROVIDER_SETUP_COMMAND = "canonry settings provider gemini --api-key <key>";
|
|
22221
|
+
var GEMINI_KEY_URL = "https://aistudio.google.com/apikey";
|
|
22063
22222
|
function buildSetupNudgeLine(input) {
|
|
22064
|
-
|
|
22065
|
-
const
|
|
22066
|
-
if (
|
|
22223
|
+
const machineFormat = isMachineFormat(input.format);
|
|
22224
|
+
const handoff = PAGE_HEALTH_HANDOFF_COMMANDS.has(input.command);
|
|
22225
|
+
if (!handoff) {
|
|
22226
|
+
if (machineFormat || !input.stderrIsTTY) return null;
|
|
22227
|
+
const [root = input.command] = input.command.split(".");
|
|
22228
|
+
if (NUDGE_EXEMPT_ROOTS.has(root)) return null;
|
|
22229
|
+
}
|
|
22067
22230
|
const setupState = input.getSetupState();
|
|
22068
22231
|
if (!setupState) return null;
|
|
22069
22232
|
if (setupState.provider_count > 0) return null;
|
|
22070
|
-
|
|
22233
|
+
if (setupState.project_count === 0) return null;
|
|
22234
|
+
if (machineFormat) {
|
|
22235
|
+
return `${JSON.stringify({
|
|
22236
|
+
notice: {
|
|
22237
|
+
code: NO_PROVIDER_NOTICE_CODE,
|
|
22238
|
+
message: "AI Visibility needs an answer-engine provider. Page Health does not.",
|
|
22239
|
+
setupCommand: PROVIDER_SETUP_COMMAND,
|
|
22240
|
+
keyUrl: GEMINI_KEY_URL,
|
|
22241
|
+
note: "A provider key is the operator's credential: they add it in the dashboard, or run the setup command in their own terminal while the server is running. Never ask for it in chat."
|
|
22242
|
+
}
|
|
22243
|
+
})}
|
|
22244
|
+
`;
|
|
22245
|
+
}
|
|
22246
|
+
if (!input.stderrIsTTY) {
|
|
22247
|
+
return `[canonry] ${NO_PROVIDER_NOTICE_CODE}: AI Visibility needs an answer-engine provider. Page Health does not. The operator adds a key in the dashboard, or runs \`${PROVIDER_SETUP_COMMAND}\` in their own terminal while the server is running (free key at ${GEMINI_KEY_URL}). Never ask for the key in chat.
|
|
22248
|
+
`;
|
|
22249
|
+
}
|
|
22250
|
+
return `
|
|
22251
|
+
\u2192 AI Visibility needs an answer-engine provider. Page Health does not.
|
|
22252
|
+
Add one in the dashboard after \`canonry serve\`, or while the server is running:
|
|
22253
|
+
${PROVIDER_SETUP_COMMAND} (free key at aistudio.google.com)
|
|
22254
|
+
`;
|
|
22071
22255
|
}
|
|
22072
22256
|
|
|
22073
22257
|
// src/cli.ts
|
|
@@ -22247,7 +22431,7 @@ async function runCli(args = process.argv.slice(2)) {
|
|
|
22247
22431
|
}
|
|
22248
22432
|
const nudge = buildSetupNudgeLine({
|
|
22249
22433
|
command: resolvedCommand,
|
|
22250
|
-
|
|
22434
|
+
format,
|
|
22251
22435
|
stderrIsTTY: Boolean(process.stderr.isTTY),
|
|
22252
22436
|
getSetupState: buildSetupState
|
|
22253
22437
|
});
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
computeFactorAverages,
|
|
6
6
|
layoutSiteCrawlGraphInput,
|
|
7
7
|
persistSiteCrawlGraphLayout
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-222NAFTY.js";
|
|
9
9
|
import {
|
|
10
10
|
PACKAGE_VERSION,
|
|
11
11
|
canonryMcpTools
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5IXQAOVK.js";
|
|
13
13
|
import {
|
|
14
14
|
HISTORY_WINDOW_RUNS,
|
|
15
15
|
IntelligenceService,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
siteCrawlPages,
|
|
86
86
|
siteCrawlSnapshots,
|
|
87
87
|
trafficSources
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-46JZR2IV.js";
|
|
89
89
|
import {
|
|
90
90
|
RunKinds,
|
|
91
91
|
SiteCrawlFetchStates,
|
|
@@ -115,7 +115,7 @@ import {
|
|
|
115
115
|
roundPreservingTotal,
|
|
116
116
|
siteAuditPageFactorSchema,
|
|
117
117
|
wilsonInterval
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-MRKV43TV.js";
|
|
119
119
|
|
|
120
120
|
// src/demo-server.ts
|
|
121
121
|
import { dirname, join as join2 } from "path";
|
package/dist/index.d.ts
CHANGED
|
@@ -453,7 +453,7 @@ interface CanonryConfig {
|
|
|
453
453
|
places?: PlacesConfigEntry;
|
|
454
454
|
embed?: EmbedConfigEntry;
|
|
455
455
|
}
|
|
456
|
-
declare function loadConfig(): CanonryConfig;
|
|
456
|
+
declare function loadConfig(configPath?: string): CanonryConfig;
|
|
457
457
|
|
|
458
458
|
declare function createServer(opts: {
|
|
459
459
|
config: CanonryConfig;
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KF7LRHGJ.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-NDQOCFJQ.js";
|
|
10
|
+
import "./chunk-222NAFTY.js";
|
|
11
|
+
import "./chunk-5IXQAOVK.js";
|
|
12
|
+
import "./chunk-46JZR2IV.js";
|
|
13
|
+
import "./chunk-MRKV43TV.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6H2BC5EY.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-NDQOCFJQ.js";
|
|
8
|
+
import "./chunk-5IXQAOVK.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
|
11
11
|
updateCheckEnvOptOut
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MRKV43TV.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/cli.ts
|
|
15
15
|
import { randomUUID } from "crypto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
|
|
6
6
|
"keywords": [
|
|
@@ -86,33 +86,33 @@
|
|
|
86
86
|
"tsup": "^8.5.1",
|
|
87
87
|
"tsx": "^4.19.0",
|
|
88
88
|
"@ainyc/canonry-web": "0.0.0",
|
|
89
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
90
89
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
91
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
92
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
93
90
|
"@ainyc/canonry-db": "0.0.0",
|
|
91
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
92
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
93
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
94
94
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
95
|
-
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
96
95
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
96
|
+
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
97
97
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
98
|
+
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
98
99
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
99
100
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
100
|
-
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
101
101
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
102
|
-
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
103
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
104
102
|
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
103
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
104
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
105
105
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
106
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
106
107
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
107
108
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
108
109
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
109
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
110
110
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
111
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
112
|
-
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
113
111
|
"@ainyc/canonry-provider-muse": "0.0.0",
|
|
114
|
-
"@ainyc/canonry-
|
|
115
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
112
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
113
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
114
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
115
|
+
"@ainyc/canonry-integration-typesafe": "0.0.0"
|
|
116
116
|
},
|
|
117
117
|
"scripts": {
|
|
118
118
|
"build": "pnpm run build:cli && pnpm run build:web",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as a,u as h,j as e}from"./vendor-tanstack-ZXXkndVj.js";import{dJ as L,dK as P,cH as E,x as u,B as x,v,T as M}from"./index-DIA9jvMi.js";const o=100;function k(s){if(s==="all")return;const n=Number.parseInt(s,10);return new Date(Date.now()-n*24*60*60*1e3).toISOString()}function O(s){const n=s.userAgent?.toLowerCase()??"";return n.includes("canonry-mcp")?"MCP":n.includes("canonry-cli")?"CLI":n.includes("mozilla/")?"Dashboard":s.actor==="scheduler"?"Scheduler":s.actor==="agent"?"Agent":s.actor==="mcp"?"MCP":s.actor==="cli"?"CLI":s.actor}function B(s){return/delete|remove|revoke|disconnect|failed|refused/.test(s)?"negative":/create|add|connect|completed/.test(s)?"positive":/update|replace|sync|apply/.test(s)?"caution":"neutral"}function D(s){return[s.action,s.actor,s.entityType,s.entityId,s.actorSession,s.userAgent,s.diff==null?"":JSON.stringify(s.diff)].filter(Boolean).join(" ").toLowerCase()}function F({projectName:s}){const[n,l]=a.useState(0),[c,y]=a.useState("90d"),[m,N]=a.useState(""),[p,w]=a.useState(""),S=a.useMemo(()=>k(c),[c]),g={limit:o,offset:n*o,since:S,actor:m||void 0},C=h({...L({client:u,path:{name:s??""},query:g}),enabled:!!s}),A=h({...P({client:u,query:g}),enabled:!s}),f=h({...E({client:u}),enabled:!s}),i=s?C:A,r=i.data??[],I=a.useMemo(()=>new Map((f.data??[]).map(t=>[t.id,t.displayName||t.name])),[f.data]),d=p.trim().toLowerCase(),j=a.useMemo(()=>d?r.filter(t=>D(t).includes(d)):r,[r,d]),b=t=>{l(0),t()};return i.isLoading?e.jsx("p",{className:"supporting-copy mt-6",role:"status",children:"Loading change history…"}):e.jsxs("section",{className:"mt-6","aria-labelledby":"change-history-heading",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Audit trail"}),e.jsx("h2",{id:"change-history-heading",children:"Change history"}),e.jsx("p",{className:"supporting-copy mt-1 max-w-2xl",children:"Configuration and operator actions. Execution outcomes remain in Runs."})]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",onClick:()=>{i.refetch()},disabled:i.isFetching,children:i.isFetching?"Refreshing…":"Refresh"})]}),e.jsxs("div",{className:"mt-4 grid gap-2 sm:grid-cols-3",children:[e.jsx("input",{type:"search","aria-label":"Search change history",value:p,onChange:t=>w(t.target.value),placeholder:"Search actions, entities, or details",className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong placeholder-mono-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600"}),e.jsxs("select",{"aria-label":"Filter change history by actor",value:m,onChange:t=>b(()=>N(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"",children:"All actors"}),e.jsx("option",{value:"api",children:"API and dashboard"}),e.jsx("option",{value:"cli",children:"CLI"}),e.jsx("option",{value:"scheduler",children:"Scheduler"}),e.jsx("option",{value:"agent",children:"Agent"}),e.jsx("option",{value:"mcp",children:"MCP"})]}),e.jsxs("select",{"aria-label":"Filter change history by date range",value:c,onChange:t=>b(()=>y(t.target.value)),className:"min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"30d",children:"Last 30 days"}),e.jsx("option",{value:"90d",children:"Last 90 days"}),e.jsx("option",{value:"365d",children:"Last year"}),e.jsx("option",{value:"all",children:"All retained history"})]})]}),i.isError?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"Change history unavailable"}),e.jsx("p",{children:i.error instanceof Error?i.error.message:"Could not load the audit trail."})]}):j.length===0?e.jsxs(v,{className:"surface-card empty-card mt-4",children:[e.jsx("h3",{children:"No changes match these filters"}),e.jsx("p",{children:"Widen the date range or clear the actor and search filters."})]}):e.jsx("div",{className:"evidence-table-wrap mt-4",children:e.jsxs("table",{className:"evidence-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"When"}),s?null:e.jsx("th",{children:"Scope"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Entity"}),e.jsx("th",{children:"Origin"}),e.jsx("th",{children:"Details"})]})}),e.jsx("tbody",{children:j.map(t=>e.jsxs("tr",{children:[e.jsx("td",{className:"whitespace-nowrap tabular-nums text-muted",children:new Date(t.createdAt).toLocaleString()}),s?null:e.jsx("td",{className:"text-secondary",children:t.projectId?I.get(t.projectId)??`Deleted project · ${t.projectId}`:"Instance settings"}),e.jsx("td",{children:e.jsx(M,{tone:B(t.action),children:t.action})}),e.jsxs("td",{children:[e.jsx("span",{className:"text-strong",children:t.entityType}),t.entityId?e.jsx("span",{className:"mt-0.5 block max-w-48 truncate font-mono text-[11px] text-faint",title:t.entityId,children:t.entityId}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"text-secondary",children:O(t)}),t.actorSession?e.jsxs("span",{className:"mt-0.5 block max-w-40 truncate font-mono text-[11px] text-faint",title:t.actorSession,children:["Session ",t.actorSession]}):null]}),e.jsx("td",{children:t.diff==null?e.jsx("span",{className:"text-faint",children:"No field diff"}):e.jsxs("details",{children:[e.jsx("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary hover:text-strong",children:"View diff"}),e.jsx("pre",{className:"max-h-72 max-w-xl overflow-auto whitespace-pre-wrap break-words rounded-md bg-bg-elevated p-3 text-xs text-secondary",children:JSON.stringify(t.diff,null,2)})]})})]},t.id))})]})}),!i.isError&&(n>0||r.length===o)?e.jsxs("div",{className:"mt-4 flex items-center justify-between gap-3",children:[e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:n===0,onClick:()=>l(t=>Math.max(0,t-1)),children:"Previous"}),e.jsxs("span",{className:"text-xs tabular-nums text-muted",children:["Page ",n+1]}),e.jsx(x,{type:"button",variant:"outline",size:"sm",disabled:r.length<o,onClick:()=>l(t=>t+1),children:"Next"})]}):null]})}export{F as A};
|