@canonry/canonry 7.19.0 → 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.
Files changed (32) hide show
  1. package/assets/agent-workspace/skills/aero/references/agent-operations.md +14 -0
  2. package/assets/agent-workspace/skills/canonry/SKILL.md +14 -0
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +33 -1
  4. package/assets/assets/{AuditHistoryPanel-DEEWm-4t.js → AuditHistoryPanel-C0vj3liH.js} +1 -1
  5. package/assets/assets/{BacklinksPage-F5QBgXbF.js → BacklinksPage-TnDsI9Wu.js} +1 -1
  6. package/assets/assets/{HistoryPage-CNp42sUO.js → HistoryPage-DEEC3g6M.js} +1 -1
  7. package/assets/assets/{MeasurementPropertyPage-XpI9hVMb.js → MeasurementPropertyPage-MT4tFOwx.js} +1 -1
  8. package/assets/assets/{ProjectPage-B_V4QpyI.js → ProjectPage-NI-bjpfN.js} +1 -1
  9. package/assets/assets/{RunsPage-PTHloZl3.js → RunsPage-GIKqPu0J.js} +1 -1
  10. package/assets/assets/{SettingsPage-C-aDo2zf.js → SettingsPage-DLFwSj4J.js} +1 -1
  11. package/assets/assets/{SiteHealthSection-DvoT8IuX.js → SiteHealthSection-CYG9IMh5.js} +3 -3
  12. package/assets/assets/{TrafficPage-DahJoMKF.js → TrafficPage-oOxDmxQq.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-BGlHXOlk.js → TrafficSourceDetailPage-BGrwpVvM.js} +1 -1
  14. package/assets/assets/{extract-error-message-CP_fyJLM.js → extract-error-message-DRDQFsgG.js} +1 -1
  15. package/assets/assets/{index-C5V8xlr0.js → index-B_2gPTCa.js} +20 -20
  16. package/assets/assets/{react-sigma_core.esm.min-DUS8srfg.js → react-sigma_core.esm.min-DzDqz7hq.js} +1 -1
  17. package/assets/assets/{v2-overview-adapter-ycJ1guZb.js → v2-overview-adapter-BHzFliuj.js} +1 -1
  18. package/assets/index.html +1 -1
  19. package/dist/{chunk-A75L7CUV.js → chunk-222NAFTY.js} +2 -2
  20. package/dist/{chunk-UUI4HOEL.js → chunk-46JZR2IV.js} +46 -8
  21. package/dist/{chunk-VSTKTQPS.js → chunk-5IXQAOVK.js} +16 -1
  22. package/dist/{chunk-PBTTPZZE.js → chunk-6H2BC5EY.js} +3 -3
  23. package/dist/{chunk-OMP5OLBK.js → chunk-KF7LRHGJ.js} +368 -211
  24. package/dist/{chunk-CYHUZ2JQ.js → chunk-MRKV43TV.js} +19 -0
  25. package/dist/{chunk-35IIFDIT.js → chunk-NDQOCFJQ.js} +61 -43
  26. package/dist/cli.js +213 -39
  27. package/dist/{demo-server-K5G54GOE.js → demo-server-32PU7BM6.js} +4 -4
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.js +6 -6
  30. package/dist/{intelligence-service-LV2TQMMR.js → intelligence-service-256DQBVR.js} +2 -2
  31. package/dist/mcp.js +4 -4
  32. package/package.json +10 -10
@@ -42,6 +42,7 @@ var ProviderNames = {
42
42
  };
43
43
  var providerNameSchema = z2.string().min(1);
44
44
  var providerModelsSchema = z2.record(z2.string(), z2.string().trim().min(1));
45
+ var API_PROVIDER_NAMES = ["gemini", "openai", "claude", "perplexity", "muse", "local"];
45
46
  var apiProviderNameSchema = z2.string().min(1);
46
47
  function isBrowserProvider(name) {
47
48
  return name.startsWith("cdp:");
@@ -15170,6 +15171,19 @@ var providerSummaryEntryDtoSchema = z40.object({
15170
15171
  /** Whether Vertex AI is configured for this provider (Gemini only). */
15171
15172
  vertexConfigured: z40.boolean().optional()
15172
15173
  });
15174
+ var providerReloadRequestSchema = z40.object({
15175
+ configPath: z40.string().min(1).max(4096).optional(),
15176
+ databasePath: z40.string().min(1).max(4096).optional()
15177
+ }).strict().refine(
15178
+ (input) => input.configPath === void 0 === (input.databasePath === void 0),
15179
+ "configPath and databasePath must be supplied together"
15180
+ );
15181
+ var providerReloadErrorReasonSchema = z40.enum(["install-identity-mismatch"]);
15182
+ var ProviderReloadErrorReasons = providerReloadErrorReasonSchema.enum;
15183
+ var providerReloadResponseDtoSchema = z40.object({
15184
+ reloaded: z40.literal(true),
15185
+ providers: z40.array(providerSummaryEntryDtoSchema)
15186
+ });
15173
15187
  var providerCatalogEntryDtoSchema = z40.object({
15174
15188
  name: z40.string(),
15175
15189
  displayName: z40.string(),
@@ -21914,6 +21928,7 @@ var UI_ROUTE_FIXED_CHILDREN = /* @__PURE__ */ new Set([
21914
21928
  "locations/discover",
21915
21929
  "notifications/events",
21916
21930
  "operations/logs",
21931
+ "providers/reload",
21917
21932
  "queries/generate",
21918
21933
  "queries/replace-preview",
21919
21934
  "runs/latest",
@@ -22637,6 +22652,7 @@ export {
22637
22652
  RetrievalContracts,
22638
22653
  providerQuotaPolicySchema,
22639
22654
  ProviderNames,
22655
+ API_PROVIDER_NAMES,
22640
22656
  isBrowserProvider,
22641
22657
  resolveProviderInput,
22642
22658
  locationContextSchema,
@@ -23224,6 +23240,9 @@ export {
23224
23240
  LlmCapabilities,
23225
23241
  LLM_CAPABILITIES,
23226
23242
  providerSummaryEntryDtoSchema,
23243
+ providerReloadRequestSchema,
23244
+ ProviderReloadErrorReasons,
23245
+ providerReloadResponseDtoSchema,
23227
23246
  integrationSettingsSummaryDtoSchema,
23228
23247
  settingsDtoSchema,
23229
23248
  ProviderBatchRequestOutcomes,
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-VSTKTQPS.js";
8
+ } from "./chunk-5IXQAOVK.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -36,7 +36,6 @@ import {
36
36
  operationalLogListReadSchema,
37
37
  providerBatchConfigSchema,
38
38
  providerPricingSchema,
39
- providerQuotaPolicySchema,
40
39
  resolveProviderModel,
41
40
  restrictedWriteScopes,
42
41
  schedulableRunKindSchema,
@@ -50,7 +49,7 @@ import {
50
49
  skillsClientSchema,
51
50
  upgradeCaveatFor,
52
51
  upgradeCommandFor
53
- } from "./chunk-CYHUZ2JQ.js";
52
+ } from "./chunk-MRKV43TV.js";
54
53
 
55
54
  // src/config.ts
56
55
  import fs from "fs";
@@ -153,6 +152,26 @@ var envSchema = z2.object({
153
152
  CANONRY_RESEARCH_ALLOW_VIEWERS: z2.string().optional(),
154
153
  CANONRY_RESEARCH_VIEWER_DAILY_RUN_LIMIT: z2.coerce.number().int().positive().default(DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT)
155
154
  });
155
+ var BOOTSTRAP_PROVIDER_DEFAULT_MODELS = {
156
+ gemini: "gemini-flash-latest",
157
+ openai: "gpt-5.4",
158
+ claude: "claude-sonnet-4-6",
159
+ perplexity: resolveProviderModel("perplexity", "fast"),
160
+ muse: "muse-spark-1.3",
161
+ local: "llama3"
162
+ };
163
+ var BOOTSTRAP_PROVIDER_DEFAULT_QUOTA = {
164
+ maxConcurrency: 2,
165
+ maxRequestsPerMinute: 10,
166
+ maxRequestsPerDay: 500
167
+ };
168
+ function withBootstrapProviderDefaults(name, entry) {
169
+ return {
170
+ ...entry,
171
+ model: entry.model ?? BOOTSTRAP_PROVIDER_DEFAULT_MODELS[name],
172
+ quota: entry.quota ?? { ...BOOTSTRAP_PROVIDER_DEFAULT_QUOTA }
173
+ };
174
+ }
156
175
  var bootstrapEnvSchema = z2.object({
157
176
  CANONRY_API_KEY: z2.string().optional(),
158
177
  CANONRY_API_URL: z2.string().optional(),
@@ -186,13 +205,9 @@ function getBootstrapEnv(source, overrides) {
186
205
  if (parsed.GEMINI_API_KEY || parsed.GEMINI_VERTEX_PROJECT) {
187
206
  providers.gemini = {
188
207
  apiKey: parsed.GEMINI_API_KEY ?? "",
189
- model: parsed.GEMINI_MODEL || "gemini-flash-latest",
208
+ model: parsed.GEMINI_MODEL || void 0,
190
209
  baseUrl: parsed.GEMINI_BASE_URL,
191
- quota: providerQuotaPolicySchema.parse({
192
- maxConcurrency: 2,
193
- maxRequestsPerMinute: 10,
194
- maxRequestsPerDay: 500
195
- }),
210
+ quota: void 0,
196
211
  vertexProject: parsed.GEMINI_VERTEX_PROJECT,
197
212
  vertexRegion: parsed.GEMINI_VERTEX_REGION,
198
213
  vertexCredentials: parsed.GEMINI_VERTEX_CREDENTIALS
@@ -201,60 +216,41 @@ function getBootstrapEnv(source, overrides) {
201
216
  if (parsed.OPENAI_API_KEY) {
202
217
  providers.openai = {
203
218
  apiKey: parsed.OPENAI_API_KEY,
204
- model: parsed.OPENAI_MODEL || "gpt-5.4",
219
+ model: parsed.OPENAI_MODEL || void 0,
205
220
  baseUrl: parsed.OPENAI_BASE_URL,
206
- quota: providerQuotaPolicySchema.parse({
207
- maxConcurrency: 2,
208
- maxRequestsPerMinute: 10,
209
- maxRequestsPerDay: 500
210
- })
221
+ quota: void 0
211
222
  };
212
223
  }
213
224
  if (parsed.ANTHROPIC_API_KEY) {
214
225
  providers.claude = {
215
226
  apiKey: parsed.ANTHROPIC_API_KEY,
216
- model: parsed.ANTHROPIC_MODEL || "claude-sonnet-4-6",
217
- quota: providerQuotaPolicySchema.parse({
218
- maxConcurrency: 2,
219
- maxRequestsPerMinute: 10,
220
- maxRequestsPerDay: 500
221
- })
227
+ model: parsed.ANTHROPIC_MODEL || void 0,
228
+ quota: void 0
222
229
  };
223
230
  }
224
231
  if (parsed.PERPLEXITY_API_KEY) {
225
232
  providers.perplexity = {
226
233
  apiKey: parsed.PERPLEXITY_API_KEY,
227
- model: resolveProviderModel("perplexity", parsed.PERPLEXITY_MODEL || "fast"),
228
- quota: providerQuotaPolicySchema.parse({
229
- maxConcurrency: 2,
230
- maxRequestsPerMinute: 10,
231
- maxRequestsPerDay: 500
232
- })
234
+ // A retired Sonar name resolves to the Agent API preset that now answers.
235
+ model: parsed.PERPLEXITY_MODEL ? resolveProviderModel("perplexity", parsed.PERPLEXITY_MODEL) : void 0,
236
+ quota: void 0
233
237
  };
234
238
  }
235
239
  const museKey = parsed.MUSE_API_KEY?.trim();
236
240
  if (museKey) {
237
241
  providers.muse = {
238
242
  apiKey: museKey,
239
- model: parsed.MUSE_MODEL?.trim() || "muse-spark-1.3",
243
+ model: parsed.MUSE_MODEL?.trim() || void 0,
240
244
  baseUrl: parsed.MUSE_BASE_URL?.trim() || void 0,
241
- quota: providerQuotaPolicySchema.parse({
242
- maxConcurrency: 2,
243
- maxRequestsPerMinute: 10,
244
- maxRequestsPerDay: 500
245
- })
245
+ quota: void 0
246
246
  };
247
247
  }
248
248
  if (parsed.LOCAL_BASE_URL) {
249
249
  providers.local = {
250
250
  baseUrl: parsed.LOCAL_BASE_URL,
251
251
  apiKey: parsed.LOCAL_API_KEY,
252
- model: parsed.LOCAL_MODEL || "llama3",
253
- quota: providerQuotaPolicySchema.parse({
254
- maxConcurrency: 2,
255
- maxRequestsPerMinute: 10,
256
- maxRequestsPerDay: 500
257
- })
252
+ model: parsed.LOCAL_MODEL || void 0,
253
+ quota: void 0
258
254
  };
259
255
  }
260
256
  return {
@@ -380,8 +376,7 @@ function getConfigDir() {
380
376
  function getConfigPath() {
381
377
  return path.join(getConfigDir(), "config.yaml");
382
378
  }
383
- function loadConfig() {
384
- const configPath = getConfigPath();
379
+ function loadConfig(configPath = getConfigPath()) {
385
380
  if (!fs.existsSync(configPath)) {
386
381
  throw new Error(
387
382
  `Config not found at ${configPath}.
@@ -3176,6 +3171,22 @@ var putApiV1SettingsProvidersByName = (options) => {
3176
3171
  }
3177
3172
  });
3178
3173
  };
3174
+ var postApiV1SettingsProvidersReload = (options) => {
3175
+ return (options?.client ?? client).post({
3176
+ security: [
3177
+ {
3178
+ scheme: "bearer",
3179
+ type: "http"
3180
+ }
3181
+ ],
3182
+ url: "/api/v1/settings/providers/reload",
3183
+ ...options,
3184
+ headers: {
3185
+ "Content-Type": "application/json",
3186
+ ...options?.headers
3187
+ }
3188
+ });
3189
+ };
3179
3190
  var putApiV1SettingsGoogle = (options) => {
3180
3191
  return (options.client ?? client).put({
3181
3192
  security: [
@@ -6572,7 +6583,8 @@ var ApiClient = class {
6572
6583
  throw new CliError({
6573
6584
  code: "CONNECTION_ERROR",
6574
6585
  message: connectionFailureMessage(this.originUrl),
6575
- exitCode: EXIT_SYSTEM_ERROR
6586
+ exitCode: EXIT_SYSTEM_ERROR,
6587
+ details: { connectionUnavailable: true }
6576
6588
  });
6577
6589
  }
6578
6590
  throw new CliError({ code: "CONNECTION_ERROR", message: msg, exitCode: EXIT_SYSTEM_ERROR });
@@ -7634,6 +7646,11 @@ var ApiClient = class {
7634
7646
  () => putApiV1SettingsGoogle({ client: this.heyClient, body })
7635
7647
  );
7636
7648
  }
7649
+ async reloadProviders(body = {}, signal) {
7650
+ return this.invoke(
7651
+ () => postApiV1SettingsProvidersReload({ client: this.heyClient, body, signal })
7652
+ );
7653
+ }
7637
7654
  async createSnapshot(body) {
7638
7655
  return this.invoke(() => postApiV1Snapshot({ client: this.heyClient, body }));
7639
7656
  }
@@ -10000,7 +10017,7 @@ var OPERATIONS_GUIDE = {
10000
10017
  "guidance": "Build the requested summary from stored project overview, organic evidence, and the relevant visibility, measurement, integration, or traffic reads. Retain evidence dates, scope, sample sizes, missing data, and separate mention/citation signals; do not generate fresh runs implicitly."
10001
10018
  }
10002
10019
  },
10003
- "markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `operations`, `prospecting`, `measurement`, `integrations`,\n`reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Compact `nextCursor` completes only `pageList`; use `list` to enumerate\none ranking, markets, observed names or cited domains, preserving filters.\nFirst-page sibling lists are bounded summaries. Keep sample sizes and ties\nvisible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\n### Agent operations\n\nUse `canonry_key_self` (CLI `canonry key whoami --format json`) to inspect the\ncurrent credential's scopes, project boundary, and host-derived `operator`\nauthority without exposing its token. Missing `operator` means unapproved.\n`canonry_settings_get` and\n`canonry_telemetry_get` describe the connected server, not the agent's local\nmachine. Telemetry reports configured preference, effective state, and any\nenvironment override; inspecting status never creates an anonymous identifier.\nAfter approval, `canonry_telemetry_update` changes that preference and\n`canonry_provider_settings_update` changes an already-configured provider's\nmodel/quota. Both require `settings.write`; neither accepts credentials.\nServer telemetry reads and updates additionally require operator authority.\nOrdinary audit-history reads omit internal telemetry events and their state.\n\nOperator authority is deny-by-default and separate from customer admin roles.\nThe deployment owner must approve a dedicated, instance-wide API key's ID in\nthe server environment variable `CANONRY_OPERATOR_KEY_IDS` (comma-separated IDs),\nthen restart the server. Empty/unset approves nobody; wildcards are invalid.\nKeep the bearer private to internal operators; never approve a customer-held or\nshared proxy/bootstrap key. Use `logs.read` for read-only diagnostics, adding\n`settings.write` only when telemetry control is required. Ordinary key creation,\naccount roles, OAuth consent, and caller headers cannot grant operator status.\nRevoking an approved key invalidates it immediately. Host enrollment is a trust\nbootstrap step, intentionally unavailable through customer-facing APIs.\nAPI, CLI, and MCP enforce the same boundary; MCP hides internal tools unless\nthe server confirms operator authority, including in explicit read-only mode.\nProject analytics, research, and normal project permissions are unchanged.\n\n`canonry_logs_list` reads bounded, redacted runtime events from both the\napplication logger and Fastify request/error logging. It requires an\ninstance-wide `logs.read` grant (or wildcard) and a host-approved direct bearer.\nBrowser sessions, OAuth/delegated credentials, customer admins, and project-scoped\nkeys cannot use it, even with a project filter or a matching allowlist ID.\nA `logs.read`-only key is read-only automatically, without a\nsecond `read` marker. Named `*.read` scopes cannot grant mutations; an explicit\nwrite grant is needed and remains subject to its route gates. Returned messages\nare sanitized and bounded; raw request or response bodies, headers, cookies,\nprovider payloads, and stacks are not\npart of the queryable surface. The same secret-redaction policy runs before\nconsole output and storage. Do not deliberately log secrets: redaction is a\ndefense in depth, not permission to put credentials into diagnostic strings.\nOpaque escaped payloads containing secret assignments are omitted when safe\npartial masking cannot be guaranteed; correlate their retained error codes and IDs.\n\nFile-backed hosts retain runtime logs in SQLite across restarts, bounded to\n10,000 events and seven days. In-memory hosts report `retention: \"process\"`.\nFilter by `actor`, `requestId`, `runId`, `projectId`, `module`, `level`, or an\ninclusive `since`/`until` interval. Keep filters unchanged when resuming an\nopaque cursor; retention eviction can invalidate it. Inspect `retentionPolicy`,\n`captureErrors`, `dropped`, `truncated`, and `retention` before drawing\nconclusions. Missing logs are not proof that an action did not happen. Use\n`canonry_project_history` or `canonry_history_global` for persistent audit events;\noffset pages have deterministic ordering but are not snapshots of concurrent writes.\n\nAudit `actor` comes from authenticated identity (`user:<id>` or `api-key:<id>`),\nnot a caller-supplied header. A delegated MCP credential records its originating\nuser as actor and the actual credential in `credentialId`. `requestId` correlates\nHTTP events; `userAgent` and `actorSession` are bounded, untrusted client hints,\nnever identity or permission grants. Older audit rows are not backfilled with\nidentities the server cannot prove.\n\nBoth shipped HTTP hosts issue restart-safe UUID request IDs and return them in\n`x-request-id`. Use that value to correlate a CLI/API failure with log entries;\nHTTP diagnostics retain the method and route template, not raw URL parameters.\nRequest-bound loggers retain completion attribution, while generic background\ncontinuations stop inheriting caller identity after the response completes.\nCapture covers the owning server process after initialization, not arbitrary\nconsole output, other worker processes, or host/container logs. Run one server\ninstance per process and database, as required by the single-tenant deployment\nmodel; this is not a cross-tenant or distributed log collector.\n\nFor CLI use, settings reads are remote. Google setup and telemetry retain their\nlocal defaults: pass `--target server` explicitly to configure the connected\nserver. `schedule list <project>` lists all schedule kinds, and\n`notify events --target server` discovers the server's event catalog.\n\nMCP returns legacy text JSON plus structured results. Objects keep their shape;\narrays use `{items: [...]}` in `structuredContent`, and scalars use `{value: ...}`.\nErrors preserve the existing envelope and CLI exit codes: HTTP 4xx (including\n429 policy limits) use exit 1; HTTP 5xx use exit 2. Server-provided `Retry-After`\nand request IDs are exposed as `retryAfterMs` and `requestId` when available;\nclients do not infer retryability from HTTP 429 or retry automatically.\nFor a write with an ambiguous outcome, inspect saved state or its receipt before\nretrying; a retry hint is not proof that repeating a write is safe.\n\n### Action boundaries\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
10020
+ "markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `operations`, `prospecting`, `measurement`, `integrations`,\n`reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`next` lists stored reads. Optional `actions` lists loaded tools for work that\nrequires approval; listing an action does not authorize or execute it.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Setup:** Page Health needs no answer-engine provider; AI Visibility does.\nAfter a Page Health result on an install with no provider (a `NO_PROVIDER`\nnotice, or doctor's `providers.none-configured`), propose AI Visibility setup\nas the next step. The operator adds the provider key in the dashboard or in\ntheir own terminal; never ask for it in chat.\nRerunning `canonry bootstrap` after a provider change reloads saved provider\nsettings on a matching running local server and reports whether they became\nactive. If the server is offline, start it to apply the saved settings. For an\nexplicit reload of the connected server's own config, use\n`canonry settings reload-providers` or `canonry_providers_reload` with install\nadministrator authority. Remote servers are never reloaded automatically by\nbootstrap, and a local server that belongs to another install is left alone.\nPorts and database settings still need a restart.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Prospecting:** generate a one-shot company snapshot without creating a project.\nInspect stored provider settings first. Agree on the company, domain, selected\nproviders, and queries before starting the quota-spending snapshot action.\nBrowser-only selection requires manual queries. Progressive stdio help offers\nthe discovery toolkit when this connection permits snapshots; load it, then\ncall help again. Fixed catalogs offer only already available actions. Read-only\nand restricted connections must not bypass missing snapshot access.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. For Advanced Property mention rankings, use\n`canonry_measurement_portfolio_summary` and its `mentionRanking.strongest`,\n`.weakest`, and `.excluded` lists. It defaults to non-brand questions; state the\nreturned class and report branded results separately. An unavailable portfolio\naggregate does not invalidate available Property mention rates. Flag excluded\nProperties individually; do not silently replace mention ranking with citation\nranking. Compact `nextCursor` completes only `pageList`; use `list` to enumerate\none ranking, markets, observed names or cited domains, preserving filters.\nFirst-page sibling lists are bounded summaries. Keep sample sizes and ties\nvisible. Preparing a report does not\nauthorize new measurement.\n\n## Authority and approval\n\n### Agent operations\n\nUse `canonry_key_self` (CLI `canonry key whoami --format json`) to inspect the\ncurrent credential's scopes, project boundary, and host-derived `operator`\nauthority without exposing its token. Missing `operator` means unapproved.\n`canonry_settings_get` and\n`canonry_telemetry_get` describe the connected server, not the agent's local\nmachine. Telemetry reports configured preference, effective state, and any\nenvironment override; inspecting status never creates an anonymous identifier.\nAfter approval, `canonry_telemetry_update` changes that preference and\n`canonry_provider_settings_update` changes an already-configured provider's\nmodel/quota. Both require `settings.write`; neither accepts credentials.\nServer telemetry reads and updates additionally require operator authority.\nOrdinary audit-history reads omit internal telemetry events and their state.\n\nOperator authority is deny-by-default and separate from customer admin roles.\nThe deployment owner must approve a dedicated, instance-wide API key's ID in\nthe server environment variable `CANONRY_OPERATOR_KEY_IDS` (comma-separated IDs),\nthen restart the server. Empty/unset approves nobody; wildcards are invalid.\nKeep the bearer private to internal operators; never approve a customer-held or\nshared proxy/bootstrap key. Use `logs.read` for read-only diagnostics, adding\n`settings.write` only when telemetry control is required. Ordinary key creation,\naccount roles, OAuth consent, and caller headers cannot grant operator status.\nRevoking an approved key invalidates it immediately. Host enrollment is a trust\nbootstrap step, intentionally unavailable through customer-facing APIs.\nAPI, CLI, and MCP enforce the same boundary; MCP hides internal tools unless\nthe server confirms operator authority, including in explicit read-only mode.\nProject analytics, research, and normal project permissions are unchanged.\n\n`canonry_logs_list` reads bounded, redacted runtime events from both the\napplication logger and Fastify request/error logging. It requires an\ninstance-wide `logs.read` grant (or wildcard) and a host-approved direct bearer.\nBrowser sessions, OAuth/delegated credentials, customer admins, and project-scoped\nkeys cannot use it, even with a project filter or a matching allowlist ID.\nA `logs.read`-only key is read-only automatically, without a\nsecond `read` marker. Named `*.read` scopes cannot grant mutations; an explicit\nwrite grant is needed and remains subject to its route gates. Returned messages\nare sanitized and bounded; raw request or response bodies, headers, cookies,\nprovider payloads, and stacks are not\npart of the queryable surface. The same secret-redaction policy runs before\nconsole output and storage. Do not deliberately log secrets: redaction is a\ndefense in depth, not permission to put credentials into diagnostic strings.\nOpaque escaped payloads containing secret assignments are omitted when safe\npartial masking cannot be guaranteed; correlate their retained error codes and IDs.\n\nFile-backed hosts retain runtime logs in SQLite across restarts, bounded to\n10,000 events and seven days. In-memory hosts report `retention: \"process\"`.\nFilter by `actor`, `requestId`, `runId`, `projectId`, `module`, `level`, or an\ninclusive `since`/`until` interval. Keep filters unchanged when resuming an\nopaque cursor; retention eviction can invalidate it. Inspect `retentionPolicy`,\n`captureErrors`, `dropped`, `truncated`, and `retention` before drawing\nconclusions. Missing logs are not proof that an action did not happen. Use\n`canonry_project_history` or `canonry_history_global` for persistent audit events;\noffset pages have deterministic ordering but are not snapshots of concurrent writes.\n\nAudit `actor` comes from authenticated identity (`user:<id>` or `api-key:<id>`),\nnot a caller-supplied header. A delegated MCP credential records its originating\nuser as actor and the actual credential in `credentialId`. `requestId` correlates\nHTTP events; `userAgent` and `actorSession` are bounded, untrusted client hints,\nnever identity or permission grants. Older audit rows are not backfilled with\nidentities the server cannot prove.\n\nBoth shipped HTTP hosts issue restart-safe UUID request IDs and return them in\n`x-request-id`. Use that value to correlate a CLI/API failure with log entries;\nHTTP diagnostics retain the method and route template, not raw URL parameters.\nRequest-bound loggers retain completion attribution, while generic background\ncontinuations stop inheriting caller identity after the response completes.\nCapture covers the owning server process after initialization, not arbitrary\nconsole output, other worker processes, or host/container logs. Run one server\ninstance per process and database, as required by the single-tenant deployment\nmodel; this is not a cross-tenant or distributed log collector.\n\nFor CLI use, settings reads are remote. Google setup and telemetry retain their\nlocal defaults: pass `--target server` explicitly to configure the connected\nserver. `schedule list <project>` lists all schedule kinds, and\n`notify events --target server` discovers the server's event catalog.\n\nMCP returns legacy text JSON plus structured results. Objects keep their shape;\narrays use `{items: [...]}` in `structuredContent`, and scalars use `{value: ...}`.\nErrors preserve the existing envelope and CLI exit codes: HTTP 4xx (including\n429 policy limits) use exit 1; HTTP 5xx use exit 2. Server-provided `Retry-After`\nand request IDs are exposed as `retryAfterMs` and `requestId` when available;\nclients do not infer retryability from HTTP 429 or retry automatically.\nFor a write with an ambiguous outcome, inspect saved state or its receipt before\nretrying; a retry hint is not proof that repeating a write is safe.\n\n### Action boundaries\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
10004
10021
  };
10005
10022
 
10006
10023
  // src/mcp/operations-guide.ts
@@ -10561,6 +10578,7 @@ export {
10561
10578
  sentimentInstallReadiness,
10562
10579
  dashboardManagedRunKindsSchema,
10563
10580
  resolveOperatorApiKeyIds,
10581
+ withBootstrapProviderDefaults,
10564
10582
  getBootstrapEnv,
10565
10583
  providerConfigFromEntry,
10566
10584
  adapterSupportsBatch,