@ainyc/canonry 4.109.0 → 4.111.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.
Files changed (27) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +1 -1
  2. package/assets/assets/{BacklinksPage-D48kAAiT.js → BacklinksPage-Ccp5dJm2.js} +1 -1
  3. package/assets/assets/ChartPrimitives-DZI_FVyX.js +1 -0
  4. package/assets/assets/ProjectPage-feeXXGgl.js +7 -0
  5. package/assets/assets/{RunRow-DQy-Gy9t.js → RunRow-CPf7aV1o.js} +1 -1
  6. package/assets/assets/{RunsPage-DRRG4uZS.js → RunsPage-CI8AcUal.js} +1 -1
  7. package/assets/assets/{SettingsPage-Pf0B9gMT.js → SettingsPage-QI2X5EIb.js} +1 -1
  8. package/assets/assets/{TrafficPage-Cd2OL96L.js → TrafficPage-CcELR6n1.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-CiyttCo2.js → TrafficSourceDetailPage-C-9rc4ly.js} +1 -1
  10. package/assets/assets/{arrow-left-DaIR4jsx.js → arrow-left-3WT6TImA.js} +1 -1
  11. package/assets/assets/{extract-error-message-HqopXrW4.js → extract-error-message-43ehRbIG.js} +1 -1
  12. package/assets/assets/{index-CthlUeHu.js → index-BpnaXO_X.js} +65 -65
  13. package/assets/assets/index-JD5rv_sY.css +1 -0
  14. package/assets/assets/{trash-2-DUel-9g8.js → trash-2-Dk-RvBpF.js} +1 -1
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-YEOLQT5S.js → chunk-4TQOZJPF.js} +39 -19
  17. package/dist/{chunk-3HKBUYIY.js → chunk-CVXBE3ST.js} +44 -1
  18. package/dist/{chunk-QZQLZL3C.js → chunk-Y26GYDS6.js} +2 -1
  19. package/dist/{chunk-WXAHSQOX.js → chunk-ZT7GVLS3.js} +18 -0
  20. package/dist/cli.js +409 -106
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-NXZXNM7T.js → intelligence-service-4MQUT3OO.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +8 -8
  25. package/assets/assets/ChartPrimitives-CLSeu1W4.js +0 -1
  26. package/assets/assets/ProjectPage-D20d2kjG.js +0 -7
  27. package/assets/assets/index-CjrSrPKf.css +0 -1
@@ -270,7 +270,7 @@ import {
270
270
  wordpressSchemaDeployResultDtoSchema,
271
271
  wordpressSchemaStatusResultDtoSchema,
272
272
  wordpressStatusDtoSchema
273
- } from "./chunk-WXAHSQOX.js";
273
+ } from "./chunk-ZT7GVLS3.js";
274
274
 
275
275
  // src/intelligence-service.ts
276
276
  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";
@@ -1160,6 +1160,14 @@ var discoverySessions = sqliteTable("discovery_sessions", {
1160
1160
  dedupClusterMinSims: text("dedup_cluster_min_sims", { mode: "json" }).$type(),
1161
1161
  dedupBandPairFraction: real("dedup_band_pair_fraction"),
1162
1162
  dedupPairsTotal: integer("dedup_pairs_total"),
1163
+ // Seed provider set (canonical order; null = legacy / Gemini-only) — part of
1164
+ // session identity for consolidation — and per-provider candidate counts.
1165
+ seedProviders: text("seed_providers", { mode: "json" }).$type(),
1166
+ seedProviderCounts: text("seed_provider_counts", { mode: "json" }).$type(),
1167
+ // TRUE canonical count after dedup, BEFORE the probe-budget slice. seed_count
1168
+ // is post-truncation (probedCanonicals.length), so a deliberately small
1169
+ // maxProbes deflates it; this column is the honest numerator.
1170
+ canonicalCount: integer("canonical_count"),
1163
1171
  dedupThreshold: real("dedup_threshold"),
1164
1172
  probeCount: integer("probe_count"),
1165
1173
  citedCount: integer("cited_count"),
@@ -3452,6 +3460,25 @@ var MIGRATION_VERSIONS = [
3452
3460
  `ALTER TABLE discovery_sessions ADD COLUMN dedup_band_pair_fraction REAL`,
3453
3461
  `ALTER TABLE discovery_sessions ADD COLUMN dedup_pairs_total INTEGER`
3454
3462
  ]
3463
+ },
3464
+ {
3465
+ version: 93,
3466
+ name: "discovery-session-seed-providers",
3467
+ statements: [
3468
+ // Seed provider set (consolidation identity) + per-provider candidate
3469
+ // counts. Additive + nullable — legacy rows stay null (downgrade-safe).
3470
+ `ALTER TABLE discovery_sessions ADD COLUMN seed_providers TEXT`,
3471
+ `ALTER TABLE discovery_sessions ADD COLUMN seed_provider_counts TEXT`
3472
+ ]
3473
+ },
3474
+ {
3475
+ version: 94,
3476
+ name: "discovery-session-canonical-count",
3477
+ statements: [
3478
+ // True post-dedup, pre-truncation canonical count (seed_count is
3479
+ // post-truncation). Additive + nullable (downgrade-safe).
3480
+ `ALTER TABLE discovery_sessions ADD COLUMN canonical_count INTEGER`
3481
+ ]
3455
3482
  }
3456
3483
  ];
3457
3484
  function rebuildBacklinkTableWithSource(tx, table) {
@@ -18119,6 +18146,7 @@ var routeCatalog = [
18119
18146
  properties: {
18120
18147
  icpDescription: { type: "string", description: "Free-text ICP. Required if the project does not have spec.icpDescription stored." },
18121
18148
  buyerDescription: { type: "string", description: "Who evaluates or buys the offering, separate from the ICP. When present, every generated seed query is anchored on this buyer and the seed prompt enforces buyer-fit." },
18149
+ seedProviders: { type: "array", items: { type: "string", enum: ["gemini", "openai"] }, minItems: 1, description: "Which providers generate seed candidates. Omit for the Gemini-only default. Canonicalized (deduped + sorted); part of the session consolidation identity." },
18122
18150
  dedupThreshold: { type: "number", description: "Cosine similarity threshold for clustering. Defaults to 0.95." },
18123
18151
  maxProbes: { type: "integer", description: "Max canonical queries to probe in this session. Default 100, hard cap 500." },
18124
18152
  probeConcurrency: {
@@ -33812,6 +33840,8 @@ async function discoveryRoutes(app, opts) {
33812
33840
  "icpDescription is required. Pass it in the request body or store it on the project (spec.icpDescription)."
33813
33841
  );
33814
33842
  }
33843
+ const requestedSeedProviders = parsed.data.seedProviders ?? null;
33844
+ const seedProviders = requestedSeedProviders && !(requestedSeedProviders.length === 1 && requestedSeedProviders[0] === "gemini") ? requestedSeedProviders : null;
33815
33845
  const locations = orderLocationsDefaultFirst(
33816
33846
  resolveLocations(project.locations, parsed.data.locations),
33817
33847
  project.defaultLocation
@@ -33841,6 +33871,10 @@ async function discoveryRoutes(app, opts) {
33841
33871
  // never reuses — a one-time, bounded (2h window) non-reuse after
33842
33872
  // upgrade, never a wrong reuse.
33843
33873
  locations.length === 0 ? or5(isNull(discoverySessions.locations), eq35(discoverySessions.locations, locations)) : eq35(discoverySessions.locations, locations),
33874
+ // Seed provider set is identity: a different phrasing distribution
33875
+ // must never reuse another set's session. Null (= Gemini-only
33876
+ // default, including explicit ['gemini']) matches legacy rows.
33877
+ seedProviders == null ? isNull(discoverySessions.seedProviders) : eq35(discoverySessions.seedProviders, seedProviders),
33844
33878
  inArray12(discoverySessions.status, [
33845
33879
  DiscoverySessionStatuses.queued,
33846
33880
  DiscoverySessionStatuses.seeding,
@@ -33860,6 +33894,7 @@ async function discoveryRoutes(app, opts) {
33860
33894
  status: DiscoverySessionStatuses.queued,
33861
33895
  icpDescription,
33862
33896
  buyerDescription: parsed.data.buyerDescription ?? null,
33897
+ seedProviders,
33863
33898
  locations,
33864
33899
  dedupThreshold: parsed.data.dedupThreshold,
33865
33900
  competitorMap: [],
@@ -33896,6 +33931,7 @@ async function discoveryRoutes(app, opts) {
33896
33931
  projectId: project.id,
33897
33932
  icpDescription,
33898
33933
  buyerDescription: parsed.data.buyerDescription,
33934
+ seedProviders: seedProviders ?? void 0,
33899
33935
  dedupThreshold: parsed.data.dedupThreshold,
33900
33936
  maxProbes: parsed.data.maxProbes,
33901
33937
  probeConcurrency: parsed.data.probeConcurrency,
@@ -34154,6 +34190,9 @@ function serializeSession(row) {
34154
34190
  buyerDescription: row.buyerDescription ?? null,
34155
34191
  locations: row.locations ?? null,
34156
34192
  seedRawCandidates: row.seedRawCandidates ?? null,
34193
+ seedProviders: row.seedProviders ?? null,
34194
+ seedProviderCounts: row.seedProviderCounts ?? null,
34195
+ canonicalCount: row.canonicalCount ?? null,
34157
34196
  dedupClusterMinSims: row.dedupClusterMinSims ?? null,
34158
34197
  dedupBandPairFraction: row.dedupBandPairFraction ?? null,
34159
34198
  dedupPairsTotal: row.dedupPairsTotal ?? null,
@@ -34266,6 +34305,7 @@ async function executeDiscovery(opts) {
34266
34305
  project: opts.project,
34267
34306
  icpDescription: opts.icpDescription,
34268
34307
  buyerDescription: opts.buyerDescription,
34308
+ seedProviders: opts.seedProviders,
34269
34309
  locations: opts.locations ?? []
34270
34310
  });
34271
34311
  const { kept: unbrandedCandidates, droppedBranded } = filterBrandedSeedCandidates({
@@ -34297,11 +34337,14 @@ async function executeDiscovery(opts) {
34297
34337
  seedFromAnswerCount: seedResult.fromAnswerCount ?? null,
34298
34338
  seedFromGroundingCount: seedResult.fromGroundingCount ?? null,
34299
34339
  seedBrandFilteredCount: droppedBranded.length,
34340
+ canonicalCount: canonicals.length,
34300
34341
  // Full seed provenance + dedup calibration diagnostics: the raw
34301
34342
  // candidate list (as the seed dep returned it, pre-filter) makes every
34302
34343
  // live session a replayable fixture; the similarity stats are the data
34303
34344
  // the 0.95-threshold decision was missing. No gate reads any of these.
34304
34345
  seedRawCandidates: seedResult.candidates,
34346
+ seedProviders: opts.seedProviders ?? null,
34347
+ seedProviderCounts: seedResult.providerCounts ?? null,
34305
34348
  dedupClusterMinSims: dedupStats.perClusterMinSimilarity,
34306
34349
  dedupBandPairFraction: dedupStats.bandPairFraction,
34307
34350
  dedupPairsTotal: dedupStats.pairsTotal,
@@ -25,7 +25,7 @@ import {
25
25
  trafficConnectVercelRequestSchema,
26
26
  trafficConnectWordpressRequestSchema,
27
27
  trafficEventKindSchema
28
- } from "./chunk-WXAHSQOX.js";
28
+ } from "./chunk-ZT7GVLS3.js";
29
29
 
30
30
  // src/config.ts
31
31
  import fs from "fs";
@@ -5566,6 +5566,7 @@ var discoveryRunInputSchema = z2.object({
5566
5566
  // upper bound; this just clarifies the meaning of each knob.
5567
5567
  icpDescription: z2.string().min(1).optional().describe("Free-text ICP description. If omitted, the project must already have spec.icpDescription stored."),
5568
5568
  buyerDescription: z2.string().min(1).optional().describe("Who evaluates or buys the offering, separate from the ICP. When present, every generated query is anchored on this buyer."),
5569
+ seedProviders: z2.array(z2.enum(["gemini", "openai"])).min(1).optional().describe('Which providers generate seed candidates. Omit for the Gemini-only default; ["gemini","openai"] merges both phrasing distributions before dedup.'),
5569
5570
  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."),
5570
5571
  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}.`),
5571
5572
  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.`)
@@ -2241,6 +2241,14 @@ var discoverySessionDtoSchema = z17.object({
2241
2241
  /** Dedup calibration: fraction of all pairs in the ambiguous 0.90-0.97 band. */
2242
2242
  dedupBandPairFraction: z17.number().nullable().optional(),
2243
2243
  dedupPairsTotal: z17.number().int().nullable().optional(),
2244
+ /** Seed provider set the session ran with (canonical order); null = legacy /
2245
+ * Gemini-only default. */
2246
+ seedProviders: z17.array(z17.string()).nullable().optional(),
2247
+ /** Raw candidate count contributed per seed provider. */
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(),
2244
2252
  dedupThreshold: z17.number().nullable().optional(),
2245
2253
  probeCount: z17.number().int().nullable().optional(),
2246
2254
  citedCount: z17.number().int().nullable().default(null),
@@ -2317,6 +2325,8 @@ function containsWholeToken(normalized, token) {
2317
2325
  }
2318
2326
  return false;
2319
2327
  }
2328
+ var DISCOVERY_SEED_PROVIDERS = ["gemini", "openai"];
2329
+ var discoverySeedProviderSchema = z17.enum(DISCOVERY_SEED_PROVIDERS);
2320
2330
  var discoveryRunRequestSchema = z17.object({
2321
2331
  icpDescription: z17.string().min(1).optional(),
2322
2332
  /**
@@ -2326,6 +2336,14 @@ var discoveryRunRequestSchema = z17.object({
2326
2336
  * generic provider comparisons.
2327
2337
  */
2328
2338
  buyerDescription: z17.string().min(1).optional(),
2339
+ /**
2340
+ * Which providers generate seed candidates. Omitted = Gemini-only (the
2341
+ * historical behaviour). Canonicalized (deduped + sorted) so the value is
2342
+ * stable for session-identity comparison. Part of the consolidation
2343
+ * IDENTITY: a different provider set produces a different phrasing
2344
+ * distribution, so it must never reuse another set's session.
2345
+ */
2346
+ seedProviders: z17.array(discoverySeedProviderSchema).min(1).transform((arr) => [...new Set(arr)].sort()).optional(),
2329
2347
  dedupThreshold: z17.number().min(0).max(1).optional(),
2330
2348
  maxProbes: z17.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional(),
2331
2349
  /**