@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.
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +3 -1
- package/assets/assets/{BacklinksPage-CDAv0ggn.js → BacklinksPage-BNrvc-gV.js} +1 -1
- package/assets/assets/{ChartPrimitives-CnAmsyt7.js → ChartPrimitives-BlIkdUdy.js} +1 -1
- package/assets/assets/{ProjectPage-C9KEgRxD.js → ProjectPage-CAyx_xNr.js} +2 -2
- package/assets/assets/{RunRow-CVZ5o8fg.js → RunRow-CAPnKzi7.js} +1 -1
- package/assets/assets/{RunsPage-Bzy5c0MZ.js → RunsPage-idnuzKBn.js} +1 -1
- package/assets/assets/{SettingsPage-B1ocxPBe.js → SettingsPage-Bka67uJq.js} +1 -1
- package/assets/assets/{TrafficPage-D2zepQOC.js → TrafficPage-C_o-rA5o.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-C7JuAkaK.js → TrafficSourceDetailPage-D_jvoSTV.js} +1 -1
- package/assets/assets/{arrow-left-Bv3CWylm.js → arrow-left-B-JfzARi.js} +1 -1
- package/assets/assets/{extract-error-message-BtVid5TP.js → extract-error-message-BhPbjIX6.js} +1 -1
- package/assets/assets/{index-DmNti_xn.js → index-uPSrDA8e.js} +61 -61
- package/assets/assets/{trash-2-BoimCsYz.js → trash-2-BbRvn40h.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-I2BJC3DT.js → chunk-23HGQV22.js} +439 -207
- package/dist/{chunk-3K3QRSYE.js → chunk-DLBQU3VG.js} +93 -2
- package/dist/{chunk-62YB3ML7.js → chunk-LLJPZKHG.js} +46 -1
- package/dist/{chunk-7BMSWI2K.js → chunk-SELXBOAP.js} +19 -4
- package/dist/cli.js +63 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-AHHBQKRD.js → intelligence-service-ZHUJKZRO.js} +2 -2
- package/dist/mcp.js +2 -2
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
3
|
+
} from "./chunk-SELXBOAP.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-LLJPZKHG.js";
|
|
7
|
+
import "./chunk-DLBQU3VG.js";
|
|
8
|
+
import "./chunk-23HGQV22.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-LLJPZKHG.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
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.
|
|
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-
|
|
85
|
-
"@ainyc/canonry-provider-
|
|
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",
|