@ainyc/canonry 4.31.0 → 4.33.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/canonry/references/canonry-cli.md +2 -1
- package/assets/assets/{index-C4UBTDDS.js → index-47V0U52s.js} +105 -105
- package/assets/index.html +1 -1
- package/dist/{chunk-5STLZRGB.js → chunk-5EBN7736.js} +24 -1
- package/dist/{chunk-U3YKRV47.js → chunk-BJXHETQW.js} +1 -1
- package/dist/{chunk-PUTJHEVR.js → chunk-JJHBPITI.js} +528 -17
- package/dist/{chunk-HTNC6AWN.js → chunk-XW3F5EEW.js} +113 -81
- package/dist/cli.js +131 -10
- package/dist/index.d.ts +20 -0
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-CJONZ7ST.js → intelligence-service-XKOUBRCE.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +8 -8
|
@@ -300,6 +300,74 @@ var notificationCreateRequestSchema = z3.object({
|
|
|
300
300
|
|
|
301
301
|
// ../contracts/src/project.ts
|
|
302
302
|
import { z as z4 } from "zod";
|
|
303
|
+
|
|
304
|
+
// ../contracts/src/errors.ts
|
|
305
|
+
var AppError = class extends Error {
|
|
306
|
+
code;
|
|
307
|
+
statusCode;
|
|
308
|
+
details;
|
|
309
|
+
constructor(code, message, statusCode, details) {
|
|
310
|
+
super(message);
|
|
311
|
+
this.name = "AppError";
|
|
312
|
+
this.code = code;
|
|
313
|
+
this.statusCode = statusCode;
|
|
314
|
+
this.details = details;
|
|
315
|
+
}
|
|
316
|
+
toJSON() {
|
|
317
|
+
return {
|
|
318
|
+
error: {
|
|
319
|
+
code: this.code,
|
|
320
|
+
message: this.message,
|
|
321
|
+
...this.details ? { details: this.details } : {}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
function notFound(entity, id) {
|
|
327
|
+
return new AppError("NOT_FOUND", `${entity} '${id}' not found`, 404);
|
|
328
|
+
}
|
|
329
|
+
function validationError(message, details) {
|
|
330
|
+
return new AppError("VALIDATION_ERROR", message, 400, details);
|
|
331
|
+
}
|
|
332
|
+
function authRequired() {
|
|
333
|
+
return new AppError("AUTH_REQUIRED", "Authentication required", 401);
|
|
334
|
+
}
|
|
335
|
+
function authInvalid() {
|
|
336
|
+
return new AppError("AUTH_INVALID", "Invalid API key", 401);
|
|
337
|
+
}
|
|
338
|
+
function providerError(message, details) {
|
|
339
|
+
return new AppError("PROVIDER_ERROR", message, 502, details);
|
|
340
|
+
}
|
|
341
|
+
function runInProgress(projectName) {
|
|
342
|
+
return new AppError("RUN_IN_PROGRESS", `A run is already in progress for '${projectName}'`, 409);
|
|
343
|
+
}
|
|
344
|
+
function runNotCancellable(runId, status) {
|
|
345
|
+
return new AppError("RUN_NOT_CANCELLABLE", `Run '${runId}' is already in terminal state '${status}' and cannot be cancelled`, 409);
|
|
346
|
+
}
|
|
347
|
+
function unsupportedKind(kind) {
|
|
348
|
+
return new AppError("UNSUPPORTED_KIND", `Kind '${kind}' is not supported in this version`, 400);
|
|
349
|
+
}
|
|
350
|
+
function notImplemented(message) {
|
|
351
|
+
return new AppError("NOT_IMPLEMENTED", message, 501);
|
|
352
|
+
}
|
|
353
|
+
function deliveryFailed(message) {
|
|
354
|
+
return new AppError("DELIVERY_FAILED", message, 502);
|
|
355
|
+
}
|
|
356
|
+
function agentBusy(projectName) {
|
|
357
|
+
return new AppError(
|
|
358
|
+
"AGENT_BUSY",
|
|
359
|
+
`Aero is already running a turn for '${projectName}'. Retry after the current turn settles.`,
|
|
360
|
+
409
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
function missingDependency(message, details) {
|
|
364
|
+
return new AppError("MISSING_DEPENDENCY", message, 422, details);
|
|
365
|
+
}
|
|
366
|
+
function internalError(message, details) {
|
|
367
|
+
return new AppError("INTERNAL_ERROR", message, 500, details);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// ../contracts/src/project.ts
|
|
303
371
|
var configSourceSchema = z4.enum(["cli", "api", "config-file"]);
|
|
304
372
|
function findDuplicateLocationLabels(locations) {
|
|
305
373
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -317,6 +385,26 @@ function hasLocationLabel(locations, label) {
|
|
|
317
385
|
if (!label) return true;
|
|
318
386
|
return locations.some((location) => location.label === label);
|
|
319
387
|
}
|
|
388
|
+
function resolveLocations(projectLocations, requestedLabels) {
|
|
389
|
+
const normalizedRequest = (requestedLabels ?? []).map((label) => label.trim()).filter((label) => label.length > 0);
|
|
390
|
+
if (normalizedRequest.length === 0) return [...projectLocations];
|
|
391
|
+
const byLabel = new Map(projectLocations.map((loc) => [loc.label.toLowerCase(), loc]));
|
|
392
|
+
const resolved = [];
|
|
393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
394
|
+
for (const label of normalizedRequest) {
|
|
395
|
+
const key = label.toLowerCase();
|
|
396
|
+
if (seen.has(key)) continue;
|
|
397
|
+
const match = byLabel.get(key);
|
|
398
|
+
if (!match) {
|
|
399
|
+
throw validationError(
|
|
400
|
+
`Location "${label}" is not configured for this project. Add it to the project's locations or omit the locations override.`
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
seen.add(key);
|
|
404
|
+
resolved.push(match);
|
|
405
|
+
}
|
|
406
|
+
return resolved;
|
|
407
|
+
}
|
|
320
408
|
var projectUpsertRequestSchema = z4.object({
|
|
321
409
|
displayName: z4.string().min(1),
|
|
322
410
|
canonicalDomain: z4.string().min(1),
|
|
@@ -542,72 +630,6 @@ function resolveConfigSpecQueries(spec) {
|
|
|
542
630
|
return spec.queries ?? spec.keywords ?? [];
|
|
543
631
|
}
|
|
544
632
|
|
|
545
|
-
// ../contracts/src/errors.ts
|
|
546
|
-
var AppError = class extends Error {
|
|
547
|
-
code;
|
|
548
|
-
statusCode;
|
|
549
|
-
details;
|
|
550
|
-
constructor(code, message, statusCode, details) {
|
|
551
|
-
super(message);
|
|
552
|
-
this.name = "AppError";
|
|
553
|
-
this.code = code;
|
|
554
|
-
this.statusCode = statusCode;
|
|
555
|
-
this.details = details;
|
|
556
|
-
}
|
|
557
|
-
toJSON() {
|
|
558
|
-
return {
|
|
559
|
-
error: {
|
|
560
|
-
code: this.code,
|
|
561
|
-
message: this.message,
|
|
562
|
-
...this.details ? { details: this.details } : {}
|
|
563
|
-
}
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
};
|
|
567
|
-
function notFound(entity, id) {
|
|
568
|
-
return new AppError("NOT_FOUND", `${entity} '${id}' not found`, 404);
|
|
569
|
-
}
|
|
570
|
-
function validationError(message, details) {
|
|
571
|
-
return new AppError("VALIDATION_ERROR", message, 400, details);
|
|
572
|
-
}
|
|
573
|
-
function authRequired() {
|
|
574
|
-
return new AppError("AUTH_REQUIRED", "Authentication required", 401);
|
|
575
|
-
}
|
|
576
|
-
function authInvalid() {
|
|
577
|
-
return new AppError("AUTH_INVALID", "Invalid API key", 401);
|
|
578
|
-
}
|
|
579
|
-
function providerError(message, details) {
|
|
580
|
-
return new AppError("PROVIDER_ERROR", message, 502, details);
|
|
581
|
-
}
|
|
582
|
-
function runInProgress(projectName) {
|
|
583
|
-
return new AppError("RUN_IN_PROGRESS", `A run is already in progress for '${projectName}'`, 409);
|
|
584
|
-
}
|
|
585
|
-
function runNotCancellable(runId, status) {
|
|
586
|
-
return new AppError("RUN_NOT_CANCELLABLE", `Run '${runId}' is already in terminal state '${status}' and cannot be cancelled`, 409);
|
|
587
|
-
}
|
|
588
|
-
function unsupportedKind(kind) {
|
|
589
|
-
return new AppError("UNSUPPORTED_KIND", `Kind '${kind}' is not supported in this version`, 400);
|
|
590
|
-
}
|
|
591
|
-
function notImplemented(message) {
|
|
592
|
-
return new AppError("NOT_IMPLEMENTED", message, 501);
|
|
593
|
-
}
|
|
594
|
-
function deliveryFailed(message) {
|
|
595
|
-
return new AppError("DELIVERY_FAILED", message, 502);
|
|
596
|
-
}
|
|
597
|
-
function agentBusy(projectName) {
|
|
598
|
-
return new AppError(
|
|
599
|
-
"AGENT_BUSY",
|
|
600
|
-
`Aero is already running a turn for '${projectName}'. Retry after the current turn settles.`,
|
|
601
|
-
409
|
|
602
|
-
);
|
|
603
|
-
}
|
|
604
|
-
function missingDependency(message, details) {
|
|
605
|
-
return new AppError("MISSING_DEPENDENCY", message, 422, details);
|
|
606
|
-
}
|
|
607
|
-
function internalError(message, details) {
|
|
608
|
-
return new AppError("INTERNAL_ERROR", message, 500, details);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
633
|
// ../contracts/src/google.ts
|
|
612
634
|
import { z as z6 } from "zod";
|
|
613
635
|
var googleConnectionTypeSchema = z6.enum(["gsc", "ga4"]);
|
|
@@ -2442,7 +2464,15 @@ var DISCOVERY_MAX_PROBES_CAP = 500;
|
|
|
2442
2464
|
var discoveryRunRequestSchema = z21.object({
|
|
2443
2465
|
icpDescription: z21.string().min(1).optional(),
|
|
2444
2466
|
dedupThreshold: z21.number().min(0).max(1).optional(),
|
|
2445
|
-
maxProbes: z21.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional()
|
|
2467
|
+
maxProbes: z21.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional(),
|
|
2468
|
+
/**
|
|
2469
|
+
* Optional override of the project's location labels, constraining seed
|
|
2470
|
+
* generation to a subset of the configured service areas. Each label must
|
|
2471
|
+
* match a configured project location (resolved server-side via
|
|
2472
|
+
* `resolveLocations`). Omitted means "use every project location" — a
|
|
2473
|
+
* project with no locations is unaffected.
|
|
2474
|
+
*/
|
|
2475
|
+
locations: z21.array(z21.string().min(1)).optional()
|
|
2446
2476
|
});
|
|
2447
2477
|
var discoveryPromoteRequestSchema = z21.object({
|
|
2448
2478
|
buckets: z21.array(discoveryBucketSchema).min(1).optional(),
|
|
@@ -2614,20 +2644,6 @@ export {
|
|
|
2614
2644
|
getProviderLocationHandling,
|
|
2615
2645
|
notificationEventSchema,
|
|
2616
2646
|
notificationCreateRequestSchema,
|
|
2617
|
-
findDuplicateLocationLabels,
|
|
2618
|
-
hasLocationLabel,
|
|
2619
|
-
projectUpsertRequestSchema,
|
|
2620
|
-
queryBatchRequestSchema,
|
|
2621
|
-
keywordBatchRequestSchema,
|
|
2622
|
-
queryGenerateRequestSchema,
|
|
2623
|
-
keywordGenerateRequestSchema,
|
|
2624
|
-
competitorBatchRequestSchema,
|
|
2625
|
-
normalizeProjectDomain,
|
|
2626
|
-
registrableDomain,
|
|
2627
|
-
brandLabelFromDomain,
|
|
2628
|
-
effectiveDomains,
|
|
2629
|
-
projectConfigSchema,
|
|
2630
|
-
resolveConfigSpecQueries,
|
|
2631
2647
|
AppError,
|
|
2632
2648
|
notFound,
|
|
2633
2649
|
validationError,
|
|
@@ -2642,6 +2658,21 @@ export {
|
|
|
2642
2658
|
agentBusy,
|
|
2643
2659
|
missingDependency,
|
|
2644
2660
|
internalError,
|
|
2661
|
+
findDuplicateLocationLabels,
|
|
2662
|
+
hasLocationLabel,
|
|
2663
|
+
resolveLocations,
|
|
2664
|
+
projectUpsertRequestSchema,
|
|
2665
|
+
queryBatchRequestSchema,
|
|
2666
|
+
keywordBatchRequestSchema,
|
|
2667
|
+
queryGenerateRequestSchema,
|
|
2668
|
+
keywordGenerateRequestSchema,
|
|
2669
|
+
competitorBatchRequestSchema,
|
|
2670
|
+
normalizeProjectDomain,
|
|
2671
|
+
registrableDomain,
|
|
2672
|
+
brandLabelFromDomain,
|
|
2673
|
+
effectiveDomains,
|
|
2674
|
+
projectConfigSchema,
|
|
2675
|
+
resolveConfigSpecQueries,
|
|
2645
2676
|
wordpressEnvSchema,
|
|
2646
2677
|
AgentProviderIds,
|
|
2647
2678
|
AGENT_PROVIDER_IDS,
|
|
@@ -2705,6 +2736,7 @@ export {
|
|
|
2705
2736
|
VerificationStatuses,
|
|
2706
2737
|
trafficConnectCloudRunRequestSchema,
|
|
2707
2738
|
trafficConnectWordpressRequestSchema,
|
|
2739
|
+
trafficConnectVercelRequestSchema,
|
|
2708
2740
|
trafficEventKindSchema,
|
|
2709
2741
|
TrafficEventKinds,
|
|
2710
2742
|
discoveryBucketSchema,
|
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
setTelemetrySource,
|
|
21
21
|
showFirstRunNotice,
|
|
22
22
|
trackEvent
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-JJHBPITI.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-
|
|
39
|
+
} from "./chunk-5EBN7736.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-
|
|
52
|
+
} from "./chunk-BJXHETQW.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-
|
|
74
|
+
} from "./chunk-XW3F5EEW.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-
|
|
626
|
+
const { IntelligenceService } = await import("./intelligence-service-XKOUBRCE.js");
|
|
627
627
|
const config = loadConfig();
|
|
628
628
|
const db = createClient(config.database);
|
|
629
629
|
migrate(db);
|
|
@@ -1971,6 +1971,7 @@ function buildRunBody(opts, icpDescription) {
|
|
|
1971
1971
|
if (icpDescription) body.icpDescription = icpDescription;
|
|
1972
1972
|
if (opts.dedupThreshold !== void 0) body.dedupThreshold = opts.dedupThreshold;
|
|
1973
1973
|
if (opts.maxProbes !== void 0) body.maxProbes = opts.maxProbes;
|
|
1974
|
+
if (opts.locations && opts.locations.length > 0) body.locations = opts.locations;
|
|
1974
1975
|
return body;
|
|
1975
1976
|
}
|
|
1976
1977
|
function resolveIcpAngles(opts) {
|
|
@@ -2241,6 +2242,12 @@ Usage: ${usage}`, {
|
|
|
2241
2242
|
}
|
|
2242
2243
|
return parsed;
|
|
2243
2244
|
}
|
|
2245
|
+
function parseLocationsOption(values) {
|
|
2246
|
+
const raw = getStringArray(values, "locations");
|
|
2247
|
+
if (!raw || raw.length === 0) return void 0;
|
|
2248
|
+
const expanded = raw.flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
|
|
2249
|
+
return expanded.length > 0 ? expanded : void 0;
|
|
2250
|
+
}
|
|
2244
2251
|
function parseBucketsOption(values, usage) {
|
|
2245
2252
|
const raw = getStringArray(values, "bucket");
|
|
2246
2253
|
if (!raw || raw.length === 0) return void 0;
|
|
@@ -2307,20 +2314,22 @@ Usage: ${usage}`,
|
|
|
2307
2314
|
var DISCOVER_CLI_COMMANDS = [
|
|
2308
2315
|
{
|
|
2309
2316
|
path: ["discover", "run"],
|
|
2310
|
-
usage: 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]',
|
|
2317
|
+
usage: 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]',
|
|
2311
2318
|
options: {
|
|
2312
2319
|
icp: stringOption(),
|
|
2313
2320
|
"icp-angle": multiStringOption(),
|
|
2321
|
+
locations: multiStringOption(),
|
|
2314
2322
|
"dedup-threshold": stringOption(),
|
|
2315
2323
|
"max-probes": stringOption(),
|
|
2316
2324
|
wait: { type: "boolean", default: false }
|
|
2317
2325
|
},
|
|
2318
2326
|
run: async (input) => {
|
|
2319
|
-
const usage = 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]';
|
|
2327
|
+
const usage = 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]';
|
|
2320
2328
|
const project = requireProject(input, "discover.run", usage);
|
|
2321
2329
|
await discoverRun(project, {
|
|
2322
2330
|
icp: getString(input.values, "icp"),
|
|
2323
2331
|
icpAngles: getStringArray(input.values, "icp-angle"),
|
|
2332
|
+
locations: parseLocationsOption(input.values),
|
|
2324
2333
|
dedupThreshold: parseFloatOption(input.values, "dedup-threshold", usage),
|
|
2325
2334
|
maxProbes: parseIntegerOption(input, "max-probes", {
|
|
2326
2335
|
command: "discover.run",
|
|
@@ -2334,20 +2343,22 @@ var DISCOVER_CLI_COMMANDS = [
|
|
|
2334
2343
|
},
|
|
2335
2344
|
{
|
|
2336
2345
|
path: ["discover", "seed"],
|
|
2337
|
-
usage: 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]',
|
|
2346
|
+
usage: 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]',
|
|
2338
2347
|
options: {
|
|
2339
2348
|
icp: stringOption(),
|
|
2340
2349
|
"icp-angle": multiStringOption(),
|
|
2350
|
+
locations: multiStringOption(),
|
|
2341
2351
|
"dedup-threshold": stringOption(),
|
|
2342
2352
|
"max-probes": stringOption(),
|
|
2343
2353
|
wait: { type: "boolean", default: false }
|
|
2344
2354
|
},
|
|
2345
2355
|
run: async (input) => {
|
|
2346
|
-
const usage = 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]';
|
|
2356
|
+
const usage = 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.85] [--max-probes 100] [--wait] [--format json]';
|
|
2347
2357
|
const project = requireProject(input, "discover.seed", usage);
|
|
2348
2358
|
await discoverSeed(project, {
|
|
2349
2359
|
icp: getString(input.values, "icp"),
|
|
2350
2360
|
icpAngles: getStringArray(input.values, "icp-angle"),
|
|
2361
|
+
locations: parseLocationsOption(input.values),
|
|
2351
2362
|
dedupThreshold: parseFloatOption(input.values, "dedup-threshold", usage),
|
|
2352
2363
|
maxProbes: parseIntegerOption(input, "max-probes", {
|
|
2353
2364
|
command: "discover.seed",
|
|
@@ -3345,6 +3356,84 @@ async function trafficConnectCloudRun(project, opts) {
|
|
|
3345
3356
|
console.log("");
|
|
3346
3357
|
console.log(`Next: canonry traffic sync ${project} --source ${result.id}`);
|
|
3347
3358
|
}
|
|
3359
|
+
async function trafficConnectVercel(project, opts) {
|
|
3360
|
+
if (!opts.projectId) {
|
|
3361
|
+
throw new CliError({
|
|
3362
|
+
code: "TRAFFIC_VERCEL_PROJECT_ID_REQUIRED",
|
|
3363
|
+
message: "--project-id is required",
|
|
3364
|
+
displayMessage: "Error: --project-id is required (the Vercel project id, e.g. prj_...)",
|
|
3365
|
+
details: { project }
|
|
3366
|
+
});
|
|
3367
|
+
}
|
|
3368
|
+
if (!opts.teamId) {
|
|
3369
|
+
throw new CliError({
|
|
3370
|
+
code: "TRAFFIC_VERCEL_TEAM_ID_REQUIRED",
|
|
3371
|
+
message: "--team-id is required",
|
|
3372
|
+
displayMessage: "Error: --team-id is required (the Vercel team / owner id, e.g. team_...)",
|
|
3373
|
+
details: { project }
|
|
3374
|
+
});
|
|
3375
|
+
}
|
|
3376
|
+
if (opts.token && opts.tokenFile) {
|
|
3377
|
+
throw new CliError({
|
|
3378
|
+
code: "TRAFFIC_VERCEL_TOKEN_CONFLICT",
|
|
3379
|
+
message: "--token and --token-file are mutually exclusive",
|
|
3380
|
+
displayMessage: "Error: pass either --token <token> or --token-file <path>, not both",
|
|
3381
|
+
details: { project }
|
|
3382
|
+
});
|
|
3383
|
+
}
|
|
3384
|
+
let token = opts.token?.trim() ?? "";
|
|
3385
|
+
if (!token && opts.tokenFile) {
|
|
3386
|
+
const fs13 = await import("fs");
|
|
3387
|
+
try {
|
|
3388
|
+
token = fs13.readFileSync(opts.tokenFile, "utf-8").trim();
|
|
3389
|
+
} catch (e) {
|
|
3390
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
3391
|
+
throw new CliError({
|
|
3392
|
+
code: "TRAFFIC_VERCEL_TOKEN_FILE_READ_ERROR",
|
|
3393
|
+
message: `Failed to read --token-file: ${msg}`,
|
|
3394
|
+
displayMessage: `Error: failed to read --token-file "${opts.tokenFile}": ${msg}`,
|
|
3395
|
+
details: { project, tokenFile: opts.tokenFile }
|
|
3396
|
+
});
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
if (!token) {
|
|
3400
|
+
throw new CliError({
|
|
3401
|
+
code: "TRAFFIC_VERCEL_TOKEN_REQUIRED",
|
|
3402
|
+
message: "--token or --token-file is required",
|
|
3403
|
+
displayMessage: "Error: pass --token <token> or --token-file <path>",
|
|
3404
|
+
details: { project }
|
|
3405
|
+
});
|
|
3406
|
+
}
|
|
3407
|
+
if (opts.environment && opts.environment !== "production" && opts.environment !== "preview") {
|
|
3408
|
+
throw new CliError({
|
|
3409
|
+
code: "TRAFFIC_VERCEL_INVALID_ENVIRONMENT",
|
|
3410
|
+
message: '--environment must be "production" or "preview"',
|
|
3411
|
+
displayMessage: 'Error: --environment must be "production" or "preview"',
|
|
3412
|
+
details: { project, environment: opts.environment }
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
const client = getClient6();
|
|
3416
|
+
const result = await client.trafficConnectVercel(project, {
|
|
3417
|
+
projectId: opts.projectId,
|
|
3418
|
+
teamId: opts.teamId,
|
|
3419
|
+
token,
|
|
3420
|
+
environment: opts.environment,
|
|
3421
|
+
displayName: opts.displayName
|
|
3422
|
+
});
|
|
3423
|
+
if (opts.format === "json") {
|
|
3424
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3425
|
+
return;
|
|
3426
|
+
}
|
|
3427
|
+
console.log(`Vercel traffic source connected for project "${project}".`);
|
|
3428
|
+
console.log(` Source ID: ${result.id}`);
|
|
3429
|
+
console.log(` Display name: ${result.displayName}`);
|
|
3430
|
+
console.log(` Status: ${result.status}`);
|
|
3431
|
+
console.log(` Project ID: ${result.config.projectId ?? "(unset)"}`);
|
|
3432
|
+
console.log(` Team ID: ${result.config.teamId ?? "(unset)"}`);
|
|
3433
|
+
console.log(` Environment: ${result.config.environment ?? "(unset)"}`);
|
|
3434
|
+
console.log("");
|
|
3435
|
+
console.log(`Next: canonry traffic sync ${project} --source ${result.id}`);
|
|
3436
|
+
}
|
|
3348
3437
|
async function trafficBackfill(project, opts) {
|
|
3349
3438
|
if (!opts.source) {
|
|
3350
3439
|
throw new CliError({
|
|
@@ -3626,6 +3715,38 @@ var TRAFFIC_CLI_COMMANDS = [
|
|
|
3626
3715
|
});
|
|
3627
3716
|
}
|
|
3628
3717
|
},
|
|
3718
|
+
{
|
|
3719
|
+
path: ["traffic", "connect", "vercel"],
|
|
3720
|
+
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]",
|
|
3721
|
+
options: {
|
|
3722
|
+
"project-id": stringOption(),
|
|
3723
|
+
"team-id": stringOption(),
|
|
3724
|
+
token: stringOption(),
|
|
3725
|
+
"token-file": stringOption(),
|
|
3726
|
+
environment: stringOption(),
|
|
3727
|
+
"display-name": stringOption()
|
|
3728
|
+
},
|
|
3729
|
+
run: async (input) => {
|
|
3730
|
+
const project = requireProject(
|
|
3731
|
+
input,
|
|
3732
|
+
"traffic.connect.vercel",
|
|
3733
|
+
"canonry traffic connect vercel <project> --project-id <prj> --team-id <team> (--token <token> | --token-file <path>)"
|
|
3734
|
+
);
|
|
3735
|
+
const projectId = getString(input.values, "project-id");
|
|
3736
|
+
if (!projectId) throw new Error("--project-id is required");
|
|
3737
|
+
const teamId = getString(input.values, "team-id");
|
|
3738
|
+
if (!teamId) throw new Error("--team-id is required");
|
|
3739
|
+
await trafficConnectVercel(project, {
|
|
3740
|
+
projectId,
|
|
3741
|
+
teamId,
|
|
3742
|
+
token: getString(input.values, "token"),
|
|
3743
|
+
tokenFile: getString(input.values, "token-file"),
|
|
3744
|
+
environment: getString(input.values, "environment"),
|
|
3745
|
+
displayName: getString(input.values, "display-name"),
|
|
3746
|
+
format: input.format
|
|
3747
|
+
});
|
|
3748
|
+
}
|
|
3749
|
+
},
|
|
3629
3750
|
{
|
|
3630
3751
|
path: ["traffic", "connect"],
|
|
3631
3752
|
usage: "canonry traffic connect <provider> <project> [args]",
|
|
@@ -3633,7 +3754,7 @@ var TRAFFIC_CLI_COMMANDS = [
|
|
|
3633
3754
|
unknownSubcommand(input.positionals[0], {
|
|
3634
3755
|
command: "traffic connect",
|
|
3635
3756
|
usage: "canonry traffic connect <provider> <project> [args]",
|
|
3636
|
-
available: ["cloud-run", "wordpress"]
|
|
3757
|
+
available: ["cloud-run", "wordpress", "vercel"]
|
|
3637
3758
|
});
|
|
3638
3759
|
}
|
|
3639
3760
|
},
|
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-
|
|
3
|
+
} from "./chunk-JJHBPITI.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-5EBN7736.js";
|
|
7
|
+
import "./chunk-BJXHETQW.js";
|
|
8
|
+
import "./chunk-XW3F5EEW.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
CliError,
|
|
3
3
|
canonryMcpTools,
|
|
4
4
|
createApiClient
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-5EBN7736.js";
|
|
6
|
+
import "./chunk-XW3F5EEW.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.
|
|
3
|
+
"version": "4.33.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",
|
|
@@ -61,22 +61,22 @@
|
|
|
61
61
|
"tsup": "^8.5.1",
|
|
62
62
|
"tsx": "^4.19.0",
|
|
63
63
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
64
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
65
64
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
66
65
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
67
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
68
|
-
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
69
66
|
"@ainyc/canonry-db": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
72
71
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
73
72
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
74
73
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
75
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
77
74
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
76
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
78
77
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
79
|
-
"@ainyc/canonry-provider-
|
|
78
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
79
|
+
"@ainyc/canonry-provider-local": "0.0.0"
|
|
80
80
|
},
|
|
81
81
|
"scripts": {
|
|
82
82
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|