@ainyc/canonry 4.31.0 → 4.32.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.
@@ -19,9 +19,10 @@ import {
19
19
  schedulableRunKindSchema,
20
20
  scheduleUpsertRequestSchema,
21
21
  trafficConnectCloudRunRequestSchema,
22
+ trafficConnectVercelRequestSchema,
22
23
  trafficConnectWordpressRequestSchema,
23
24
  trafficEventKindSchema
24
- } from "./chunk-HTNC6AWN.js";
25
+ } from "./chunk-5M4PP6P4.js";
25
26
 
26
27
  // src/config.ts
27
28
  import fs from "fs";
@@ -779,6 +780,13 @@ var ApiClient = class {
779
780
  body
780
781
  );
781
782
  }
783
+ async trafficConnectVercel(project, body) {
784
+ return this.request(
785
+ "POST",
786
+ `/projects/${encodeURIComponent(project)}/traffic/connect/vercel`,
787
+ body
788
+ );
789
+ }
782
790
  async trafficSync(project, sourceId, body) {
783
791
  return this.request(
784
792
  "POST",
@@ -1242,6 +1250,10 @@ var trafficConnectWordpressInputSchema = z2.object({
1242
1250
  project: projectNameSchema,
1243
1251
  request: trafficConnectWordpressRequestSchema
1244
1252
  });
1253
+ var trafficConnectVercelInputSchema = z2.object({
1254
+ project: projectNameSchema,
1255
+ request: trafficConnectVercelRequestSchema
1256
+ });
1245
1257
  var trafficSyncInputSchema = z2.object({
1246
1258
  project: projectNameSchema,
1247
1259
  sourceId: z2.string().min(1).describe("Traffic source ID returned by canonry_traffic_connect_cloud_run or canonry_traffic_sources_list."),
@@ -1878,6 +1890,17 @@ var canonryMcpTools = [
1878
1890
  openApiOperations: ["POST /api/v1/projects/{name}/traffic/connect/wordpress"],
1879
1891
  handler: (client, input) => client.trafficConnectWordpress(input.project, input.request)
1880
1892
  }),
1893
+ defineTool({
1894
+ name: "canonry_traffic_connect_vercel",
1895
+ title: "Connect Vercel traffic source",
1896
+ description: "Connect a Vercel project as a server-side traffic source. Pulls request logs from Vercel's internal request-logs endpoint \u2014 no in-app instrumentation needed. Probes the endpoint with the supplied API token before persisting \u2014 a bad token or wrong project / team id surfaces as a 502 error. Reconnecting updates the existing active Vercel source in place. The API token is stored in ~/.canonry/config.yaml (not the DB) and never echoed back.",
1897
+ access: "write",
1898
+ tier: "traffic",
1899
+ inputSchema: trafficConnectVercelInputSchema,
1900
+ annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
1901
+ openApiOperations: ["POST /api/v1/projects/{name}/traffic/connect/vercel"],
1902
+ handler: (client, input) => client.trafficConnectVercel(input.project, input.request)
1903
+ }),
1881
1904
  defineTool({
1882
1905
  name: "canonry_traffic_sync",
1883
1906
  title: "Sync Cloud Run traffic source",
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  setTelemetrySource,
21
21
  showFirstRunNotice,
22
22
  trackEvent
23
- } from "./chunk-PUTJHEVR.js";
23
+ } from "./chunk-7I65IXVU.js";
24
24
  import {
25
25
  CliError,
26
26
  EXIT_SYSTEM_ERROR,
@@ -36,7 +36,7 @@ import {
36
36
  saveConfig,
37
37
  saveConfigPatch,
38
38
  usageError
39
- } from "./chunk-5STLZRGB.js";
39
+ } from "./chunk-LVX5TOYA.js";
40
40
  import {
41
41
  apiKeys,
42
42
  competitors,
@@ -49,7 +49,7 @@ import {
49
49
  queries,
50
50
  querySnapshots,
51
51
  runs
52
- } from "./chunk-U3YKRV47.js";
52
+ } from "./chunk-LUAJVZVZ.js";
53
53
  import {
54
54
  CcReleaseSyncStatuses,
55
55
  CheckScopes,
@@ -71,7 +71,7 @@ import {
71
71
  providerQuotaPolicySchema,
72
72
  resolveProviderInput,
73
73
  skillsClientSchema
74
- } from "./chunk-HTNC6AWN.js";
74
+ } from "./chunk-5M4PP6P4.js";
75
75
 
76
76
  // src/cli.ts
77
77
  import { pathToFileURL } from "url";
@@ -623,7 +623,7 @@ function readStoredGroundingSources(rawResponse) {
623
623
  return result;
624
624
  }
625
625
  async function backfillInsightsCommand(project, opts) {
626
- const { IntelligenceService } = await import("./intelligence-service-CJONZ7ST.js");
626
+ const { IntelligenceService } = await import("./intelligence-service-RSRWDBHS.js");
627
627
  const config = loadConfig();
628
628
  const db = createClient(config.database);
629
629
  migrate(db);
@@ -3345,6 +3345,84 @@ async function trafficConnectCloudRun(project, opts) {
3345
3345
  console.log("");
3346
3346
  console.log(`Next: canonry traffic sync ${project} --source ${result.id}`);
3347
3347
  }
3348
+ async function trafficConnectVercel(project, opts) {
3349
+ if (!opts.projectId) {
3350
+ throw new CliError({
3351
+ code: "TRAFFIC_VERCEL_PROJECT_ID_REQUIRED",
3352
+ message: "--project-id is required",
3353
+ displayMessage: "Error: --project-id is required (the Vercel project id, e.g. prj_...)",
3354
+ details: { project }
3355
+ });
3356
+ }
3357
+ if (!opts.teamId) {
3358
+ throw new CliError({
3359
+ code: "TRAFFIC_VERCEL_TEAM_ID_REQUIRED",
3360
+ message: "--team-id is required",
3361
+ displayMessage: "Error: --team-id is required (the Vercel team / owner id, e.g. team_...)",
3362
+ details: { project }
3363
+ });
3364
+ }
3365
+ if (opts.token && opts.tokenFile) {
3366
+ throw new CliError({
3367
+ code: "TRAFFIC_VERCEL_TOKEN_CONFLICT",
3368
+ message: "--token and --token-file are mutually exclusive",
3369
+ displayMessage: "Error: pass either --token <token> or --token-file <path>, not both",
3370
+ details: { project }
3371
+ });
3372
+ }
3373
+ let token = opts.token?.trim() ?? "";
3374
+ if (!token && opts.tokenFile) {
3375
+ const fs13 = await import("fs");
3376
+ try {
3377
+ token = fs13.readFileSync(opts.tokenFile, "utf-8").trim();
3378
+ } catch (e) {
3379
+ const msg = e instanceof Error ? e.message : String(e);
3380
+ throw new CliError({
3381
+ code: "TRAFFIC_VERCEL_TOKEN_FILE_READ_ERROR",
3382
+ message: `Failed to read --token-file: ${msg}`,
3383
+ displayMessage: `Error: failed to read --token-file "${opts.tokenFile}": ${msg}`,
3384
+ details: { project, tokenFile: opts.tokenFile }
3385
+ });
3386
+ }
3387
+ }
3388
+ if (!token) {
3389
+ throw new CliError({
3390
+ code: "TRAFFIC_VERCEL_TOKEN_REQUIRED",
3391
+ message: "--token or --token-file is required",
3392
+ displayMessage: "Error: pass --token <token> or --token-file <path>",
3393
+ details: { project }
3394
+ });
3395
+ }
3396
+ if (opts.environment && opts.environment !== "production" && opts.environment !== "preview") {
3397
+ throw new CliError({
3398
+ code: "TRAFFIC_VERCEL_INVALID_ENVIRONMENT",
3399
+ message: '--environment must be "production" or "preview"',
3400
+ displayMessage: 'Error: --environment must be "production" or "preview"',
3401
+ details: { project, environment: opts.environment }
3402
+ });
3403
+ }
3404
+ const client = getClient6();
3405
+ const result = await client.trafficConnectVercel(project, {
3406
+ projectId: opts.projectId,
3407
+ teamId: opts.teamId,
3408
+ token,
3409
+ environment: opts.environment,
3410
+ displayName: opts.displayName
3411
+ });
3412
+ if (opts.format === "json") {
3413
+ console.log(JSON.stringify(result, null, 2));
3414
+ return;
3415
+ }
3416
+ console.log(`Vercel traffic source connected for project "${project}".`);
3417
+ console.log(` Source ID: ${result.id}`);
3418
+ console.log(` Display name: ${result.displayName}`);
3419
+ console.log(` Status: ${result.status}`);
3420
+ console.log(` Project ID: ${result.config.projectId ?? "(unset)"}`);
3421
+ console.log(` Team ID: ${result.config.teamId ?? "(unset)"}`);
3422
+ console.log(` Environment: ${result.config.environment ?? "(unset)"}`);
3423
+ console.log("");
3424
+ console.log(`Next: canonry traffic sync ${project} --source ${result.id}`);
3425
+ }
3348
3426
  async function trafficBackfill(project, opts) {
3349
3427
  if (!opts.source) {
3350
3428
  throw new CliError({
@@ -3626,6 +3704,38 @@ var TRAFFIC_CLI_COMMANDS = [
3626
3704
  });
3627
3705
  }
3628
3706
  },
3707
+ {
3708
+ path: ["traffic", "connect", "vercel"],
3709
+ usage: "canonry traffic connect vercel <project> --project-id <prj> --team-id <team> (--token <token> | --token-file <path>) [--environment production|preview] [--display-name <name>] [--format json]",
3710
+ options: {
3711
+ "project-id": stringOption(),
3712
+ "team-id": stringOption(),
3713
+ token: stringOption(),
3714
+ "token-file": stringOption(),
3715
+ environment: stringOption(),
3716
+ "display-name": stringOption()
3717
+ },
3718
+ run: async (input) => {
3719
+ const project = requireProject(
3720
+ input,
3721
+ "traffic.connect.vercel",
3722
+ "canonry traffic connect vercel <project> --project-id <prj> --team-id <team> (--token <token> | --token-file <path>)"
3723
+ );
3724
+ const projectId = getString(input.values, "project-id");
3725
+ if (!projectId) throw new Error("--project-id is required");
3726
+ const teamId = getString(input.values, "team-id");
3727
+ if (!teamId) throw new Error("--team-id is required");
3728
+ await trafficConnectVercel(project, {
3729
+ projectId,
3730
+ teamId,
3731
+ token: getString(input.values, "token"),
3732
+ tokenFile: getString(input.values, "token-file"),
3733
+ environment: getString(input.values, "environment"),
3734
+ displayName: getString(input.values, "display-name"),
3735
+ format: input.format
3736
+ });
3737
+ }
3738
+ },
3629
3739
  {
3630
3740
  path: ["traffic", "connect"],
3631
3741
  usage: "canonry traffic connect <provider> <project> [args]",
@@ -3633,7 +3743,7 @@ var TRAFFIC_CLI_COMMANDS = [
3633
3743
  unknownSubcommand(input.positionals[0], {
3634
3744
  command: "traffic connect",
3635
3745
  usage: "canonry traffic connect <provider> <project> [args]",
3636
- available: ["cloud-run", "wordpress"]
3746
+ available: ["cloud-run", "wordpress", "vercel"]
3637
3747
  });
3638
3748
  }
3639
3749
  },
package/dist/index.d.ts CHANGED
@@ -107,6 +107,25 @@ interface WordpressTrafficConnectionConfigEntry {
107
107
  interface WordpressTrafficConfigEntry {
108
108
  connections?: WordpressTrafficConnectionConfigEntry[];
109
109
  }
110
+ type VercelTrafficEnvironment = 'production' | 'preview';
111
+ /**
112
+ * Per-project Vercel traffic connection. Authenticates against Vercel's
113
+ * internal `request-logs` endpoint using a Vercel API token. The project id,
114
+ * team id, and environment are non-secret and also mirrored onto the
115
+ * `traffic_sources` row; the token lives only here.
116
+ */
117
+ interface VercelTrafficConnectionConfigEntry {
118
+ projectName: string;
119
+ projectId: string;
120
+ teamId: string;
121
+ token: string;
122
+ environment: VercelTrafficEnvironment;
123
+ createdAt: string;
124
+ updatedAt: string;
125
+ }
126
+ interface VercelTrafficConfigEntry {
127
+ connections?: VercelTrafficConnectionConfigEntry[];
128
+ }
110
129
  interface AgentConfigEntry {
111
130
  /** Agent mode. Only 'disabled' is valid until the native loop ships. */
112
131
  mode?: 'disabled';
@@ -130,6 +149,7 @@ interface CanonryConfig {
130
149
  cloudRun?: CloudRunConfigEntry;
131
150
  wordpress?: WordpressConfigEntry;
132
151
  wordpressTraffic?: WordpressTrafficConfigEntry;
152
+ vercelTraffic?: VercelTrafficConfigEntry;
133
153
  dashboardPasswordHash?: string;
134
154
  telemetry?: boolean;
135
155
  anonymousId?: string;
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-PUTJHEVR.js";
3
+ } from "./chunk-7I65IXVU.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-5STLZRGB.js";
7
- import "./chunk-U3YKRV47.js";
8
- import "./chunk-HTNC6AWN.js";
6
+ } from "./chunk-LVX5TOYA.js";
7
+ import "./chunk-LUAJVZVZ.js";
8
+ import "./chunk-5M4PP6P4.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-U3YKRV47.js";
4
- import "./chunk-HTNC6AWN.js";
3
+ } from "./chunk-LUAJVZVZ.js";
4
+ import "./chunk-5M4PP6P4.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  CliError,
3
3
  canonryMcpTools,
4
4
  createApiClient
5
- } from "./chunk-5STLZRGB.js";
6
- import "./chunk-HTNC6AWN.js";
5
+ } from "./chunk-LVX5TOYA.js";
6
+ import "./chunk-5M4PP6P4.js";
7
7
 
8
8
  // src/mcp/cli.ts
9
9
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.31.0",
3
+ "version": "4.32.0",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -60,23 +60,23 @@
60
60
  "@types/node-cron": "^3.0.11",
61
61
  "tsup": "^8.5.1",
62
62
  "tsx": "^4.19.0",
63
- "@ainyc/canonry-api-routes": "0.0.0",
64
63
  "@ainyc/canonry-config": "0.0.0",
65
- "@ainyc/canonry-contracts": "0.0.0",
66
- "@ainyc/canonry-intelligence": "0.0.0",
64
+ "@ainyc/canonry-api-routes": "0.0.0",
65
+ "@ainyc/canonry-db": "0.0.0",
67
66
  "@ainyc/canonry-integration-bing": "0.0.0",
67
+ "@ainyc/canonry-intelligence": "0.0.0",
68
68
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
69
- "@ainyc/canonry-db": "0.0.0",
69
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
70
70
  "@ainyc/canonry-integration-google": "0.0.0",
71
71
  "@ainyc/canonry-integration-traffic": "0.0.0",
72
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
72
  "@ainyc/canonry-integration-wordpress": "0.0.0",
73
+ "@ainyc/canonry-contracts": "0.0.0",
74
74
  "@ainyc/canonry-provider-cdp": "0.0.0",
75
+ "@ainyc/canonry-provider-gemini": "0.0.0",
75
76
  "@ainyc/canonry-provider-local": "0.0.0",
77
+ "@ainyc/canonry-provider-claude": "0.0.0",
76
78
  "@ainyc/canonry-provider-openai": "0.0.0",
77
- "@ainyc/canonry-provider-gemini": "0.0.0",
78
- "@ainyc/canonry-provider-perplexity": "0.0.0",
79
- "@ainyc/canonry-provider-claude": "0.0.0"
79
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
80
80
  },
81
81
  "scripts": {
82
82
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",