@ainyc/canonry 4.105.0 → 4.106.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 +1 -0
- package/assets/assets/{BacklinksPage-Kls1x7Zh.js → BacklinksPage-CBmXc-I8.js} +1 -1
- package/assets/assets/{ChartPrimitives-DteNu5zR.js → ChartPrimitives-Sl2xFVla.js} +1 -1
- package/assets/assets/{ProjectPage-edkqv28l.js → ProjectPage-CwPd7SMA.js} +1 -1
- package/assets/assets/{RunRow-DSQNNTkL.js → RunRow-StjPY-W-.js} +1 -1
- package/assets/assets/{RunsPage-CNlAmkea.js → RunsPage-C4z3tX5G.js} +1 -1
- package/assets/assets/{SettingsPage-CbZCrj9s.js → SettingsPage-DwgWiTFo.js} +1 -1
- package/assets/assets/{TrafficPage-BA27Ssn7.js → TrafficPage-CF0sdg6i.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-ObEEBBgZ.js → TrafficSourceDetailPage-9y4px0yp.js} +1 -1
- package/assets/assets/{arrow-left-C6gsO8Mi.js → arrow-left-Clk2AKwp.js} +1 -1
- package/assets/assets/{extract-error-message-C8UnfNTz.js → extract-error-message-Ccitgmu-.js} +1 -1
- package/assets/assets/{index-BFQXjVBq.js → index-wC-7udKS.js} +39 -39
- package/assets/assets/{trash-2-CX3yohiP.js → trash-2-CgxrJFpf.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-XRKGLZF6.js → chunk-2AWATO4I.js} +50 -7
- package/dist/{chunk-UCKUZCIM.js → chunk-F3MKVMS5.js} +62 -13
- package/dist/{chunk-IDSJTITA.js → chunk-VGMTLUUM.js} +4 -2
- package/dist/{chunk-LZW4ABXX.js → chunk-VOR5ZTUU.js} +50 -1
- package/dist/cli.js +21 -8
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-UBGH5QF4.js → intelligence-service-JGZU27U3.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./index-
|
|
1
|
+
import{c}from"./index-wC-7udKS.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-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-wC-7udKS.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">
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-VGMTLUUM.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -115,7 +115,7 @@ import {
|
|
|
115
115
|
siteAuditPages,
|
|
116
116
|
siteAuditSnapshots,
|
|
117
117
|
usageCounters
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-F3MKVMS5.js";
|
|
119
119
|
import {
|
|
120
120
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
121
121
|
AGENT_PROVIDER_IDS,
|
|
@@ -178,7 +178,7 @@ import {
|
|
|
178
178
|
validationError,
|
|
179
179
|
winnabilityClassLabel,
|
|
180
180
|
withRetry
|
|
181
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-VOR5ZTUU.js";
|
|
182
182
|
|
|
183
183
|
// src/telemetry.ts
|
|
184
184
|
import crypto from "crypto";
|
|
@@ -5506,6 +5506,42 @@ import crypto13 from "crypto";
|
|
|
5506
5506
|
import { and as and9, eq as eq11 } from "drizzle-orm";
|
|
5507
5507
|
var log12 = createLogger("DiscoveryRun");
|
|
5508
5508
|
var DEFAULT_SEED_COUNT = 30;
|
|
5509
|
+
var EMBED_RETRY_MAX_RETRIES = 3;
|
|
5510
|
+
var EMBED_RETRY_MAX_DELAY_MS = 1e4;
|
|
5511
|
+
var EMBED_ATTEMPT_TIMEOUT_MS = 6e4;
|
|
5512
|
+
function withAttemptTimeout(promise, timeoutMs, label) {
|
|
5513
|
+
return new Promise((resolve, reject) => {
|
|
5514
|
+
const timer = setTimeout(
|
|
5515
|
+
() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
|
|
5516
|
+
timeoutMs
|
|
5517
|
+
);
|
|
5518
|
+
promise.then(
|
|
5519
|
+
(value) => {
|
|
5520
|
+
clearTimeout(timer);
|
|
5521
|
+
resolve(value);
|
|
5522
|
+
},
|
|
5523
|
+
(err) => {
|
|
5524
|
+
clearTimeout(timer);
|
|
5525
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
5526
|
+
}
|
|
5527
|
+
);
|
|
5528
|
+
});
|
|
5529
|
+
}
|
|
5530
|
+
async function embedWithRetry(fn, opts = {}) {
|
|
5531
|
+
const attemptTimeoutMs = opts.attemptTimeoutMs ?? EMBED_ATTEMPT_TIMEOUT_MS;
|
|
5532
|
+
return withRetry(
|
|
5533
|
+
() => withAttemptTimeout(fn(), attemptTimeoutMs, "Discovery embedding call"),
|
|
5534
|
+
{
|
|
5535
|
+
maxRetries: opts.maxRetries ?? EMBED_RETRY_MAX_RETRIES,
|
|
5536
|
+
isRetryable: isRetryableHttpError,
|
|
5537
|
+
maxDelayMs: EMBED_RETRY_MAX_DELAY_MS,
|
|
5538
|
+
sleep: opts.sleep,
|
|
5539
|
+
onRetry: opts.onRetry ?? (({ attempt, delayMs }) => {
|
|
5540
|
+
log12.warn("discovery.embed.retry", { attempt, delayMs });
|
|
5541
|
+
})
|
|
5542
|
+
}
|
|
5543
|
+
);
|
|
5544
|
+
}
|
|
5509
5545
|
var QUERIES_PER_INTENT_BUCKET = 6;
|
|
5510
5546
|
async function executeDiscoveryRun(opts) {
|
|
5511
5547
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -5538,6 +5574,7 @@ async function executeDiscoveryRun(opts) {
|
|
|
5538
5574
|
icpDescription: opts.icpDescription,
|
|
5539
5575
|
dedupThreshold: opts.dedupThreshold,
|
|
5540
5576
|
maxProbes: opts.maxProbes,
|
|
5577
|
+
probeConcurrency: opts.probeConcurrency,
|
|
5541
5578
|
locations: opts.locations,
|
|
5542
5579
|
deps
|
|
5543
5580
|
});
|
|
@@ -5592,12 +5629,17 @@ function buildDefaultDeps(registry) {
|
|
|
5592
5629
|
const fromGrounding = normalized.searchQueries ?? [];
|
|
5593
5630
|
return {
|
|
5594
5631
|
candidates: [...fromAnswer, ...fromGrounding],
|
|
5595
|
-
provider: "gemini"
|
|
5632
|
+
provider: "gemini",
|
|
5633
|
+
// Session diagnostics: the raw-candidate split by source, persisted on
|
|
5634
|
+
// discovery_sessions so seed-quality calibration is measurable.
|
|
5635
|
+
fromAnswerCount: fromAnswer.length,
|
|
5636
|
+
fromGroundingCount: fromGrounding.length
|
|
5596
5637
|
};
|
|
5597
5638
|
},
|
|
5598
5639
|
async embed(queries2) {
|
|
5599
|
-
|
|
5600
|
-
|
|
5640
|
+
const apiKey = cfg.apiKey;
|
|
5641
|
+
if (apiKey) {
|
|
5642
|
+
return embedWithRetry(() => embedQueries(queries2, { apiKey, baseUrl: cfg.baseUrl }));
|
|
5601
5643
|
}
|
|
5602
5644
|
throw new Error("Discovery currently requires a Gemini API key. Vertex-mode embeddings are not yet implemented.");
|
|
5603
5645
|
},
|
|
@@ -6431,7 +6473,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
6431
6473
|
return result;
|
|
6432
6474
|
}
|
|
6433
6475
|
async function backfillInsightsCommand(project, opts) {
|
|
6434
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
6476
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-JGZU27U3.js");
|
|
6435
6477
|
const config = loadConfig();
|
|
6436
6478
|
const db = createClient(config.database);
|
|
6437
6479
|
migrate(db);
|
|
@@ -11898,6 +11940,7 @@ async function createServer(opts) {
|
|
|
11898
11940
|
icpDescription: input.icpDescription,
|
|
11899
11941
|
dedupThreshold: input.dedupThreshold,
|
|
11900
11942
|
maxProbes: input.maxProbes,
|
|
11943
|
+
probeConcurrency: input.probeConcurrency,
|
|
11901
11944
|
locations: input.locations
|
|
11902
11945
|
}).then(() => runCoordinator.onRunCompleted(input.runId, input.projectId)).catch((err) => {
|
|
11903
11946
|
app.log.error({ runId: input.runId, err }, "Discovery run failed");
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
DEFAULT_DISCOVERY_PROMOTE_BUCKETS,
|
|
14
14
|
DEFAULT_DISCOVERY_PROMOTE_COMPETITOR_TYPES,
|
|
15
15
|
DISCOVERY_DEFAULT_DEDUP_THRESHOLD,
|
|
16
|
+
DISCOVERY_DEFAULT_PROBE_CONCURRENCY,
|
|
17
|
+
DISCOVERY_PROBE_CONCURRENCY_CAP,
|
|
16
18
|
DISCOVERY_PROMOTE_COMPETITOR_CAP,
|
|
17
19
|
DISCOVERY_PROMOTE_COMPETITOR_MIN_HITS,
|
|
18
20
|
DiscoveryBuckets,
|
|
@@ -171,6 +173,7 @@ import {
|
|
|
171
173
|
keywordGenerateRequestSchema,
|
|
172
174
|
latestProjectRunDtoSchema,
|
|
173
175
|
locationContextSchema,
|
|
176
|
+
mapWithConcurrency,
|
|
174
177
|
mentionStateFromAnswerMentioned,
|
|
175
178
|
missingDependency,
|
|
176
179
|
normalizeProjectAliases,
|
|
@@ -264,7 +267,7 @@ import {
|
|
|
264
267
|
wordpressSchemaDeployResultDtoSchema,
|
|
265
268
|
wordpressSchemaStatusResultDtoSchema,
|
|
266
269
|
wordpressStatusDtoSchema
|
|
267
|
-
} from "./chunk-
|
|
270
|
+
} from "./chunk-VOR5ZTUU.js";
|
|
268
271
|
|
|
269
272
|
// src/intelligence-service.ts
|
|
270
273
|
import { eq as eq38, desc as desc18, asc as asc6, and as and28, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
|
|
@@ -1133,6 +1136,11 @@ var discoverySessions = sqliteTable("discovery_sessions", {
|
|
|
1133
1136
|
seedProvider: text("seed_provider"),
|
|
1134
1137
|
seedCountRaw: integer("seed_count_raw"),
|
|
1135
1138
|
seedCount: integer("seed_count"),
|
|
1139
|
+
// Diagnostics: split of the raw seed candidates by source — the model's
|
|
1140
|
+
// answer text vs. the grounding fan-out (issued search queries). Recorded at
|
|
1141
|
+
// seed time; nullable for legacy sessions. No gate/warning math reads these.
|
|
1142
|
+
seedFromAnswerCount: integer("seed_from_answer_count"),
|
|
1143
|
+
seedFromGroundingCount: integer("seed_from_grounding_count"),
|
|
1136
1144
|
dedupThreshold: real("dedup_threshold"),
|
|
1137
1145
|
probeCount: integer("probe_count"),
|
|
1138
1146
|
citedCount: integer("cited_count"),
|
|
@@ -3370,6 +3378,18 @@ var MIGRATION_VERSIONS = [
|
|
|
3370
3378
|
`ALTER TABLE api_keys ADD COLUMN project_id TEXT REFERENCES projects(id) ON DELETE CASCADE`,
|
|
3371
3379
|
`CREATE INDEX IF NOT EXISTS idx_api_keys_project ON api_keys(project_id)`
|
|
3372
3380
|
]
|
|
3381
|
+
},
|
|
3382
|
+
{
|
|
3383
|
+
version: 88,
|
|
3384
|
+
name: "discovery-session-seed-source-counts",
|
|
3385
|
+
statements: [
|
|
3386
|
+
// Diagnostics: split of raw seed candidates by source (answer text vs.
|
|
3387
|
+
// grounding fan-out), recorded at seed time. Nullable — legacy sessions
|
|
3388
|
+
// stay null. ALTER ADD COLUMN is idempotent (the runner swallows the
|
|
3389
|
+
// duplicate-column error on retry).
|
|
3390
|
+
`ALTER TABLE discovery_sessions ADD COLUMN seed_from_answer_count INTEGER`,
|
|
3391
|
+
`ALTER TABLE discovery_sessions ADD COLUMN seed_from_grounding_count INTEGER`
|
|
3392
|
+
]
|
|
3373
3393
|
}
|
|
3374
3394
|
];
|
|
3375
3395
|
function rebuildBacklinkTableWithSource(tx, table) {
|
|
@@ -18025,7 +18045,7 @@ var routeCatalog = [
|
|
|
18025
18045
|
method: "post",
|
|
18026
18046
|
path: "/api/v1/projects/{name}/discover/run",
|
|
18027
18047
|
summary: "Start a tracked-basket discovery session",
|
|
18028
|
-
description: 'Kicks off a discovery session for the project. The pipeline: ICP description \u2192 Gemini grounded seed prompt \u2192 embed + cluster (cosine \u2265 0.95 by default) \u2192 pick canonical representatives \u2192 probe each canonical via Gemini grounding \u2192 classify into cited / aspirational / wasted-surface \u2192 aggregate competitor map. Returns immediately with `{ runId, sessionId, status: "running", consolidated }`; the actual work runs in the background. Poll `GET /projects/{name}/discover/sessions/{id}` until `status` is `completed` or `failed`. Concurrent/duplicate requests for the same (project, ICP) are consolidated onto a single in-flight session: the response carries `consolidated: true` and `200 OK` instead of `201`, and the request\'s `dedupThreshold` / `maxProbes` are ignored (the in-flight session keeps its original config).',
|
|
18048
|
+
description: 'Kicks off a discovery session for the project. The pipeline: ICP description \u2192 Gemini grounded seed prompt \u2192 embed + cluster (cosine \u2265 0.95 by default) \u2192 pick canonical representatives \u2192 probe each canonical via Gemini grounding \u2192 classify into cited / aspirational / wasted-surface \u2192 aggregate competitor map. Returns immediately with `{ runId, sessionId, status: "running", consolidated }`; the actual work runs in the background. Poll `GET /projects/{name}/discover/sessions/{id}` until `status` is `completed` or `failed`. Concurrent/duplicate requests for the same (project, ICP) are consolidated onto a single in-flight session: the response carries `consolidated: true` and `200 OK` instead of `201`, and the request\'s `dedupThreshold` / `maxProbes` / `probeConcurrency` are ignored (the in-flight session keeps its original config).',
|
|
18029
18049
|
tags: ["discovery"],
|
|
18030
18050
|
parameters: [nameParameter],
|
|
18031
18051
|
requestBody: {
|
|
@@ -18038,6 +18058,12 @@ var routeCatalog = [
|
|
|
18038
18058
|
icpDescription: { type: "string", description: "Free-text ICP. Required if the project does not have spec.icpDescription stored." },
|
|
18039
18059
|
dedupThreshold: { type: "number", description: "Cosine similarity threshold for clustering. Defaults to 0.95." },
|
|
18040
18060
|
maxProbes: { type: "integer", description: "Max canonical queries to probe in this session. Default 100, hard cap 500." },
|
|
18061
|
+
probeConcurrency: {
|
|
18062
|
+
type: "integer",
|
|
18063
|
+
minimum: 1,
|
|
18064
|
+
maximum: 8,
|
|
18065
|
+
description: "How many probes may run in parallel. Default 1 (strictly serial \u2014 the historical behaviour), hard cap 8. Probe rows are persisted in canonical order regardless of concurrency, so this only shortens wall-clock time."
|
|
18066
|
+
},
|
|
18041
18067
|
locations: {
|
|
18042
18068
|
type: "array",
|
|
18043
18069
|
items: { type: "string" },
|
|
@@ -24244,7 +24270,7 @@ function buildAmbiguousSlugMessage(slug, pages) {
|
|
|
24244
24270
|
}).join(", ");
|
|
24245
24271
|
return `Multiple pages matched slug "${slug}". Candidates: ${candidates}.`;
|
|
24246
24272
|
}
|
|
24247
|
-
async function
|
|
24273
|
+
async function mapWithConcurrency2(items, limit, iteratee) {
|
|
24248
24274
|
const results = new Array(items.length);
|
|
24249
24275
|
let nextIndex = 0;
|
|
24250
24276
|
async function worker() {
|
|
@@ -24541,7 +24567,7 @@ function buildManualMetaAssist(siteUrl, slug, link, meta) {
|
|
|
24541
24567
|
async function bulkSetSeoMeta(connection, entries, env) {
|
|
24542
24568
|
const site = resolveEnvironment(connection, env);
|
|
24543
24569
|
const { strategy, plugins } = await detectSeoWriteStrategy(connection, site.env);
|
|
24544
|
-
const results = await
|
|
24570
|
+
const results = await mapWithConcurrency2(
|
|
24545
24571
|
entries,
|
|
24546
24572
|
3,
|
|
24547
24573
|
async (entry) => {
|
|
@@ -24699,7 +24725,7 @@ async function deploySchema(connection, slug, schemas, env) {
|
|
|
24699
24725
|
async function deploySchemaFromProfile(connection, profile, env) {
|
|
24700
24726
|
const site = resolveEnvironment(connection, env);
|
|
24701
24727
|
const slugEntries = Object.entries(profile.pages);
|
|
24702
|
-
const results = await
|
|
24728
|
+
const results = await mapWithConcurrency2(
|
|
24703
24729
|
slugEntries,
|
|
24704
24730
|
3,
|
|
24705
24731
|
async ([slug, entries]) => {
|
|
@@ -24721,7 +24747,7 @@ async function deploySchemaFromProfile(connection, profile, env) {
|
|
|
24721
24747
|
async function getSchemaStatus(connection, env) {
|
|
24722
24748
|
const site = resolveEnvironment(connection, env);
|
|
24723
24749
|
const pages = await listPages(connection, site.env);
|
|
24724
|
-
const details = await
|
|
24750
|
+
const details = await mapWithConcurrency2(
|
|
24725
24751
|
pages,
|
|
24726
24752
|
5,
|
|
24727
24753
|
async (page) => getPageDetail(connection, page.slug, site.env)
|
|
@@ -24822,7 +24848,7 @@ async function runAudit(connection, env) {
|
|
|
24822
24848
|
const site = resolveEnvironment(connection, env);
|
|
24823
24849
|
const pages = await listPages(connection, site.env);
|
|
24824
24850
|
const plugins = await listActivePlugins(connection, site.env);
|
|
24825
|
-
const details = await
|
|
24851
|
+
const details = await mapWithConcurrency2(
|
|
24826
24852
|
pages,
|
|
24827
24853
|
5,
|
|
24828
24854
|
async (page) => getPageDetail(connection, page.slug, site.env, plugins)
|
|
@@ -33792,6 +33818,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
33792
33818
|
icpDescription,
|
|
33793
33819
|
dedupThreshold: parsed.data.dedupThreshold,
|
|
33794
33820
|
maxProbes: parsed.data.maxProbes,
|
|
33821
|
+
probeConcurrency: parsed.data.probeConcurrency,
|
|
33795
33822
|
locations
|
|
33796
33823
|
});
|
|
33797
33824
|
return reply.status(201).send({
|
|
@@ -34041,6 +34068,8 @@ function serializeSession(row) {
|
|
|
34041
34068
|
seedProvider: row.seedProvider ?? null,
|
|
34042
34069
|
seedCountRaw: row.seedCountRaw ?? null,
|
|
34043
34070
|
seedCount: row.seedCount ?? null,
|
|
34071
|
+
seedFromAnswerCount: row.seedFromAnswerCount ?? null,
|
|
34072
|
+
seedFromGroundingCount: row.seedFromGroundingCount ?? null,
|
|
34044
34073
|
dedupThreshold: row.dedupThreshold ?? null,
|
|
34045
34074
|
probeCount: row.probeCount ?? null,
|
|
34046
34075
|
citedCount: row.citedCount ?? null,
|
|
@@ -34134,6 +34163,10 @@ async function executeDiscovery(opts) {
|
|
|
34134
34163
|
const dedupThreshold = opts.dedupThreshold ?? DISCOVERY_DEFAULT_DEDUP_THRESHOLD;
|
|
34135
34164
|
const requestedMax = opts.maxProbes ?? DEFAULT_MAX_PROBES;
|
|
34136
34165
|
const maxProbes = Math.min(Math.max(1, requestedMax), ABSOLUTE_MAX_PROBES);
|
|
34166
|
+
const probeConcurrency = Math.min(
|
|
34167
|
+
Math.max(1, Math.floor(opts.probeConcurrency ?? DISCOVERY_DEFAULT_PROBE_CONCURRENCY)),
|
|
34168
|
+
DISCOVERY_PROBE_CONCURRENCY_CAP
|
|
34169
|
+
);
|
|
34137
34170
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
34138
34171
|
opts.db.update(discoverySessions).set({
|
|
34139
34172
|
status: DiscoverySessionStatuses.seeding,
|
|
@@ -34164,12 +34197,21 @@ async function executeDiscovery(opts) {
|
|
|
34164
34197
|
seedProvider: seedResult.provider,
|
|
34165
34198
|
seedCountRaw,
|
|
34166
34199
|
seedCount,
|
|
34200
|
+
// Seed-source diagnostics (answer text vs. grounding fan-out). Null when
|
|
34201
|
+
// the seed dep does not report the split. Not consumed by any gate.
|
|
34202
|
+
seedFromAnswerCount: seedResult.fromAnswerCount ?? null,
|
|
34203
|
+
seedFromGroundingCount: seedResult.fromGroundingCount ?? null,
|
|
34167
34204
|
warning
|
|
34168
34205
|
}).where(eq36(discoverySessions.id, opts.sessionId)).run();
|
|
34206
|
+
const probeResults = await mapWithConcurrency(
|
|
34207
|
+
probedCanonicals,
|
|
34208
|
+
probeConcurrency,
|
|
34209
|
+
(query) => opts.deps.probe({ project: opts.project, query })
|
|
34210
|
+
);
|
|
34169
34211
|
const probeRows = [];
|
|
34170
34212
|
const buckets = { cited: 0, aspirational: 0, "wasted-surface": 0 };
|
|
34171
|
-
|
|
34172
|
-
|
|
34213
|
+
const insertBaseMs = Date.now();
|
|
34214
|
+
const rowsToInsert = probeResults.map((probe, index2) => {
|
|
34173
34215
|
const bucket = classifyProbeBucket({
|
|
34174
34216
|
citationState: probe.citationState,
|
|
34175
34217
|
citedDomains: probe.citedDomains,
|
|
@@ -34177,18 +34219,25 @@ async function executeDiscovery(opts) {
|
|
|
34177
34219
|
});
|
|
34178
34220
|
probeRows.push({ citedDomains: probe.citedDomains, bucket });
|
|
34179
34221
|
buckets[bucket]++;
|
|
34180
|
-
|
|
34222
|
+
return {
|
|
34181
34223
|
id: crypto28.randomUUID(),
|
|
34182
34224
|
sessionId: opts.sessionId,
|
|
34183
34225
|
projectId: opts.project.id,
|
|
34184
|
-
query,
|
|
34226
|
+
query: probedCanonicals[index2],
|
|
34185
34227
|
bucket,
|
|
34186
34228
|
citationState: probe.citationState,
|
|
34187
34229
|
answerMentioned: probe.answerMentioned,
|
|
34188
34230
|
citedDomains: probe.citedDomains,
|
|
34189
34231
|
rawResponse: JSON.stringify(probe.rawResponse),
|
|
34190
|
-
createdAt:
|
|
34191
|
-
}
|
|
34232
|
+
createdAt: new Date(insertBaseMs + index2).toISOString()
|
|
34233
|
+
};
|
|
34234
|
+
});
|
|
34235
|
+
if (rowsToInsert.length > 0) {
|
|
34236
|
+
opts.db.transaction((tx) => {
|
|
34237
|
+
for (const values of rowsToInsert) {
|
|
34238
|
+
tx.insert(discoveryProbes).values(values).run();
|
|
34239
|
+
}
|
|
34240
|
+
});
|
|
34192
34241
|
}
|
|
34193
34242
|
const domains = buildCompetitorMap(probeRows, opts.project).map((entry) => entry.domain);
|
|
34194
34243
|
const classification = await classifyCompetitorDomains(
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
3
3
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
4
4
|
DISCOVERY_MAX_PROBES_CAP,
|
|
5
|
+
DISCOVERY_PROBE_CONCURRENCY_CAP,
|
|
5
6
|
backlinkSourceSchema,
|
|
6
7
|
competitorBatchRequestSchema,
|
|
7
8
|
discoveryBucketSchema,
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
trafficConnectVercelRequestSchema,
|
|
25
26
|
trafficConnectWordpressRequestSchema,
|
|
26
27
|
trafficEventKindSchema
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-VOR5ZTUU.js";
|
|
28
29
|
|
|
29
30
|
// src/config.ts
|
|
30
31
|
import fs from "fs";
|
|
@@ -5565,7 +5566,8 @@ var discoveryRunInputSchema = z2.object({
|
|
|
5565
5566
|
// upper bound; this just clarifies the meaning of each knob.
|
|
5566
5567
|
icpDescription: z2.string().min(1).optional().describe("Free-text ICP description. If omitted, the project must already have spec.icpDescription stored."),
|
|
5567
5568
|
dedupThreshold: z2.number().min(0).max(1).optional().describe("Cosine similarity threshold for clustering seed candidates. Defaults to 0.85. Lower values dedupe more aggressively."),
|
|
5568
|
-
maxProbes: z2.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional().describe(`Max canonical queries to probe in this session. Default 100, hard cap ${DISCOVERY_MAX_PROBES_CAP}.`)
|
|
5569
|
+
maxProbes: z2.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional().describe(`Max canonical queries to probe in this session. Default 100, hard cap ${DISCOVERY_MAX_PROBES_CAP}.`),
|
|
5570
|
+
probeConcurrency: z2.number().int().min(1).max(DISCOVERY_PROBE_CONCURRENCY_CAP).optional().describe(`How many probes may run in parallel. Default 1 (strictly serial), hard cap ${DISCOVERY_PROBE_CONCURRENCY_CAP}. Probe rows are persisted in canonical order regardless of concurrency, so this only shortens wall-clock time.`)
|
|
5569
5571
|
}).optional()
|
|
5570
5572
|
});
|
|
5571
5573
|
var discoverySessionsListInputSchema = z2.object({
|
|
@@ -1188,6 +1188,33 @@ function isRetryableHttpError(err) {
|
|
|
1188
1188
|
return true;
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
// ../contracts/src/concurrency.ts
|
|
1192
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
1193
|
+
if (items.length === 0) return [];
|
|
1194
|
+
const limit = Math.min(Math.max(1, Math.floor(concurrency)), items.length);
|
|
1195
|
+
const results = new Array(items.length);
|
|
1196
|
+
const state = {
|
|
1197
|
+
nextIndex: 0,
|
|
1198
|
+
firstFailure: null
|
|
1199
|
+
};
|
|
1200
|
+
async function worker() {
|
|
1201
|
+
for (; ; ) {
|
|
1202
|
+
if (state.firstFailure) return;
|
|
1203
|
+
const index = state.nextIndex++;
|
|
1204
|
+
if (index >= items.length) return;
|
|
1205
|
+
try {
|
|
1206
|
+
results[index] = await fn(items[index], index);
|
|
1207
|
+
} catch (err) {
|
|
1208
|
+
state.firstFailure ??= { err };
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
await Promise.all(Array.from({ length: limit }, () => worker()));
|
|
1214
|
+
if (state.firstFailure) throw state.firstFailure.err;
|
|
1215
|
+
return results;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1191
1218
|
// ../contracts/src/bing.ts
|
|
1192
1219
|
import { z as z9 } from "zod";
|
|
1193
1220
|
var bingConnectionDtoSchema = z9.object({
|
|
@@ -2150,6 +2177,15 @@ var discoverySessionDtoSchema = z17.object({
|
|
|
2150
2177
|
seedProvider: z17.string().nullable().optional(),
|
|
2151
2178
|
seedCountRaw: z17.number().int().nullable().optional(),
|
|
2152
2179
|
seedCount: z17.number().int().nullable().optional(),
|
|
2180
|
+
/**
|
|
2181
|
+
* Diagnostics: how many raw seed candidates came from the model's answer
|
|
2182
|
+
* text vs. from the grounding fan-out (the search queries the engine
|
|
2183
|
+
* actually issued). Recorded at seed time so seed-quality calibration is
|
|
2184
|
+
* measurable per session. Null on legacy sessions (or when a seed dep does
|
|
2185
|
+
* not report the split). Purely additive — no gate or warning reads these.
|
|
2186
|
+
*/
|
|
2187
|
+
seedFromAnswerCount: z17.number().int().nullable().optional(),
|
|
2188
|
+
seedFromGroundingCount: z17.number().int().nullable().optional(),
|
|
2153
2189
|
dedupThreshold: z17.number().nullable().optional(),
|
|
2154
2190
|
probeCount: z17.number().int().nullable().optional(),
|
|
2155
2191
|
citedCount: z17.number().int().nullable().default(null),
|
|
@@ -2171,13 +2207,15 @@ var discoverySessionDetailDtoSchema = discoverySessionDtoSchema.extend({
|
|
|
2171
2207
|
probes: z17.array(discoveryProbeDtoSchema).default([])
|
|
2172
2208
|
});
|
|
2173
2209
|
var DISCOVERY_MAX_PROBES_CAP = 500;
|
|
2210
|
+
var DISCOVERY_PROBE_CONCURRENCY_CAP = 8;
|
|
2211
|
+
var DISCOVERY_DEFAULT_PROBE_CONCURRENCY = 1;
|
|
2174
2212
|
var DISCOVERY_DEFAULT_DEDUP_THRESHOLD = 0.95;
|
|
2175
2213
|
var DISCOVERY_SEED_COLLAPSE_RATIO = 0.2;
|
|
2176
2214
|
var DISCOVERY_SEED_COLLAPSE_MIN_RAW = 10;
|
|
2177
2215
|
function seedCollapseWarning(input) {
|
|
2178
2216
|
const { seedCountRaw, canonicalCount, dedupThreshold } = input;
|
|
2179
2217
|
if (seedCountRaw < DISCOVERY_SEED_COLLAPSE_MIN_RAW) return null;
|
|
2180
|
-
if (canonicalCount / seedCountRaw
|
|
2218
|
+
if (canonicalCount / seedCountRaw > DISCOVERY_SEED_COLLAPSE_RATIO) return null;
|
|
2181
2219
|
const noun = canonicalCount === 1 ? "query" : "queries";
|
|
2182
2220
|
return `Seed dedup collapsed ${seedCountRaw} raw candidates into ${canonicalCount} canonical ${noun} at threshold ${dedupThreshold}. Distinct intents were likely merged into one cluster; re-run with a higher --dedup-threshold.`;
|
|
2183
2221
|
}
|
|
@@ -2185,6 +2223,14 @@ var discoveryRunRequestSchema = z17.object({
|
|
|
2185
2223
|
icpDescription: z17.string().min(1).optional(),
|
|
2186
2224
|
dedupThreshold: z17.number().min(0).max(1).optional(),
|
|
2187
2225
|
maxProbes: z17.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional(),
|
|
2226
|
+
/**
|
|
2227
|
+
* How many probes may run in parallel for this session. Defaults to
|
|
2228
|
+
* `DISCOVERY_DEFAULT_PROBE_CONCURRENCY` (1 — strictly serial, the historical
|
|
2229
|
+
* behaviour) when omitted; capped at `DISCOVERY_PROBE_CONCURRENCY_CAP`.
|
|
2230
|
+
* Probe results are persisted in canonical order regardless of concurrency,
|
|
2231
|
+
* so this only changes wall-clock time, never output order.
|
|
2232
|
+
*/
|
|
2233
|
+
probeConcurrency: z17.number().int().min(1).max(DISCOVERY_PROBE_CONCURRENCY_CAP).optional(),
|
|
2188
2234
|
/**
|
|
2189
2235
|
* Optional override of the project's location labels, constraining seed
|
|
2190
2236
|
* generation to a subset of the configured service areas. Each label must
|
|
@@ -5531,6 +5577,7 @@ export {
|
|
|
5531
5577
|
formatGbpMetricLabel,
|
|
5532
5578
|
withRetry,
|
|
5533
5579
|
isRetryableHttpError,
|
|
5580
|
+
mapWithConcurrency,
|
|
5534
5581
|
bingUrlInspectionDtoSchema,
|
|
5535
5582
|
bingCoverageSummaryDtoSchema,
|
|
5536
5583
|
bingKeywordStatsDtoSchema,
|
|
@@ -5609,6 +5656,8 @@ export {
|
|
|
5609
5656
|
discoverySessionDtoSchema,
|
|
5610
5657
|
discoverySessionDetailDtoSchema,
|
|
5611
5658
|
DISCOVERY_MAX_PROBES_CAP,
|
|
5659
|
+
DISCOVERY_PROBE_CONCURRENCY_CAP,
|
|
5660
|
+
DISCOVERY_DEFAULT_PROBE_CONCURRENCY,
|
|
5612
5661
|
DISCOVERY_DEFAULT_DEDUP_THRESHOLD,
|
|
5613
5662
|
seedCollapseWarning,
|
|
5614
5663
|
discoveryRunRequestSchema,
|
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setTelemetrySource,
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackEvent
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-2AWATO4I.js";
|
|
33
33
|
import {
|
|
34
34
|
CliError,
|
|
35
35
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
saveConfig,
|
|
47
47
|
saveConfigPatch,
|
|
48
48
|
usageError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-VGMTLUUM.js";
|
|
50
50
|
import {
|
|
51
51
|
apiKeys,
|
|
52
52
|
createClient,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
projects,
|
|
55
55
|
queries,
|
|
56
56
|
renderReportHtml
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-F3MKVMS5.js";
|
|
58
58
|
import {
|
|
59
59
|
BacklinkSources,
|
|
60
60
|
CcReleaseSyncStatuses,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
providerQuotaPolicySchema,
|
|
81
81
|
resolveProviderInput,
|
|
82
82
|
winnabilityClassSchema
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-VOR5ZTUU.js";
|
|
84
84
|
|
|
85
85
|
// src/cli.ts
|
|
86
86
|
import { pathToFileURL } from "url";
|
|
@@ -1657,6 +1657,7 @@ function buildRunBody(opts, icpDescription) {
|
|
|
1657
1657
|
if (icpDescription) body.icpDescription = icpDescription;
|
|
1658
1658
|
if (opts.dedupThreshold !== void 0) body.dedupThreshold = opts.dedupThreshold;
|
|
1659
1659
|
if (opts.maxProbes !== void 0) body.maxProbes = opts.maxProbes;
|
|
1660
|
+
if (opts.probeConcurrency !== void 0) body.probeConcurrency = opts.probeConcurrency;
|
|
1660
1661
|
if (opts.locations && opts.locations.length > 0) body.locations = opts.locations;
|
|
1661
1662
|
return body;
|
|
1662
1663
|
}
|
|
@@ -2056,17 +2057,18 @@ Usage: ${usage}`,
|
|
|
2056
2057
|
var DISCOVER_CLI_COMMANDS = [
|
|
2057
2058
|
{
|
|
2058
2059
|
path: ["discover", "run"],
|
|
2059
|
-
usage: 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--wait] [--format json]',
|
|
2060
|
+
usage: 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--probe-concurrency 3] [--wait] [--format json]',
|
|
2060
2061
|
options: {
|
|
2061
2062
|
icp: stringOption(),
|
|
2062
2063
|
"icp-angle": multiStringOption(),
|
|
2063
2064
|
locations: multiStringOption(),
|
|
2064
2065
|
"dedup-threshold": stringOption(),
|
|
2065
2066
|
"max-probes": stringOption(),
|
|
2067
|
+
"probe-concurrency": stringOption(),
|
|
2066
2068
|
wait: { type: "boolean", default: false }
|
|
2067
2069
|
},
|
|
2068
2070
|
run: async (input) => {
|
|
2069
|
-
const usage = 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--wait] [--format json]';
|
|
2071
|
+
const usage = 'canonry discover run <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--probe-concurrency 3] [--wait] [--format json]';
|
|
2070
2072
|
const project = requireProject(input, "discover.run", usage);
|
|
2071
2073
|
await discoverRun(project, {
|
|
2072
2074
|
icp: getString(input.values, "icp"),
|
|
@@ -2078,6 +2080,11 @@ var DISCOVER_CLI_COMMANDS = [
|
|
|
2078
2080
|
usage,
|
|
2079
2081
|
message: "--max-probes must be an integer"
|
|
2080
2082
|
}),
|
|
2083
|
+
probeConcurrency: parseIntegerOption(input, "probe-concurrency", {
|
|
2084
|
+
command: "discover.run",
|
|
2085
|
+
usage,
|
|
2086
|
+
message: "--probe-concurrency must be an integer"
|
|
2087
|
+
}),
|
|
2081
2088
|
wait: getBoolean(input.values, "wait"),
|
|
2082
2089
|
format: input.format
|
|
2083
2090
|
});
|
|
@@ -2085,17 +2092,18 @@ var DISCOVER_CLI_COMMANDS = [
|
|
|
2085
2092
|
},
|
|
2086
2093
|
{
|
|
2087
2094
|
path: ["discover", "seed"],
|
|
2088
|
-
usage: 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--wait] [--format json]',
|
|
2095
|
+
usage: 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--probe-concurrency 3] [--wait] [--format json]',
|
|
2089
2096
|
options: {
|
|
2090
2097
|
icp: stringOption(),
|
|
2091
2098
|
"icp-angle": multiStringOption(),
|
|
2092
2099
|
locations: multiStringOption(),
|
|
2093
2100
|
"dedup-threshold": stringOption(),
|
|
2094
2101
|
"max-probes": stringOption(),
|
|
2102
|
+
"probe-concurrency": stringOption(),
|
|
2095
2103
|
wait: { type: "boolean", default: false }
|
|
2096
2104
|
},
|
|
2097
2105
|
run: async (input) => {
|
|
2098
|
-
const usage = 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--wait] [--format json]';
|
|
2106
|
+
const usage = 'canonry discover seed <project> [--icp "..."] [--icp-angle "..."] [--locations michigan,florida] [--dedup-threshold 0.95] [--max-probes 100] [--probe-concurrency 3] [--wait] [--format json]';
|
|
2099
2107
|
const project = requireProject(input, "discover.seed", usage);
|
|
2100
2108
|
await discoverSeed(project, {
|
|
2101
2109
|
icp: getString(input.values, "icp"),
|
|
@@ -2107,6 +2115,11 @@ var DISCOVER_CLI_COMMANDS = [
|
|
|
2107
2115
|
usage,
|
|
2108
2116
|
message: "--max-probes must be an integer"
|
|
2109
2117
|
}),
|
|
2118
|
+
probeConcurrency: parseIntegerOption(input, "probe-concurrency", {
|
|
2119
|
+
command: "discover.seed",
|
|
2120
|
+
usage,
|
|
2121
|
+
message: "--probe-concurrency must be an integer"
|
|
2122
|
+
}),
|
|
2110
2123
|
wait: getBoolean(input.values, "wait"),
|
|
2111
2124
|
format: input.format
|
|
2112
2125
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2AWATO4I.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-VGMTLUUM.js";
|
|
7
|
+
import "./chunk-F3MKVMS5.js";
|
|
8
|
+
import "./chunk-VOR5ZTUU.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VGMTLUUM.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VOR5ZTUU.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
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.106.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",
|
|
@@ -66,24 +66,24 @@
|
|
|
66
66
|
"tsup": "^8.5.1",
|
|
67
67
|
"tsx": "^4.19.0",
|
|
68
68
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
69
70
|
"@ainyc/canonry-config": "0.0.0",
|
|
70
71
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
71
72
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
72
73
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
73
74
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
75
75
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
77
76
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
77
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
78
78
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
79
79
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
80
80
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
81
81
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
82
|
-
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
83
82
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
84
|
-
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
85
83
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
86
84
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
85
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
86
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
87
87
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
88
88
|
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
89
89
|
},
|