@ainyc/canonry 4.180.7 → 4.182.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/README.md +80 -45
- package/assets/agent-workspace/skills/canonry/SKILL.md +13 -10
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +7 -6
- package/assets/assets/{AuditHistoryPanel-B1lmI7wm.js → AuditHistoryPanel-1_FHpzj-.js} +1 -1
- package/assets/assets/{BacklinksPage-Bw61uQu8.js → BacklinksPage-045za10_.js} +1 -1
- package/assets/assets/{ChartPrimitives-DG35TyhH.js → ChartPrimitives-DLEICrrL.js} +1 -1
- package/assets/assets/{HistoryPage-D8z9-NkT.js → HistoryPage-36K_6asu.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-CXX9GFj8.js → MeasurementPropertyPage-B4DJGoY6.js} +1 -1
- package/assets/assets/ProjectPage-CshC68Ne.js +9 -0
- package/assets/assets/{RunRow-DXHy16T3.js → RunRow-U2CN755e.js} +1 -1
- package/assets/assets/{RunsPage-D2aE620i.js → RunsPage-D0CtU4d-.js} +1 -1
- package/assets/assets/SettingsPage-zMWieTPK.js +1 -0
- package/assets/assets/SiteHealthSection-TpQPu_Uj.js +4 -0
- package/assets/assets/{TrafficPage-DFHWgvkU.js → TrafficPage-DfLUt-64.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DxjyRL8Y.js → TrafficSourceDetailPage-DbjNNWSt.js} +1 -1
- package/assets/assets/extract-error-message-CWqz1QPC.js +1 -0
- package/assets/assets/index-Brb7M_6G.js +86 -0
- package/assets/assets/index-DwdK2e4e.css +1 -0
- package/assets/assets/{react-sigma_core.esm.min-DAcOZae7.js → react-sigma_core.esm.min-Drqprr9L.js} +1 -1
- package/assets/assets/{vendor-lucide-nYKv-BB7.js → vendor-lucide-XjCNFK0x.js} +1 -1
- package/assets/assets/{vendor-markdown-Bn7fRwrx.js → vendor-markdown-9tTeP8v7.js} +1 -1
- package/assets/assets/{vendor-radix-4UOaVWza.js → vendor-radix-BpmvLvpp.js} +1 -1
- package/assets/assets/{vendor-recharts-D8rt5lKn.js → vendor-recharts-FA0uySU7.js} +1 -1
- package/assets/assets/{vendor-tanstack-Dock0eH1.js → vendor-tanstack-CYBjbqVr.js} +1 -1
- package/assets/index.html +7 -7
- package/dist/{chunk-VZO6CLHY.js → chunk-BDJT7XZL.js} +169 -64
- package/dist/{chunk-RXXZ5BU5.js → chunk-DY5ZDKQW.js} +183 -1
- package/dist/{chunk-CWXPBQR5.js → chunk-FVC7PGYQ.js} +47 -5
- package/dist/{chunk-XYTSKRO3.js → chunk-I3KSOMJA.js} +2 -2
- package/dist/{chunk-WJFBNCVD.js → chunk-K45YKXE4.js} +4310 -3323
- package/dist/cli.js +323 -99
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-MEPYXRBS.js → intelligence-service-HGA553GT.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +7 -7
- package/assets/assets/ProjectPage-BaN_rvoV.js +0 -9
- package/assets/assets/SettingsPage-BiiFqarS.js +0 -1
- package/assets/assets/SiteHealthSection-DCH2Ejtc.js +0 -4
- package/assets/assets/extract-error-message-BdXUZQW9.js +0 -1
- package/assets/assets/index-BuEq5Rhg.css +0 -1
- package/assets/assets/index-CSictO9U.js +0 -83
|
@@ -78,6 +78,14 @@ function runInProgress(projectName) {
|
|
|
78
78
|
function operationInProgress(message, details) {
|
|
79
79
|
return new AppError("OPERATION_IN_PROGRESS", message, 409, details);
|
|
80
80
|
}
|
|
81
|
+
function scheduleVersionConflict(expectedUpdatedAt, actualUpdatedAt) {
|
|
82
|
+
return new AppError(
|
|
83
|
+
"SCHEDULE_VERSION_CONFLICT",
|
|
84
|
+
"The schedule changed since it was loaded. Reload it before saving.",
|
|
85
|
+
409,
|
|
86
|
+
{ expectedUpdatedAt, actualUpdatedAt }
|
|
87
|
+
);
|
|
88
|
+
}
|
|
81
89
|
function measurementPlanRevisionConflict(expectedActiveRevision, actualActiveRevision) {
|
|
82
90
|
return new AppError(
|
|
83
91
|
"MEASUREMENT_PLAN_REVISION_CONFLICT",
|
|
@@ -6715,6 +6723,22 @@ var measurementDraftUpsertCompetitorRequestSchema = z15.object({
|
|
|
6715
6723
|
groupKey: measurementV2StableKeySchema,
|
|
6716
6724
|
competitor: measurementDraftCompetitorSchema
|
|
6717
6725
|
}).strict();
|
|
6726
|
+
var measurementDraftPinCompetitorRequestSchema = z15.object({
|
|
6727
|
+
expectedActiveRevision: measurementDraftRevisionSchema,
|
|
6728
|
+
groupKey: measurementV2StableKeySchema,
|
|
6729
|
+
domain: z15.string().trim().min(1).refine((value) => hostOf(value) !== null, "A competitor domain must be a valid hostname"),
|
|
6730
|
+
label: z15.string().trim().min(1).optional(),
|
|
6731
|
+
aliases: z15.array(z15.string().trim().min(1)).optional()
|
|
6732
|
+
}).strict();
|
|
6733
|
+
var measurementDraftPinCompetitorResponseSchema = measurementDraftMutationResponseSchema.extend({
|
|
6734
|
+
groupKey: measurementV2StableKeySchema,
|
|
6735
|
+
competitor: measurementDraftCompetitorSchema,
|
|
6736
|
+
draftCreated: z15.boolean(),
|
|
6737
|
+
published: z15.object({
|
|
6738
|
+
revision: measurementDraftRevisionSchema,
|
|
6739
|
+
competitorsChanged: z15.literal(false)
|
|
6740
|
+
}).strict()
|
|
6741
|
+
}).strict();
|
|
6718
6742
|
var measurementDraftRemoveCompetitorRequestSchema = z15.object({
|
|
6719
6743
|
groupKey: measurementV2StableKeySchema,
|
|
6720
6744
|
competitorKey: measurementV2StableKeySchema
|
|
@@ -6818,6 +6842,8 @@ var measurementSetupResponseSchema = z15.object({
|
|
|
6818
6842
|
state: measurementSetupStateSchema,
|
|
6819
6843
|
nextAction: measurementSetupNextActionSchema,
|
|
6820
6844
|
mode: measurementSetupModeSchema,
|
|
6845
|
+
/** Whether this project's selected provider roster contains an engine the host can execute now. */
|
|
6846
|
+
answerVisibilityProviderReady: z15.boolean(),
|
|
6821
6847
|
activeRevision: measurementDraftRevisionSchema.nullable(),
|
|
6822
6848
|
activeSchemaVersion: z15.union([z15.literal(1), z15.literal(2)]).nullable(),
|
|
6823
6849
|
draft: z15.object({
|
|
@@ -10748,6 +10774,11 @@ var scheduleDtoSchema = z31.object({
|
|
|
10748
10774
|
createdAt: z31.string(),
|
|
10749
10775
|
updatedAt: z31.string()
|
|
10750
10776
|
});
|
|
10777
|
+
var scheduleExpectedUpdatedAtSchema = z31.string().datetime();
|
|
10778
|
+
function nextScheduleUpdatedAt(previous, nowMs = Date.now()) {
|
|
10779
|
+
const previousMs = previous === void 0 ? Number.NaN : Date.parse(previous);
|
|
10780
|
+
return new Date(Number.isFinite(previousMs) ? Math.max(nowMs, previousMs + 1) : nowMs).toISOString();
|
|
10781
|
+
}
|
|
10751
10782
|
var scheduleUpsertRequestSchema = z31.object({
|
|
10752
10783
|
/** Run kind. Defaults to 'answer-visibility' so existing callers don't have to change. */
|
|
10753
10784
|
kind: schedulableRunKindSchema.optional(),
|
|
@@ -10757,7 +10788,12 @@ var scheduleUpsertRequestSchema = z31.object({
|
|
|
10757
10788
|
enabled: z31.boolean().optional().default(true),
|
|
10758
10789
|
providers: z31.array(providerNameSchema).optional().default([]),
|
|
10759
10790
|
/** Required when kind === 'traffic-sync'. Forbidden for other kinds. Validated server-side. */
|
|
10760
|
-
sourceId: z31.string().optional()
|
|
10791
|
+
sourceId: z31.string().optional(),
|
|
10792
|
+
/**
|
|
10793
|
+
* Optimistic concurrency guard. A timestamp updates only that exact version;
|
|
10794
|
+
* null creates only while the schedule is absent. Omit for legacy behavior.
|
|
10795
|
+
*/
|
|
10796
|
+
expectedUpdatedAt: scheduleExpectedUpdatedAtSchema.nullable().optional()
|
|
10761
10797
|
}).refine(
|
|
10762
10798
|
(data) => data.preset && !data.cron || !data.preset && data.cron,
|
|
10763
10799
|
{ message: 'Exactly one of "preset" or "cron" must be provided' }
|
|
@@ -11815,6 +11851,143 @@ var sourceBreakdownDtoSchema = z35.object({
|
|
|
11815
11851
|
/** Applied ranked-list limit; null when the full list is returned. */
|
|
11816
11852
|
limit: z35.number().int().nullable()
|
|
11817
11853
|
});
|
|
11854
|
+
var competitorLandscapeSurfaceClassSchema = z35.enum([
|
|
11855
|
+
"own",
|
|
11856
|
+
"direct-competitor",
|
|
11857
|
+
"ota-aggregator",
|
|
11858
|
+
"editorial-media",
|
|
11859
|
+
"other",
|
|
11860
|
+
"unknown"
|
|
11861
|
+
]);
|
|
11862
|
+
var competitorLandscapeScopeSchema = z35.discriminatedUnion("kind", [
|
|
11863
|
+
z35.object({ kind: z35.literal("project") }).strict(),
|
|
11864
|
+
z35.object({ kind: z35.literal("group"), groupKey: z35.string().trim().min(1) }).strict(),
|
|
11865
|
+
z35.object({ kind: z35.literal("all-markets") }).strict()
|
|
11866
|
+
]);
|
|
11867
|
+
var competitorLandscapeQueryClassSchema = z35.enum(["all", "branded", "non-brand"]);
|
|
11868
|
+
var competitorLandscapeModeSchema = z35.enum(["project", "all-markets"]);
|
|
11869
|
+
var competitorLandscapeQuerySchema = z35.object({
|
|
11870
|
+
window: metricsWindowSchema.optional(),
|
|
11871
|
+
groupKey: z35.string().trim().min(1).optional(),
|
|
11872
|
+
scope: competitorLandscapeModeSchema.optional(),
|
|
11873
|
+
provider: z35.string().trim().min(1).optional(),
|
|
11874
|
+
/** Exact requested model ID; provider is required to disambiguate model names. */
|
|
11875
|
+
model: modelIdSchema.optional(),
|
|
11876
|
+
/** Opt-in agent comparison; the default landscape remains pooled. */
|
|
11877
|
+
groupBy: z35.literal("model").optional(),
|
|
11878
|
+
queryClass: competitorLandscapeQueryClassSchema.optional(),
|
|
11879
|
+
location: z35.string().trim().min(1).optional(),
|
|
11880
|
+
runId: z35.string().trim().min(1).optional()
|
|
11881
|
+
}).strict().superRefine((value, context) => {
|
|
11882
|
+
if (value.scope === "all-markets" && value.groupKey !== void 0) {
|
|
11883
|
+
context.addIssue({
|
|
11884
|
+
code: "custom",
|
|
11885
|
+
path: ["groupKey"],
|
|
11886
|
+
message: "groupKey cannot be combined with scope=all-markets"
|
|
11887
|
+
});
|
|
11888
|
+
}
|
|
11889
|
+
if (value.model !== void 0 && value.provider === void 0) {
|
|
11890
|
+
context.addIssue({
|
|
11891
|
+
code: "custom",
|
|
11892
|
+
path: ["provider"],
|
|
11893
|
+
message: "provider is required when filtering by model"
|
|
11894
|
+
});
|
|
11895
|
+
}
|
|
11896
|
+
});
|
|
11897
|
+
var competitorLandscapeRowSchema = z35.object({
|
|
11898
|
+
domain: z35.string().trim().min(1),
|
|
11899
|
+
label: z35.string().trim().min(1),
|
|
11900
|
+
surfaceClass: competitorLandscapeSurfaceClassSchema,
|
|
11901
|
+
pinned: z35.boolean(),
|
|
11902
|
+
/** One answer-text match at most per result. */
|
|
11903
|
+
mentionCount: z35.number().int().nonnegative(),
|
|
11904
|
+
/**
|
|
11905
|
+
* Percentage points (0..100). Null outside the competitive denominator, and
|
|
11906
|
+
* null for any selection that pools query classes: a brand wins its own
|
|
11907
|
+
* branded queries by definition, so a pooled ratio flatters the project and
|
|
11908
|
+
* buries every competitor. Counts stay populated either way.
|
|
11909
|
+
*/
|
|
11910
|
+
shareOfVoice: z35.number().min(0).max(100).nullable(),
|
|
11911
|
+
/** One source-list credit at most per result. Independent of mentions. */
|
|
11912
|
+
citationCount: z35.number().int().nonnegative(),
|
|
11913
|
+
/** Answer-text result count behind the mention field. */
|
|
11914
|
+
answeredResults: z35.number().int().nonnegative(),
|
|
11915
|
+
firstSeenAt: z35.string().datetime().nullable(),
|
|
11916
|
+
lastSeenAt: z35.string().datetime().nullable(),
|
|
11917
|
+
sampleUrls: z35.array(z35.string().url()).max(3)
|
|
11918
|
+
}).strict();
|
|
11919
|
+
var competitorLandscapeEvidenceSchema = z35.object({
|
|
11920
|
+
answeredResults: z35.number().int().nonnegative(),
|
|
11921
|
+
sourceResults: z35.number().int().nonnegative(),
|
|
11922
|
+
missingAnswerTextResults: z35.number().int().nonnegative(),
|
|
11923
|
+
/** Project plus direct-competitor named credits behind SOV. */
|
|
11924
|
+
mentionCredits: z35.number().int().nonnegative(),
|
|
11925
|
+
/** Citation captures that cannot prove a complete source list; never inferred as misses. */
|
|
11926
|
+
incompleteSourceResults: z35.number().int().nonnegative(),
|
|
11927
|
+
/** Stored probe snapshots intentionally omitted from every landscape metric. */
|
|
11928
|
+
excludedProbeResults: z35.number().int().nonnegative(),
|
|
11929
|
+
/** Stored snapshots from queued/running/failed/cancelled runs omitted from every metric. */
|
|
11930
|
+
excludedNonCompletedResults: z35.number().int().nonnegative()
|
|
11931
|
+
}).strict();
|
|
11932
|
+
var COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT = 50;
|
|
11933
|
+
var competitorLandscapeModelGroupSchema = z35.object({
|
|
11934
|
+
provider: z35.string().trim().min(1),
|
|
11935
|
+
/** Null preserves historical observations with unknown requested model identity. */
|
|
11936
|
+
model: modelIdSchema.nullable(),
|
|
11937
|
+
/** Raw upstream-reported identity; never filled from the requested model or current settings. */
|
|
11938
|
+
servedModels: modelEvidenceStateSchema,
|
|
11939
|
+
snapshotCount: z35.number().int().positive(),
|
|
11940
|
+
project: competitorLandscapeRowSchema,
|
|
11941
|
+
pinned: z35.array(competitorLandscapeRowSchema),
|
|
11942
|
+
observed: z35.array(competitorLandscapeRowSchema),
|
|
11943
|
+
otherSources: z35.array(competitorLandscapeRowSchema),
|
|
11944
|
+
evidence: competitorLandscapeEvidenceSchema,
|
|
11945
|
+
/** Per-group ranked-row truncation; all pins and full-population denominators remain included. */
|
|
11946
|
+
truncated: z35.boolean()
|
|
11947
|
+
}).strict();
|
|
11948
|
+
var competitorLandscapeModelComparisonSchema = z35.object({
|
|
11949
|
+
basis: z35.literal("requested-model"),
|
|
11950
|
+
groups: z35.array(competitorLandscapeModelGroupSchema).max(COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT),
|
|
11951
|
+
totalGroups: z35.number().int().nonnegative(),
|
|
11952
|
+
/** Groups sort by provider and requested model. Use provider/model filters to narrow a truncated result. */
|
|
11953
|
+
truncated: z35.boolean()
|
|
11954
|
+
}).strict();
|
|
11955
|
+
var competitorLandscapeResponseSchema = z35.object({
|
|
11956
|
+
window: metricsWindowSchema,
|
|
11957
|
+
scope: competitorLandscapeScopeSchema,
|
|
11958
|
+
project: competitorLandscapeRowSchema,
|
|
11959
|
+
/** Explicit/custom competitors, preserved even with zero observations. */
|
|
11960
|
+
pinned: z35.array(competitorLandscapeRowSchema),
|
|
11961
|
+
/** Stored-discovery direct competitors, ordered by historical mention share. */
|
|
11962
|
+
observed: z35.array(competitorLandscapeRowSchema),
|
|
11963
|
+
/** Aggregators, editorial, unknown, and other cited sources; never share-of-voice competitors. */
|
|
11964
|
+
otherSources: z35.array(competitorLandscapeRowSchema),
|
|
11965
|
+
evidence: competitorLandscapeEvidenceSchema,
|
|
11966
|
+
/** Present only when groupBy=model; pooled fields remain available and unchanged. */
|
|
11967
|
+
modelComparison: competitorLandscapeModelComparisonSchema.optional(),
|
|
11968
|
+
/** Present only for Advanced market reads; active metrics stay frozen while draft pins remain pending publish. */
|
|
11969
|
+
marketState: z35.object({
|
|
11970
|
+
activeRevision: z35.number().int().positive(),
|
|
11971
|
+
draft: z35.object({
|
|
11972
|
+
etag: z35.string().trim().min(1),
|
|
11973
|
+
/** Draft-only market identities included in `pinned` for this response. */
|
|
11974
|
+
pendingCompetitorDomains: z35.array(z35.string().trim().min(1))
|
|
11975
|
+
}).strict().nullable()
|
|
11976
|
+
}).strict().nullable(),
|
|
11977
|
+
/** Echoes all applied filters so a client never mistakes a scoped reading for a project-wide one. */
|
|
11978
|
+
filters: z35.object({
|
|
11979
|
+
scope: competitorLandscapeModeSchema,
|
|
11980
|
+
groupKey: z35.string().nullable(),
|
|
11981
|
+
provider: z35.string().nullable(),
|
|
11982
|
+
model: modelIdSchema.optional(),
|
|
11983
|
+
groupBy: z35.literal("model").optional(),
|
|
11984
|
+
queryClass: competitorLandscapeQueryClassSchema,
|
|
11985
|
+
location: z35.string().nullable(),
|
|
11986
|
+
runId: z35.string().nullable()
|
|
11987
|
+
}).strict(),
|
|
11988
|
+
/** True when ranked observed/source lists exceed the server cap; pinned rows are never dropped. */
|
|
11989
|
+
truncated: z35.boolean()
|
|
11990
|
+
}).strict();
|
|
11818
11991
|
function parseWindow(value) {
|
|
11819
11992
|
if (value === void 0 || value === "") return "all";
|
|
11820
11993
|
const parsed = metricsWindowSchema.safeParse(value);
|
|
@@ -16436,6 +16609,7 @@ export {
|
|
|
16436
16609
|
noQueries,
|
|
16437
16610
|
runInProgress,
|
|
16438
16611
|
operationInProgress,
|
|
16612
|
+
scheduleVersionConflict,
|
|
16439
16613
|
measurementPlanRevisionConflict,
|
|
16440
16614
|
measurementCompiledChecksumConflict,
|
|
16441
16615
|
measurementRunRevisionMismatch,
|
|
@@ -16568,6 +16742,7 @@ export {
|
|
|
16568
16742
|
measurementChangesResponseSchema,
|
|
16569
16743
|
measurementDataQualityQuerySchema,
|
|
16570
16744
|
measurementDataQualityResponseSchema,
|
|
16745
|
+
measurementDraftCompetitorSchema,
|
|
16571
16746
|
measurementDraftAuthoringSchema,
|
|
16572
16747
|
MEASUREMENT_DRAFT_MAX_ASSIGNMENTS_PER_ACTION,
|
|
16573
16748
|
MEASUREMENT_DRAFT_MAX_GROUPS,
|
|
@@ -16600,6 +16775,8 @@ export {
|
|
|
16600
16775
|
measurementDraftUpsertGroupRequestSchema,
|
|
16601
16776
|
measurementDraftRemoveGroupRequestSchema,
|
|
16602
16777
|
measurementDraftUpsertCompetitorRequestSchema,
|
|
16778
|
+
measurementDraftPinCompetitorRequestSchema,
|
|
16779
|
+
measurementDraftPinCompetitorResponseSchema,
|
|
16603
16780
|
measurementDraftRemoveCompetitorRequestSchema,
|
|
16604
16781
|
measurementDraftCompilePreviewResponseSchema,
|
|
16605
16782
|
measurementDraftDiffPreviewResponseSchema,
|
|
@@ -16854,6 +17031,8 @@ export {
|
|
|
16854
17031
|
schedulableRunKindSchema,
|
|
16855
17032
|
SchedulableRunKinds,
|
|
16856
17033
|
scheduleDtoSchema,
|
|
17034
|
+
scheduleExpectedUpdatedAtSchema,
|
|
17035
|
+
nextScheduleUpdatedAt,
|
|
16857
17036
|
scheduleUpsertRequestSchema,
|
|
16858
17037
|
categorizeSource,
|
|
16859
17038
|
categorizeSourceWithCompetitors,
|
|
@@ -16897,6 +17076,9 @@ export {
|
|
|
16897
17076
|
modelIdsEquivalent,
|
|
16898
17077
|
brandMetricsDtoSchema,
|
|
16899
17078
|
sourceBreakdownDtoSchema,
|
|
17079
|
+
competitorLandscapeQuerySchema,
|
|
17080
|
+
COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT,
|
|
17081
|
+
competitorLandscapeResponseSchema,
|
|
16900
17082
|
parseWindow,
|
|
16901
17083
|
windowCutoff,
|
|
16902
17084
|
resolveDateRange,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
classifySkillFile,
|
|
26
26
|
coerceSkillManifest,
|
|
27
27
|
competitorBatchRequestSchema,
|
|
28
|
+
competitorLandscapeQuerySchema,
|
|
28
29
|
describeError,
|
|
29
30
|
discoveryBucketSchema,
|
|
30
31
|
discoveryCompetitorTypeSchema,
|
|
@@ -92,7 +93,7 @@ import {
|
|
|
92
93
|
trafficConnectWordpressRequestSchema,
|
|
93
94
|
trafficEventKindSchema,
|
|
94
95
|
trafficSeriesGranularitySchema
|
|
95
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-DY5ZDKQW.js";
|
|
96
97
|
|
|
97
98
|
// src/config.ts
|
|
98
99
|
import fs from "fs";
|
|
@@ -160,8 +161,8 @@ function loadConfig() {
|
|
|
160
161
|
if (!fs.existsSync(configPath)) {
|
|
161
162
|
throw new Error(
|
|
162
163
|
`Config not found at ${configPath}.
|
|
163
|
-
Run "canonry
|
|
164
|
-
|
|
164
|
+
Run "canonry bootstrap" to create the local Page Health runtime; provider credentials are optional.
|
|
165
|
+
Use "canonry init" instead only when you want interactive provider/OAuth provisioning.`
|
|
165
166
|
);
|
|
166
167
|
}
|
|
167
168
|
const raw = fs.readFileSync(configPath, "utf-8");
|
|
@@ -174,8 +175,10 @@ For CI/Docker, use "canonry bootstrap" with env vars (GEMINI_API_KEY, OPENAI_API
|
|
|
174
175
|
].filter(Boolean).join(", ");
|
|
175
176
|
throw new Error(
|
|
176
177
|
`Invalid config at ${configPath} \u2014 missing: ${missing}.
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
Back up this config privately before you repair it.
|
|
179
|
+
Restore the missing values from a known-good backup. If none exists, recover the original values before you retry.
|
|
180
|
+
Keep the original API key and database path. Do not share secrets.
|
|
181
|
+
Do not use "canonry init --force" for recovery. It replaces credentials without a backup.`
|
|
179
182
|
);
|
|
180
183
|
}
|
|
181
184
|
if (parsed.geminiApiKey && !parsed.providers?.gemini) {
|
|
@@ -2396,6 +2399,18 @@ var postApiV1ProjectsByNameCompetitors = (options) => {
|
|
|
2396
2399
|
}
|
|
2397
2400
|
});
|
|
2398
2401
|
};
|
|
2402
|
+
var getApiV1ProjectsByNameAnalyticsCompetitors = (options) => {
|
|
2403
|
+
return (options.client ?? client).get({
|
|
2404
|
+
security: [
|
|
2405
|
+
{
|
|
2406
|
+
scheme: "bearer",
|
|
2407
|
+
type: "http"
|
|
2408
|
+
}
|
|
2409
|
+
],
|
|
2410
|
+
url: "/api/v1/projects/{name}/analytics/competitors",
|
|
2411
|
+
...options
|
|
2412
|
+
});
|
|
2413
|
+
};
|
|
2399
2414
|
var getApiV1ProjectsByNameRuns = (options) => {
|
|
2400
2415
|
return (options.client ?? client).get({
|
|
2401
2416
|
security: [
|
|
@@ -6581,6 +6596,16 @@ var ApiClient = class {
|
|
|
6581
6596
|
})
|
|
6582
6597
|
);
|
|
6583
6598
|
}
|
|
6599
|
+
/** Stored competitor SOV, optionally grouped or filtered by requested model; never starts provider work. */
|
|
6600
|
+
async getCompetitorLandscape(project, opts = {}) {
|
|
6601
|
+
return this.invoke(
|
|
6602
|
+
() => getApiV1ProjectsByNameAnalyticsCompetitors({
|
|
6603
|
+
client: this.heyClient,
|
|
6604
|
+
path: { name: project },
|
|
6605
|
+
query: opts
|
|
6606
|
+
})
|
|
6607
|
+
);
|
|
6608
|
+
}
|
|
6584
6609
|
async getAnalyticsGaps(project, window) {
|
|
6585
6610
|
return this.invoke(
|
|
6586
6611
|
() => getApiV1ProjectsByNameAnalyticsGaps({
|
|
@@ -9086,6 +9111,9 @@ var competitorsInputSchema = z3.object({
|
|
|
9086
9111
|
project: projectNameSchema,
|
|
9087
9112
|
request: competitorBatchRequestSchema
|
|
9088
9113
|
});
|
|
9114
|
+
var competitorLandscapeInputSchema = competitorLandscapeQuerySchema.safeExtend({
|
|
9115
|
+
project: projectNameSchema
|
|
9116
|
+
}).strict();
|
|
9089
9117
|
var projectUpsertInputSchema = z3.object({
|
|
9090
9118
|
project: projectNameSchema,
|
|
9091
9119
|
request: projectUpsertRequestSchema
|
|
@@ -9478,6 +9506,20 @@ var canonryMcpTools = [
|
|
|
9478
9506
|
openApiOperations: ["GET /api/v1/projects/{name}/analytics/sources"],
|
|
9479
9507
|
handler: (client2, input) => client2.getAnalyticsSources(input.project, { window: input.window, limit: input.limit })
|
|
9480
9508
|
}),
|
|
9509
|
+
defineTool({
|
|
9510
|
+
name: "canonry_competitor_landscape",
|
|
9511
|
+
title: "Get historical competitor landscape",
|
|
9512
|
+
description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. Model groups are capped at 50 and disclose truncation.",
|
|
9513
|
+
access: "read",
|
|
9514
|
+
tier: "monitoring",
|
|
9515
|
+
inputSchema: competitorLandscapeInputSchema,
|
|
9516
|
+
annotations: readAnnotations(),
|
|
9517
|
+
openApiOperations: ["GET /api/v1/projects/{name}/analytics/competitors"],
|
|
9518
|
+
handler: (client2, input) => {
|
|
9519
|
+
const { project, ...query } = input;
|
|
9520
|
+
return client2.getCompetitorLandscape(project, query);
|
|
9521
|
+
}
|
|
9522
|
+
}),
|
|
9481
9523
|
defineTool({
|
|
9482
9524
|
name: "canonry_search",
|
|
9483
9525
|
title: "Search project (composite)",
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
installSkills,
|
|
6
6
|
loadConfigRaw,
|
|
7
7
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FVC7PGYQ.js";
|
|
9
9
|
import {
|
|
10
10
|
SKILL_MANIFEST_FILENAME,
|
|
11
11
|
SkillsClients
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DY5ZDKQW.js";
|
|
13
13
|
|
|
14
14
|
// src/skills-autosync.ts
|
|
15
15
|
import fs from "fs";
|