@ainyc/canonry 4.85.0 → 4.86.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 (23) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +3 -1
  2. package/assets/assets/{BacklinksPage-CDAv0ggn.js → BacklinksPage-BNrvc-gV.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-CnAmsyt7.js → ChartPrimitives-BlIkdUdy.js} +1 -1
  4. package/assets/assets/{ProjectPage-C9KEgRxD.js → ProjectPage-CAyx_xNr.js} +2 -2
  5. package/assets/assets/{RunRow-CVZ5o8fg.js → RunRow-CAPnKzi7.js} +1 -1
  6. package/assets/assets/{RunsPage-Bzy5c0MZ.js → RunsPage-idnuzKBn.js} +1 -1
  7. package/assets/assets/{SettingsPage-B1ocxPBe.js → SettingsPage-Bka67uJq.js} +1 -1
  8. package/assets/assets/{TrafficPage-D2zepQOC.js → TrafficPage-C_o-rA5o.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-C7JuAkaK.js → TrafficSourceDetailPage-D_jvoSTV.js} +1 -1
  10. package/assets/assets/{arrow-left-Bv3CWylm.js → arrow-left-B-JfzARi.js} +1 -1
  11. package/assets/assets/{extract-error-message-BtVid5TP.js → extract-error-message-BhPbjIX6.js} +1 -1
  12. package/assets/assets/{index-DmNti_xn.js → index-uPSrDA8e.js} +61 -61
  13. package/assets/assets/{trash-2-BoimCsYz.js → trash-2-BbRvn40h.js} +1 -1
  14. package/assets/index.html +1 -1
  15. package/dist/{chunk-I2BJC3DT.js → chunk-23HGQV22.js} +439 -207
  16. package/dist/{chunk-3K3QRSYE.js → chunk-DLBQU3VG.js} +93 -2
  17. package/dist/{chunk-62YB3ML7.js → chunk-LLJPZKHG.js} +46 -1
  18. package/dist/{chunk-7BMSWI2K.js → chunk-SELXBOAP.js} +19 -4
  19. package/dist/cli.js +63 -4
  20. package/dist/index.js +4 -4
  21. package/dist/{intelligence-service-AHHBQKRD.js → intelligence-service-ZHUJKZRO.js} +2 -2
  22. package/dist/mcp.js +2 -2
  23. package/package.json +7 -7
@@ -46,8 +46,10 @@ import {
46
46
  adsSummaryDtoSchema,
47
47
  adsSyncResponseSchema,
48
48
  agentProvidersResponseDtoSchema,
49
+ aggregateHarvestedQueries,
49
50
  apiKeyDtoSchema,
50
51
  apiKeyListDtoSchema,
52
+ applyHarvestSemanticNovelty,
51
53
  auditLogEntrySchema,
52
54
  authInvalid,
53
55
  authRequired,
@@ -70,6 +72,7 @@ import {
70
72
  brandKeyFromText,
71
73
  brandLabelFromDomain,
72
74
  brandMetricsDtoSchema,
75
+ buildHarvestAnchorTerms,
73
76
  categorizeSource,
74
77
  categorizeSourceWithCompetitors,
75
78
  categoryLabel,
@@ -104,6 +107,7 @@ import {
104
107
  deriveWinnabilityClass,
105
108
  determineAnswerMentioned,
106
109
  discoveryBucketSchema,
110
+ discoveryHarvestDtoSchema,
107
111
  discoveryPromotePreviewSchema,
108
112
  discoveryPromoteRequestSchema,
109
113
  discoveryPromoteResultSchema,
@@ -130,6 +134,7 @@ import {
130
134
  ga4SocialReferralHistoryEntrySchema,
131
135
  ga4StatusDtoSchema,
132
136
  ga4SyncResponseDtoSchema,
137
+ gateHarvestedSearchQueries,
133
138
  gbpAccountListResponseSchema,
134
139
  gbpDailyMetricListResponseSchema,
135
140
  gbpDiscoverRequestSchema,
@@ -248,7 +253,7 @@ import {
248
253
  wordpressSchemaDeployResultDtoSchema,
249
254
  wordpressSchemaStatusResultDtoSchema,
250
255
  wordpressStatusDtoSchema
251
- } from "./chunk-I2BJC3DT.js";
256
+ } from "./chunk-23HGQV22.js";
252
257
 
253
258
  // src/intelligence-service.ts
254
259
  import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
@@ -13577,6 +13582,7 @@ var SCHEMA_TABLE = {
13577
13582
  DomainClassificationsResponseDto: domainClassificationsResponseDtoSchema,
13578
13583
  RecommendationBriefDto: recommendationBriefDtoSchema,
13579
13584
  RecommendationExplanationDto: recommendationExplanationDtoSchema,
13585
+ DiscoveryHarvestDto: discoveryHarvestDtoSchema,
13580
13586
  DiscoveryPromotePreview: discoveryPromotePreviewSchema,
13581
13587
  DiscoveryPromoteResult: discoveryPromoteResultSchema,
13582
13588
  DiscoverySessionDetailDto: discoverySessionDetailDtoSchema,
@@ -17432,6 +17438,23 @@ var routeCatalog = [
17432
17438
  404: errorResponse("Project or session not found.")
17433
17439
  }
17434
17440
  },
17441
+ {
17442
+ method: "get",
17443
+ path: "/api/v1/projects/{name}/discover/sessions/{id}/harvest",
17444
+ summary: "Harvest issued search queries (grounding fan-out) from a session",
17445
+ description: "Reads the search queries the answer engine actually issued to answer each probe (Gemini's `groundingMetadata.webSearchQueries` fan-out) back out of the session's stored probe payloads, then runs a mandatory quality gate and returns the survivors as candidate seeds, ranked by how many distinct probes issued each one. The gate drops navigational/phone lookups, over-specific outliers, off-subject acronym collisions, exact already-tracked matches, and \u2014 via an embedding cosine pass over the project's tracked queries \u2014 semantic duplicates (paraphrases/synonyms an exact match can't see). `semanticNoveltyApplied` reports whether that embedding pass ran (it falls back to exact-match when embeddings are unavailable). These are a THIRD signal \u2014 *issued retrieval queries* \u2014 distinct from `mention` (answer text) and `cited` (source list); they carry no demand of their own. Read-only and derived: nothing is probed, tracked, or promoted. `minProbeHits` raises the recurrence floor; `anchor=false` disables the subject anchor for new-subject discovery on a well-scoped project. `stats` carries the raw count and a per-reason rejection tally. Issue #713.",
17446
+ tags: ["discovery"],
17447
+ parameters: [
17448
+ nameParameter,
17449
+ { name: "id", in: "path", required: true, description: "Discovery session ID.", schema: stringSchema },
17450
+ { name: "minProbeHits", in: "query", required: false, description: "Minimum number of distinct probes a candidate must appear in to be admitted (recurrence floor). Default 1.", schema: stringSchema },
17451
+ { name: "anchor", in: "query", required: false, description: 'Set to "false" to disable the subject-anchor filter. Default applies it (when the subject corpus is rich enough).', schema: stringSchema }
17452
+ ],
17453
+ responses: {
17454
+ 200: jsonResponse("Harvested candidate seeds + gate stats returned.", "DiscoveryHarvestDto"),
17455
+ 404: errorResponse("Project or session not found.")
17456
+ }
17457
+ },
17435
17458
  {
17436
17459
  method: "get",
17437
17460
  path: "/api/v1/projects/{name}/discover/sessions/{id}/promote",
@@ -32896,6 +32919,72 @@ async function discoveryRoutes(app, opts) {
32896
32919
  return reply.send(detail);
32897
32920
  }
32898
32921
  );
32922
+ app.get(
32923
+ "/projects/:name/discover/sessions/:id/harvest",
32924
+ async (request, reply) => {
32925
+ const project = resolveProject(app.db, request.params.name);
32926
+ const session = app.db.select().from(discoverySessions).where(eq34(discoverySessions.id, request.params.id)).get();
32927
+ if (!session || session.projectId !== project.id) {
32928
+ throw notFound("Discovery session", request.params.id);
32929
+ }
32930
+ const parsedFloor = parseInt(request.query.minProbeHits ?? "", 10);
32931
+ const minProbeHits = Number.isNaN(parsedFloor) || parsedFloor < 1 ? 1 : parsedFloor;
32932
+ const applyAnchor = request.query.anchor !== "false";
32933
+ const provider = session.seedProvider ?? "gemini";
32934
+ const probeRows = app.db.select().from(discoveryProbes).where(eq34(discoveryProbes.sessionId, session.id)).all();
32935
+ const extract = opts.harvestSearchQueries;
32936
+ const probesWithQueries = probeRows.map((row) => {
32937
+ if (!extract || !row.rawResponse) return { searchQueries: [] };
32938
+ try {
32939
+ const raw = JSON.parse(row.rawResponse);
32940
+ return { searchQueries: extract({ provider, rawResponse: raw }) };
32941
+ } catch {
32942
+ return { searchQueries: [] };
32943
+ }
32944
+ });
32945
+ const trackedQueries = app.db.select({ query: queries.query }).from(queries).where(eq34(queries.projectId, project.id)).all().map((r) => r.query);
32946
+ const anchorTerms = buildHarvestAnchorTerms(
32947
+ [session.icpDescription ?? "", ...trackedQueries],
32948
+ effectiveDomains(project)
32949
+ );
32950
+ const aggregated = aggregateHarvestedQueries(probesWithQueries);
32951
+ let result = gateHarvestedSearchQueries({
32952
+ candidates: aggregated,
32953
+ trackedQueries,
32954
+ anchorTerms,
32955
+ minProbeHits,
32956
+ applyAnchor
32957
+ });
32958
+ let semanticNoveltyApplied = false;
32959
+ if (opts.embedQueries && result.admitted.length > 0 && trackedQueries.length > 0) {
32960
+ try {
32961
+ const candidateTexts = result.admitted.map((c) => c.query);
32962
+ const vectors = await opts.embedQueries([...candidateTexts, ...trackedQueries]);
32963
+ if (vectors.length === candidateTexts.length + trackedQueries.length) {
32964
+ result = applyHarvestSemanticNovelty({
32965
+ result,
32966
+ candidateVectors: vectors.slice(0, candidateTexts.length),
32967
+ trackedVectors: vectors.slice(candidateTexts.length)
32968
+ });
32969
+ semanticNoveltyApplied = true;
32970
+ }
32971
+ } catch {
32972
+ }
32973
+ }
32974
+ const harvest = {
32975
+ sessionId: session.id,
32976
+ projectId: project.id,
32977
+ provider,
32978
+ status: session.status,
32979
+ minProbeHits,
32980
+ anchorApplied: result.anchorApplied,
32981
+ semanticNoveltyApplied,
32982
+ candidates: result.admitted,
32983
+ stats: result.stats
32984
+ };
32985
+ return reply.send(harvest);
32986
+ }
32987
+ );
32899
32988
  app.get(
32900
32989
  "/projects/:name/discover/sessions/:id/promote",
32901
32990
  async (request, reply) => {
@@ -33581,7 +33670,9 @@ async function apiRoutes(app, opts) {
33581
33670
  discoverLatestRelease: opts.discoverLatestRelease
33582
33671
  });
33583
33672
  await api.register(discoveryRoutes, {
33584
- onDiscoveryRunRequested: opts.onDiscoveryRunRequested
33673
+ onDiscoveryRunRequested: opts.onDiscoveryRunRequested,
33674
+ harvestSearchQueries: opts.harvestSearchQueries,
33675
+ embedQueries: opts.embedQueries
33585
33676
  });
33586
33677
  await api.register(technicalAeoRoutes, {
33587
33678
  onSiteAuditRequested: opts.onSiteAuditRequested
@@ -23,7 +23,7 @@ import {
23
23
  trafficConnectVercelRequestSchema,
24
24
  trafficConnectWordpressRequestSchema,
25
25
  trafficEventKindSchema
26
- } from "./chunk-I2BJC3DT.js";
26
+ } from "./chunk-23HGQV22.js";
27
27
 
28
28
  // src/config.ts
29
29
  import fs from "fs";
@@ -3454,6 +3454,18 @@ var getApiV1ProjectsByNameDiscoverSessionsById = (options) => {
3454
3454
  ...options
3455
3455
  });
3456
3456
  };
3457
+ var getApiV1ProjectsByNameDiscoverSessionsByIdHarvest = (options) => {
3458
+ return (options.client ?? client).get({
3459
+ security: [
3460
+ {
3461
+ scheme: "bearer",
3462
+ type: "http"
3463
+ }
3464
+ ],
3465
+ url: "/api/v1/projects/{name}/discover/sessions/{id}/harvest",
3466
+ ...options
3467
+ });
3468
+ };
3457
3469
  var getApiV1ProjectsByNameDiscoverSessionsByIdPromote = (options) => {
3458
3470
  return (options.client ?? client).get({
3459
3471
  security: [
@@ -4750,6 +4762,19 @@ var ApiClient = class {
4750
4762
  })
4751
4763
  );
4752
4764
  }
4765
+ async getDiscoveryHarvest(project, sessionId, opts) {
4766
+ return this.invoke(
4767
+ () => getApiV1ProjectsByNameDiscoverSessionsByIdHarvest({
4768
+ client: this.heyClient,
4769
+ path: { name: project, id: sessionId },
4770
+ query: {
4771
+ minProbeHits: opts?.minProbeHits !== void 0 ? String(opts.minProbeHits) : void 0,
4772
+ // The server treats anchor=false as "disable"; omit otherwise.
4773
+ anchor: opts?.anchor === false ? "false" : void 0
4774
+ }
4775
+ })
4776
+ );
4777
+ }
4753
4778
  async previewDiscoveryPromote(project, sessionId) {
4754
4779
  return this.invoke(
4755
4780
  () => getApiV1ProjectsByNameDiscoverSessionsByIdPromote({
@@ -5494,6 +5519,12 @@ var discoverySessionIdInputSchema = z2.object({
5494
5519
  project: projectNameSchema,
5495
5520
  sessionId: z2.string().min(1).describe("Discovery session ID returned by canonry_discover_run_start.")
5496
5521
  });
5522
+ var discoveryHarvestInputSchema = z2.object({
5523
+ project: projectNameSchema,
5524
+ sessionId: z2.string().min(1).describe("Discovery session ID returned by canonry_discover_run_start."),
5525
+ minProbeHits: z2.number().int().positive().optional().describe("Recurrence floor \u2014 a candidate must have appeared in at least this many distinct probes to be admitted. Default 1."),
5526
+ anchor: z2.boolean().optional().describe("Apply the subject-anchor filter that drops off-topic acronym collisions. Default true; pass false for new-subject discovery on a well-scoped project.")
5527
+ });
5497
5528
  var discoveryPromoteInputSchema = z2.object({
5498
5529
  project: projectNameSchema,
5499
5530
  sessionId: z2.string().min(1).describe("Discovery session ID returned by canonry_discover_run_start."),
@@ -6749,6 +6780,20 @@ var canonryMcpTools = [
6749
6780
  openApiOperations: ["GET /api/v1/projects/{name}/discover/sessions/{id}"],
6750
6781
  handler: (client2, input) => client2.getDiscoverySession(input.project, input.sessionId)
6751
6782
  }),
6783
+ defineTool({
6784
+ name: "canonry_discover_harvest",
6785
+ title: "Harvest discovery search queries",
6786
+ description: `Read the search queries the answer engine actually issued (Gemini's grounding fan-out) back out of a session's stored probes, gate them for buyer-intent + novelty, and return the survivors as candidate seeds ranked by how many distinct probes issued each one. These are a THIRD signal \u2014 issued retrieval queries \u2014 distinct from mention (answer text) and cited (source list); they carry no demand of their own. Read-only and derived: nothing is probed, tracked, or promoted. Use it to surface "queries the model searched for that you aren't tracking yet"; the operator/agent then decides what to add via canonry_query_add. minProbeHits raises the recurrence floor; anchor=false disables the subject filter. stats carries the raw count and per-reason rejection tally.`,
6787
+ access: "read",
6788
+ tier: "discovery",
6789
+ inputSchema: discoveryHarvestInputSchema,
6790
+ annotations: readAnnotations(),
6791
+ openApiOperations: ["GET /api/v1/projects/{name}/discover/sessions/{id}/harvest"],
6792
+ handler: (client2, input) => client2.getDiscoveryHarvest(input.project, input.sessionId, {
6793
+ minProbeHits: input.minProbeHits,
6794
+ anchor: input.anchor
6795
+ })
6796
+ }),
6752
6797
  defineTool({
6753
6798
  name: "canonry_discover_promote_preview",
6754
6799
  title: "Preview discovery promotion",
@@ -9,7 +9,7 @@ import {
9
9
  loadConfig,
10
10
  loadConfigRaw,
11
11
  saveConfigPatch
12
- } from "./chunk-62YB3ML7.js";
12
+ } from "./chunk-LLJPZKHG.js";
13
13
  import {
14
14
  CC_CACHE_DIR,
15
15
  DUCKDB_SPEC,
@@ -104,7 +104,7 @@ import {
104
104
  siteAuditPages,
105
105
  siteAuditSnapshots,
106
106
  usageCounters
107
- } from "./chunk-3K3QRSYE.js";
107
+ } from "./chunk-DLBQU3VG.js";
108
108
  import {
109
109
  AGENT_MEMORY_VALUE_MAX_BYTES,
110
110
  AGENT_PROVIDER_IDS,
@@ -160,7 +160,7 @@ import {
160
160
  validationError,
161
161
  winnabilityClassLabel,
162
162
  withRetry
163
- } from "./chunk-I2BJC3DT.js";
163
+ } from "./chunk-23HGQV22.js";
164
164
 
165
165
  // src/telemetry.ts
166
166
  import crypto from "crypto";
@@ -6289,7 +6289,7 @@ function readStoredGroundingSources(rawResponse) {
6289
6289
  return result;
6290
6290
  }
6291
6291
  async function backfillInsightsCommand(project, opts) {
6292
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-AHHBQKRD.js");
6292
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ZHUJKZRO.js");
6293
6293
  const config = loadConfig();
6294
6294
  const db = createClient(config.database);
6295
6295
  migrate(db);
@@ -10877,6 +10877,21 @@ async function createServer(opts) {
10877
10877
  app.log.error({ runId: input.runId, err }, "Discovery run failed");
10878
10878
  });
10879
10879
  },
10880
+ // Read issued search queries (fan-out) back out of a stored probe payload.
10881
+ // Discovery is Gemini-only today, so the Gemini extractor handles every
10882
+ // probe; the provider arg lets a future multi-provider discovery dispatch.
10883
+ harvestSearchQueries: ({ rawResponse }) => extractSearchQueriesFromRaw(rawResponse),
10884
+ // Embed seam for the harvest's semantic novelty pass — the same Gemini
10885
+ // embedder the discovery seed pipeline uses. Resolved at call time so a
10886
+ // provider key set after boot is picked up; rejects (→ route degrades to
10887
+ // exact-match novelty) when no Gemini key is configured.
10888
+ embedQueries: (queriesToEmbed) => {
10889
+ const cfg = registry.get("gemini")?.config;
10890
+ if (!cfg?.apiKey) {
10891
+ return Promise.reject(new Error("Gemini API key not configured; harvest semantic novelty unavailable"));
10892
+ }
10893
+ return embedQueries(queriesToEmbed, { apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
10894
+ },
10880
10895
  onSiteAuditRequested: (runId, projectId, auditOpts) => {
10881
10896
  runSiteAudit(runId, projectId, auditOpts);
10882
10897
  },
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-7BMSWI2K.js";
30
+ } from "./chunk-SELXBOAP.js";
31
31
  import {
32
32
  CliError,
33
33
  EXIT_SYSTEM_ERROR,
@@ -44,7 +44,7 @@ import {
44
44
  saveConfig,
45
45
  saveConfigPatch,
46
46
  usageError
47
- } from "./chunk-62YB3ML7.js";
47
+ } from "./chunk-LLJPZKHG.js";
48
48
  import {
49
49
  apiKeys,
50
50
  createClient,
@@ -52,7 +52,7 @@ import {
52
52
  projects,
53
53
  queries,
54
54
  renderReportHtml
55
- } from "./chunk-3K3QRSYE.js";
55
+ } from "./chunk-DLBQU3VG.js";
56
56
  import {
57
57
  BacklinkSources,
58
58
  CcReleaseSyncStatuses,
@@ -77,7 +77,7 @@ import {
77
77
  providerQuotaPolicySchema,
78
78
  resolveProviderInput,
79
79
  winnabilityClassSchema
80
- } from "./chunk-I2BJC3DT.js";
80
+ } from "./chunk-23HGQV22.js";
81
81
 
82
82
  // src/cli.ts
83
83
  import { pathToFileURL } from "url";
@@ -1832,6 +1832,39 @@ async function discoverShow(project, sessionId, opts) {
1832
1832
  }
1833
1833
  printSessionDetail(session);
1834
1834
  }
1835
+ async function discoverHarvest(project, sessionId, opts) {
1836
+ const client = getClient4();
1837
+ const harvest = await client.getDiscoveryHarvest(project, sessionId, {
1838
+ minProbeHits: opts.minProbeHits,
1839
+ anchor: opts.anchor
1840
+ });
1841
+ if (opts.format === "json") {
1842
+ console.log(JSON.stringify(harvest, null, 2));
1843
+ return;
1844
+ }
1845
+ if (opts.format === "jsonl") {
1846
+ const context = { project, sessionId, provider: harvest.provider };
1847
+ emitJsonl(harvest.candidates.map((c) => ({ ...context, ...c })));
1848
+ return;
1849
+ }
1850
+ const r = harvest.stats.rejected;
1851
+ console.log(`Harvested issued search queries \u2014 session ${harvest.sessionId} (${harvest.provider})`);
1852
+ console.log(
1853
+ ` ${harvest.stats.admitted} admitted of ${harvest.stats.rawCandidates} raw \xB7 floor=${harvest.minProbeHits} \xB7 anchor=${harvest.anchorApplied ? "on" : "off"} \xB7 novelty=${harvest.semanticNoveltyApplied ? "semantic" : "exact-only"}`
1854
+ );
1855
+ console.log(
1856
+ ` rejected: ${r.belowFloor} below-floor \xB7 ${r.length} length \xB7 ${r.navigational} navigational \xB7 ${r.duplicate} already-tracked \xB7 ${r.semanticDuplicate} synonym \xB7 ${r.offAnchor} off-subject`
1857
+ );
1858
+ if (harvest.candidates.length === 0) {
1859
+ console.log(" (no candidates \u2014 nothing to track from this session)");
1860
+ return;
1861
+ }
1862
+ console.log("");
1863
+ console.log(" HITS QUERY");
1864
+ for (const candidate of harvest.candidates) {
1865
+ console.log(` ${String(candidate.probeHits).padStart(4)} ${candidate.query}`);
1866
+ }
1867
+ }
1835
1868
  async function discoverPromotePreview(project, sessionId, opts) {
1836
1869
  const client = getClient4();
1837
1870
  const preview = await client.previewDiscoveryPromote(project, sessionId);
@@ -2156,6 +2189,32 @@ var DISCOVER_CLI_COMMANDS = [
2156
2189
  });
2157
2190
  }
2158
2191
  },
2192
+ {
2193
+ path: ["discover", "harvest"],
2194
+ usage: "canonry discover harvest <project> <session-id> [--min-probe-hits <n>] [--no-anchor] [--format json|jsonl]",
2195
+ options: {
2196
+ "min-probe-hits": stringOption(),
2197
+ "no-anchor": { type: "boolean", default: false }
2198
+ },
2199
+ run: async (input) => {
2200
+ const usage = "canonry discover harvest <project> <session-id> [--min-probe-hits <n>] [--no-anchor] [--format json|jsonl]";
2201
+ const project = requireProject(input, "discover.harvest", usage);
2202
+ const sessionId = requirePositional(input, 1, {
2203
+ command: "discover.harvest",
2204
+ usage,
2205
+ message: "session ID is required"
2206
+ });
2207
+ await discoverHarvest(project, sessionId, {
2208
+ minProbeHits: parseIntegerOption(input, "min-probe-hits", {
2209
+ command: "discover.harvest",
2210
+ usage,
2211
+ message: "--min-probe-hits must be an integer"
2212
+ }),
2213
+ anchor: !getBoolean(input.values, "no-anchor"),
2214
+ format: input.format
2215
+ });
2216
+ }
2217
+ },
2159
2218
  {
2160
2219
  path: ["discover", "promote", "preview"],
2161
2220
  usage: "canonry discover promote preview <project> <session-id> [--format json]",
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-7BMSWI2K.js";
3
+ } from "./chunk-SELXBOAP.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-62YB3ML7.js";
7
- import "./chunk-3K3QRSYE.js";
8
- import "./chunk-I2BJC3DT.js";
6
+ } from "./chunk-LLJPZKHG.js";
7
+ import "./chunk-DLBQU3VG.js";
8
+ import "./chunk-23HGQV22.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-3K3QRSYE.js";
4
- import "./chunk-I2BJC3DT.js";
3
+ } from "./chunk-DLBQU3VG.js";
4
+ import "./chunk-23HGQV22.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-62YB3ML7.js";
6
+ } from "./chunk-LLJPZKHG.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-I2BJC3DT.js";
9
+ } from "./chunk-23HGQV22.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.85.0",
3
+ "version": "4.86.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",
@@ -62,14 +62,14 @@
62
62
  "@types/node-cron": "^3.0.11",
63
63
  "tsup": "^8.5.1",
64
64
  "tsx": "^4.19.0",
65
- "@ainyc/canonry-config": "0.0.0",
66
65
  "@ainyc/canonry-api-client": "0.0.0",
67
66
  "@ainyc/canonry-api-routes": "0.0.0",
67
+ "@ainyc/canonry-config": "0.0.0",
68
+ "@ainyc/canonry-contracts": "0.0.0",
68
69
  "@ainyc/canonry-db": "0.0.0",
69
70
  "@ainyc/canonry-integration-bing": "0.0.0",
70
71
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
71
72
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
72
- "@ainyc/canonry-contracts": "0.0.0",
73
73
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
74
74
  "@ainyc/canonry-integration-google": "0.0.0",
75
75
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
@@ -78,11 +78,11 @@
78
78
  "@ainyc/canonry-intelligence": "0.0.0",
79
79
  "@ainyc/canonry-integration-wordpress": "0.0.0",
80
80
  "@ainyc/canonry-provider-cdp": "0.0.0",
81
- "@ainyc/canonry-provider-gemini": "0.0.0",
82
- "@ainyc/canonry-provider-local": "0.0.0",
83
81
  "@ainyc/canonry-provider-claude": "0.0.0",
84
- "@ainyc/canonry-provider-openai": "0.0.0",
85
- "@ainyc/canonry-provider-perplexity": "0.0.0"
82
+ "@ainyc/canonry-provider-local": "0.0.0",
83
+ "@ainyc/canonry-provider-gemini": "0.0.0",
84
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
85
+ "@ainyc/canonry-provider-openai": "0.0.0"
86
86
  },
87
87
  "scripts": {
88
88
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",