@ainyc/canonry 2.16.0 → 2.16.3
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/assets/{index-DMx3Oy9W.css → index-Ec4au-rY.css} +1 -1
- package/assets/assets/index-Wi4Qqm0A.js +302 -0
- package/assets/index.html +2 -2
- package/dist/{chunk-CKABU6PE.js → chunk-75EV36V6.js} +525 -214
- package/dist/{chunk-HNVRN5QL.js → chunk-7DVIJC6L.js} +144 -62
- package/dist/cli.js +90 -2
- package/dist/index.js +2 -2
- package/dist/mcp.js +1 -1
- package/package.json +8 -8
- package/assets/assets/index-B18l8ugs.js +0 -302
|
@@ -1913,6 +1913,69 @@ function normalizeUrlPath(input) {
|
|
|
1913
1913
|
return `${pathPart}?${encodeQuery(pairs)}`;
|
|
1914
1914
|
}
|
|
1915
1915
|
|
|
1916
|
+
// ../contracts/src/citations.ts
|
|
1917
|
+
import { z as z18 } from "zod";
|
|
1918
|
+
var citationCoverageProviderSchema = z18.object({
|
|
1919
|
+
provider: z18.string(),
|
|
1920
|
+
citationState: citationStateSchema,
|
|
1921
|
+
cited: z18.boolean(),
|
|
1922
|
+
runId: z18.string(),
|
|
1923
|
+
runCreatedAt: z18.string()
|
|
1924
|
+
});
|
|
1925
|
+
var citationCoverageRowSchema = z18.object({
|
|
1926
|
+
keywordId: z18.string(),
|
|
1927
|
+
keyword: z18.string(),
|
|
1928
|
+
providers: z18.array(citationCoverageProviderSchema),
|
|
1929
|
+
citedCount: z18.number().int().nonnegative(),
|
|
1930
|
+
totalProviders: z18.number().int().nonnegative()
|
|
1931
|
+
});
|
|
1932
|
+
var competitorGapRowSchema = z18.object({
|
|
1933
|
+
keywordId: z18.string(),
|
|
1934
|
+
keyword: z18.string(),
|
|
1935
|
+
provider: z18.string(),
|
|
1936
|
+
citingCompetitors: z18.array(z18.string()),
|
|
1937
|
+
runId: z18.string(),
|
|
1938
|
+
runCreatedAt: z18.string()
|
|
1939
|
+
});
|
|
1940
|
+
var citationVisibilitySummarySchema = z18.object({
|
|
1941
|
+
providersConfigured: z18.number().int().nonnegative(),
|
|
1942
|
+
providersCiting: z18.number().int().nonnegative(),
|
|
1943
|
+
totalKeywords: z18.number().int().nonnegative(),
|
|
1944
|
+
keywordsCited: z18.number().int().nonnegative(),
|
|
1945
|
+
keywordsFullyCovered: z18.number().int().nonnegative(),
|
|
1946
|
+
keywordsUncovered: z18.number().int().nonnegative(),
|
|
1947
|
+
latestRunId: z18.string().nullable(),
|
|
1948
|
+
latestRunAt: z18.string().nullable()
|
|
1949
|
+
});
|
|
1950
|
+
var citationVisibilityResponseSchema = z18.object({
|
|
1951
|
+
summary: citationVisibilitySummarySchema,
|
|
1952
|
+
byKeyword: z18.array(citationCoverageRowSchema),
|
|
1953
|
+
competitorGaps: z18.array(competitorGapRowSchema),
|
|
1954
|
+
status: z18.enum(["ready", "no-data"]),
|
|
1955
|
+
reason: z18.enum(["no-runs-yet", "no-keywords"]).optional()
|
|
1956
|
+
});
|
|
1957
|
+
function emptyCitationVisibility(reason) {
|
|
1958
|
+
return {
|
|
1959
|
+
summary: {
|
|
1960
|
+
providersConfigured: 0,
|
|
1961
|
+
providersCiting: 0,
|
|
1962
|
+
totalKeywords: 0,
|
|
1963
|
+
keywordsCited: 0,
|
|
1964
|
+
keywordsFullyCovered: 0,
|
|
1965
|
+
keywordsUncovered: 0,
|
|
1966
|
+
latestRunId: null,
|
|
1967
|
+
latestRunAt: null
|
|
1968
|
+
},
|
|
1969
|
+
byKeyword: [],
|
|
1970
|
+
competitorGaps: [],
|
|
1971
|
+
status: "no-data",
|
|
1972
|
+
reason
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
function citationStateToCited(state) {
|
|
1976
|
+
return state === "cited";
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1916
1979
|
// src/client.ts
|
|
1917
1980
|
function createApiClient() {
|
|
1918
1981
|
const config = loadConfig();
|
|
@@ -2524,6 +2587,12 @@ var ApiClient = class {
|
|
|
2524
2587
|
const qs = limit ? `?limit=${limit}` : "";
|
|
2525
2588
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/health/history${qs}`);
|
|
2526
2589
|
}
|
|
2590
|
+
async getCitationVisibility(project) {
|
|
2591
|
+
return this.request(
|
|
2592
|
+
"GET",
|
|
2593
|
+
`/projects/${encodeURIComponent(project)}/citations/visibility`
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2527
2596
|
// --- Backlinks ---------------------------------------------------------
|
|
2528
2597
|
async backlinksStatus() {
|
|
2529
2598
|
return this.request("GET", "/backlinks/status");
|
|
@@ -2570,21 +2639,21 @@ var ApiClient = class {
|
|
|
2570
2639
|
};
|
|
2571
2640
|
|
|
2572
2641
|
// src/mcp/tool-registry.ts
|
|
2573
|
-
import { z as
|
|
2642
|
+
import { z as z20 } from "zod";
|
|
2574
2643
|
|
|
2575
2644
|
// src/mcp/schema.ts
|
|
2576
|
-
import { z as
|
|
2577
|
-
var projectNameSchema =
|
|
2578
|
-
var runIdSchema =
|
|
2579
|
-
var insightIdSchema =
|
|
2580
|
-
var analyticsWindowSchema =
|
|
2581
|
-
var emptyInputSchema =
|
|
2582
|
-
var projectInputSchema =
|
|
2645
|
+
import { z as z19 } from "zod";
|
|
2646
|
+
var projectNameSchema = z19.string().min(1).describe("Canonry project name.");
|
|
2647
|
+
var runIdSchema = z19.string().min(1).describe("Canonry run ID.");
|
|
2648
|
+
var insightIdSchema = z19.string().min(1).describe("Canonry insight ID.");
|
|
2649
|
+
var analyticsWindowSchema = z19.enum(["7d", "30d", "90d", "all"]).describe("Analytics time window.");
|
|
2650
|
+
var emptyInputSchema = z19.object({});
|
|
2651
|
+
var projectInputSchema = z19.object({
|
|
2583
2652
|
project: projectNameSchema
|
|
2584
2653
|
});
|
|
2585
2654
|
function toJsonSchema(schema, name) {
|
|
2586
2655
|
return {
|
|
2587
|
-
...
|
|
2656
|
+
...z19.toJSONSchema(schema, { target: "draft-7" }),
|
|
2588
2657
|
title: name
|
|
2589
2658
|
};
|
|
2590
2659
|
}
|
|
@@ -2626,119 +2695,119 @@ function defineTool(tool) {
|
|
|
2626
2695
|
inputJsonSchema: toJsonSchema(tool.inputSchema, tool.name)
|
|
2627
2696
|
};
|
|
2628
2697
|
}
|
|
2629
|
-
var runTriggerInputSchema =
|
|
2698
|
+
var runTriggerInputSchema = z20.object({
|
|
2630
2699
|
project: projectNameSchema,
|
|
2631
2700
|
request: runTriggerRequestSchema.optional()
|
|
2632
2701
|
});
|
|
2633
|
-
var runsListInputSchema =
|
|
2702
|
+
var runsListInputSchema = z20.object({
|
|
2634
2703
|
project: projectNameSchema,
|
|
2635
|
-
limit:
|
|
2704
|
+
limit: z20.number().int().positive().max(500).optional()
|
|
2636
2705
|
});
|
|
2637
|
-
var runGetInputSchema =
|
|
2706
|
+
var runGetInputSchema = z20.object({
|
|
2638
2707
|
runId: runIdSchema
|
|
2639
2708
|
});
|
|
2640
|
-
var timelineInputSchema =
|
|
2709
|
+
var timelineInputSchema = z20.object({
|
|
2641
2710
|
project: projectNameSchema,
|
|
2642
|
-
location:
|
|
2711
|
+
location: z20.string().optional().describe("Location label. Use an empty string for locationless results.")
|
|
2643
2712
|
});
|
|
2644
|
-
var snapshotsListInputSchema =
|
|
2713
|
+
var snapshotsListInputSchema = z20.object({
|
|
2645
2714
|
project: projectNameSchema,
|
|
2646
|
-
limit:
|
|
2647
|
-
offset:
|
|
2648
|
-
location:
|
|
2715
|
+
limit: z20.number().int().positive().max(500).optional(),
|
|
2716
|
+
offset: z20.number().int().nonnegative().optional(),
|
|
2717
|
+
location: z20.string().optional().describe("Location label. Use an empty string for locationless results.")
|
|
2649
2718
|
});
|
|
2650
|
-
var snapshotsDiffInputSchema =
|
|
2719
|
+
var snapshotsDiffInputSchema = z20.object({
|
|
2651
2720
|
project: projectNameSchema,
|
|
2652
2721
|
run1: runIdSchema,
|
|
2653
2722
|
run2: runIdSchema
|
|
2654
2723
|
});
|
|
2655
|
-
var insightsListInputSchema =
|
|
2724
|
+
var insightsListInputSchema = z20.object({
|
|
2656
2725
|
project: projectNameSchema,
|
|
2657
|
-
dismissed:
|
|
2726
|
+
dismissed: z20.boolean().optional(),
|
|
2658
2727
|
runId: runIdSchema.optional()
|
|
2659
2728
|
});
|
|
2660
|
-
var insightInputSchema =
|
|
2729
|
+
var insightInputSchema = z20.object({
|
|
2661
2730
|
project: projectNameSchema,
|
|
2662
2731
|
insightId: insightIdSchema
|
|
2663
2732
|
});
|
|
2664
|
-
var healthHistoryInputSchema =
|
|
2733
|
+
var healthHistoryInputSchema = z20.object({
|
|
2665
2734
|
project: projectNameSchema,
|
|
2666
|
-
limit:
|
|
2735
|
+
limit: z20.number().int().positive().max(100).optional()
|
|
2667
2736
|
});
|
|
2668
|
-
var gscPerformanceInputSchema =
|
|
2737
|
+
var gscPerformanceInputSchema = z20.object({
|
|
2669
2738
|
project: projectNameSchema,
|
|
2670
|
-
startDate:
|
|
2671
|
-
endDate:
|
|
2672
|
-
query:
|
|
2673
|
-
page:
|
|
2674
|
-
limit:
|
|
2739
|
+
startDate: z20.string().optional(),
|
|
2740
|
+
endDate: z20.string().optional(),
|
|
2741
|
+
query: z20.string().optional(),
|
|
2742
|
+
page: z20.string().optional(),
|
|
2743
|
+
limit: z20.number().int().positive().max(500).optional(),
|
|
2675
2744
|
window: analyticsWindowSchema.optional()
|
|
2676
2745
|
});
|
|
2677
|
-
var gscInspectionsInputSchema =
|
|
2746
|
+
var gscInspectionsInputSchema = z20.object({
|
|
2678
2747
|
project: projectNameSchema,
|
|
2679
|
-
url:
|
|
2680
|
-
limit:
|
|
2748
|
+
url: z20.string().optional(),
|
|
2749
|
+
limit: z20.number().int().positive().max(500).optional()
|
|
2681
2750
|
});
|
|
2682
|
-
var gscCoverageHistoryInputSchema =
|
|
2751
|
+
var gscCoverageHistoryInputSchema = z20.object({
|
|
2683
2752
|
project: projectNameSchema,
|
|
2684
|
-
limit:
|
|
2753
|
+
limit: z20.number().int().positive().max(500).optional()
|
|
2685
2754
|
});
|
|
2686
|
-
var gaWindowInputSchema =
|
|
2755
|
+
var gaWindowInputSchema = z20.object({
|
|
2687
2756
|
project: projectNameSchema,
|
|
2688
2757
|
window: analyticsWindowSchema.optional()
|
|
2689
2758
|
});
|
|
2690
2759
|
var gaTrafficInputSchema = gaWindowInputSchema.extend({
|
|
2691
|
-
limit:
|
|
2760
|
+
limit: z20.number().int().positive().max(500).optional()
|
|
2692
2761
|
});
|
|
2693
|
-
var keywordsInputSchema =
|
|
2762
|
+
var keywordsInputSchema = z20.object({
|
|
2694
2763
|
project: projectNameSchema,
|
|
2695
2764
|
request: keywordBatchRequestSchema
|
|
2696
2765
|
});
|
|
2697
|
-
var keywordGenerateInputSchema =
|
|
2766
|
+
var keywordGenerateInputSchema = z20.object({
|
|
2698
2767
|
project: projectNameSchema,
|
|
2699
2768
|
request: keywordGenerateRequestSchema
|
|
2700
2769
|
});
|
|
2701
|
-
var competitorsInputSchema =
|
|
2770
|
+
var competitorsInputSchema = z20.object({
|
|
2702
2771
|
project: projectNameSchema,
|
|
2703
2772
|
request: competitorBatchRequestSchema
|
|
2704
2773
|
});
|
|
2705
|
-
var projectUpsertInputSchema =
|
|
2774
|
+
var projectUpsertInputSchema = z20.object({
|
|
2706
2775
|
project: projectNameSchema,
|
|
2707
2776
|
request: projectUpsertRequestSchema
|
|
2708
2777
|
});
|
|
2709
|
-
var applyConfigInputSchema =
|
|
2778
|
+
var applyConfigInputSchema = z20.object({
|
|
2710
2779
|
config: projectConfigSchema
|
|
2711
2780
|
});
|
|
2712
|
-
var scheduleSetInputSchema =
|
|
2781
|
+
var scheduleSetInputSchema = z20.object({
|
|
2713
2782
|
project: projectNameSchema,
|
|
2714
2783
|
schedule: scheduleUpsertRequestSchema
|
|
2715
2784
|
});
|
|
2716
|
-
var agentWebhookAttachInputSchema =
|
|
2785
|
+
var agentWebhookAttachInputSchema = z20.object({
|
|
2717
2786
|
project: projectNameSchema,
|
|
2718
|
-
url:
|
|
2787
|
+
url: z20.string().url()
|
|
2719
2788
|
});
|
|
2720
|
-
var doctorInputSchema =
|
|
2789
|
+
var doctorInputSchema = z20.object({
|
|
2721
2790
|
project: projectNameSchema.optional().describe("Project name to scope project-level checks. Omit to run global checks (provider keys, config, etc.)."),
|
|
2722
|
-
checks:
|
|
2791
|
+
checks: z20.array(z20.string().min(1)).optional().describe('Optional check IDs or wildcard prefixes (e.g. "google.auth.*", "config.providers"). Empty/omitted runs all matching checks for the chosen scope.')
|
|
2723
2792
|
});
|
|
2724
|
-
var contentTargetsInputSchema =
|
|
2793
|
+
var contentTargetsInputSchema = z20.object({
|
|
2725
2794
|
project: projectNameSchema,
|
|
2726
|
-
limit:
|
|
2727
|
-
includeInProgress:
|
|
2795
|
+
limit: z20.number().int().positive().max(500).optional().describe("Max rows. Defaults to all. Use a small number (3-10) when summarizing for the user."),
|
|
2796
|
+
includeInProgress: z20.boolean().optional().describe("Include rows that already have an in-flight tracked action. Default false.")
|
|
2728
2797
|
});
|
|
2729
|
-
var backlinksDomainsInputSchema =
|
|
2798
|
+
var backlinksDomainsInputSchema = z20.object({
|
|
2730
2799
|
project: projectNameSchema,
|
|
2731
|
-
limit:
|
|
2732
|
-
release:
|
|
2800
|
+
limit: z20.number().int().positive().max(200).optional().describe("Max linking-domain rows. Default 50, max 200."),
|
|
2801
|
+
release: z20.string().optional().describe("Common Crawl release id (e.g., cc-main-2026-jan-feb-mar). Omit for the most recent release with data.")
|
|
2733
2802
|
});
|
|
2734
|
-
var memoryUpsertInputSchema =
|
|
2803
|
+
var memoryUpsertInputSchema = z20.object({
|
|
2735
2804
|
project: projectNameSchema,
|
|
2736
|
-
key:
|
|
2737
|
-
value:
|
|
2805
|
+
key: z20.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH).describe(`Stable identifier for the note (max ${AGENT_MEMORY_KEY_MAX_LENGTH} chars). Writing the same key overwrites the prior value.`),
|
|
2806
|
+
value: z20.string().min(1).describe(`Plain-text note body (max ${AGENT_MEMORY_VALUE_MAX_BYTES} bytes). Use for durable operator preferences, migration context, or non-obvious reasoning that should survive future sessions.`)
|
|
2738
2807
|
});
|
|
2739
|
-
var memoryForgetInputSchema =
|
|
2808
|
+
var memoryForgetInputSchema = z20.object({
|
|
2740
2809
|
project: projectNameSchema,
|
|
2741
|
-
key:
|
|
2810
|
+
key: z20.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH).describe("Exact key of the note to remove. No-op (status=missing) when no note exists for that key.")
|
|
2742
2811
|
});
|
|
2743
2812
|
var AGENT_WEBHOOK_EVENTS = [
|
|
2744
2813
|
notificationEventSchema.enum["run.completed"],
|
|
@@ -2786,10 +2855,10 @@ var canonryMcpTools = [
|
|
|
2786
2855
|
description: "Search query snapshots and intelligence insights for the given text. Looks at snapshot answer text, cited domains, raw provider responses, and insight title/keyword/recommendation/cause. Returns ranked hits with snippets \u2014 use it instead of paginating snapshots when you need to find a competitor mention or term.",
|
|
2787
2856
|
access: "read",
|
|
2788
2857
|
tier: "core",
|
|
2789
|
-
inputSchema:
|
|
2858
|
+
inputSchema: z20.object({
|
|
2790
2859
|
project: projectNameSchema,
|
|
2791
|
-
q:
|
|
2792
|
-
limit:
|
|
2860
|
+
q: z20.string().min(2).describe("Search term, at least 2 characters."),
|
|
2861
|
+
limit: z20.number().int().positive().max(50).optional().describe("Max combined hits (1-50, default 25).")
|
|
2793
2862
|
}),
|
|
2794
2863
|
annotations: readAnnotations(),
|
|
2795
2864
|
openApiOperations: ["GET /api/v1/projects/{name}/search"],
|
|
@@ -2942,6 +3011,17 @@ var canonryMcpTools = [
|
|
|
2942
3011
|
openApiOperations: ["GET /api/v1/projects/{name}/health/history"],
|
|
2943
3012
|
handler: (client, input) => client.getHealthHistory(input.project, input.limit)
|
|
2944
3013
|
}),
|
|
3014
|
+
defineTool({
|
|
3015
|
+
name: "canonry_citations_visibility",
|
|
3016
|
+
title: "Get citation visibility",
|
|
3017
|
+
description: 'Single-call AI citation surface for a Canonry project. Returns the project headline (cited by N of M engines), per-keyword engine coverage rows from the latest snapshot per (keyword \xD7 provider), and a competitor-gap list (keywords where a configured competitor is cited but the project is not). Carries `status: "no-data"` with `reason: "no-keywords"` or `"no-runs-yet"` when inputs are missing.',
|
|
3018
|
+
access: "read",
|
|
3019
|
+
tier: "monitoring",
|
|
3020
|
+
inputSchema: projectInputSchema,
|
|
3021
|
+
annotations: readAnnotations(),
|
|
3022
|
+
openApiOperations: ["GET /api/v1/projects/{name}/citations/visibility"],
|
|
3023
|
+
handler: (client, input) => client.getCitationVisibility(input.project)
|
|
3024
|
+
}),
|
|
2945
3025
|
defineTool({
|
|
2946
3026
|
name: "canonry_content_targets",
|
|
2947
3027
|
title: "Get content targets",
|
|
@@ -3538,6 +3618,8 @@ export {
|
|
|
3538
3618
|
CheckCategories,
|
|
3539
3619
|
summarizeCheckResults,
|
|
3540
3620
|
normalizeUrlPath,
|
|
3621
|
+
emptyCitationVisibility,
|
|
3622
|
+
citationStateToCited,
|
|
3541
3623
|
createApiClient,
|
|
3542
3624
|
ApiClient,
|
|
3543
3625
|
canonryMcpTools
|
package/dist/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
setGoogleAuthConfig,
|
|
18
18
|
showFirstRunNotice,
|
|
19
19
|
trackEvent
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-75EV36V6.js";
|
|
21
21
|
import {
|
|
22
22
|
CcReleaseSyncStatuses,
|
|
23
23
|
CheckScopes,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
saveConfig,
|
|
46
46
|
saveConfigPatch,
|
|
47
47
|
usageError
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-7DVIJC6L.js";
|
|
49
49
|
import {
|
|
50
50
|
apiKeys,
|
|
51
51
|
competitors,
|
|
@@ -6326,6 +6326,84 @@ async function searchProject(project, opts) {
|
|
|
6326
6326
|
}
|
|
6327
6327
|
}
|
|
6328
6328
|
|
|
6329
|
+
// src/commands/citations.ts
|
|
6330
|
+
async function showCitationVisibility(project, opts) {
|
|
6331
|
+
const client = createApiClient();
|
|
6332
|
+
const data = await client.getCitationVisibility(project);
|
|
6333
|
+
if (opts.format === "json") {
|
|
6334
|
+
console.log(JSON.stringify(data, null, 2));
|
|
6335
|
+
return;
|
|
6336
|
+
}
|
|
6337
|
+
if (data.status === "no-data") {
|
|
6338
|
+
if (data.reason === "no-keywords") {
|
|
6339
|
+
console.log("No keywords configured. Add some with `canonry keyword add`.");
|
|
6340
|
+
} else {
|
|
6341
|
+
console.log("No citation data yet \u2014 run a sweep first (canonry run <project>).");
|
|
6342
|
+
}
|
|
6343
|
+
return;
|
|
6344
|
+
}
|
|
6345
|
+
printSummary(data);
|
|
6346
|
+
console.log("");
|
|
6347
|
+
printCoverage(data);
|
|
6348
|
+
if (data.competitorGaps.length > 0) {
|
|
6349
|
+
console.log("");
|
|
6350
|
+
printGaps2(data);
|
|
6351
|
+
}
|
|
6352
|
+
}
|
|
6353
|
+
function printSummary(data) {
|
|
6354
|
+
const { providersCiting, providersConfigured, totalKeywords, keywordsCited, keywordsFullyCovered, keywordsUncovered } = data.summary;
|
|
6355
|
+
console.log(`Citation visibility \u2014 cited by ${providersCiting}/${providersConfigured} engines`);
|
|
6356
|
+
if (data.summary.latestRunAt) {
|
|
6357
|
+
console.log(`Latest run: ${data.summary.latestRunAt}`);
|
|
6358
|
+
}
|
|
6359
|
+
console.log(`Keywords: ${totalKeywords}`);
|
|
6360
|
+
console.log(` cited (any): ${keywordsCited}`);
|
|
6361
|
+
console.log(` fully covered: ${keywordsFullyCovered}`);
|
|
6362
|
+
console.log(` uncovered: ${keywordsUncovered}`);
|
|
6363
|
+
}
|
|
6364
|
+
function printCoverage(data) {
|
|
6365
|
+
if (data.byKeyword.length === 0) {
|
|
6366
|
+
console.log("No keyword coverage rows.");
|
|
6367
|
+
return;
|
|
6368
|
+
}
|
|
6369
|
+
const providerSet = /* @__PURE__ */ new Set();
|
|
6370
|
+
for (const row of data.byKeyword) {
|
|
6371
|
+
for (const p of row.providers) providerSet.add(p.provider);
|
|
6372
|
+
}
|
|
6373
|
+
const providerColumns = Array.from(providerSet).sort();
|
|
6374
|
+
if (providerColumns.length === 0) {
|
|
6375
|
+
console.log("Per-keyword coverage:");
|
|
6376
|
+
for (const row of data.byKeyword) {
|
|
6377
|
+
console.log(` ${row.keyword.padEnd(35)} no snapshots`);
|
|
6378
|
+
}
|
|
6379
|
+
return;
|
|
6380
|
+
}
|
|
6381
|
+
const keywordWidth = Math.max(7, ...data.byKeyword.map((r) => r.keyword.length));
|
|
6382
|
+
const header = ["Keyword".padEnd(keywordWidth), ...providerColumns.map((p) => p.padEnd(10)), "Coverage"].join(" ");
|
|
6383
|
+
console.log("Per-keyword coverage:");
|
|
6384
|
+
console.log(header);
|
|
6385
|
+
console.log("\u2500".repeat(header.length));
|
|
6386
|
+
for (const row of data.byKeyword) {
|
|
6387
|
+
const cells = providerColumns.map((p) => {
|
|
6388
|
+
const provider = row.providers.find((x) => x.provider === p);
|
|
6389
|
+
if (!provider) return "\u2013".padEnd(10);
|
|
6390
|
+
return (provider.cited ? "\u2713" : "\u2717").padEnd(10);
|
|
6391
|
+
});
|
|
6392
|
+
const coverage = `${row.citedCount}/${row.totalProviders}`;
|
|
6393
|
+
console.log([row.keyword.padEnd(keywordWidth), ...cells, coverage].join(" "));
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6396
|
+
function printGaps2(data) {
|
|
6397
|
+
console.log("Competitor gaps (not cited but a competitor is):");
|
|
6398
|
+
const keywordWidth = Math.max(7, ...data.competitorGaps.map((g) => g.keyword.length));
|
|
6399
|
+
const providerWidth = Math.max(8, ...data.competitorGaps.map((g) => g.provider.length));
|
|
6400
|
+
for (const gap of data.competitorGaps) {
|
|
6401
|
+
console.log(
|
|
6402
|
+
` ${gap.keyword.padEnd(keywordWidth)} ${gap.provider.padEnd(providerWidth)} ${gap.citingCompetitors.join(", ")}`
|
|
6403
|
+
);
|
|
6404
|
+
}
|
|
6405
|
+
}
|
|
6406
|
+
|
|
6329
6407
|
// src/cli-commands/intelligence.ts
|
|
6330
6408
|
var INTELLIGENCE_CLI_COMMANDS = [
|
|
6331
6409
|
{
|
|
@@ -6400,6 +6478,16 @@ var INTELLIGENCE_CLI_COMMANDS = [
|
|
|
6400
6478
|
});
|
|
6401
6479
|
await searchProject(project, { query, limit, format: input.format });
|
|
6402
6480
|
}
|
|
6481
|
+
},
|
|
6482
|
+
{
|
|
6483
|
+
path: ["citations", "visibility"],
|
|
6484
|
+
usage: "canonry citations visibility <project> [--format json]",
|
|
6485
|
+
options: {},
|
|
6486
|
+
run: async (input) => {
|
|
6487
|
+
const usage = "canonry citations visibility <project> [--format json]";
|
|
6488
|
+
const project = requireProject(input, "citations visibility", usage);
|
|
6489
|
+
await showCitationVisibility(project, { format: input.format });
|
|
6490
|
+
}
|
|
6403
6491
|
}
|
|
6404
6492
|
];
|
|
6405
6493
|
|
package/dist/index.js
CHANGED
package/dist/mcp.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "2.16.
|
|
3
|
+
"version": "2.16.3",
|
|
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",
|
|
@@ -60,20 +60,20 @@
|
|
|
60
60
|
"tsup": "^8.5.1",
|
|
61
61
|
"tsx": "^4.19.0",
|
|
62
62
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
63
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
64
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
65
63
|
"@ainyc/canonry-db": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
67
64
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
65
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
66
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
71
71
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
72
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
72
73
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
74
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
73
75
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
75
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-provider-gemini": "0.0.0"
|
|
76
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
79
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|