@canonry/canonry 5.10.0 → 5.12.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 +13 -2
- package/assets/assets/{AuditHistoryPanel-C1mws7FA.js → AuditHistoryPanel-DL_NSpfm.js} +1 -1
- package/assets/assets/{BacklinksPage-DP9BUn0y.js → BacklinksPage-BtcBybtX.js} +1 -1
- package/assets/assets/{HistoryPage-Bmo40fKZ.js → HistoryPage-jXj-qi9c.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-DyqZVFEx.js → MeasurementPropertyPage-DKw401ok.js} +1 -1
- package/assets/assets/{ProjectPage-DBJvI-H1.js → ProjectPage-og4qfFFD.js} +1 -1
- package/assets/assets/{RunRow-BSZcQ0v6.js → RunRow-nK5iaZe1.js} +1 -1
- package/assets/assets/{RunsPage-CIkLV-XY.js → RunsPage-CMgr3YSF.js} +1 -1
- package/assets/assets/{SettingsPage-TJ6l-L5i.js → SettingsPage-QtElCcew.js} +1 -1
- package/assets/assets/{SiteHealthSection-CKvDNoSp.js → SiteHealthSection-DNdVVl30.js} +3 -3
- package/assets/assets/{TrafficPage-BNaCL4v4.js → TrafficPage-C0WgvfRj.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-WQu7Tf56.js → TrafficSourceDetailPage-jOTedQtt.js} +1 -1
- package/assets/assets/{extract-error-message-DMgow2EC.js → extract-error-message-DO_053o0.js} +1 -1
- package/assets/assets/index-CnVwWE3V.js +86 -0
- package/assets/assets/{index-DQw9KQwS.css → index-EJC8PSbh.css} +1 -1
- package/assets/assets/{react-sigma_core.esm.min-YECPUDRj.js → react-sigma_core.esm.min-DJttq2UK.js} +1 -1
- package/assets/assets/{v2-overview-adapter-BFf9y-xb.js → v2-overview-adapter-BC_oa__K.js} +1 -1
- package/assets/assets/{vendor-lucide-2cuPDw3H.js → vendor-lucide-N6vOpZmh.js} +1 -1
- package/assets/index.html +3 -3
- package/dist/{chunk-KBPSOB55.js → chunk-DOC4QQLS.js} +2110 -1871
- package/dist/{chunk-W67ORZUR.js → chunk-KBSAEALE.js} +123 -32
- package/dist/{chunk-S7D23FEE.js → chunk-LWGYRN3T.js} +2 -2
- package/dist/{chunk-KEMMVSAQ.js → chunk-NYRRWWEE.js} +50 -2
- package/dist/{chunk-HF6MAKWE.js → chunk-S4BIBUCK.js} +2 -2
- package/dist/{chunk-GQ37ALYP.js → chunk-WJGUBZSW.js} +209 -52
- package/dist/cli.js +106 -14
- package/dist/{demo-server-DKH73GRD.js → demo-server-OTXS6ZHS.js} +3 -3
- package/dist/index.d.ts +28 -1
- package/dist/index.js +5 -5
- package/dist/{intelligence-service-7PVUFJTX.js → intelligence-service-K4U55A2J.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +13 -13
- package/assets/assets/index-BHIRnvQi.js +0 -86
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
6
6
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
7
|
+
AGENT_PROVIDER_IDS,
|
|
7
8
|
CANONRY_NPM_PACKAGE_URL,
|
|
8
9
|
CodingAgents,
|
|
9
10
|
DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT,
|
|
@@ -26,7 +27,9 @@ import {
|
|
|
26
27
|
adsOperationReconcileRequestSchema,
|
|
27
28
|
adsPauseRequestSchema,
|
|
28
29
|
adsUnresolvedOperationListQuerySchema,
|
|
30
|
+
agentConversationCreateSchema,
|
|
29
31
|
agentPluginClientLabel,
|
|
32
|
+
agentProviderIdSchema,
|
|
30
33
|
apiKeyDtoSchema,
|
|
31
34
|
backlinkSourceSchema,
|
|
32
35
|
canonicalizeGtmAccountId,
|
|
@@ -130,7 +133,7 @@ import {
|
|
|
130
133
|
upgradeCaveatFor,
|
|
131
134
|
upgradeCommandFor,
|
|
132
135
|
visibilityReportRequestSchema
|
|
133
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-NYRRWWEE.js";
|
|
134
137
|
|
|
135
138
|
// src/cli-error.ts
|
|
136
139
|
function isMachineFormat(format) {
|
|
@@ -205,6 +208,8 @@ var dashboardManagedSweepsSchema = z.boolean().nullish();
|
|
|
205
208
|
var researchAllowViewersSchema = z.boolean().nullish();
|
|
206
209
|
var researchViewerDailyRunLimitSchema = z.number().int().positive().nullish();
|
|
207
210
|
var dashboardManagedRunKindsSchema = z.array(schedulableRunKindSchema).nullish();
|
|
211
|
+
var agentProviderSchema = agentProviderIdSchema.nullish();
|
|
212
|
+
var agentModelSchema = z.string().trim().min(1).nullish();
|
|
208
213
|
function resolveOperatorApiKeyIds(source) {
|
|
209
214
|
const raw = source.CANONRY_OPERATOR_KEY_IDS?.trim();
|
|
210
215
|
if (!raw) return [];
|
|
@@ -459,6 +464,24 @@ Do not use "canonry init --force" for recovery. It replaces credentials without
|
|
|
459
464
|
message: `Invalid config at ${configPath}: research.viewerDailyRunLimit must be a positive integer or left blank.`
|
|
460
465
|
});
|
|
461
466
|
}
|
|
467
|
+
if (!agentProviderSchema.safeParse(parsed.agent?.provider).success) {
|
|
468
|
+
throw new CliError({
|
|
469
|
+
code: "CONFIG_INVALID",
|
|
470
|
+
message: `Invalid config at ${configPath}: agent.provider must be one of ${AGENT_PROVIDER_IDS.join(", ")}, or left blank.`
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
if (!agentModelSchema.safeParse(parsed.agent?.model).success) {
|
|
474
|
+
throw new CliError({
|
|
475
|
+
code: "CONFIG_INVALID",
|
|
476
|
+
message: `Invalid config at ${configPath}: agent.model must be a non-empty string or left blank.`
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
if (parsed.agent?.model && !parsed.agent?.provider) {
|
|
480
|
+
throw new CliError({
|
|
481
|
+
code: "CONFIG_INVALID",
|
|
482
|
+
message: `Invalid config at ${configPath}: agent.model requires agent.provider \u2014 a model id is only meaningful against the provider that serves it.`
|
|
483
|
+
});
|
|
484
|
+
}
|
|
462
485
|
if (parsed.geminiApiKey && !parsed.providers?.gemini) {
|
|
463
486
|
parsed.providers = {
|
|
464
487
|
...parsed.providers,
|
|
@@ -624,56 +647,6 @@ function configExists() {
|
|
|
624
647
|
return fs.existsSync(getConfigPath());
|
|
625
648
|
}
|
|
626
649
|
|
|
627
|
-
// src/client.ts
|
|
628
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
629
|
-
|
|
630
|
-
// src/client-reliability.ts
|
|
631
|
-
function parseRetryAfterMs(header, now = Date.now()) {
|
|
632
|
-
if (!header) return void 0;
|
|
633
|
-
const value = header.trim();
|
|
634
|
-
if (!value) return void 0;
|
|
635
|
-
if (/^\d+(?:\.\d+)?$/.test(value)) {
|
|
636
|
-
const delayMs2 = Number(value) * 1e3;
|
|
637
|
-
return Number.isFinite(delayMs2) && delayMs2 >= 0 && delayMs2 <= Number.MAX_SAFE_INTEGER ? delayMs2 : void 0;
|
|
638
|
-
}
|
|
639
|
-
if (!/^[a-z]{3},\s/i.test(value)) return void 0;
|
|
640
|
-
const target = Date.parse(value);
|
|
641
|
-
if (!Number.isFinite(target)) return void 0;
|
|
642
|
-
const delayMs = Math.max(0, target - now);
|
|
643
|
-
return Number.isSafeInteger(delayMs) ? delayMs : void 0;
|
|
644
|
-
}
|
|
645
|
-
function httpErrorDetails(serverDetails, response) {
|
|
646
|
-
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
647
|
-
const requestId = response.headers.get("x-request-id") ?? response.headers.get("request-id");
|
|
648
|
-
return {
|
|
649
|
-
...serverDetails && typeof serverDetails === "object" && !Array.isArray(serverDetails) ? serverDetails : {},
|
|
650
|
-
httpStatus: response.status,
|
|
651
|
-
...retryAfterMs === void 0 ? {} : { retryAfterMs },
|
|
652
|
-
...requestId ? { requestId } : {}
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
function isConnectionFailure(message) {
|
|
656
|
-
return message.includes("fetch failed") || message.includes("ECONNREFUSED") || message.includes("connect ECONNREFUSED");
|
|
657
|
-
}
|
|
658
|
-
function connectionFailureMessage(target) {
|
|
659
|
-
return `Could not connect to canonry server at ${redactRequestTarget(target)}. Check that this URL is reachable and the server is running. For a local Canonry instance, start it with "canonry start" (a background daemon, stopped with "canonry stop"), or "canonry serve" to run it in the foreground.`;
|
|
660
|
-
}
|
|
661
|
-
function redactRequestTarget(target) {
|
|
662
|
-
try {
|
|
663
|
-
const url = new URL(target);
|
|
664
|
-
url.username = "";
|
|
665
|
-
url.password = "";
|
|
666
|
-
for (const key of [...url.searchParams.keys()]) {
|
|
667
|
-
if (isSensitiveDiagnosticQueryKey(key)) {
|
|
668
|
-
url.searchParams.set(key, "<redacted>");
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
return url.toString();
|
|
672
|
-
} catch {
|
|
673
|
-
return target.replace(/\/\/[^/@]*@/, "//");
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
650
|
// ../api-client-generated/src/generated/core/bodySerializer.gen.ts
|
|
678
651
|
var jsonBodySerializer = {
|
|
679
652
|
bodySerializer: (body) => JSON.stringify(
|
|
@@ -5939,6 +5912,70 @@ var getApiV1ProjectsByNameTechnicalAeoRunsByRunIdProgress = (options) => {
|
|
|
5939
5912
|
...options
|
|
5940
5913
|
});
|
|
5941
5914
|
};
|
|
5915
|
+
var getApiV1ProjectsByNameAgentConversations = (options) => {
|
|
5916
|
+
return (options.client ?? client).get({
|
|
5917
|
+
security: [
|
|
5918
|
+
{
|
|
5919
|
+
scheme: "bearer",
|
|
5920
|
+
type: "http"
|
|
5921
|
+
}
|
|
5922
|
+
],
|
|
5923
|
+
url: "/api/v1/projects/{name}/agent/conversations",
|
|
5924
|
+
...options
|
|
5925
|
+
});
|
|
5926
|
+
};
|
|
5927
|
+
var postApiV1ProjectsByNameAgentConversations = (options) => {
|
|
5928
|
+
return (options.client ?? client).post({
|
|
5929
|
+
security: [
|
|
5930
|
+
{
|
|
5931
|
+
scheme: "bearer",
|
|
5932
|
+
type: "http"
|
|
5933
|
+
}
|
|
5934
|
+
],
|
|
5935
|
+
url: "/api/v1/projects/{name}/agent/conversations",
|
|
5936
|
+
...options,
|
|
5937
|
+
headers: {
|
|
5938
|
+
"Content-Type": "application/json",
|
|
5939
|
+
...options.headers
|
|
5940
|
+
}
|
|
5941
|
+
});
|
|
5942
|
+
};
|
|
5943
|
+
var deleteApiV1ProjectsByNameAgentConversationsById = (options) => {
|
|
5944
|
+
return (options.client ?? client).delete({
|
|
5945
|
+
security: [
|
|
5946
|
+
{
|
|
5947
|
+
scheme: "bearer",
|
|
5948
|
+
type: "http"
|
|
5949
|
+
}
|
|
5950
|
+
],
|
|
5951
|
+
url: "/api/v1/projects/{name}/agent/conversations/{id}",
|
|
5952
|
+
...options
|
|
5953
|
+
});
|
|
5954
|
+
};
|
|
5955
|
+
var getApiV1ProjectsByNameAgentConversationsById = (options) => {
|
|
5956
|
+
return (options.client ?? client).get({
|
|
5957
|
+
security: [
|
|
5958
|
+
{
|
|
5959
|
+
scheme: "bearer",
|
|
5960
|
+
type: "http"
|
|
5961
|
+
}
|
|
5962
|
+
],
|
|
5963
|
+
url: "/api/v1/projects/{name}/agent/conversations/{id}",
|
|
5964
|
+
...options
|
|
5965
|
+
});
|
|
5966
|
+
};
|
|
5967
|
+
var postApiV1ProjectsByNameAgentConversationsByIdResume = (options) => {
|
|
5968
|
+
return (options.client ?? client).post({
|
|
5969
|
+
security: [
|
|
5970
|
+
{
|
|
5971
|
+
scheme: "bearer",
|
|
5972
|
+
type: "http"
|
|
5973
|
+
}
|
|
5974
|
+
],
|
|
5975
|
+
url: "/api/v1/projects/{name}/agent/conversations/{id}/resume",
|
|
5976
|
+
...options
|
|
5977
|
+
});
|
|
5978
|
+
};
|
|
5942
5979
|
var deleteApiV1ProjectsByNameAgentTranscript = (options) => {
|
|
5943
5980
|
return (options.client ?? client).delete({
|
|
5944
5981
|
security: [
|
|
@@ -6033,6 +6070,56 @@ function createClient2(opts) {
|
|
|
6033
6070
|
return createClient(config);
|
|
6034
6071
|
}
|
|
6035
6072
|
|
|
6073
|
+
// src/client.ts
|
|
6074
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
6075
|
+
|
|
6076
|
+
// src/client-reliability.ts
|
|
6077
|
+
function parseRetryAfterMs(header, now = Date.now()) {
|
|
6078
|
+
if (!header) return void 0;
|
|
6079
|
+
const value = header.trim();
|
|
6080
|
+
if (!value) return void 0;
|
|
6081
|
+
if (/^\d+(?:\.\d+)?$/.test(value)) {
|
|
6082
|
+
const delayMs2 = Number(value) * 1e3;
|
|
6083
|
+
return Number.isFinite(delayMs2) && delayMs2 >= 0 && delayMs2 <= Number.MAX_SAFE_INTEGER ? delayMs2 : void 0;
|
|
6084
|
+
}
|
|
6085
|
+
if (!/^[a-z]{3},\s/i.test(value)) return void 0;
|
|
6086
|
+
const target = Date.parse(value);
|
|
6087
|
+
if (!Number.isFinite(target)) return void 0;
|
|
6088
|
+
const delayMs = Math.max(0, target - now);
|
|
6089
|
+
return Number.isSafeInteger(delayMs) ? delayMs : void 0;
|
|
6090
|
+
}
|
|
6091
|
+
function httpErrorDetails(serverDetails, response) {
|
|
6092
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
6093
|
+
const requestId = response.headers.get("x-request-id") ?? response.headers.get("request-id");
|
|
6094
|
+
return {
|
|
6095
|
+
...serverDetails && typeof serverDetails === "object" && !Array.isArray(serverDetails) ? serverDetails : {},
|
|
6096
|
+
httpStatus: response.status,
|
|
6097
|
+
...retryAfterMs === void 0 ? {} : { retryAfterMs },
|
|
6098
|
+
...requestId ? { requestId } : {}
|
|
6099
|
+
};
|
|
6100
|
+
}
|
|
6101
|
+
function isConnectionFailure(message) {
|
|
6102
|
+
return message.includes("fetch failed") || message.includes("ECONNREFUSED") || message.includes("connect ECONNREFUSED");
|
|
6103
|
+
}
|
|
6104
|
+
function connectionFailureMessage(target) {
|
|
6105
|
+
return `Could not connect to canonry server at ${redactRequestTarget(target)}. Check that this URL is reachable and the server is running. For a local Canonry instance, start it with "canonry start" (a background daemon, stopped with "canonry stop"), or "canonry serve" to run it in the foreground.`;
|
|
6106
|
+
}
|
|
6107
|
+
function redactRequestTarget(target) {
|
|
6108
|
+
try {
|
|
6109
|
+
const url = new URL(target);
|
|
6110
|
+
url.username = "";
|
|
6111
|
+
url.password = "";
|
|
6112
|
+
for (const key of [...url.searchParams.keys()]) {
|
|
6113
|
+
if (isSensitiveDiagnosticQueryKey(key)) {
|
|
6114
|
+
url.searchParams.set(key, "<redacted>");
|
|
6115
|
+
}
|
|
6116
|
+
}
|
|
6117
|
+
return url.toString();
|
|
6118
|
+
} catch {
|
|
6119
|
+
return target.replace(/\/\/[^/@]*@/, "//");
|
|
6120
|
+
}
|
|
6121
|
+
}
|
|
6122
|
+
|
|
6036
6123
|
// src/client.ts
|
|
6037
6124
|
function parseServerUpdateAvailable(value) {
|
|
6038
6125
|
if (!value || typeof value !== "object") return null;
|
|
@@ -6212,6 +6299,21 @@ var ApiClient = class {
|
|
|
6212
6299
|
// generated SDK and we route them through `invoke()` like every other
|
|
6213
6300
|
// endpoint. The SSE `POST /agent/prompt` is intentionally not here — it
|
|
6214
6301
|
// stays on `streamPost()` below since the SDK can't represent SSE cleanly.
|
|
6302
|
+
async listAgentConversations(project, query) {
|
|
6303
|
+
return this.invoke(() => getApiV1ProjectsByNameAgentConversations({ client: this.heyClient, path: { name: project }, query }));
|
|
6304
|
+
}
|
|
6305
|
+
async getAgentConversation(project, id) {
|
|
6306
|
+
return this.invoke(() => getApiV1ProjectsByNameAgentConversationsById({ client: this.heyClient, path: { name: project, id } }));
|
|
6307
|
+
}
|
|
6308
|
+
async createAgentConversation(project, id) {
|
|
6309
|
+
return this.invoke(() => postApiV1ProjectsByNameAgentConversations({ client: this.heyClient, path: { name: project }, body: { id } }));
|
|
6310
|
+
}
|
|
6311
|
+
async resumeAgentConversation(project, id) {
|
|
6312
|
+
return this.invoke(() => postApiV1ProjectsByNameAgentConversationsByIdResume({ client: this.heyClient, path: { name: project, id } }));
|
|
6313
|
+
}
|
|
6314
|
+
async deleteAgentConversation(project, id) {
|
|
6315
|
+
return this.invoke(() => deleteApiV1ProjectsByNameAgentConversationsById({ client: this.heyClient, path: { name: project, id } }));
|
|
6316
|
+
}
|
|
6215
6317
|
async getAgentTranscript(project) {
|
|
6216
6318
|
return this.invoke(
|
|
6217
6319
|
() => getApiV1ProjectsByNameAgentTranscript({ client: this.heyClient, path: { name: project } })
|
|
@@ -11784,10 +11886,65 @@ var canonryMcpTools = [
|
|
|
11784
11886
|
openApiOperations: ["DELETE /api/v1/projects/{name}/agent/memory"],
|
|
11785
11887
|
handler: (client2, input) => client2.forgetAgentMemory(input.project, input.key)
|
|
11786
11888
|
}),
|
|
11889
|
+
defineTool({
|
|
11890
|
+
name: "canonry_agent_conversations_list",
|
|
11891
|
+
title: "List Aero conversations",
|
|
11892
|
+
description: "List Aero conversations. Instance administrators only. New and resume preserve the previous conversation; shared project notes are retained. Creation requires a UUID that must be reused on retries.",
|
|
11893
|
+
access: "read",
|
|
11894
|
+
tier: "agent",
|
|
11895
|
+
inputSchema: projectInputSchema.extend({ offset: z4.number().int().min(0).optional(), limit: z4.number().int().min(1).max(100).optional() }),
|
|
11896
|
+
annotations: readAnnotations(),
|
|
11897
|
+
openApiOperations: ["GET /api/v1/projects/{name}/agent/conversations"],
|
|
11898
|
+
handler: (client2, input) => client2.listAgentConversations(input.project, { offset: input.offset, limit: input.limit })
|
|
11899
|
+
}),
|
|
11900
|
+
defineTool({
|
|
11901
|
+
name: "canonry_agent_conversations_get",
|
|
11902
|
+
title: "Read an Aero conversation",
|
|
11903
|
+
description: "Read an Aero conversation. Instance administrators only. New and resume preserve the previous conversation; shared project notes are retained. Creation requires a UUID that must be reused on retries.",
|
|
11904
|
+
access: "read",
|
|
11905
|
+
tier: "agent",
|
|
11906
|
+
inputSchema: projectInputSchema.extend({ id: z4.string().min(1) }),
|
|
11907
|
+
annotations: readAnnotations(),
|
|
11908
|
+
openApiOperations: ["GET /api/v1/projects/{name}/agent/conversations/{id}"],
|
|
11909
|
+
handler: (client2, input) => client2.getAgentConversation(input.project, input.id)
|
|
11910
|
+
}),
|
|
11911
|
+
defineTool({
|
|
11912
|
+
name: "canonry_agent_conversations_new",
|
|
11913
|
+
title: "Start a new Aero conversation",
|
|
11914
|
+
description: "Start a new Aero conversation. Instance administrators only. New and resume preserve the previous conversation; shared project notes are retained. Creation requires a UUID that must be reused on retries.",
|
|
11915
|
+
access: "write",
|
|
11916
|
+
tier: "agent",
|
|
11917
|
+
inputSchema: projectInputSchema.extend(agentConversationCreateSchema.shape),
|
|
11918
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
11919
|
+
openApiOperations: ["POST /api/v1/projects/{name}/agent/conversations"],
|
|
11920
|
+
handler: (client2, input) => client2.createAgentConversation(input.project, input.id)
|
|
11921
|
+
}),
|
|
11922
|
+
defineTool({
|
|
11923
|
+
name: "canonry_agent_conversations_resume",
|
|
11924
|
+
title: "Resume an Aero conversation",
|
|
11925
|
+
description: "Resume an Aero conversation. Instance administrators only. New and resume preserve the previous conversation; shared project notes are retained. Creation requires a UUID that must be reused on retries.",
|
|
11926
|
+
access: "write",
|
|
11927
|
+
tier: "agent",
|
|
11928
|
+
inputSchema: projectInputSchema.extend({ id: z4.string().min(1) }),
|
|
11929
|
+
annotations: writeAnnotations({ idempotentHint: true }),
|
|
11930
|
+
openApiOperations: ["POST /api/v1/projects/{name}/agent/conversations/{id}/resume"],
|
|
11931
|
+
handler: (client2, input) => client2.resumeAgentConversation(input.project, input.id)
|
|
11932
|
+
}),
|
|
11933
|
+
defineTool({
|
|
11934
|
+
name: "canonry_agent_conversations_delete",
|
|
11935
|
+
title: "Delete an Aero conversation",
|
|
11936
|
+
description: "Delete an Aero conversation. Instance administrators only. New and resume preserve the previous conversation; shared project notes are retained. Creation requires a UUID that must be reused on retries.",
|
|
11937
|
+
access: "write",
|
|
11938
|
+
tier: "agent",
|
|
11939
|
+
inputSchema: projectInputSchema.extend({ id: z4.string().min(1) }),
|
|
11940
|
+
annotations: writeAnnotations({ idempotentHint: true, destructiveHint: true }),
|
|
11941
|
+
openApiOperations: ["DELETE /api/v1/projects/{name}/agent/conversations/{id}"],
|
|
11942
|
+
handler: (client2, input) => client2.deleteAgentConversation(input.project, input.id)
|
|
11943
|
+
}),
|
|
11787
11944
|
defineTool({
|
|
11788
11945
|
name: "canonry_agent_clear",
|
|
11789
11946
|
title: "Clear agent transcript",
|
|
11790
|
-
description: "Clear the rolling Aero conversation for a project \u2014 wipes the transcript, the in-memory pending follow-up buffer, and the persisted follow-up queue. Memory entries (canonry_memory_*) are preserved.
|
|
11947
|
+
description: "Clear the rolling Aero conversation for a project \u2014 wipes the transcript, the in-memory pending follow-up buffer, and the persisted follow-up queue. Memory entries (canonry_memory_*) are preserved. Destructive legacy operation. Prefer canonry_agent_conversations_new to start fresh while preserving history.",
|
|
11791
11948
|
access: "write",
|
|
11792
11949
|
tier: "agent",
|
|
11793
11950
|
inputSchema: projectInputSchema,
|
package/dist/cli.js
CHANGED
|
@@ -35,11 +35,11 @@ import {
|
|
|
35
35
|
trackCliCommandFinished,
|
|
36
36
|
trackEvent,
|
|
37
37
|
waitForServerRuntimeStartup
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-KBSAEALE.js";
|
|
39
39
|
import {
|
|
40
40
|
autoSyncSkills,
|
|
41
41
|
formatAutoSyncNotice
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-S4BIBUCK.js";
|
|
43
43
|
import {
|
|
44
44
|
CliError,
|
|
45
45
|
EXIT_SYSTEM_ERROR,
|
|
@@ -66,13 +66,13 @@ import {
|
|
|
66
66
|
shouldPrintServeSkillsNudge,
|
|
67
67
|
systemError,
|
|
68
68
|
usageError
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-WJGUBZSW.js";
|
|
70
70
|
import {
|
|
71
71
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
72
72
|
trustedProxiesProblem,
|
|
73
73
|
trustedProxyProblem
|
|
74
74
|
} from "./chunk-RB2F4D3Z.js";
|
|
75
|
-
import "./chunk-
|
|
75
|
+
import "./chunk-LWGYRN3T.js";
|
|
76
76
|
import "./chunk-AOJU5LKX.js";
|
|
77
77
|
import {
|
|
78
78
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
queries,
|
|
89
89
|
renderReportHtml,
|
|
90
90
|
runs
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-DOC4QQLS.js";
|
|
92
92
|
import {
|
|
93
93
|
AdsDeliverySnapshotStatuses,
|
|
94
94
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -123,6 +123,7 @@ import {
|
|
|
123
123
|
adsGeoSearchQuerySchema,
|
|
124
124
|
adsImageUploadRequestSchema,
|
|
125
125
|
adsPauseRequestSchema,
|
|
126
|
+
agentConversationListQuerySchema,
|
|
126
127
|
agentTurnLimitsSchema,
|
|
127
128
|
agentViewContextSchema,
|
|
128
129
|
backlinkSourceSchema,
|
|
@@ -172,7 +173,7 @@ import {
|
|
|
172
173
|
snapshotProviderModeSchema,
|
|
173
174
|
visibilityReportRequestSchema,
|
|
174
175
|
winnabilityClassSchema
|
|
175
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-NYRRWWEE.js";
|
|
176
177
|
|
|
177
178
|
// src/cli.ts
|
|
178
179
|
import { pathToFileURL } from "url";
|
|
@@ -437,7 +438,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
437
438
|
async function demoCommand(options) {
|
|
438
439
|
const { host, port } = parseDemoListenOptions(options);
|
|
439
440
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
440
|
-
const { createDemoServer } = await import("./demo-server-
|
|
441
|
+
const { createDemoServer } = await import("./demo-server-OTXS6ZHS.js");
|
|
441
442
|
const app = await createDemoServer({ trustProxy });
|
|
442
443
|
let stopping = false;
|
|
443
444
|
const stop = () => {
|
|
@@ -12943,18 +12944,33 @@ async function listSchedules(project, format) {
|
|
|
12943
12944
|
function getClient24() {
|
|
12944
12945
|
return createApiClient();
|
|
12945
12946
|
}
|
|
12947
|
+
async function readCurrentSchedule(client, project, kind) {
|
|
12948
|
+
try {
|
|
12949
|
+
return await client.getSchedule(project, kind);
|
|
12950
|
+
} catch {
|
|
12951
|
+
return void 0;
|
|
12952
|
+
}
|
|
12953
|
+
}
|
|
12946
12954
|
async function setSchedule(project, opts) {
|
|
12947
12955
|
const client = getClient24();
|
|
12956
|
+
const current = await readCurrentSchedule(client, project, opts.kind);
|
|
12948
12957
|
const body = {};
|
|
12949
12958
|
if (opts.kind) body.kind = opts.kind;
|
|
12950
|
-
if (
|
|
12951
|
-
if (opts.preset) body.preset = opts.preset;
|
|
12952
|
-
if (opts.cron) body.cron = opts.cron;
|
|
12959
|
+
else if (current) body.kind = current.kind;
|
|
12953
12960
|
if (opts.everyDays || opts.startDate || opts.at) {
|
|
12954
12961
|
body.recurrence = { everyDays: Number(opts.everyDays), startDate: opts.startDate, time: opts.at };
|
|
12955
|
-
}
|
|
12962
|
+
} else if (opts.preset) body.preset = opts.preset;
|
|
12963
|
+
else if (opts.cron) body.cron = opts.cron;
|
|
12964
|
+
else if (current?.recurrence) body.recurrence = current.recurrence;
|
|
12965
|
+
else if (current?.preset) body.preset = current.preset;
|
|
12966
|
+
else if (current?.cronExpr) body.cron = current.cronExpr;
|
|
12956
12967
|
if (opts.timezone) body.timezone = opts.timezone;
|
|
12968
|
+
else if (current) body.timezone = current.timezone;
|
|
12957
12969
|
if (opts.providers?.length) body.providers = opts.providers;
|
|
12970
|
+
else if (current?.providers.length) body.providers = current.providers;
|
|
12971
|
+
if (opts.sourceId) body.sourceId = opts.sourceId;
|
|
12972
|
+
else if (current?.sourceId) body.sourceId = current.sourceId;
|
|
12973
|
+
if (current) body.expectedUpdatedAt = current.updatedAt;
|
|
12958
12974
|
const result = await client.putSchedule(project, body);
|
|
12959
12975
|
if (isMachineFormat(opts.format)) {
|
|
12960
12976
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -13014,6 +13030,29 @@ async function removeSchedule(project, format, kind) {
|
|
|
13014
13030
|
}
|
|
13015
13031
|
console.log(`Schedule removed for "${project}" (kind: ${resolvedKind})`);
|
|
13016
13032
|
}
|
|
13033
|
+
function formatNextRun(nextRunAt, timezone) {
|
|
13034
|
+
const at = new Date(nextRunAt);
|
|
13035
|
+
if (Number.isNaN(at.getTime())) return nextRunAt;
|
|
13036
|
+
try {
|
|
13037
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
13038
|
+
timeZone: timezone,
|
|
13039
|
+
year: "numeric",
|
|
13040
|
+
month: "2-digit",
|
|
13041
|
+
day: "2-digit",
|
|
13042
|
+
hour: "2-digit",
|
|
13043
|
+
minute: "2-digit",
|
|
13044
|
+
hour12: false,
|
|
13045
|
+
timeZoneName: "longOffset"
|
|
13046
|
+
}).formatToParts(at);
|
|
13047
|
+
const get = (type) => parts.find((part) => part.type === type)?.value ?? "";
|
|
13048
|
+
const offset = get("timeZoneName").replace("GMT", "") || "+00:00";
|
|
13049
|
+
const local = `${get("year")}-${get("month")}-${get("day")} ${get("hour")}:${get("minute")}`;
|
|
13050
|
+
const utc = `${String(at.getUTCHours()).padStart(2, "0")}:${String(at.getUTCMinutes()).padStart(2, "0")}Z`;
|
|
13051
|
+
return `${local} (${offset}) / ${utc}`;
|
|
13052
|
+
} catch {
|
|
13053
|
+
return nextRunAt;
|
|
13054
|
+
}
|
|
13055
|
+
}
|
|
13017
13056
|
function printSchedule(s) {
|
|
13018
13057
|
console.log(` Kind: ${s.kind}`);
|
|
13019
13058
|
if (s.preset) {
|
|
@@ -13038,7 +13077,7 @@ function printSchedule(s) {
|
|
|
13038
13077
|
console.log(` Last run: ${s.lastRunAt}`);
|
|
13039
13078
|
}
|
|
13040
13079
|
if (s.nextRunAt) {
|
|
13041
|
-
console.log(` Next run: ${s.nextRunAt}`);
|
|
13080
|
+
console.log(` Next run: ${formatNextRun(s.nextRunAt, s.timezone)}`);
|
|
13042
13081
|
}
|
|
13043
13082
|
}
|
|
13044
13083
|
|
|
@@ -18461,6 +18500,43 @@ var WORDPRESS_CLI_COMMANDS = [
|
|
|
18461
18500
|
}
|
|
18462
18501
|
];
|
|
18463
18502
|
|
|
18503
|
+
// src/commands/agent-conversations.ts
|
|
18504
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
18505
|
+
async function agentConversations(opts) {
|
|
18506
|
+
try {
|
|
18507
|
+
const client = createApiClient();
|
|
18508
|
+
const result = await (() => {
|
|
18509
|
+
switch (opts.action) {
|
|
18510
|
+
case "list":
|
|
18511
|
+
return client.listAgentConversations(opts.project, { offset: opts.offset, limit: opts.limit });
|
|
18512
|
+
case "new":
|
|
18513
|
+
return client.createAgentConversation(opts.project, opts.id ?? randomUUID2());
|
|
18514
|
+
case "show":
|
|
18515
|
+
return client.getAgentConversation(opts.project, opts.id);
|
|
18516
|
+
case "resume":
|
|
18517
|
+
return client.resumeAgentConversation(opts.project, opts.id);
|
|
18518
|
+
case "delete":
|
|
18519
|
+
return client.deleteAgentConversation(opts.project, opts.id);
|
|
18520
|
+
}
|
|
18521
|
+
})();
|
|
18522
|
+
if (isMachineFormat(opts.format)) {
|
|
18523
|
+
console.log(JSON.stringify(result, null, 2));
|
|
18524
|
+
return;
|
|
18525
|
+
}
|
|
18526
|
+
if ("conversations" in result) {
|
|
18527
|
+
if (!result.conversations.length) console.log("No Aero conversations yet.");
|
|
18528
|
+
for (const conversation of result.conversations) console.log(`${conversation.active ? "* " : " "}${conversation.id} ${conversation.title} ${conversation.updatedAt}`);
|
|
18529
|
+
if (result.nextOffset !== null) console.log(`More conversations: --offset ${result.nextOffset}`);
|
|
18530
|
+
} else if ("messages" in result) {
|
|
18531
|
+
console.log(`${result.title} \u2014 ${result.id}${result.active ? " (current)" : ""}`);
|
|
18532
|
+
for (const message of result.messages) console.log(`[${message.role}] ${typeof message.content === "string" ? message.content : JSON.stringify(message.content)}`);
|
|
18533
|
+
} else console.log(`Conversation deleted: ${result.id}. Shared project notes kept.`);
|
|
18534
|
+
} catch (error) {
|
|
18535
|
+
printCliError(error, opts.format);
|
|
18536
|
+
process.exitCode = error instanceof CliError ? error.exitCode : 2;
|
|
18537
|
+
}
|
|
18538
|
+
}
|
|
18539
|
+
|
|
18464
18540
|
// src/agent-webhook.ts
|
|
18465
18541
|
var AGENT_WEBHOOK_EVENTS = ["run.completed", "insight.critical", "insight.high", "citation.gained"];
|
|
18466
18542
|
|
|
@@ -18529,6 +18605,7 @@ async function agentAsk(opts) {
|
|
|
18529
18605
|
`/projects/${encodeURIComponent(opts.project)}/agent/prompt`,
|
|
18530
18606
|
{
|
|
18531
18607
|
prompt: opts.prompt,
|
|
18608
|
+
...opts.conversationId ? { conversationId: opts.conversationId } : {},
|
|
18532
18609
|
provider: opts.provider,
|
|
18533
18610
|
modelId: opts.modelId,
|
|
18534
18611
|
scope: opts.scope ?? "all",
|
|
@@ -18805,20 +18882,34 @@ async function agentMemoryForget(opts) {
|
|
|
18805
18882
|
// src/cli-commands/agent.ts
|
|
18806
18883
|
var AGENT_ASK_SCOPES = ["all", "read-only"];
|
|
18807
18884
|
var AGENT_CLI_COMMANDS = [
|
|
18885
|
+
...["list", "new", "show", "resume", "delete"].map((action) => ({
|
|
18886
|
+
path: ["agent", "conversations", action],
|
|
18887
|
+
usage: `canonry agent conversations ${action} <project> [--id <conversation-id>] [--offset <n>] [--limit <n>] [--format json]`,
|
|
18888
|
+
options: { id: stringOption(), offset: stringOption(), limit: stringOption() },
|
|
18889
|
+
run: async (input) => {
|
|
18890
|
+
const usage = `canonry agent conversations ${action} <project>`;
|
|
18891
|
+
const project = requireProject(input, `agent.conversations.${action}`, usage);
|
|
18892
|
+
const id = action === "new" || action === "list" ? getString(input.values, "id") : requireStringOption(input, "id", { command: `agent.conversations.${action}`, usage, message: "--id is required" });
|
|
18893
|
+
const query = agentConversationListQuerySchema.safeParse({ offset: getString(input.values, "offset"), limit: getString(input.values, "limit") });
|
|
18894
|
+
if (!query.success) throw usageError("Invalid history pagination", { message: query.error.message });
|
|
18895
|
+
await agentConversations({ project, action, id, ...query.data, format: input.format });
|
|
18896
|
+
}
|
|
18897
|
+
})),
|
|
18808
18898
|
{
|
|
18809
18899
|
path: ["agent", "ask"],
|
|
18810
|
-
usage: `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`,
|
|
18900
|
+
usage: `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`,
|
|
18811
18901
|
options: {
|
|
18812
18902
|
provider: stringOption(),
|
|
18813
18903
|
model: stringOption(),
|
|
18814
18904
|
scope: stringOption(),
|
|
18815
18905
|
profile: stringOption(),
|
|
18816
18906
|
context: stringOption(),
|
|
18907
|
+
conversation: stringOption(),
|
|
18817
18908
|
"max-tool-calls": stringOption(),
|
|
18818
18909
|
"timeout-ms": stringOption()
|
|
18819
18910
|
},
|
|
18820
18911
|
run: async (input) => {
|
|
18821
|
-
const usage = `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`;
|
|
18912
|
+
const usage = `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`;
|
|
18822
18913
|
const project = requireProject(input, "agent.ask", usage);
|
|
18823
18914
|
const prompt2 = input.positionals.slice(1).join(" ").trim();
|
|
18824
18915
|
if (!prompt2) {
|
|
@@ -18884,6 +18975,7 @@ Usage: ${usage}`, {
|
|
|
18884
18975
|
if (!parsedLimits.success) throw usageError("Invalid Aero turn limits", { message: parsedLimits.error.message });
|
|
18885
18976
|
await agentAsk({
|
|
18886
18977
|
context,
|
|
18978
|
+
conversationId: getString(input.values, "conversation"),
|
|
18887
18979
|
limits: parsedLimits.data,
|
|
18888
18980
|
project,
|
|
18889
18981
|
prompt: prompt2,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
layoutSiteCrawlGraphInput,
|
|
6
6
|
persistSiteCrawlGraphLayout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LWGYRN3T.js";
|
|
8
8
|
import {
|
|
9
9
|
PACKAGE_VERSION
|
|
10
10
|
} from "./chunk-AOJU5LKX.js";
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
siteCrawlPages,
|
|
84
84
|
siteCrawlSnapshots,
|
|
85
85
|
trafficSources
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-DOC4QQLS.js";
|
|
87
87
|
import {
|
|
88
88
|
RunKinds,
|
|
89
89
|
SiteCrawlFetchStates,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
measurementPlanV2Schema,
|
|
105
105
|
placementLinkDecision,
|
|
106
106
|
siteAuditPageFactorSchema
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-NYRRWWEE.js";
|
|
108
108
|
|
|
109
109
|
// src/demo-server.ts
|
|
110
110
|
import { dirname, join as join2 } from "path";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify';
|
|
2
2
|
import { DatabaseClient } from '@ainyc/canonry-db';
|
|
3
|
-
import { ProviderQuotaPolicy, SchedulableRunKind, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
|
|
3
|
+
import { ProviderQuotaPolicy, SchedulableRunKind, AgentProviderId, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
|
|
4
4
|
import { GoogleTokenResponse } from '@ainyc/canonry-integration-google';
|
|
5
5
|
|
|
6
6
|
type GoogleConnectionType = 'gsc' | 'ga4' | 'gbp';
|
|
@@ -289,6 +289,33 @@ interface AgentConfigEntry {
|
|
|
289
289
|
* Both resolvers live in agent-config.ts.
|
|
290
290
|
*/
|
|
291
291
|
mode?: 'disabled' | 'prompt-only';
|
|
292
|
+
/**
|
|
293
|
+
* Pin the LLM provider Aero reasons with.
|
|
294
|
+
*
|
|
295
|
+
* Absent (the default) keeps the historical behaviour: the first provider
|
|
296
|
+
* holding a usable key wins, by `autoDetectPriority`. That default is an
|
|
297
|
+
* accident of which ANSWER-ENGINE keys the install happens to hold -- an
|
|
298
|
+
* install that sweeps with Claude silently gets Claude for Aero too, at that
|
|
299
|
+
* provider's agent-tier pricing -- so any deployment that cares which model
|
|
300
|
+
* answers has to say so here rather than rely on detection order.
|
|
301
|
+
*
|
|
302
|
+
* Ranked by `resolveSessionProviderAndModel`: an explicit per-request
|
|
303
|
+
* provider beats this pin, and this pin beats both the persisted session row
|
|
304
|
+
* and auto-detection. Because it outranks the row, a pin survives the
|
|
305
|
+
* conversation-delete path that drops that row entirely. An explicit request
|
|
306
|
+
* lasts one turn: the next turn that names no provider returns to the pin.
|
|
307
|
+
*
|
|
308
|
+
* Removing the pin does not move an existing session back to detection:
|
|
309
|
+
* without a pin a session keeps its stored provider, as it always has, until
|
|
310
|
+
* its conversation is deleted. Starting a new conversation keeps it too.
|
|
311
|
+
*/
|
|
312
|
+
provider?: AgentProviderId;
|
|
313
|
+
/**
|
|
314
|
+
* Model id for `provider`. Ignored unless `provider` is set: a model slug is
|
|
315
|
+
* only meaningful against the provider that serves it. Absent uses that
|
|
316
|
+
* provider's agent-tier default.
|
|
317
|
+
*/
|
|
318
|
+
model?: string;
|
|
292
319
|
}
|
|
293
320
|
interface DashboardConfigEntry {
|
|
294
321
|
/**
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KBSAEALE.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-WJGUBZSW.js";
|
|
10
|
+
import "./chunk-LWGYRN3T.js";
|
|
11
11
|
import "./chunk-AOJU5LKX.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-DOC4QQLS.js";
|
|
13
|
+
import "./chunk-NYRRWWEE.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|