@ainyc/canonry 4.100.1 → 4.101.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 (23) hide show
  1. package/assets/assets/{BacklinksPage-v2RC8wlg.js → BacklinksPage-aysk_iGy.js} +1 -1
  2. package/assets/assets/{ChartPrimitives-B74e5pqn.js → ChartPrimitives-CmKqxndA.js} +1 -1
  3. package/assets/assets/ProjectPage-dduZrrBr.js +7 -0
  4. package/assets/assets/{RunRow-BmVPjO-m.js → RunRow-Ba77hJ4d.js} +1 -1
  5. package/assets/assets/{RunsPage-CK5atXvL.js → RunsPage-D3IAdQMB.js} +1 -1
  6. package/assets/assets/{SettingsPage-DarPFUPl.js → SettingsPage-Y54JtLw-.js} +1 -1
  7. package/assets/assets/{TrafficPage-Ddnn_WqU.js → TrafficPage-DawzPWdt.js} +1 -1
  8. package/assets/assets/{TrafficSourceDetailPage-g08SKnwZ.js → TrafficSourceDetailPage-DAhQwFVb.js} +1 -1
  9. package/assets/assets/{arrow-left-D39Vxasb.js → arrow-left-NsJbgqmV.js} +1 -1
  10. package/assets/assets/{extract-error-message-BiNWqBeh.js → extract-error-message-u00ggxeK.js} +1 -1
  11. package/assets/assets/{index-Dd4J1VhB.js → index-4YArcfwj.js} +64 -64
  12. package/assets/assets/{trash-2-xh6gsnap.js → trash-2-BBdbbe60.js} +1 -1
  13. package/assets/index.html +1 -1
  14. package/dist/{chunk-IDI6LMYL.js → chunk-2YPVK75M.js} +6 -2
  15. package/dist/{chunk-YBIT5O62.js → chunk-AV3DHH6B.js} +142 -4
  16. package/dist/{chunk-JF7EXHGA.js → chunk-HUL5FUBD.js} +6 -0
  17. package/dist/{chunk-ALJSES3X.js → chunk-O3SFVGDF.js} +531 -49
  18. package/dist/cli.js +26 -8
  19. package/dist/index.js +4 -4
  20. package/dist/{intelligence-service-TWCEKVKZ.js → intelligence-service-R6QJ3KC2.js} +2 -2
  21. package/dist/mcp.js +2 -2
  22. package/package.json +6 -6
  23. package/assets/assets/ProjectPage-BCzS7TQn.js +0 -6
@@ -1 +1 @@
1
- import{c}from"./index-Dd4J1VhB.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
1
+ import{c}from"./index-4YArcfwj.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-Dd4J1VhB.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-4YArcfwj.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Be8JdV5M.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-CQ77EO2y.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-C9EZkgbP.js">
@@ -24,7 +24,7 @@ import {
24
24
  trafficConnectVercelRequestSchema,
25
25
  trafficConnectWordpressRequestSchema,
26
26
  trafficEventKindSchema
27
- } from "./chunk-JF7EXHGA.js";
27
+ } from "./chunk-HUL5FUBD.js";
28
28
 
29
29
  // src/config.ts
30
30
  import fs from "fs";
@@ -6997,6 +6997,9 @@ var canonryMcpTools = [
6997
6997
  var CANONRY_MCP_TOOL_COUNT = canonryMcpTools.length;
6998
6998
  var CANONRY_MCP_READ_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.access === "read").length;
6999
6999
  var CANONRY_MCP_CORE_TOOL_COUNT = canonryMcpTools.filter((tool) => tool.tier === "core").length;
7000
+ var CanonryMcpToolNames = Object.freeze(
7001
+ Object.fromEntries(canonryMcpTools.map((tool) => [tool.name, tool.name]))
7002
+ );
7000
7003
 
7001
7004
  export {
7002
7005
  getConfigDir,
@@ -7016,5 +7019,6 @@ export {
7016
7019
  createApiClient,
7017
7020
  ApiClient,
7018
7021
  PACKAGE_VERSION,
7019
- canonryMcpTools
7022
+ canonryMcpTools,
7023
+ CanonryMcpToolNames
7020
7024
  };
@@ -263,7 +263,7 @@ import {
263
263
  wordpressSchemaDeployResultDtoSchema,
264
264
  wordpressSchemaStatusResultDtoSchema,
265
265
  wordpressStatusDtoSchema
266
- } from "./chunk-JF7EXHGA.js";
266
+ } from "./chunk-HUL5FUBD.js";
267
267
 
268
268
  // src/intelligence-service.ts
269
269
  import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
@@ -284,6 +284,7 @@ __export(schema_exports, {
284
284
  adsInsightsDaily: () => adsInsightsDaily,
285
285
  agentMemory: () => agentMemory,
286
286
  agentSessions: () => agentSessions,
287
+ agentToolEvents: () => agentToolEvents,
287
288
  aiReferralEventsHourly: () => aiReferralEventsHourly,
288
289
  aiUserFetchEventsHourly: () => aiUserFetchEventsHourly,
289
290
  apiKeys: () => apiKeys,
@@ -321,6 +322,7 @@ __export(schema_exports, {
321
322
  gscUrlInspections: () => gscUrlInspections,
322
323
  healthSnapshots: () => healthSnapshots,
323
324
  insights: () => insights,
325
+ llmUsageEvents: () => llmUsageEvents,
324
326
  migrationsTable: () => migrationsTable,
325
327
  notifications: () => notifications,
326
328
  projects: () => projects,
@@ -924,6 +926,53 @@ var agentMemory = sqliteTable("agent_memory", {
924
926
  uniqueIndex("uniq_agent_memory_project_key").on(table.projectId, table.key),
925
927
  index("idx_agent_memory_project_updated").on(table.projectId, table.updatedAt)
926
928
  ]);
929
+ var llmUsageEvents = sqliteTable("llm_usage_events", {
930
+ id: text("id").primaryKey(),
931
+ projectId: text("project_id").references(() => projects.id, { onDelete: "cascade" }),
932
+ runId: text("run_id").references(() => runs.id, { onDelete: "set null" }),
933
+ agentSessionId: text("agent_session_id").references(() => agentSessions.id, { onDelete: "set null" }),
934
+ feature: text("feature").notNull(),
935
+ provider: text("provider").notNull(),
936
+ model: text("model").notNull(),
937
+ responseId: text("response_id"),
938
+ inputTokens: integer("input_tokens").notNull().default(0),
939
+ outputTokens: integer("output_tokens").notNull().default(0),
940
+ cacheReadTokens: integer("cache_read_tokens").notNull().default(0),
941
+ cacheWriteTokens: integer("cache_write_tokens").notNull().default(0),
942
+ totalTokens: integer("total_tokens").notNull().default(0),
943
+ costMillicents: integer("cost_millicents").notNull().default(0),
944
+ promptFamily: text("prompt_family"),
945
+ promptVersion: text("prompt_version"),
946
+ metadata: text("metadata", { mode: "json" }).$type(),
947
+ createdAt: text("created_at").notNull()
948
+ }, (table) => [
949
+ index("idx_llm_usage_project_created").on(table.projectId, table.createdAt),
950
+ index("idx_llm_usage_feature_created").on(table.feature, table.createdAt),
951
+ index("idx_llm_usage_session_created").on(table.agentSessionId, table.createdAt),
952
+ index("idx_llm_usage_run_created").on(table.runId, table.createdAt)
953
+ ]);
954
+ var agentToolEvents = sqliteTable("agent_tool_events", {
955
+ id: text("id").primaryKey(),
956
+ projectId: text("project_id").references(() => projects.id, { onDelete: "cascade" }),
957
+ agentSessionId: text("agent_session_id").references(() => agentSessions.id, { onDelete: "set null" }),
958
+ toolCallId: text("tool_call_id").notNull(),
959
+ toolName: text("tool_name").notNull(),
960
+ assistantResponseId: text("assistant_response_id"),
961
+ provider: text("provider"),
962
+ model: text("model"),
963
+ status: text("status").notNull(),
964
+ durationMs: integer("duration_ms").notNull().default(0),
965
+ argsBytes: integer("args_bytes").notNull().default(0),
966
+ resultTextChars: integer("result_text_chars").notNull().default(0),
967
+ resultBytes: integer("result_bytes").notNull().default(0),
968
+ metadata: text("metadata", { mode: "json" }).$type(),
969
+ createdAt: text("created_at").notNull()
970
+ }, (table) => [
971
+ index("idx_agent_tool_events_project_created").on(table.projectId, table.createdAt),
972
+ index("idx_agent_tool_events_session_created").on(table.agentSessionId, table.createdAt),
973
+ index("idx_agent_tool_events_tool_created").on(table.toolName, table.createdAt),
974
+ index("idx_agent_tool_events_status_created").on(table.status, table.createdAt)
975
+ ]);
927
976
  var trafficSources = sqliteTable("traffic_sources", {
928
977
  id: text("id").primaryKey(),
929
978
  projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
@@ -3211,6 +3260,63 @@ var MIGRATION_VERSIONS = [
3211
3260
  `ALTER TABLE ads_insights_daily ADD COLUMN conversions INTEGER NOT NULL DEFAULT 0`,
3212
3261
  `ALTER TABLE ads_connections ADD COLUMN conversion_tracking_configured INTEGER NOT NULL DEFAULT 0`
3213
3262
  ]
3263
+ },
3264
+ {
3265
+ version: 84,
3266
+ name: "llm-usage-events",
3267
+ statements: [
3268
+ `CREATE TABLE IF NOT EXISTS llm_usage_events (
3269
+ id TEXT PRIMARY KEY,
3270
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
3271
+ run_id TEXT REFERENCES runs(id) ON DELETE SET NULL,
3272
+ agent_session_id TEXT REFERENCES agent_sessions(id) ON DELETE SET NULL,
3273
+ feature TEXT NOT NULL,
3274
+ provider TEXT NOT NULL,
3275
+ model TEXT NOT NULL,
3276
+ response_id TEXT,
3277
+ input_tokens INTEGER NOT NULL DEFAULT 0,
3278
+ output_tokens INTEGER NOT NULL DEFAULT 0,
3279
+ cache_read_tokens INTEGER NOT NULL DEFAULT 0,
3280
+ cache_write_tokens INTEGER NOT NULL DEFAULT 0,
3281
+ total_tokens INTEGER NOT NULL DEFAULT 0,
3282
+ cost_millicents INTEGER NOT NULL DEFAULT 0,
3283
+ prompt_family TEXT,
3284
+ prompt_version TEXT,
3285
+ metadata TEXT,
3286
+ created_at TEXT NOT NULL
3287
+ )`,
3288
+ `CREATE INDEX IF NOT EXISTS idx_llm_usage_project_created ON llm_usage_events(project_id, created_at)`,
3289
+ `CREATE INDEX IF NOT EXISTS idx_llm_usage_feature_created ON llm_usage_events(feature, created_at)`,
3290
+ `CREATE INDEX IF NOT EXISTS idx_llm_usage_session_created ON llm_usage_events(agent_session_id, created_at)`,
3291
+ `CREATE INDEX IF NOT EXISTS idx_llm_usage_run_created ON llm_usage_events(run_id, created_at)`
3292
+ ]
3293
+ },
3294
+ {
3295
+ version: 85,
3296
+ name: "agent-tool-events",
3297
+ statements: [
3298
+ `CREATE TABLE IF NOT EXISTS agent_tool_events (
3299
+ id TEXT PRIMARY KEY,
3300
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
3301
+ agent_session_id TEXT REFERENCES agent_sessions(id) ON DELETE SET NULL,
3302
+ tool_call_id TEXT NOT NULL,
3303
+ tool_name TEXT NOT NULL,
3304
+ assistant_response_id TEXT,
3305
+ provider TEXT,
3306
+ model TEXT,
3307
+ status TEXT NOT NULL,
3308
+ duration_ms INTEGER NOT NULL DEFAULT 0,
3309
+ args_bytes INTEGER NOT NULL DEFAULT 0,
3310
+ result_text_chars INTEGER NOT NULL DEFAULT 0,
3311
+ result_bytes INTEGER NOT NULL DEFAULT 0,
3312
+ metadata TEXT,
3313
+ created_at TEXT NOT NULL
3314
+ )`,
3315
+ `CREATE INDEX IF NOT EXISTS idx_agent_tool_events_project_created ON agent_tool_events(project_id, created_at)`,
3316
+ `CREATE INDEX IF NOT EXISTS idx_agent_tool_events_session_created ON agent_tool_events(agent_session_id, created_at)`,
3317
+ `CREATE INDEX IF NOT EXISTS idx_agent_tool_events_tool_created ON agent_tool_events(tool_name, created_at)`,
3318
+ `CREATE INDEX IF NOT EXISTS idx_agent_tool_events_status_created ON agent_tool_events(status, created_at)`
3319
+ ]
3214
3320
  }
3215
3321
  ];
3216
3322
  function rebuildBacklinkTableWithSource(tx, table) {
@@ -7736,6 +7842,10 @@ async function analyticsRoutes(app) {
7736
7842
  }));
7737
7843
  const projectQueries = app.db.select({ id: queries.id, createdAt: queries.createdAt }).from(queries).where(eq10(queries.projectId, project.id)).all();
7738
7844
  const queryCreatedAt = new Map(projectQueries.map((q) => [q.id, q.createdAt]));
7845
+ const mentionShareCompetitors = app.db.select({ domain: competitors.domain }).from(competitors).where(eq10(competitors.projectId, project.id)).all().map((c) => ({
7846
+ domain: c.domain,
7847
+ brandTokens: [brandLabelFromDomain(c.domain)].filter((t) => t.length >= 3)
7848
+ }));
7739
7849
  const overall = computeProviderMetric(allSnapshots);
7740
7850
  const byProvider = {};
7741
7851
  const providers = new Set(allSnapshots.map((s) => s.provider));
@@ -7746,7 +7856,7 @@ async function analyticsRoutes(app) {
7746
7856
  const latest = new Date(projectRuns[projectRuns.length - 1].createdAt);
7747
7857
  const spanDays = Math.max(1, Math.ceil((latest.getTime() - earliest.getTime()) / 864e5));
7748
7858
  const bucketSize = bucketSizeForSpan(spanDays);
7749
- const buckets = computeBuckets(allSnapshots, projectRuns, bucketSize, queryCreatedAt);
7859
+ const buckets = computeBuckets(allSnapshots, projectRuns, bucketSize, queryCreatedAt, mentionShareCompetitors);
7750
7860
  const trend = computeTrend(buckets, "citationRate");
7751
7861
  const mentionTrend = computeTrend(buckets, "mentionRate");
7752
7862
  const queryChanges = computeQueryChanges(projectQueries, cutoff);
@@ -7993,7 +8103,7 @@ function computeProviderMetric(snapshots) {
7993
8103
  mentionedCount
7994
8104
  };
7995
8105
  }
7996
- function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
8106
+ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt, mentionShareCompetitors = []) {
7997
8107
  if (projectRuns.length === 0) return [];
7998
8108
  const earliest = new Date(projectRuns[0].createdAt);
7999
8109
  const latest = new Date(projectRuns[projectRuns.length - 1].createdAt);
@@ -8030,6 +8140,7 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
8030
8140
  queryCount,
8031
8141
  mentionRate: metric.mentionRate,
8032
8142
  mentionedCount: metric.mentionedCount,
8143
+ mentionShare: computeMentionShareBucketMetric(usable, mentionShareCompetitors),
8033
8144
  byProvider
8034
8145
  });
8035
8146
  }
@@ -8037,6 +8148,26 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
8037
8148
  }
8038
8149
  return buckets;
8039
8150
  }
8151
+ function computeMentionShareBucketMetric(snapshots, mentionShareCompetitors) {
8152
+ if (mentionShareCompetitors.length === 0) {
8153
+ return { rate: null, projectMentionSnapshots: 0, competitorMentionSnapshots: 0 };
8154
+ }
8155
+ const result = buildMentionShare(
8156
+ snapshots.map((s) => ({
8157
+ projectMentioned: s.resolvedMentioned,
8158
+ answerText: s.answerText
8159
+ })),
8160
+ { competitors: mentionShareCompetitors }
8161
+ );
8162
+ const projectMentionSnapshots = result.breakdown.projectMentionSnapshots;
8163
+ const competitorMentionSnapshots = result.breakdown.competitorMentionSnapshots;
8164
+ const denominator = projectMentionSnapshots + competitorMentionSnapshots;
8165
+ return {
8166
+ rate: denominator > 0 ? round4(projectMentionSnapshots / denominator) : null,
8167
+ projectMentionSnapshots,
8168
+ competitorMentionSnapshots
8169
+ };
8170
+ }
8040
8171
  function computeQueryChanges(projectQueries, cutoff) {
8041
8172
  const byDay = /* @__PURE__ */ new Map();
8042
8173
  for (const q of projectQueries) {
@@ -17992,7 +18123,7 @@ var canonryLocalRouteCatalog = [
17992
18123
  method: "post",
17993
18124
  path: "/api/v1/projects/{name}/agent/prompt",
17994
18125
  summary: "Send a prompt to Aero and stream events back as SSE",
17995
- description: 'Posts a prompt into the project\'s Aero session and streams `AgentEvent` frames as `text/event-stream`. Each frame is `data: <JSON>\\n\\n`. The server brackets the stream with `{"type":"stream_open"}` and `{"type":"stream_close"}` control frames; `{"type":"error","message":"..."}` surfaces in-stream failures without collapsing the stream. Returns 409 `AGENT_BUSY` if another turn is already in flight for this project. Body field `scope` accepts "all" | "read-only"; omitted defaults to "read-only" (safe dashboard surface). The CLI passes "all" to keep write tools available.',
18126
+ description: 'Posts a prompt into the project\'s Aero session and streams `AgentEvent` frames as `text/event-stream`. Each frame is `data: <JSON>\\n\\n`. The server brackets the stream with `{"type":"stream_open"}` and `{"type":"stream_close"}` control frames; `{"type":"error","message":"..."}` surfaces in-stream failures without collapsing the stream. Returns 409 `AGENT_BUSY` if another turn is already in flight for this project. Body field `scope` accepts "all" | "read-only"; omitted defaults to "read-only" (safe dashboard surface). Body field `profile` accepts "default" | "ads-operator"; omitted keeps the default full Canonry operator surface. The CLI passes "all" to keep write tools available.',
17996
18127
  tags: ["agent"],
17997
18128
  parameters: [nameParameter],
17998
18129
  requestBody: {
@@ -18017,6 +18148,11 @@ var canonryLocalRouteCatalog = [
18017
18148
  type: "string",
18018
18149
  enum: ["all", "read-only"],
18019
18150
  description: 'Tool surface scope. Default "read-only". Set "all" to enable write tools.'
18151
+ },
18152
+ profile: {
18153
+ type: "string",
18154
+ enum: ["default", "ads-operator"],
18155
+ description: 'Tool profile. Default "default". Set "ads-operator" to use the narrower ads SaaS operator surface plus the ads context tool.'
18020
18156
  }
18021
18157
  }
18022
18158
  }
@@ -35195,6 +35331,8 @@ export {
35195
35331
  backlinkDomains,
35196
35332
  backlinkSummaries,
35197
35333
  agentMemory,
35334
+ llmUsageEvents,
35335
+ agentToolEvents,
35198
35336
  crawlerEventsHourly,
35199
35337
  aiUserFetchEventsHourly,
35200
35338
  rawEventSamples,
@@ -2531,6 +2531,11 @@ var providerMetricSchema = z19.object({
2531
2531
  mentionRate: z19.number(),
2532
2532
  mentionedCount: z19.number().int()
2533
2533
  });
2534
+ var mentionShareBucketMetricSchema = z19.object({
2535
+ rate: z19.number().nullable(),
2536
+ projectMentionSnapshots: z19.number().int().nonnegative(),
2537
+ competitorMentionSnapshots: z19.number().int().nonnegative()
2538
+ });
2534
2539
  var timeBucketSchema = z19.object({
2535
2540
  startDate: z19.string(),
2536
2541
  endDate: z19.string(),
@@ -2540,6 +2545,7 @@ var timeBucketSchema = z19.object({
2540
2545
  queryCount: z19.number().int(),
2541
2546
  mentionRate: z19.number(),
2542
2547
  mentionedCount: z19.number().int(),
2548
+ mentionShare: mentionShareBucketMetricSchema,
2543
2549
  byProvider: z19.record(z19.string(), providerMetricSchema)
2544
2550
  });
2545
2551
  var queryChangeEventSchema = z19.object({