@ainyc/canonry 4.14.0 → 4.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/assets/index.html CHANGED
@@ -12,8 +12,8 @@
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-B6Mi9Fd1.js"></script>
16
- <link rel="stylesheet" crossorigin href="./assets/index-D0EPNRDs.css">
15
+ <script type="module" crossorigin src="./assets/index-Qq_oMI-C.js"></script>
16
+ <link rel="stylesheet" crossorigin href="./assets/index-C1WW21tz.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="root"></div>
@@ -11,8 +11,10 @@ import {
11
11
  queryBatchRequestSchema,
12
12
  queryGenerateRequestSchema,
13
13
  runTriggerRequestSchema,
14
- scheduleUpsertRequestSchema
15
- } from "./chunk-6QTH5NS5.js";
14
+ scheduleUpsertRequestSchema,
15
+ trafficConnectCloudRunRequestSchema,
16
+ trafficEventKindSchema
17
+ } from "./chunk-ONI3TX2A.js";
16
18
 
17
19
  // src/config.ts
18
20
  import fs from "fs";
@@ -768,6 +770,37 @@ var ApiClient = class {
768
770
  body ?? {}
769
771
  );
770
772
  }
773
+ async trafficListSources(project) {
774
+ return this.request(
775
+ "GET",
776
+ `/projects/${encodeURIComponent(project)}/traffic/sources`
777
+ );
778
+ }
779
+ async trafficStatus(project) {
780
+ return this.request(
781
+ "GET",
782
+ `/projects/${encodeURIComponent(project)}/traffic/status`
783
+ );
784
+ }
785
+ async trafficGetSource(project, sourceId) {
786
+ return this.request(
787
+ "GET",
788
+ `/projects/${encodeURIComponent(project)}/traffic/sources/${encodeURIComponent(sourceId)}`
789
+ );
790
+ }
791
+ async trafficListEvents(project, params) {
792
+ const search = {};
793
+ if (params?.since) search.since = params.since;
794
+ if (params?.until) search.until = params.until;
795
+ if (params?.kind) search.kind = params.kind;
796
+ if (params?.limit !== void 0) search.limit = String(params.limit);
797
+ if (params?.sourceId) search.sourceId = params.sourceId;
798
+ const qs = Object.keys(search).length ? "?" + new URLSearchParams(search).toString() : "";
799
+ return this.request(
800
+ "GET",
801
+ `/projects/${encodeURIComponent(project)}/traffic/events${qs}`
802
+ );
803
+ }
771
804
  async wordpressConnect(project, body) {
772
805
  return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/connect`, body);
773
806
  }
@@ -1141,6 +1174,27 @@ var memoryForgetInputSchema = z2.object({
1141
1174
  project: projectNameSchema,
1142
1175
  key: z2.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH).describe("Exact key of the note to remove. No-op (status=missing) when no note exists for that key.")
1143
1176
  });
1177
+ var trafficConnectCloudRunInputSchema = z2.object({
1178
+ project: projectNameSchema,
1179
+ request: trafficConnectCloudRunRequestSchema
1180
+ });
1181
+ var trafficSyncInputSchema = z2.object({
1182
+ project: projectNameSchema,
1183
+ sourceId: z2.string().min(1).describe("Traffic source ID returned by canonry_traffic_connect_cloud_run or canonry_traffic_sources_list."),
1184
+ sinceMinutes: z2.number().int().positive().max(7 * 24 * 60).optional().describe("Lookback window in minutes. Defaults to the source's configured window (60 min) when omitted; clamped forward to lastSyncedAt to avoid double-counting.")
1185
+ });
1186
+ var trafficEventsInputSchema = z2.object({
1187
+ project: projectNameSchema,
1188
+ since: z2.string().optional().describe("ISO 8601 lower bound. Defaults to 24h ago when omitted."),
1189
+ until: z2.string().optional().describe("ISO 8601 upper bound. Defaults to now when omitted."),
1190
+ kind: z2.union([trafficEventKindSchema, z2.literal("all")]).optional().describe('Filter to "crawler" or "ai-referral"; "all" (default) returns both.'),
1191
+ sourceId: z2.string().min(1).optional().describe("Restrict to a single traffic source ID."),
1192
+ limit: z2.number().int().positive().max(5e3).optional().describe("Max combined rows. Defaults to 500, max 5000. Totals always reflect the full window.")
1193
+ });
1194
+ var trafficSourceIdInputSchema = z2.object({
1195
+ project: projectNameSchema,
1196
+ sourceId: z2.string().min(1).describe("Traffic source ID.")
1197
+ });
1144
1198
  var AGENT_WEBHOOK_EVENTS = [
1145
1199
  notificationEventSchema.enum["run.completed"],
1146
1200
  notificationEventSchema.enum["insight.critical"],
@@ -1653,6 +1707,80 @@ var canonryMcpTools = [
1653
1707
  openApiOperations: ["GET /api/v1/projects/{name}/ga/session-history"],
1654
1708
  handler: (client, input) => client.gaSessionHistory(input.project, compactStringParams(input, ["window"]))
1655
1709
  }),
1710
+ defineTool({
1711
+ name: "canonry_traffic_sources_list",
1712
+ title: "List traffic sources",
1713
+ description: "List server-side traffic sources for a Canonry project (Cloud Run, etc.). Returns non-archived sources with status, last sync timestamp, last error, and the stored config (gcpProjectId, serviceName, location, authMode). Pair with canonry_traffic_source_get for last-24h totals on a single source.",
1714
+ access: "read",
1715
+ tier: "traffic",
1716
+ inputSchema: projectInputSchema,
1717
+ annotations: readAnnotations(),
1718
+ openApiOperations: ["GET /api/v1/projects/{name}/traffic/sources"],
1719
+ handler: (client, input) => client.trafficListSources(input.project)
1720
+ }),
1721
+ defineTool({
1722
+ name: "canonry_traffic_source_get",
1723
+ title: "Get traffic source detail",
1724
+ description: "Get one traffic source plus 24h totals (crawler hits, AI-referral hits, raw event sample count) and the latest traffic-sync run summary. Use to confirm a source is healthy and observing traffic before drilling into events.",
1725
+ access: "read",
1726
+ tier: "traffic",
1727
+ inputSchema: trafficSourceIdInputSchema,
1728
+ annotations: readAnnotations(),
1729
+ openApiOperations: ["GET /api/v1/projects/{name}/traffic/sources/{id}"],
1730
+ handler: (client, input) => client.trafficGetSource(input.project, input.sourceId)
1731
+ }),
1732
+ defineTool({
1733
+ name: "canonry_traffic_status",
1734
+ title: "Traffic status (all sources)",
1735
+ description: "Single-call composite returning every non-archived traffic source plus its last-24h totals (crawler hits, AI-referral hits, sample count) and latest source-scoped traffic-sync run. Same per-entry shape as canonry_traffic_source_get, but one call covers all sources \u2014 prefer this over a list+per-source fan-out.",
1736
+ access: "read",
1737
+ tier: "traffic",
1738
+ inputSchema: projectInputSchema,
1739
+ annotations: readAnnotations(),
1740
+ openApiOperations: ["GET /api/v1/projects/{name}/traffic/status"],
1741
+ handler: (client, input) => client.trafficStatus(input.project)
1742
+ }),
1743
+ defineTool({
1744
+ name: "canonry_traffic_events",
1745
+ title: "List traffic events",
1746
+ description: 'Read crawler and AI-referral hourly rollups from server-side traffic sources. Returns a discriminated list (kind="crawler" rows carry botId/operator/verificationStatus; kind="ai-referral" rows carry product/sourceDomain/evidenceType) plus totals over the full window even when limit truncates rows. Window defaults to last 24h.',
1747
+ access: "read",
1748
+ tier: "traffic",
1749
+ inputSchema: trafficEventsInputSchema,
1750
+ annotations: readAnnotations(),
1751
+ openApiOperations: ["GET /api/v1/projects/{name}/traffic/events"],
1752
+ handler: (client, input) => {
1753
+ const params = {};
1754
+ if (input.since) params.since = input.since;
1755
+ if (input.until) params.until = input.until;
1756
+ if (input.kind) params.kind = input.kind;
1757
+ if (input.sourceId) params.sourceId = input.sourceId;
1758
+ if (input.limit !== void 0) params.limit = input.limit;
1759
+ return client.trafficListEvents(input.project, params);
1760
+ }
1761
+ }),
1762
+ defineTool({
1763
+ name: "canonry_traffic_connect_cloud_run",
1764
+ title: "Connect Cloud Run traffic source",
1765
+ description: "Connect a Google Cloud Run service as a server-side traffic source. v1 requires service-account JSON content (paste the file contents into `keyJson`); OAuth-mode is not yet supported. Reconnecting an existing source updates the credential and config in place. The private key is stored in ~/.canonry/config.yaml (not the DB) and never echoed back.",
1766
+ access: "write",
1767
+ tier: "traffic",
1768
+ inputSchema: trafficConnectCloudRunInputSchema,
1769
+ annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
1770
+ openApiOperations: ["POST /api/v1/projects/{name}/traffic/connect/cloud-run"],
1771
+ handler: (client, input) => client.trafficConnectCloudRun(input.project, input.request)
1772
+ }),
1773
+ defineTool({
1774
+ name: "canonry_traffic_sync",
1775
+ title: "Sync Cloud Run traffic source",
1776
+ description: "Pull the most recent Cloud Logging entries for a Cloud Run traffic source, classify them as crawler / AI-referral / unknown, and upsert hourly rollups + raw samples. Returns totals, bucket counts, and the run id. The window auto-clamps forward to lastSyncedAt to avoid double-counting on back-to-back calls.",
1777
+ access: "write",
1778
+ tier: "traffic",
1779
+ inputSchema: trafficSyncInputSchema,
1780
+ annotations: writeAnnotations({ idempotentHint: false, openWorldHint: true }),
1781
+ openApiOperations: ["POST /api/v1/projects/{name}/traffic/sources/{id}/sync"],
1782
+ handler: (client, input) => client.trafficSync(input.project, input.sourceId, input.sinceMinutes !== void 0 ? { sinceMinutes: input.sinceMinutes } : void 0)
1783
+ }),
1656
1784
  defineTool({
1657
1785
  name: "canonry_project_upsert",
1658
1786
  title: "Create or replace project",
@@ -1959,6 +2087,7 @@ export {
1959
2087
  getConfigDir,
1960
2088
  getConfigPath,
1961
2089
  loadConfig,
2090
+ loadConfigRaw,
1962
2091
  saveConfig,
1963
2092
  saveConfigPatch,
1964
2093
  configExists,