@ainyc/canonry 4.110.0 → 4.112.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 -1
- package/assets/assets/{BacklinksPage-Duk8YbV2.js → BacklinksPage-0OUPoMJf.js} +1 -1
- package/assets/assets/ChartPrimitives-BeJemaLi.js +1 -0
- package/assets/assets/ProjectPage-CD0RS8DR.js +7 -0
- package/assets/assets/{RunRow-DH8UMAwj.js → RunRow-CCnuv5wi.js} +1 -1
- package/assets/assets/{RunsPage-OPteH1b_.js → RunsPage-IqTj8i9c.js} +1 -1
- package/assets/assets/{SettingsPage-7cspMOFv.js → SettingsPage-DKdvVPVp.js} +1 -1
- package/assets/assets/{TrafficPage-D4pcnfc8.js → TrafficPage-xPENJ4Du.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-D-KbCCEK.js → TrafficSourceDetailPage-CP6o754T.js} +1 -1
- package/assets/assets/{arrow-left-M8KVuve8.js → arrow-left-DGiw6bsJ.js} +1 -1
- package/assets/assets/{extract-error-message-D2aTaSV5.js → extract-error-message-CYh3RHSN.js} +1 -1
- package/assets/assets/{index-ChPgQUZ5.js → index-BpHZkgFH.js} +51 -51
- package/assets/assets/index-CD6LKwQu.css +1 -0
- package/assets/assets/{trash-2-BNVgf5NY.js → trash-2-DBeJW7Iw.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-X4LLTNQZ.js → chunk-6M2ALGJA.js} +1 -1
- package/dist/{chunk-6PHBWPPN.js → chunk-KS2M7B5E.js} +8 -4
- package/dist/{chunk-JGRVQJHX.js → chunk-UOMNYP5T.js} +61 -6
- package/dist/{chunk-YQ4KOC5Z.js → chunk-VICGMHY2.js} +4 -0
- package/dist/cli.js +400 -102
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-BGLF7DQW.js → intelligence-service-RGOY43QR.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +10 -10
- package/assets/assets/ChartPrimitives-aLxtVH28.js +0 -1
- package/assets/assets/ProjectPage-Bqd0JvpC.js +0 -7
- package/assets/assets/index-CjrSrPKf.css +0 -1
|
@@ -102,6 +102,7 @@ import {
|
|
|
102
102
|
contentTargetDismissalDtoSchema,
|
|
103
103
|
contentTargetDismissalsResponseDtoSchema,
|
|
104
104
|
contentTargetsResponseDtoSchema,
|
|
105
|
+
cosineSimilarity,
|
|
105
106
|
createApiKeyRequestSchema,
|
|
106
107
|
createdApiKeyDtoSchema,
|
|
107
108
|
dedupeReportActions,
|
|
@@ -270,7 +271,7 @@ import {
|
|
|
270
271
|
wordpressSchemaDeployResultDtoSchema,
|
|
271
272
|
wordpressSchemaStatusResultDtoSchema,
|
|
272
273
|
wordpressStatusDtoSchema
|
|
273
|
-
} from "./chunk-
|
|
274
|
+
} from "./chunk-VICGMHY2.js";
|
|
274
275
|
|
|
275
276
|
// src/intelligence-service.ts
|
|
276
277
|
import { eq as eq38, desc as desc18, asc as asc6, and as and28, ne as ne5, or as or6, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
|
|
@@ -1164,6 +1165,10 @@ var discoverySessions = sqliteTable("discovery_sessions", {
|
|
|
1164
1165
|
// session identity for consolidation — and per-provider candidate counts.
|
|
1165
1166
|
seedProviders: text("seed_providers", { mode: "json" }).$type(),
|
|
1166
1167
|
seedProviderCounts: text("seed_provider_counts", { mode: "json" }).$type(),
|
|
1168
|
+
// TRUE canonical count after dedup, BEFORE the probe-budget slice. seed_count
|
|
1169
|
+
// is post-truncation (probedCanonicals.length), so a deliberately small
|
|
1170
|
+
// maxProbes deflates it; this column is the honest numerator.
|
|
1171
|
+
canonicalCount: integer("canonical_count"),
|
|
1167
1172
|
dedupThreshold: real("dedup_threshold"),
|
|
1168
1173
|
probeCount: integer("probe_count"),
|
|
1169
1174
|
citedCount: integer("cited_count"),
|
|
@@ -3466,6 +3471,15 @@ var MIGRATION_VERSIONS = [
|
|
|
3466
3471
|
`ALTER TABLE discovery_sessions ADD COLUMN seed_providers TEXT`,
|
|
3467
3472
|
`ALTER TABLE discovery_sessions ADD COLUMN seed_provider_counts TEXT`
|
|
3468
3473
|
]
|
|
3474
|
+
},
|
|
3475
|
+
{
|
|
3476
|
+
version: 94,
|
|
3477
|
+
name: "discovery-session-canonical-count",
|
|
3478
|
+
statements: [
|
|
3479
|
+
// True post-dedup, pre-truncation canonical count (seed_count is
|
|
3480
|
+
// post-truncation). Additive + nullable (downgrade-safe).
|
|
3481
|
+
`ALTER TABLE discovery_sessions ADD COLUMN canonical_count INTEGER`
|
|
3482
|
+
]
|
|
3469
3483
|
}
|
|
3470
3484
|
];
|
|
3471
3485
|
function rebuildBacklinkTableWithSource(tx, table) {
|
|
@@ -34179,6 +34193,7 @@ function serializeSession(row) {
|
|
|
34179
34193
|
seedRawCandidates: row.seedRawCandidates ?? null,
|
|
34180
34194
|
seedProviders: row.seedProviders ?? null,
|
|
34181
34195
|
seedProviderCounts: row.seedProviderCounts ?? null,
|
|
34196
|
+
canonicalCount: row.canonicalCount ?? null,
|
|
34182
34197
|
dedupClusterMinSims: row.dedupClusterMinSims ?? null,
|
|
34183
34198
|
dedupBandPairFraction: row.dedupBandPairFraction ?? null,
|
|
34184
34199
|
dedupPairsTotal: row.dedupPairsTotal ?? null,
|
|
@@ -34264,14 +34279,41 @@ async function classifyCompetitorDomains(deps, project, icpDescription, domains)
|
|
|
34264
34279
|
return {};
|
|
34265
34280
|
}
|
|
34266
34281
|
}
|
|
34267
|
-
async function pickCanonicalsWithStats(candidates, deps, dedupThreshold) {
|
|
34282
|
+
async function pickCanonicalsWithStats(candidates, deps, dedupThreshold, primaryMask) {
|
|
34268
34283
|
const emptyStats = { perClusterMinSimilarity: [], bandPairFraction: null, pairsTotal: 0 };
|
|
34269
34284
|
if (candidates.length === 0) return { canonicals: [], stats: emptyStats };
|
|
34270
34285
|
if (candidates.length === 1) return { canonicals: candidates, stats: emptyStats };
|
|
34271
34286
|
const vectors = await deps.embed(candidates);
|
|
34272
|
-
const
|
|
34273
|
-
const
|
|
34274
|
-
|
|
34287
|
+
const indices = candidates.map((_, i) => i);
|
|
34288
|
+
const hasBothRoles = primaryMask !== void 0 && primaryMask.length === candidates.length && primaryMask.some((p) => p) && primaryMask.some((p) => !p);
|
|
34289
|
+
if (!hasBothRoles) {
|
|
34290
|
+
const indexClusters = clusterByCosine(indices, vectors, dedupThreshold);
|
|
34291
|
+
const canonicals = indexClusters.map((cluster) => pickClusterRepresentative(cluster.map((i) => candidates[i])));
|
|
34292
|
+
return { canonicals, stats: computeDedupSimilarityStats(vectors, indexClusters) };
|
|
34293
|
+
}
|
|
34294
|
+
const primaryIdx = indices.filter((i) => primaryMask[i]);
|
|
34295
|
+
const primaryClusters = clusterByCosine(
|
|
34296
|
+
primaryIdx,
|
|
34297
|
+
primaryIdx.map((i) => vectors[i]),
|
|
34298
|
+
dedupThreshold
|
|
34299
|
+
);
|
|
34300
|
+
const repIndexOf = (cluster) => {
|
|
34301
|
+
const rep = pickClusterRepresentative(cluster.map((i) => candidates[i]));
|
|
34302
|
+
return cluster.find((i) => candidates[i] === rep);
|
|
34303
|
+
};
|
|
34304
|
+
const keptIdx = primaryClusters.map(repIndexOf);
|
|
34305
|
+
for (const s of indices.filter((i) => !primaryMask[i])) {
|
|
34306
|
+
const novel = keptIdx.every((k) => cosineSimilarity(vectors[s], vectors[k]) < dedupThreshold);
|
|
34307
|
+
if (novel) keptIdx.push(s);
|
|
34308
|
+
}
|
|
34309
|
+
return {
|
|
34310
|
+
canonicals: keptIdx.map((i) => candidates[i]),
|
|
34311
|
+
// Band fraction describes the candidate SPACE (not the clustering), so it is
|
|
34312
|
+
// computed over all vectors as before; per-cluster cohesion reports the
|
|
34313
|
+
// primary clusters.
|
|
34314
|
+
stats: computeDedupSimilarityStats(vectors, primaryClusters),
|
|
34315
|
+
primaryCanonicalCount: primaryClusters.length
|
|
34316
|
+
};
|
|
34275
34317
|
}
|
|
34276
34318
|
async function executeDiscovery(opts) {
|
|
34277
34319
|
const dedupThreshold = opts.dedupThreshold ?? DISCOVERY_DEFAULT_DEDUP_THRESHOLD;
|
|
@@ -34301,10 +34343,22 @@ async function executeDiscovery(opts) {
|
|
|
34301
34343
|
});
|
|
34302
34344
|
const rawCandidates = dedupeStrings(unbrandedCandidates);
|
|
34303
34345
|
const seedCountRaw = rawCandidates.length;
|
|
34346
|
+
const primaryProvider = opts.seedProviders?.[0];
|
|
34347
|
+
const multiProvider = (opts.seedProviders?.length ?? 0) >= 2 && seedResult.candidateProviders != null;
|
|
34348
|
+
let primaryMask;
|
|
34349
|
+
if (multiProvider && primaryProvider) {
|
|
34350
|
+
const providerOf = /* @__PURE__ */ new Map();
|
|
34351
|
+
seedResult.candidates.forEach((candidate, i) => {
|
|
34352
|
+
const key = candidate.trim().toLowerCase();
|
|
34353
|
+
if (!providerOf.has(key)) providerOf.set(key, seedResult.candidateProviders[i]);
|
|
34354
|
+
});
|
|
34355
|
+
primaryMask = rawCandidates.map((c) => providerOf.get(c.trim().toLowerCase()) === primaryProvider);
|
|
34356
|
+
}
|
|
34304
34357
|
const { canonicals, stats: dedupStats } = await pickCanonicalsWithStats(
|
|
34305
34358
|
rawCandidates,
|
|
34306
34359
|
{ embed: opts.deps.embed },
|
|
34307
|
-
dedupThreshold
|
|
34360
|
+
dedupThreshold,
|
|
34361
|
+
primaryMask
|
|
34308
34362
|
);
|
|
34309
34363
|
const warning = seedCollapseWarning({
|
|
34310
34364
|
seedCountRaw,
|
|
@@ -34323,6 +34377,7 @@ async function executeDiscovery(opts) {
|
|
|
34323
34377
|
seedFromAnswerCount: seedResult.fromAnswerCount ?? null,
|
|
34324
34378
|
seedFromGroundingCount: seedResult.fromGroundingCount ?? null,
|
|
34325
34379
|
seedBrandFilteredCount: droppedBranded.length,
|
|
34380
|
+
canonicalCount: canonicals.length,
|
|
34326
34381
|
// Full seed provenance + dedup calibration diagnostics: the raw
|
|
34327
34382
|
// candidate list (as the seed dep returned it, pre-filter) makes every
|
|
34328
34383
|
// live session a replayable fixture; the similarity stats are the data
|
|
@@ -2246,6 +2246,9 @@ var discoverySessionDtoSchema = z17.object({
|
|
|
2246
2246
|
seedProviders: z17.array(z17.string()).nullable().optional(),
|
|
2247
2247
|
/** Raw candidate count contributed per seed provider. */
|
|
2248
2248
|
seedProviderCounts: z17.record(z17.string(), z17.number().int()).nullable().optional(),
|
|
2249
|
+
/** True post-dedup canonical count BEFORE the probe-budget slice (seedCount
|
|
2250
|
+
* is post-truncation). Null on legacy sessions. */
|
|
2251
|
+
canonicalCount: z17.number().int().nullable().optional(),
|
|
2249
2252
|
dedupThreshold: z17.number().nullable().optional(),
|
|
2250
2253
|
probeCount: z17.number().int().nullable().optional(),
|
|
2251
2254
|
citedCount: z17.number().int().nullable().default(null),
|
|
@@ -5760,6 +5763,7 @@ export {
|
|
|
5760
5763
|
categorizeSource,
|
|
5761
5764
|
categorizeSourceWithCompetitors,
|
|
5762
5765
|
categoryLabel,
|
|
5766
|
+
cosineSimilarity,
|
|
5763
5767
|
clusterByCosine,
|
|
5764
5768
|
pickClusterRepresentative,
|
|
5765
5769
|
computeDedupSimilarityStats,
|