@ainyc/canonry 1.48.4 → 2.2.1
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 +42 -27
- package/assets/agent-workspace/AGENTS.md +3 -4
- package/assets/agent-workspace/skills/aero/SKILL.md +7 -10
- package/assets/agent-workspace/skills/aero/references/memory-patterns.md +53 -24
- package/assets/agent-workspace/skills/aero/references/orchestration.md +5 -0
- package/assets/agent-workspace/skills/aero/references/regression-playbook.md +5 -0
- package/assets/agent-workspace/skills/aero/references/reporting.md +5 -0
- package/assets/agent-workspace/skills/aero/references/wordpress-elementor-mcp.md +5 -0
- package/assets/agent-workspace/skills/aero/soul.md +30 -0
- package/assets/agent-workspace/skills/canonry-setup/references/canonry-cli.md +38 -38
- package/assets/assets/index-J73csS93.js +301 -0
- package/assets/assets/{index--ev1Bjls.css → index-yF1fs-OW.css} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-IPOVH342.js → chunk-2QNWFP6R.js} +2455 -791
- package/dist/{chunk-ZZ57GRV6.js → chunk-TAII35VC.js} +65 -1
- package/dist/cli.js +401 -766
- package/dist/index.d.ts +2 -8
- package/dist/index.js +2 -2
- package/dist/{intelligence-service-MZ7SXEGE.js → intelligence-service-C5LAYDFM.js} +1 -1
- package/package.json +11 -8
- package/assets/agent-workspace/SOUL.md +0 -54
- package/assets/assets/index-CVk23m8J.js +0 -282
package/dist/cli.js
CHANGED
|
@@ -1,53 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node --import tsx
|
|
2
2
|
import {
|
|
3
|
-
AGENT_WEBHOOK_EVENTS,
|
|
4
|
-
AgentManager,
|
|
5
3
|
CliError,
|
|
6
4
|
EXIT_SYSTEM_ERROR,
|
|
7
|
-
EXIT_USER_ERROR,
|
|
8
5
|
ProviderNames,
|
|
9
6
|
RunKinds,
|
|
10
|
-
|
|
11
|
-
buildAgentWebhookUrl,
|
|
7
|
+
coerceAgentProvider,
|
|
12
8
|
computeCompetitorOverlap,
|
|
13
9
|
configExists,
|
|
14
|
-
|
|
10
|
+
createApiClient,
|
|
15
11
|
createServer,
|
|
16
|
-
detectOpenClaw,
|
|
17
12
|
determineAnswerMentioned,
|
|
18
13
|
determineCitationState,
|
|
19
14
|
effectiveDomains,
|
|
20
15
|
extractRecommendedCompetitors,
|
|
21
16
|
formatAuditFactorScore,
|
|
22
|
-
getAeroStateDir,
|
|
23
17
|
getConfigDir,
|
|
24
18
|
getConfigPath,
|
|
25
19
|
getOrCreateAnonymousId,
|
|
26
|
-
initializeOpenClawProfile,
|
|
27
|
-
installOpenClaw,
|
|
28
20
|
isFirstRun,
|
|
29
21
|
isTelemetryEnabled,
|
|
22
|
+
listAgentProviders,
|
|
30
23
|
loadConfig,
|
|
31
24
|
notificationEventSchema,
|
|
32
25
|
printCliError,
|
|
33
|
-
providerEnvVar,
|
|
34
26
|
providerQuotaPolicySchema,
|
|
35
27
|
reparseStoredResult,
|
|
36
28
|
reparseStoredResult2,
|
|
37
29
|
reparseStoredResult3,
|
|
38
30
|
reparseStoredResult4,
|
|
39
|
-
resolveAgentCredentials,
|
|
40
31
|
resolveProviderInput,
|
|
41
32
|
saveConfig,
|
|
42
33
|
saveConfigPatch,
|
|
43
|
-
seedWorkspace,
|
|
44
34
|
setGoogleAuthConfig,
|
|
45
|
-
setOpenClawModel,
|
|
46
35
|
showFirstRunNotice,
|
|
47
36
|
trackEvent,
|
|
48
|
-
usageError
|
|
49
|
-
|
|
50
|
-
} from "./chunk-IPOVH342.js";
|
|
37
|
+
usageError
|
|
38
|
+
} from "./chunk-2QNWFP6R.js";
|
|
51
39
|
import {
|
|
52
40
|
apiKeys,
|
|
53
41
|
competitors,
|
|
@@ -57,7 +45,7 @@ import {
|
|
|
57
45
|
projects,
|
|
58
46
|
querySnapshots,
|
|
59
47
|
runs
|
|
60
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-TAII35VC.js";
|
|
61
49
|
|
|
62
50
|
// src/cli.ts
|
|
63
51
|
import { pathToFileURL } from "url";
|
|
@@ -67,9 +55,9 @@ import { parseArgs } from "util";
|
|
|
67
55
|
function commandId(spec) {
|
|
68
56
|
return spec.path.join(".");
|
|
69
57
|
}
|
|
70
|
-
function matchesPath(args,
|
|
71
|
-
if (args.length <
|
|
72
|
-
return
|
|
58
|
+
function matchesPath(args, path6) {
|
|
59
|
+
if (args.length < path6.length) return false;
|
|
60
|
+
return path6.every((segment, index) => args[index] === segment);
|
|
73
61
|
}
|
|
74
62
|
function withFormatOption(options) {
|
|
75
63
|
if (!options) {
|
|
@@ -304,7 +292,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
304
292
|
console.log(` Errors: ${providerErrors}`);
|
|
305
293
|
}
|
|
306
294
|
async function backfillInsightsCommand(project, opts) {
|
|
307
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
295
|
+
const { IntelligenceService } = await import("./intelligence-service-C5LAYDFM.js");
|
|
308
296
|
const config = loadConfig();
|
|
309
297
|
const db = createClient(config.database);
|
|
310
298
|
migrate(db);
|
|
@@ -513,460 +501,6 @@ var BACKFILL_CLI_COMMANDS = [
|
|
|
513
501
|
}
|
|
514
502
|
];
|
|
515
503
|
|
|
516
|
-
// src/client.ts
|
|
517
|
-
function createApiClient() {
|
|
518
|
-
const config = loadConfig();
|
|
519
|
-
const basePathResolved = !!config.basePath || "CANONRY_BASE_PATH" in process.env;
|
|
520
|
-
return new ApiClient(config.apiUrl, config.apiKey, { skipProbe: basePathResolved });
|
|
521
|
-
}
|
|
522
|
-
var ApiClient = class {
|
|
523
|
-
baseUrl;
|
|
524
|
-
originUrl;
|
|
525
|
-
apiKey;
|
|
526
|
-
probePromise = null;
|
|
527
|
-
probeSkipped;
|
|
528
|
-
constructor(baseUrl, apiKey, opts) {
|
|
529
|
-
this.originUrl = baseUrl.replace(/\/$/, "");
|
|
530
|
-
this.baseUrl = this.originUrl + "/api/v1";
|
|
531
|
-
this.apiKey = apiKey;
|
|
532
|
-
this.probeSkipped = opts?.skipProbe ?? false;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* On first API call, probe /health to auto-discover basePath when the user
|
|
536
|
-
* hasn't configured one locally. This lets `canonry run` in a separate shell
|
|
537
|
-
* discover that the server is running at e.g. /canonry/ without requiring
|
|
538
|
-
* config.yaml edits or CANONRY_BASE_PATH in every shell.
|
|
539
|
-
*/
|
|
540
|
-
probeBasePath() {
|
|
541
|
-
if (this.probeSkipped) return Promise.resolve();
|
|
542
|
-
if (!this.probePromise) {
|
|
543
|
-
this.probePromise = (async () => {
|
|
544
|
-
try {
|
|
545
|
-
const origin = new URL(this.originUrl).origin;
|
|
546
|
-
const res = await fetch(`${origin}/health`, {
|
|
547
|
-
signal: AbortSignal.timeout(2e3)
|
|
548
|
-
});
|
|
549
|
-
if (res.ok) {
|
|
550
|
-
const body = await res.json();
|
|
551
|
-
if (body.basePath && typeof body.basePath === "string") {
|
|
552
|
-
const normalized = "/" + body.basePath.replace(/^\/|\/$/g, "");
|
|
553
|
-
if (normalized !== "/") {
|
|
554
|
-
this.originUrl = origin + normalized;
|
|
555
|
-
this.baseUrl = this.originUrl + "/api/v1";
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
} catch {
|
|
560
|
-
}
|
|
561
|
-
})();
|
|
562
|
-
}
|
|
563
|
-
return this.probePromise;
|
|
564
|
-
}
|
|
565
|
-
async request(method, path7, body) {
|
|
566
|
-
await this.probeBasePath();
|
|
567
|
-
const url = `${this.baseUrl}${path7}`;
|
|
568
|
-
const serializedBody = body != null ? JSON.stringify(body) : void 0;
|
|
569
|
-
const headers = {
|
|
570
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
571
|
-
"Accept": "application/json",
|
|
572
|
-
...serializedBody != null ? { "Content-Type": "application/json" } : {}
|
|
573
|
-
};
|
|
574
|
-
let res;
|
|
575
|
-
try {
|
|
576
|
-
res = await fetch(url, {
|
|
577
|
-
method,
|
|
578
|
-
headers,
|
|
579
|
-
body: serializedBody
|
|
580
|
-
});
|
|
581
|
-
} catch (err) {
|
|
582
|
-
if (err instanceof CliError) throw err;
|
|
583
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
584
|
-
if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("connect ECONNREFUSED")) {
|
|
585
|
-
throw new CliError({
|
|
586
|
-
code: "CONNECTION_ERROR",
|
|
587
|
-
message: `Could not connect to canonry server at ${this.baseUrl.replace("/api/v1", "")}. Start it with "canonry serve" (or "canonry serve &" to run in background).`,
|
|
588
|
-
exitCode: EXIT_SYSTEM_ERROR
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
throw new CliError({ code: "CONNECTION_ERROR", message: msg, exitCode: EXIT_SYSTEM_ERROR });
|
|
592
|
-
}
|
|
593
|
-
if (!res.ok) {
|
|
594
|
-
let errorBody;
|
|
595
|
-
try {
|
|
596
|
-
errorBody = await res.json();
|
|
597
|
-
} catch {
|
|
598
|
-
errorBody = { error: { code: "UNKNOWN", message: res.statusText } };
|
|
599
|
-
}
|
|
600
|
-
const errorObj = errorBody && typeof errorBody === "object" && "error" in errorBody && errorBody.error && typeof errorBody.error === "object" ? errorBody.error : null;
|
|
601
|
-
const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${res.status}: ${res.statusText}`;
|
|
602
|
-
const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
|
|
603
|
-
const exitCode = res.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
|
|
604
|
-
throw new CliError({ code, message: msg, exitCode });
|
|
605
|
-
}
|
|
606
|
-
if (res.status === 204) {
|
|
607
|
-
return void 0;
|
|
608
|
-
}
|
|
609
|
-
return await res.json();
|
|
610
|
-
}
|
|
611
|
-
async putProject(name, body) {
|
|
612
|
-
return this.request("PUT", `/projects/${encodeURIComponent(name)}`, body);
|
|
613
|
-
}
|
|
614
|
-
async listProjects() {
|
|
615
|
-
return this.request("GET", "/projects");
|
|
616
|
-
}
|
|
617
|
-
async getProject(name) {
|
|
618
|
-
return this.request("GET", `/projects/${encodeURIComponent(name)}`);
|
|
619
|
-
}
|
|
620
|
-
async deleteProject(name) {
|
|
621
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(name)}`);
|
|
622
|
-
}
|
|
623
|
-
async putKeywords(project, keywords) {
|
|
624
|
-
await this.request("PUT", `/projects/${encodeURIComponent(project)}/keywords`, { keywords });
|
|
625
|
-
}
|
|
626
|
-
async listKeywords(project) {
|
|
627
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/keywords`);
|
|
628
|
-
}
|
|
629
|
-
async deleteKeywords(project, keywords) {
|
|
630
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/keywords`, { keywords });
|
|
631
|
-
}
|
|
632
|
-
async appendKeywords(project, keywords) {
|
|
633
|
-
await this.request("POST", `/projects/${encodeURIComponent(project)}/keywords`, { keywords });
|
|
634
|
-
}
|
|
635
|
-
async putCompetitors(project, competitors2) {
|
|
636
|
-
await this.request("PUT", `/projects/${encodeURIComponent(project)}/competitors`, { competitors: competitors2 });
|
|
637
|
-
}
|
|
638
|
-
async listCompetitors(project) {
|
|
639
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/competitors`);
|
|
640
|
-
}
|
|
641
|
-
async triggerRun(project, body) {
|
|
642
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/runs`, body ?? {});
|
|
643
|
-
}
|
|
644
|
-
async listRuns(project, limit) {
|
|
645
|
-
const query = limit != null ? `?limit=${encodeURIComponent(String(limit))}` : "";
|
|
646
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/runs${query}`);
|
|
647
|
-
}
|
|
648
|
-
async getRun(id) {
|
|
649
|
-
return this.request("GET", `/runs/${encodeURIComponent(id)}`);
|
|
650
|
-
}
|
|
651
|
-
async cancelRun(id) {
|
|
652
|
-
return this.request("POST", `/runs/${encodeURIComponent(id)}/cancel`);
|
|
653
|
-
}
|
|
654
|
-
async getTimeline(project) {
|
|
655
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/timeline`);
|
|
656
|
-
}
|
|
657
|
-
async getHistory(project) {
|
|
658
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/history`);
|
|
659
|
-
}
|
|
660
|
-
async getExport(project) {
|
|
661
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/export`);
|
|
662
|
-
}
|
|
663
|
-
async apply(config) {
|
|
664
|
-
return this.request("POST", "/apply", config);
|
|
665
|
-
}
|
|
666
|
-
async getStatus(project) {
|
|
667
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}`);
|
|
668
|
-
}
|
|
669
|
-
async getSettings() {
|
|
670
|
-
return this.request("GET", "/settings");
|
|
671
|
-
}
|
|
672
|
-
async createSnapshot(body) {
|
|
673
|
-
return this.request("POST", "/snapshot", body);
|
|
674
|
-
}
|
|
675
|
-
async updateProvider(name, body) {
|
|
676
|
-
return this.request("PUT", `/settings/providers/${encodeURIComponent(name)}`, body);
|
|
677
|
-
}
|
|
678
|
-
async putSchedule(project, body) {
|
|
679
|
-
return this.request("PUT", `/projects/${encodeURIComponent(project)}/schedule`, body);
|
|
680
|
-
}
|
|
681
|
-
async getSchedule(project) {
|
|
682
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/schedule`);
|
|
683
|
-
}
|
|
684
|
-
async deleteSchedule(project) {
|
|
685
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/schedule`);
|
|
686
|
-
}
|
|
687
|
-
async createNotification(project, body) {
|
|
688
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/notifications`, body);
|
|
689
|
-
}
|
|
690
|
-
async listNotifications(project) {
|
|
691
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/notifications`);
|
|
692
|
-
}
|
|
693
|
-
async deleteNotification(project, id) {
|
|
694
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/notifications/${encodeURIComponent(id)}`);
|
|
695
|
-
}
|
|
696
|
-
async testNotification(project, id) {
|
|
697
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/notifications/${encodeURIComponent(id)}/test`);
|
|
698
|
-
}
|
|
699
|
-
async addLocation(project, body) {
|
|
700
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/locations`, body);
|
|
701
|
-
}
|
|
702
|
-
async listLocations(project) {
|
|
703
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/locations`);
|
|
704
|
-
}
|
|
705
|
-
async removeLocation(project, label) {
|
|
706
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/locations/${encodeURIComponent(label)}`);
|
|
707
|
-
}
|
|
708
|
-
async setDefaultLocation(project, label) {
|
|
709
|
-
return this.request("PUT", `/projects/${encodeURIComponent(project)}/locations/default`, { label });
|
|
710
|
-
}
|
|
711
|
-
async getTelemetry() {
|
|
712
|
-
return this.request("GET", "/telemetry");
|
|
713
|
-
}
|
|
714
|
-
async updateTelemetry(enabled) {
|
|
715
|
-
return this.request("PUT", "/telemetry", { enabled });
|
|
716
|
-
}
|
|
717
|
-
async generateKeywords(project, provider, count) {
|
|
718
|
-
return this.request(
|
|
719
|
-
"POST",
|
|
720
|
-
`/projects/${encodeURIComponent(project)}/keywords/generate`,
|
|
721
|
-
{ provider, count }
|
|
722
|
-
);
|
|
723
|
-
}
|
|
724
|
-
// Google connection management
|
|
725
|
-
async googleConnect(project, body) {
|
|
726
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/connect`, body);
|
|
727
|
-
}
|
|
728
|
-
async googleConnections(project) {
|
|
729
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/connections`);
|
|
730
|
-
}
|
|
731
|
-
async googleDisconnect(project, type) {
|
|
732
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/google/connections/${encodeURIComponent(type)}`);
|
|
733
|
-
}
|
|
734
|
-
async googleProperties(project) {
|
|
735
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/properties`);
|
|
736
|
-
}
|
|
737
|
-
async googleSetProperty(project, type, propertyId) {
|
|
738
|
-
return this.request("PUT", `/projects/${encodeURIComponent(project)}/google/connections/${encodeURIComponent(type)}/property`, { propertyId });
|
|
739
|
-
}
|
|
740
|
-
async googleSetSitemap(project, type, sitemapUrl) {
|
|
741
|
-
return this.request("PUT", `/projects/${encodeURIComponent(project)}/google/connections/${encodeURIComponent(type)}/sitemap`, { sitemapUrl });
|
|
742
|
-
}
|
|
743
|
-
// GSC data
|
|
744
|
-
async gscSync(project, body) {
|
|
745
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/gsc/sync`, body ?? {});
|
|
746
|
-
}
|
|
747
|
-
async gscPerformance(project, params) {
|
|
748
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
749
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/performance${qs}`);
|
|
750
|
-
}
|
|
751
|
-
async gscInspect(project, url) {
|
|
752
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/gsc/inspect`, { url });
|
|
753
|
-
}
|
|
754
|
-
async gscInspections(project, params) {
|
|
755
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
756
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/inspections${qs}`);
|
|
757
|
-
}
|
|
758
|
-
async gscDeindexed(project) {
|
|
759
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/deindexed`);
|
|
760
|
-
}
|
|
761
|
-
async gscCoverage(project) {
|
|
762
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/coverage`);
|
|
763
|
-
}
|
|
764
|
-
async gscCoverageHistory(project, params) {
|
|
765
|
-
const qs = params?.limit != null ? `?limit=${params.limit}` : "";
|
|
766
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/coverage/history${qs}`);
|
|
767
|
-
}
|
|
768
|
-
async gscInspectSitemap(project, body) {
|
|
769
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/gsc/inspect-sitemap`, body ?? {});
|
|
770
|
-
}
|
|
771
|
-
async gscSitemaps(project) {
|
|
772
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/google/gsc/sitemaps`);
|
|
773
|
-
}
|
|
774
|
-
async gscDiscoverSitemaps(project) {
|
|
775
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/gsc/discover-sitemaps`, {});
|
|
776
|
-
}
|
|
777
|
-
// Analytics
|
|
778
|
-
async getAnalyticsMetrics(project, window) {
|
|
779
|
-
const qs = window ? `?window=${encodeURIComponent(window)}` : "";
|
|
780
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/analytics/metrics${qs}`);
|
|
781
|
-
}
|
|
782
|
-
async getAnalyticsGaps(project, window) {
|
|
783
|
-
const qs = window ? `?window=${encodeURIComponent(window)}` : "";
|
|
784
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/analytics/gaps${qs}`);
|
|
785
|
-
}
|
|
786
|
-
async getAnalyticsSources(project, window) {
|
|
787
|
-
const qs = window ? `?window=${encodeURIComponent(window)}` : "";
|
|
788
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/analytics/sources${qs}`);
|
|
789
|
-
}
|
|
790
|
-
// Google Indexing API
|
|
791
|
-
async googleRequestIndexing(project, body) {
|
|
792
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/google/indexing/request`, body);
|
|
793
|
-
}
|
|
794
|
-
// Bing Webmaster Tools
|
|
795
|
-
async bingConnect(project, body) {
|
|
796
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/bing/connect`, body);
|
|
797
|
-
}
|
|
798
|
-
async bingDisconnect(project) {
|
|
799
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/bing/disconnect`);
|
|
800
|
-
}
|
|
801
|
-
async bingStatus(project) {
|
|
802
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/status`);
|
|
803
|
-
}
|
|
804
|
-
async bingSites(project) {
|
|
805
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/sites`);
|
|
806
|
-
}
|
|
807
|
-
async bingSetSite(project, siteUrl) {
|
|
808
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/bing/set-site`, { siteUrl });
|
|
809
|
-
}
|
|
810
|
-
async bingCoverage(project) {
|
|
811
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/coverage`);
|
|
812
|
-
}
|
|
813
|
-
async bingCoverageHistory(project, params) {
|
|
814
|
-
const qs = params?.limit != null ? `?limit=${params.limit}` : "";
|
|
815
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/coverage/history${qs}`);
|
|
816
|
-
}
|
|
817
|
-
async bingInspections(project, params) {
|
|
818
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
819
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/inspections${qs}`);
|
|
820
|
-
}
|
|
821
|
-
async bingInspectUrl(project, url) {
|
|
822
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/bing/inspect-url`, { url });
|
|
823
|
-
}
|
|
824
|
-
async bingRequestIndexing(project, body) {
|
|
825
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/bing/request-indexing`, body);
|
|
826
|
-
}
|
|
827
|
-
async bingPerformance(project, params) {
|
|
828
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
829
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/bing/performance${qs}`);
|
|
830
|
-
}
|
|
831
|
-
// CDP browser provider
|
|
832
|
-
async getCdpStatus() {
|
|
833
|
-
return this.request("GET", "/cdp/status");
|
|
834
|
-
}
|
|
835
|
-
async cdpScreenshot(query, targets) {
|
|
836
|
-
return this.request("POST", "/cdp/screenshot", { query, targets });
|
|
837
|
-
}
|
|
838
|
-
async getBrowserDiff(project, runId) {
|
|
839
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/runs/${encodeURIComponent(runId)}/browser-diff`);
|
|
840
|
-
}
|
|
841
|
-
// Google Analytics 4
|
|
842
|
-
async gaConnect(project, body) {
|
|
843
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/ga/connect`, body);
|
|
844
|
-
}
|
|
845
|
-
async gaDisconnect(project) {
|
|
846
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/ga/disconnect`);
|
|
847
|
-
}
|
|
848
|
-
async gaStatus(project) {
|
|
849
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/status`);
|
|
850
|
-
}
|
|
851
|
-
async gaSync(project, body) {
|
|
852
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/ga/sync`, body ?? {});
|
|
853
|
-
}
|
|
854
|
-
async gaTraffic(project, params) {
|
|
855
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
856
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/traffic${qs}`);
|
|
857
|
-
}
|
|
858
|
-
async gaCoverage(project) {
|
|
859
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/coverage`);
|
|
860
|
-
}
|
|
861
|
-
async gaAiReferralHistory(project, params) {
|
|
862
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
863
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/ai-referral-history${qs}`);
|
|
864
|
-
}
|
|
865
|
-
async gaSocialReferralHistory(project, params) {
|
|
866
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
867
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-history${qs}`);
|
|
868
|
-
}
|
|
869
|
-
async gaSocialReferralTrend(project) {
|
|
870
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-trend`);
|
|
871
|
-
}
|
|
872
|
-
async gaAttributionTrend(project) {
|
|
873
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/attribution-trend`);
|
|
874
|
-
}
|
|
875
|
-
async gaSessionHistory(project, params) {
|
|
876
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
877
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/session-history${qs}`);
|
|
878
|
-
}
|
|
879
|
-
async wordpressConnect(project, body) {
|
|
880
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/connect`, body);
|
|
881
|
-
}
|
|
882
|
-
async wordpressDisconnect(project) {
|
|
883
|
-
await this.request("DELETE", `/projects/${encodeURIComponent(project)}/wordpress/disconnect`);
|
|
884
|
-
}
|
|
885
|
-
async wordpressStatus(project) {
|
|
886
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/status`);
|
|
887
|
-
}
|
|
888
|
-
async wordpressPages(project, env) {
|
|
889
|
-
const qs = env ? `?env=${encodeURIComponent(env)}` : "";
|
|
890
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/pages${qs}`);
|
|
891
|
-
}
|
|
892
|
-
async wordpressPage(project, slug, env) {
|
|
893
|
-
const params = new URLSearchParams({ slug });
|
|
894
|
-
if (env) params.set("env", env);
|
|
895
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/page?${params.toString()}`);
|
|
896
|
-
}
|
|
897
|
-
async wordpressCreatePage(project, body) {
|
|
898
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/pages`, body);
|
|
899
|
-
}
|
|
900
|
-
async wordpressUpdatePage(project, body) {
|
|
901
|
-
return this.request("PUT", `/projects/${encodeURIComponent(project)}/wordpress/page`, body);
|
|
902
|
-
}
|
|
903
|
-
async wordpressSetMeta(project, body) {
|
|
904
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/page/meta`, body);
|
|
905
|
-
}
|
|
906
|
-
async wordpressBulkSetMeta(project, body) {
|
|
907
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/pages/meta/bulk`, body);
|
|
908
|
-
}
|
|
909
|
-
async wordpressSchema(project, slug, env) {
|
|
910
|
-
const params = new URLSearchParams({ slug });
|
|
911
|
-
if (env) params.set("env", env);
|
|
912
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/schema?${params.toString()}`);
|
|
913
|
-
}
|
|
914
|
-
async wordpressSetSchema(project, body) {
|
|
915
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/schema/manual`, body);
|
|
916
|
-
}
|
|
917
|
-
async wordpressSchemaDeploy(project, body) {
|
|
918
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/schema/deploy`, body);
|
|
919
|
-
}
|
|
920
|
-
async wordpressSchemaStatus(project, env) {
|
|
921
|
-
const params = new URLSearchParams();
|
|
922
|
-
if (env) params.set("env", env);
|
|
923
|
-
const qs = params.toString();
|
|
924
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/schema/status${qs ? `?${qs}` : ""}`);
|
|
925
|
-
}
|
|
926
|
-
async wordpressOnboard(project, body) {
|
|
927
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/onboard`, body);
|
|
928
|
-
}
|
|
929
|
-
async wordpressLlmsTxt(project, env) {
|
|
930
|
-
const qs = env ? `?env=${encodeURIComponent(env)}` : "";
|
|
931
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/llms-txt${qs}`);
|
|
932
|
-
}
|
|
933
|
-
async wordpressSetLlmsTxt(project, body) {
|
|
934
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/llms-txt/manual`, body);
|
|
935
|
-
}
|
|
936
|
-
async wordpressAudit(project, env) {
|
|
937
|
-
const qs = env ? `?env=${encodeURIComponent(env)}` : "";
|
|
938
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/audit${qs}`);
|
|
939
|
-
}
|
|
940
|
-
async wordpressDiff(project, slug) {
|
|
941
|
-
const params = new URLSearchParams({ slug });
|
|
942
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/diff?${params.toString()}`);
|
|
943
|
-
}
|
|
944
|
-
async wordpressStagingStatus(project) {
|
|
945
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/wordpress/staging/status`);
|
|
946
|
-
}
|
|
947
|
-
async wordpressStagingPush(project) {
|
|
948
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/staging/push`);
|
|
949
|
-
}
|
|
950
|
-
// ── Intelligence ──────────────────────────────────────────────────────
|
|
951
|
-
async getInsights(project, opts) {
|
|
952
|
-
const params = new URLSearchParams();
|
|
953
|
-
if (opts?.dismissed) params.set("dismissed", "true");
|
|
954
|
-
if (opts?.runId) params.set("runId", opts.runId);
|
|
955
|
-
const qs = params.toString();
|
|
956
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/insights${qs ? `?${qs}` : ""}`);
|
|
957
|
-
}
|
|
958
|
-
async dismissInsight(project, id) {
|
|
959
|
-
return this.request("POST", `/projects/${encodeURIComponent(project)}/insights/${encodeURIComponent(id)}/dismiss`);
|
|
960
|
-
}
|
|
961
|
-
async getHealth(project) {
|
|
962
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/health/latest`);
|
|
963
|
-
}
|
|
964
|
-
async getHealthHistory(project, limit) {
|
|
965
|
-
const qs = limit ? `?limit=${limit}` : "";
|
|
966
|
-
return this.request("GET", `/projects/${encodeURIComponent(project)}/health/history${qs}`);
|
|
967
|
-
}
|
|
968
|
-
};
|
|
969
|
-
|
|
970
504
|
// src/commands/bing.ts
|
|
971
505
|
function getClient() {
|
|
972
506
|
return createApiClient();
|
|
@@ -6868,8 +6402,8 @@ async function wordpressSetMeta(project, body) {
|
|
|
6868
6402
|
}
|
|
6869
6403
|
async function wordpressBulkSetMeta(project, opts) {
|
|
6870
6404
|
const fs8 = await import("fs/promises");
|
|
6871
|
-
const
|
|
6872
|
-
const filePath =
|
|
6405
|
+
const path6 = await import("path");
|
|
6406
|
+
const filePath = path6.resolve(opts.from);
|
|
6873
6407
|
let raw;
|
|
6874
6408
|
try {
|
|
6875
6409
|
raw = await fs8.readFile(filePath, "utf8");
|
|
@@ -6970,9 +6504,9 @@ async function wordpressSetSchema(project, body) {
|
|
|
6970
6504
|
}
|
|
6971
6505
|
async function wordpressSchemaDeploy(project, opts) {
|
|
6972
6506
|
const fs8 = await import("fs/promises");
|
|
6973
|
-
const
|
|
6507
|
+
const path6 = await import("path");
|
|
6974
6508
|
const yaml = await import("yaml").catch(() => null);
|
|
6975
|
-
const filePath =
|
|
6509
|
+
const filePath = path6.resolve(opts.profile);
|
|
6976
6510
|
let raw;
|
|
6977
6511
|
try {
|
|
6978
6512
|
raw = await fs8.readFile(filePath, "utf8");
|
|
@@ -7081,9 +6615,9 @@ async function wordpressOnboard(project, opts) {
|
|
|
7081
6615
|
let profileData;
|
|
7082
6616
|
if (opts.profile) {
|
|
7083
6617
|
const fs8 = await import("fs/promises");
|
|
7084
|
-
const
|
|
6618
|
+
const path6 = await import("path");
|
|
7085
6619
|
const yaml = await import("yaml").catch(() => null);
|
|
7086
|
-
const filePath =
|
|
6620
|
+
const filePath = path6.resolve(opts.profile);
|
|
7087
6621
|
let raw;
|
|
7088
6622
|
try {
|
|
7089
6623
|
raw = await fs8.readFile(filePath, "utf8");
|
|
@@ -7667,215 +7201,11 @@ var WORDPRESS_CLI_COMMANDS = [
|
|
|
7667
7201
|
}
|
|
7668
7202
|
];
|
|
7669
7203
|
|
|
7204
|
+
// src/agent-webhook.ts
|
|
7205
|
+
var AGENT_WEBHOOK_EVENTS = ["run.completed", "insight.critical", "insight.high", "citation.gained"];
|
|
7206
|
+
|
|
7670
7207
|
// src/commands/agent.ts
|
|
7671
|
-
import path6 from "path";
|
|
7672
|
-
function resolveStateDir(opts) {
|
|
7673
|
-
if (opts?.stateDir) return opts.stateDir;
|
|
7674
|
-
try {
|
|
7675
|
-
const config = loadConfig();
|
|
7676
|
-
const profile = config.agent?.profile ?? "aero";
|
|
7677
|
-
return getAeroStateDir(profile);
|
|
7678
|
-
} catch {
|
|
7679
|
-
return getAeroStateDir();
|
|
7680
|
-
}
|
|
7681
|
-
}
|
|
7682
|
-
function resolveConfig() {
|
|
7683
|
-
try {
|
|
7684
|
-
return loadConfig().agent ?? {};
|
|
7685
|
-
} catch {
|
|
7686
|
-
return {};
|
|
7687
|
-
}
|
|
7688
|
-
}
|
|
7689
|
-
async function agentStatus(opts) {
|
|
7690
|
-
const stateDir = resolveStateDir(opts);
|
|
7691
|
-
const config = resolveConfig();
|
|
7692
|
-
const mgr = new AgentManager(config, stateDir);
|
|
7693
|
-
const status = mgr.status();
|
|
7694
|
-
if (opts?.format === "json") {
|
|
7695
|
-
console.log(JSON.stringify(status, null, 2));
|
|
7696
|
-
return;
|
|
7697
|
-
}
|
|
7698
|
-
if (status.state === "running") {
|
|
7699
|
-
console.log(`Agent: running (PID ${status.pid}, port ${status.port})`);
|
|
7700
|
-
if (status.startedAt) {
|
|
7701
|
-
console.log(`Started: ${status.startedAt}`);
|
|
7702
|
-
}
|
|
7703
|
-
} else {
|
|
7704
|
-
console.log("Agent: stopped");
|
|
7705
|
-
}
|
|
7706
|
-
}
|
|
7707
|
-
async function agentStart(opts) {
|
|
7708
|
-
const stateDir = resolveStateDir(opts);
|
|
7709
|
-
const config = resolveConfig();
|
|
7710
|
-
const mgr = new AgentManager(config, stateDir);
|
|
7711
|
-
await mgr.start();
|
|
7712
|
-
const status = mgr.status();
|
|
7713
|
-
if (opts?.format === "json") {
|
|
7714
|
-
console.log(JSON.stringify(status, null, 2));
|
|
7715
|
-
} else {
|
|
7716
|
-
console.log(`Agent started (PID ${status.pid}, port ${status.port})`);
|
|
7717
|
-
}
|
|
7718
|
-
}
|
|
7719
|
-
async function agentStop(opts) {
|
|
7720
|
-
const stateDir = resolveStateDir(opts);
|
|
7721
|
-
const config = resolveConfig();
|
|
7722
|
-
const mgr = new AgentManager(config, stateDir);
|
|
7723
|
-
await mgr.stop();
|
|
7724
|
-
if (opts?.format === "json") {
|
|
7725
|
-
console.log(JSON.stringify({ state: "stopped" }, null, 2));
|
|
7726
|
-
} else {
|
|
7727
|
-
console.log("Agent stopped");
|
|
7728
|
-
}
|
|
7729
|
-
}
|
|
7730
|
-
async function agentReset(opts) {
|
|
7731
|
-
const stateDir = resolveStateDir(opts);
|
|
7732
|
-
const config = resolveConfig();
|
|
7733
|
-
const mgr = new AgentManager(config, stateDir);
|
|
7734
|
-
await mgr.reset();
|
|
7735
|
-
if (opts?.format === "json") {
|
|
7736
|
-
console.log(JSON.stringify({ state: "reset" }, null, 2));
|
|
7737
|
-
} else {
|
|
7738
|
-
console.log('Agent reset \u2014 workspace wiped. Run "canonry agent setup" to re-initialize.');
|
|
7739
|
-
}
|
|
7740
|
-
}
|
|
7741
|
-
async function agentSetup(opts) {
|
|
7742
|
-
const isJson = opts?.format === "json";
|
|
7743
|
-
let agentLLM;
|
|
7744
|
-
if (!configExists()) {
|
|
7745
|
-
const initOpts = {
|
|
7746
|
-
geminiKey: opts?.geminiKey,
|
|
7747
|
-
openaiKey: opts?.openaiKey,
|
|
7748
|
-
claudeKey: opts?.claudeKey,
|
|
7749
|
-
perplexityKey: opts?.perplexityKey,
|
|
7750
|
-
localUrl: opts?.localUrl,
|
|
7751
|
-
localModel: opts?.localModel,
|
|
7752
|
-
localKey: opts?.localKey,
|
|
7753
|
-
googleClientId: opts?.googleClientId,
|
|
7754
|
-
googleClientSecret: opts?.googleClientSecret,
|
|
7755
|
-
agentProvider: opts?.agentProvider,
|
|
7756
|
-
agentKey: opts?.agentKey,
|
|
7757
|
-
agentModel: opts?.agentModel
|
|
7758
|
-
};
|
|
7759
|
-
if (isJson) {
|
|
7760
|
-
agentLLM = await suppressStdout(() => initCommand(initOpts)) ?? void 0;
|
|
7761
|
-
} else {
|
|
7762
|
-
agentLLM = await initCommand(initOpts) ?? void 0;
|
|
7763
|
-
}
|
|
7764
|
-
}
|
|
7765
|
-
const existingConfig = resolveConfig();
|
|
7766
|
-
let detection = await detectOpenClaw(existingConfig);
|
|
7767
|
-
if (!detection.found) {
|
|
7768
|
-
detection = await autoInstallOrFail(opts?.format);
|
|
7769
|
-
}
|
|
7770
|
-
const profile = existingConfig.profile ?? "aero";
|
|
7771
|
-
const gatewayPort = opts?.gatewayPort ?? existingConfig.gatewayPort ?? 3579;
|
|
7772
|
-
const stateDir = opts?.stateDir ?? getAeroStateDir(profile);
|
|
7773
|
-
saveConfigPatch({
|
|
7774
|
-
agent: {
|
|
7775
|
-
binary: detection.path,
|
|
7776
|
-
profile,
|
|
7777
|
-
gatewayPort,
|
|
7778
|
-
autoStart: existingConfig.autoStart
|
|
7779
|
-
}
|
|
7780
|
-
});
|
|
7781
|
-
initializeOpenClawProfile(detection.path, profile, path6.join(stateDir, "workspace"));
|
|
7782
|
-
configureOpenClawGateway(detection.path, profile, gatewayPort);
|
|
7783
|
-
const creds = agentLLM ?? resolveAgentCredentials({
|
|
7784
|
-
agentProvider: opts?.agentProvider,
|
|
7785
|
-
agentKey: opts?.agentKey,
|
|
7786
|
-
agentModel: opts?.agentModel,
|
|
7787
|
-
stateDir
|
|
7788
|
-
});
|
|
7789
|
-
if (creds.key) {
|
|
7790
|
-
writeAgentEnv(stateDir, providerEnvVar(creds.provider), creds.key);
|
|
7791
|
-
if (opts?.format !== "json") {
|
|
7792
|
-
console.log(`Agent LLM: ${creds.provider} credentials configured`);
|
|
7793
|
-
}
|
|
7794
|
-
}
|
|
7795
|
-
if (creds.model) {
|
|
7796
|
-
setOpenClawModel(detection.path, profile, creds.model);
|
|
7797
|
-
if (opts?.format !== "json") {
|
|
7798
|
-
console.log(`Agent model: ${creds.model}`);
|
|
7799
|
-
}
|
|
7800
|
-
}
|
|
7801
|
-
seedWorkspace(stateDir);
|
|
7802
|
-
const attachSummary = await attachAgentWebhookToAllProjects(gatewayPort);
|
|
7803
|
-
if (opts?.format === "json") {
|
|
7804
|
-
console.log(JSON.stringify({
|
|
7805
|
-
state: "configured",
|
|
7806
|
-
binary: detection.path,
|
|
7807
|
-
version: detection.version,
|
|
7808
|
-
profile,
|
|
7809
|
-
gatewayPort,
|
|
7810
|
-
stateDir,
|
|
7811
|
-
attached: attachSummary
|
|
7812
|
-
}, null, 2));
|
|
7813
|
-
} else {
|
|
7814
|
-
console.log(`OpenClaw: ${detection.path} (${detection.version})`);
|
|
7815
|
-
console.log(`Profile: ${profile}`);
|
|
7816
|
-
console.log(`Gateway port: ${gatewayPort}`);
|
|
7817
|
-
console.log(`State dir: ${stateDir}`);
|
|
7818
|
-
if (attachSummary.attached > 0 || attachSummary.alreadyAttached > 0) {
|
|
7819
|
-
console.log(
|
|
7820
|
-
`Agent webhook: ${attachSummary.attached} attached, ${attachSummary.alreadyAttached} already present (via ${attachSummary.path})`
|
|
7821
|
-
);
|
|
7822
|
-
}
|
|
7823
|
-
console.log("Agent setup complete.");
|
|
7824
|
-
}
|
|
7825
|
-
}
|
|
7826
|
-
async function attachAgentWebhookToAllProjects(gatewayPort) {
|
|
7827
|
-
let config;
|
|
7828
|
-
try {
|
|
7829
|
-
config = loadConfig();
|
|
7830
|
-
} catch {
|
|
7831
|
-
return { path: "skipped", attached: 0, alreadyAttached: 0 };
|
|
7832
|
-
}
|
|
7833
|
-
try {
|
|
7834
|
-
const client = createApiClient();
|
|
7835
|
-
const projectList = await client.listProjects();
|
|
7836
|
-
const agentUrl = buildAgentWebhookUrl(gatewayPort);
|
|
7837
|
-
let attached2 = 0;
|
|
7838
|
-
let alreadyAttached2 = 0;
|
|
7839
|
-
for (const project of projectList) {
|
|
7840
|
-
const existing = await client.listNotifications(project.name);
|
|
7841
|
-
if (existing.some((n) => n.source === "agent")) {
|
|
7842
|
-
alreadyAttached2++;
|
|
7843
|
-
continue;
|
|
7844
|
-
}
|
|
7845
|
-
await client.createNotification(project.name, {
|
|
7846
|
-
channel: "webhook",
|
|
7847
|
-
url: agentUrl,
|
|
7848
|
-
events: [...AGENT_WEBHOOK_EVENTS],
|
|
7849
|
-
source: "agent"
|
|
7850
|
-
});
|
|
7851
|
-
attached2++;
|
|
7852
|
-
}
|
|
7853
|
-
return { path: "api", attached: attached2, alreadyAttached: alreadyAttached2 };
|
|
7854
|
-
} catch (err) {
|
|
7855
|
-
if (!isConnectionError(err)) throw err;
|
|
7856
|
-
}
|
|
7857
|
-
const db = createClient(config.database);
|
|
7858
|
-
migrate(db);
|
|
7859
|
-
const rows = db.select({ id: projects.id }).from(projects).all();
|
|
7860
|
-
let attached = 0;
|
|
7861
|
-
let alreadyAttached = 0;
|
|
7862
|
-
for (const row of rows) {
|
|
7863
|
-
const result = attachAgentWebhookDirect(db, row.id, gatewayPort);
|
|
7864
|
-
if (result === "attached") attached++;
|
|
7865
|
-
else alreadyAttached++;
|
|
7866
|
-
}
|
|
7867
|
-
return { path: "db", attached, alreadyAttached };
|
|
7868
|
-
}
|
|
7869
|
-
function isConnectionError(err) {
|
|
7870
|
-
if (!(err instanceof Error)) return false;
|
|
7871
|
-
const msg = err.message.toLowerCase();
|
|
7872
|
-
const code = err.code ?? "";
|
|
7873
|
-
return code === "CONNECTION_ERROR" || code === "ECONNREFUSED" || code === "ENOTFOUND" || msg.includes("could not connect") || msg.includes("econnrefused") || msg.includes("fetch failed") || msg.includes("connection refused");
|
|
7874
|
-
}
|
|
7875
7208
|
async function agentAttach(opts) {
|
|
7876
|
-
const config = loadConfig();
|
|
7877
|
-
const gatewayPort = config.agent?.gatewayPort ?? 3579;
|
|
7878
|
-
const agentUrl = buildAgentWebhookUrl(gatewayPort);
|
|
7879
7209
|
const client = createApiClient();
|
|
7880
7210
|
const existing = await client.listNotifications(opts.project);
|
|
7881
7211
|
const hasAgent = existing.some((n) => n.source === "agent");
|
|
@@ -7889,14 +7219,14 @@ async function agentAttach(opts) {
|
|
|
7889
7219
|
}
|
|
7890
7220
|
const result = await client.createNotification(opts.project, {
|
|
7891
7221
|
channel: "webhook",
|
|
7892
|
-
url:
|
|
7222
|
+
url: opts.url,
|
|
7893
7223
|
events: [...AGENT_WEBHOOK_EVENTS],
|
|
7894
7224
|
source: "agent"
|
|
7895
7225
|
});
|
|
7896
7226
|
if (opts.format === "json") {
|
|
7897
7227
|
console.log(JSON.stringify({ status: "attached", project: opts.project, notificationId: result.id }));
|
|
7898
7228
|
} else {
|
|
7899
|
-
console.log(`Agent webhook attached to "${opts.project}"`);
|
|
7229
|
+
console.log(`Agent webhook attached to "${opts.project}" (${opts.url})`);
|
|
7900
7230
|
}
|
|
7901
7231
|
}
|
|
7902
7232
|
async function agentDetach(opts) {
|
|
@@ -7918,136 +7248,441 @@ async function agentDetach(opts) {
|
|
|
7918
7248
|
console.log(`Agent webhook detached from "${opts.project}"`);
|
|
7919
7249
|
}
|
|
7920
7250
|
}
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7251
|
+
|
|
7252
|
+
// src/commands/agent-ask.ts
|
|
7253
|
+
async function agentAsk(opts) {
|
|
7254
|
+
const format = opts.format === "json" ? "json" : "text";
|
|
7255
|
+
const isJson = format === "json";
|
|
7256
|
+
const controller = new AbortController();
|
|
7257
|
+
const onSigint = () => controller.abort();
|
|
7258
|
+
process.on("SIGINT", onSigint);
|
|
7259
|
+
let sawStreamError = false;
|
|
7260
|
+
try {
|
|
7261
|
+
const client = createApiClient();
|
|
7262
|
+
const res = await client.streamPost(
|
|
7263
|
+
`/projects/${encodeURIComponent(opts.project)}/agent/prompt`,
|
|
7264
|
+
{
|
|
7265
|
+
prompt: opts.prompt,
|
|
7266
|
+
provider: opts.provider,
|
|
7267
|
+
modelId: opts.modelId,
|
|
7268
|
+
scope: opts.scope ?? "all"
|
|
7269
|
+
},
|
|
7270
|
+
controller.signal
|
|
7271
|
+
);
|
|
7272
|
+
if (!res.body) {
|
|
7273
|
+
throw new CliError({
|
|
7274
|
+
code: "API_ERROR",
|
|
7275
|
+
message: "Server returned no response body",
|
|
7276
|
+
exitCode: EXIT_SYSTEM_ERROR
|
|
7277
|
+
});
|
|
7278
|
+
}
|
|
7279
|
+
for await (const event of parseSse(res.body)) {
|
|
7280
|
+
renderEvent(event, isJson);
|
|
7281
|
+
if (event.type === "message_end" && event.message.role === "assistant") {
|
|
7282
|
+
const msg = event.message;
|
|
7283
|
+
if (msg.stopReason === "error" || msg.errorMessage) sawStreamError = true;
|
|
7284
|
+
} else if (event.type === "error") {
|
|
7285
|
+
sawStreamError = true;
|
|
7286
|
+
}
|
|
7287
|
+
}
|
|
7288
|
+
if (sawStreamError) process.exitCode = EXIT_SYSTEM_ERROR;
|
|
7289
|
+
} catch (err) {
|
|
7290
|
+
printCliError(err, format);
|
|
7291
|
+
process.exitCode = err instanceof CliError ? err.exitCode : EXIT_SYSTEM_ERROR;
|
|
7292
|
+
} finally {
|
|
7293
|
+
process.off("SIGINT", onSigint);
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7296
|
+
async function* parseSse(stream) {
|
|
7297
|
+
const reader = stream.getReader();
|
|
7298
|
+
const decoder = new TextDecoder();
|
|
7299
|
+
let buffer = "";
|
|
7300
|
+
try {
|
|
7301
|
+
while (true) {
|
|
7302
|
+
const { value, done } = await reader.read();
|
|
7303
|
+
if (done) break;
|
|
7304
|
+
buffer += decoder.decode(value, { stream: true });
|
|
7305
|
+
let boundary = buffer.indexOf("\n\n");
|
|
7306
|
+
while (boundary !== -1) {
|
|
7307
|
+
const frame = buffer.slice(0, boundary);
|
|
7308
|
+
buffer = buffer.slice(boundary + 2);
|
|
7309
|
+
for (const line of frame.split("\n")) {
|
|
7310
|
+
if (!line.startsWith("data:")) continue;
|
|
7311
|
+
const payload = line.slice(5).trim();
|
|
7312
|
+
if (!payload) continue;
|
|
7313
|
+
try {
|
|
7314
|
+
yield JSON.parse(payload);
|
|
7315
|
+
} catch {
|
|
7316
|
+
}
|
|
7317
|
+
}
|
|
7318
|
+
boundary = buffer.indexOf("\n\n");
|
|
7319
|
+
}
|
|
7320
|
+
}
|
|
7321
|
+
} finally {
|
|
7322
|
+
try {
|
|
7323
|
+
reader.releaseLock();
|
|
7324
|
+
} catch {
|
|
7325
|
+
}
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
function renderEvent(event, isJson) {
|
|
7329
|
+
if (isJson) {
|
|
7330
|
+
console.log(JSON.stringify(event));
|
|
7331
|
+
return;
|
|
7332
|
+
}
|
|
7333
|
+
switch (event.type) {
|
|
7334
|
+
case "tool_execution_start":
|
|
7335
|
+
console.log(`
|
|
7336
|
+
\u27D0 ${event.toolName} ${JSON.stringify(event.args)}`);
|
|
7337
|
+
break;
|
|
7338
|
+
case "tool_execution_end":
|
|
7339
|
+
console.log(` ${event.isError ? "\u2717" : "\u2713"} ${event.toolName}`);
|
|
7340
|
+
break;
|
|
7341
|
+
case "message_end": {
|
|
7342
|
+
const message = event.message;
|
|
7343
|
+
if (message.role === "assistant") {
|
|
7344
|
+
for (const block of message.content) {
|
|
7345
|
+
if (block.type === "text" && block.text.trim().length > 0) {
|
|
7346
|
+
console.log("\n" + block.text);
|
|
7347
|
+
}
|
|
7348
|
+
}
|
|
7349
|
+
}
|
|
7350
|
+
break;
|
|
7351
|
+
}
|
|
7352
|
+
case "error":
|
|
7353
|
+
console.error(`Agent stream error: ${event.message}`);
|
|
7354
|
+
break;
|
|
7355
|
+
}
|
|
7356
|
+
}
|
|
7357
|
+
|
|
7358
|
+
// src/commands/agent-providers.ts
|
|
7359
|
+
async function agentProviders(opts) {
|
|
7360
|
+
const format = opts.format === "json" ? "json" : "text";
|
|
7361
|
+
try {
|
|
7362
|
+
const client = createApiClient();
|
|
7363
|
+
const res = await client.listAgentProviders(opts.project);
|
|
7364
|
+
if (format === "json") {
|
|
7365
|
+
console.log(JSON.stringify(res, null, 2));
|
|
7366
|
+
return;
|
|
7367
|
+
}
|
|
7368
|
+
console.log(
|
|
7369
|
+
`Aero providers for ${opts.project} (default: ${res.defaultProvider ?? "none configured"})
|
|
7370
|
+
`
|
|
7371
|
+
);
|
|
7372
|
+
const idWidth = Math.max(...res.providers.map((p) => p.id.length), 8);
|
|
7373
|
+
for (const p of res.providers) {
|
|
7374
|
+
const status = p.configured ? "\u2713" : "\u2717";
|
|
7375
|
+
const source = p.keySource ? `(${p.keySource})` : "";
|
|
7376
|
+
console.log(
|
|
7377
|
+
` ${status} ${p.id.padEnd(idWidth)} ${p.label} \u2014 model ${p.defaultModel} ${source}`.trimEnd()
|
|
7378
|
+
);
|
|
7379
|
+
}
|
|
7380
|
+
} catch (err) {
|
|
7381
|
+
printCliError(err, format);
|
|
7382
|
+
if (err instanceof CliError) process.exitCode = err.exitCode;
|
|
7383
|
+
else process.exitCode = 2;
|
|
7924
7384
|
}
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7385
|
+
}
|
|
7386
|
+
|
|
7387
|
+
// src/commands/agent-transcript.ts
|
|
7388
|
+
async function agentTranscript(opts) {
|
|
7389
|
+
const format = opts.format === "json" ? "json" : "text";
|
|
7390
|
+
try {
|
|
7391
|
+
const client = createApiClient();
|
|
7392
|
+
const transcript = await client.getAgentTranscript(opts.project);
|
|
7928
7393
|
if (format === "json") {
|
|
7929
|
-
console.
|
|
7394
|
+
console.log(JSON.stringify(transcript, null, 2));
|
|
7395
|
+
return;
|
|
7396
|
+
}
|
|
7397
|
+
if (transcript.messages.length === 0) {
|
|
7398
|
+
console.log(`No Aero conversation yet for "${opts.project}".`);
|
|
7399
|
+
return;
|
|
7400
|
+
}
|
|
7401
|
+
console.log(
|
|
7402
|
+
`Aero session for ${opts.project} \u2014 ${transcript.modelProvider ?? "unknown"}/${transcript.modelId ?? "unknown"} \u2014 updated ${transcript.updatedAt ?? "never"}`
|
|
7403
|
+
);
|
|
7404
|
+
console.log(`${transcript.messages.length} message${transcript.messages.length === 1 ? "" : "s"}
|
|
7405
|
+
`);
|
|
7406
|
+
for (const msg of transcript.messages) {
|
|
7407
|
+
console.log(`[${msg.role}]`);
|
|
7408
|
+
if (typeof msg.content === "string") {
|
|
7409
|
+
console.log(msg.content);
|
|
7410
|
+
} else if (Array.isArray(msg.content)) {
|
|
7411
|
+
for (const block of msg.content) {
|
|
7412
|
+
const t = block.type;
|
|
7413
|
+
if (t === "text") console.log(block.text);
|
|
7414
|
+
else if (t === "toolCall") console.log(`\u27D0 ${block.name} ${JSON.stringify(block.arguments)}`);
|
|
7415
|
+
else if (t === "toolResult") console.log(` ${block.isError ? "\u2717" : "\u2713"} tool-result`);
|
|
7416
|
+
}
|
|
7417
|
+
}
|
|
7418
|
+
console.log();
|
|
7419
|
+
}
|
|
7420
|
+
} catch (err) {
|
|
7421
|
+
printCliError(err, format);
|
|
7422
|
+
if (err instanceof CliError) process.exitCode = err.exitCode;
|
|
7423
|
+
else process.exitCode = 2;
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
async function agentTranscriptReset(opts) {
|
|
7427
|
+
const format = opts.format === "json" ? "json" : "text";
|
|
7428
|
+
try {
|
|
7429
|
+
const client = createApiClient();
|
|
7430
|
+
await client.resetAgentTranscript(opts.project);
|
|
7431
|
+
if (format === "json") {
|
|
7432
|
+
console.log(JSON.stringify({ status: "reset", project: opts.project }));
|
|
7930
7433
|
} else {
|
|
7931
|
-
console.
|
|
7434
|
+
console.log(`Aero conversation reset for "${opts.project}".`);
|
|
7932
7435
|
}
|
|
7933
|
-
|
|
7934
|
-
|
|
7436
|
+
} catch (err) {
|
|
7437
|
+
printCliError(err, format);
|
|
7438
|
+
if (err instanceof CliError) process.exitCode = err.exitCode;
|
|
7439
|
+
else process.exitCode = 2;
|
|
7935
7440
|
}
|
|
7936
|
-
|
|
7937
|
-
|
|
7441
|
+
}
|
|
7442
|
+
|
|
7443
|
+
// src/commands/agent-memory.ts
|
|
7444
|
+
function toFormat2(raw) {
|
|
7445
|
+
return raw === "json" ? "json" : "text";
|
|
7446
|
+
}
|
|
7447
|
+
async function agentMemoryList(opts) {
|
|
7448
|
+
const format = toFormat2(opts.format);
|
|
7449
|
+
try {
|
|
7450
|
+
const client = createApiClient();
|
|
7451
|
+
const result = await client.listAgentMemory(opts.project);
|
|
7452
|
+
if (format === "json") {
|
|
7453
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7454
|
+
return;
|
|
7455
|
+
}
|
|
7456
|
+
if (result.entries.length === 0) {
|
|
7457
|
+
console.log(`No Aero memory notes for "${opts.project}".`);
|
|
7458
|
+
return;
|
|
7459
|
+
}
|
|
7460
|
+
console.log(`Aero memory for ${opts.project} \u2014 ${result.entries.length} note(s)
|
|
7461
|
+
`);
|
|
7462
|
+
for (const entry of result.entries) {
|
|
7463
|
+
console.log(`[${entry.source}] ${entry.key} (updated ${entry.updatedAt})`);
|
|
7464
|
+
console.log(` ${entry.value.replace(/\n/g, "\n ")}`);
|
|
7465
|
+
console.log();
|
|
7466
|
+
}
|
|
7467
|
+
} catch (err) {
|
|
7468
|
+
printCliError(err, format);
|
|
7469
|
+
process.exitCode = err instanceof CliError ? err.exitCode : 2;
|
|
7938
7470
|
}
|
|
7939
|
-
return install.detection;
|
|
7940
7471
|
}
|
|
7941
|
-
async function
|
|
7942
|
-
const
|
|
7943
|
-
console.log = () => {
|
|
7944
|
-
};
|
|
7472
|
+
async function agentMemorySet(opts) {
|
|
7473
|
+
const format = toFormat2(opts.format);
|
|
7945
7474
|
try {
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7475
|
+
const client = createApiClient();
|
|
7476
|
+
const result = await client.setAgentMemory(opts.project, {
|
|
7477
|
+
key: opts.key,
|
|
7478
|
+
value: opts.value
|
|
7479
|
+
});
|
|
7480
|
+
if (format === "json") {
|
|
7481
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7482
|
+
return;
|
|
7483
|
+
}
|
|
7484
|
+
console.log(`Stored note "${result.entry.key}" for "${opts.project}" (source=${result.entry.source}).`);
|
|
7485
|
+
} catch (err) {
|
|
7486
|
+
printCliError(err, format);
|
|
7487
|
+
process.exitCode = err instanceof CliError ? err.exitCode : 2;
|
|
7488
|
+
}
|
|
7489
|
+
}
|
|
7490
|
+
async function agentMemoryForget(opts) {
|
|
7491
|
+
const format = toFormat2(opts.format);
|
|
7492
|
+
try {
|
|
7493
|
+
const client = createApiClient();
|
|
7494
|
+
const result = await client.forgetAgentMemory(opts.project, opts.key);
|
|
7495
|
+
if (format === "json") {
|
|
7496
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7497
|
+
return;
|
|
7498
|
+
}
|
|
7499
|
+
if (result.status === "forgotten") {
|
|
7500
|
+
console.log(`Forgot note "${opts.key}" for "${opts.project}".`);
|
|
7501
|
+
} else {
|
|
7502
|
+
console.log(`No note with key "${opts.key}" for "${opts.project}".`);
|
|
7503
|
+
}
|
|
7504
|
+
} catch (err) {
|
|
7505
|
+
printCliError(err, format);
|
|
7506
|
+
process.exitCode = err instanceof CliError ? err.exitCode : 2;
|
|
7949
7507
|
}
|
|
7950
7508
|
}
|
|
7951
7509
|
|
|
7952
7510
|
// src/cli-commands/agent.ts
|
|
7511
|
+
var AGENT_ASK_SCOPES = ["all", "read-only"];
|
|
7953
7512
|
var AGENT_CLI_COMMANDS = [
|
|
7954
7513
|
{
|
|
7955
|
-
path: ["agent", "
|
|
7956
|
-
usage:
|
|
7957
|
-
options: {
|
|
7514
|
+
path: ["agent", "ask"],
|
|
7515
|
+
usage: `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--format json]`,
|
|
7516
|
+
options: {
|
|
7517
|
+
provider: stringOption(),
|
|
7518
|
+
model: stringOption(),
|
|
7519
|
+
scope: stringOption()
|
|
7520
|
+
},
|
|
7958
7521
|
run: async (input) => {
|
|
7959
|
-
|
|
7522
|
+
const [project, ...rest] = input.positionals;
|
|
7523
|
+
if (!project || rest.length === 0) {
|
|
7524
|
+
console.error('Usage: canonry agent ask <project> "<prompt>"');
|
|
7525
|
+
process.exitCode = 1;
|
|
7526
|
+
return;
|
|
7527
|
+
}
|
|
7528
|
+
const providerInput = getString(input.values, "provider");
|
|
7529
|
+
if (providerInput && !coerceAgentProvider(providerInput)) {
|
|
7530
|
+
console.error(`--provider must be one of: ${listAgentProviders().join(", ")}`);
|
|
7531
|
+
process.exitCode = 1;
|
|
7532
|
+
return;
|
|
7533
|
+
}
|
|
7534
|
+
const scopeInput = getString(input.values, "scope");
|
|
7535
|
+
if (scopeInput && !AGENT_ASK_SCOPES.includes(scopeInput)) {
|
|
7536
|
+
console.error(`--scope must be one of: ${AGENT_ASK_SCOPES.join(", ")}`);
|
|
7537
|
+
process.exitCode = 1;
|
|
7538
|
+
return;
|
|
7539
|
+
}
|
|
7540
|
+
await agentAsk({
|
|
7541
|
+
project,
|
|
7542
|
+
prompt: rest.join(" "),
|
|
7543
|
+
provider: coerceAgentProvider(providerInput),
|
|
7544
|
+
modelId: getString(input.values, "model"),
|
|
7545
|
+
scope: scopeInput,
|
|
7546
|
+
format: input.format
|
|
7547
|
+
});
|
|
7960
7548
|
}
|
|
7961
7549
|
},
|
|
7962
7550
|
{
|
|
7963
|
-
path: ["agent", "
|
|
7964
|
-
usage: "canonry agent
|
|
7551
|
+
path: ["agent", "providers"],
|
|
7552
|
+
usage: "canonry agent providers <project> [--format json]",
|
|
7965
7553
|
options: {},
|
|
7966
7554
|
run: async (input) => {
|
|
7967
|
-
|
|
7555
|
+
const project = input.positionals[0];
|
|
7556
|
+
if (!project) {
|
|
7557
|
+
console.error("Usage: canonry agent providers <project>");
|
|
7558
|
+
process.exitCode = 1;
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
await agentProviders({ project, format: input.format });
|
|
7968
7562
|
}
|
|
7969
7563
|
},
|
|
7970
7564
|
{
|
|
7971
|
-
path: ["agent", "
|
|
7972
|
-
usage: "canonry agent
|
|
7973
|
-
options: {
|
|
7565
|
+
path: ["agent", "attach"],
|
|
7566
|
+
usage: "canonry agent attach <project> --url <webhook-url> [--format json]",
|
|
7567
|
+
options: {
|
|
7568
|
+
url: stringOption()
|
|
7569
|
+
},
|
|
7974
7570
|
run: async (input) => {
|
|
7975
|
-
|
|
7571
|
+
const project = input.positionals[0];
|
|
7572
|
+
if (!project) {
|
|
7573
|
+
console.error("Usage: canonry agent attach <project> --url <webhook-url>");
|
|
7574
|
+
process.exitCode = 1;
|
|
7575
|
+
return;
|
|
7576
|
+
}
|
|
7577
|
+
const url = getString(input.values, "url");
|
|
7578
|
+
if (!url) {
|
|
7579
|
+
console.error("Missing required --url flag. Specify the agent webhook URL to attach.");
|
|
7580
|
+
process.exitCode = 1;
|
|
7581
|
+
return;
|
|
7582
|
+
}
|
|
7583
|
+
await agentAttach({ project, url, format: input.format });
|
|
7976
7584
|
}
|
|
7977
7585
|
},
|
|
7978
7586
|
{
|
|
7979
|
-
path: ["agent", "
|
|
7980
|
-
usage: "canonry agent
|
|
7587
|
+
path: ["agent", "detach"],
|
|
7588
|
+
usage: "canonry agent detach <project> [--format json]",
|
|
7981
7589
|
options: {},
|
|
7982
7590
|
run: async (input) => {
|
|
7983
|
-
|
|
7591
|
+
const project = input.positionals[0];
|
|
7592
|
+
if (!project) {
|
|
7593
|
+
console.error("Usage: canonry agent detach <project>");
|
|
7594
|
+
process.exitCode = 1;
|
|
7595
|
+
return;
|
|
7596
|
+
}
|
|
7597
|
+
await agentDetach({ project, format: input.format });
|
|
7984
7598
|
}
|
|
7985
7599
|
},
|
|
7986
7600
|
{
|
|
7987
|
-
path: ["agent", "
|
|
7988
|
-
usage: "canonry agent
|
|
7601
|
+
path: ["agent", "transcript"],
|
|
7602
|
+
usage: "canonry agent transcript <project> [--format json]",
|
|
7989
7603
|
options: {},
|
|
7990
7604
|
run: async (input) => {
|
|
7991
7605
|
const project = input.positionals[0];
|
|
7992
7606
|
if (!project) {
|
|
7993
|
-
console.error("Usage: canonry agent
|
|
7607
|
+
console.error("Usage: canonry agent transcript <project>");
|
|
7994
7608
|
process.exitCode = 1;
|
|
7995
7609
|
return;
|
|
7996
7610
|
}
|
|
7997
|
-
await
|
|
7611
|
+
await agentTranscript({ project, format: input.format });
|
|
7998
7612
|
}
|
|
7999
7613
|
},
|
|
8000
7614
|
{
|
|
8001
|
-
path: ["agent", "
|
|
8002
|
-
usage: "canonry agent
|
|
7615
|
+
path: ["agent", "reset"],
|
|
7616
|
+
usage: "canonry agent reset <project> [--format json]",
|
|
8003
7617
|
options: {},
|
|
8004
7618
|
run: async (input) => {
|
|
8005
7619
|
const project = input.positionals[0];
|
|
8006
7620
|
if (!project) {
|
|
8007
|
-
console.error("Usage: canonry agent
|
|
7621
|
+
console.error("Usage: canonry agent reset <project>");
|
|
8008
7622
|
process.exitCode = 1;
|
|
8009
7623
|
return;
|
|
8010
7624
|
}
|
|
8011
|
-
await
|
|
7625
|
+
await agentTranscriptReset({ project, format: input.format });
|
|
7626
|
+
}
|
|
7627
|
+
},
|
|
7628
|
+
{
|
|
7629
|
+
path: ["agent", "memory", "list"],
|
|
7630
|
+
usage: "canonry agent memory list <project> [--format json]",
|
|
7631
|
+
options: {},
|
|
7632
|
+
run: async (input) => {
|
|
7633
|
+
const project = input.positionals[0];
|
|
7634
|
+
if (!project) {
|
|
7635
|
+
throw usageError("Usage: canonry agent memory list <project>", {
|
|
7636
|
+
message: "project name is required"
|
|
7637
|
+
});
|
|
7638
|
+
}
|
|
7639
|
+
await agentMemoryList({ project, format: input.format });
|
|
8012
7640
|
}
|
|
8013
7641
|
},
|
|
8014
7642
|
{
|
|
8015
|
-
path: ["agent", "
|
|
8016
|
-
usage: "canonry agent
|
|
7643
|
+
path: ["agent", "memory", "set"],
|
|
7644
|
+
usage: "canonry agent memory set <project> --key <k> --value <v> [--format json]",
|
|
8017
7645
|
options: {
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
"agent-model": stringOption(),
|
|
8021
|
-
"gateway-port": { type: "string" },
|
|
8022
|
-
"gemini-key": stringOption(),
|
|
8023
|
-
"openai-key": stringOption(),
|
|
8024
|
-
"claude-key": stringOption(),
|
|
8025
|
-
"perplexity-key": stringOption(),
|
|
8026
|
-
"local-url": stringOption(),
|
|
8027
|
-
"local-model": stringOption(),
|
|
8028
|
-
"local-key": stringOption(),
|
|
8029
|
-
"google-client-id": stringOption(),
|
|
8030
|
-
"google-client-secret": stringOption()
|
|
7646
|
+
key: stringOption(),
|
|
7647
|
+
value: stringOption()
|
|
8031
7648
|
},
|
|
8032
7649
|
run: async (input) => {
|
|
8033
|
-
const
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
7650
|
+
const project = input.positionals[0];
|
|
7651
|
+
if (!project) {
|
|
7652
|
+
throw usageError("Usage: canonry agent memory set <project> --key <k> --value <v>", {
|
|
7653
|
+
message: "project name is required"
|
|
7654
|
+
});
|
|
7655
|
+
}
|
|
7656
|
+
const key = getString(input.values, "key");
|
|
7657
|
+
const value = getString(input.values, "value");
|
|
7658
|
+
if (!key || !value) {
|
|
7659
|
+
throw usageError("--key and --value are both required.", {
|
|
7660
|
+
message: "--key and --value are both required"
|
|
7661
|
+
});
|
|
7662
|
+
}
|
|
7663
|
+
await agentMemorySet({ project, key, value, format: input.format });
|
|
7664
|
+
}
|
|
7665
|
+
},
|
|
7666
|
+
{
|
|
7667
|
+
path: ["agent", "memory", "forget"],
|
|
7668
|
+
usage: "canonry agent memory forget <project> --key <k> [--format json]",
|
|
7669
|
+
options: {
|
|
7670
|
+
key: stringOption()
|
|
7671
|
+
},
|
|
7672
|
+
run: async (input) => {
|
|
7673
|
+
const project = input.positionals[0];
|
|
7674
|
+
if (!project) {
|
|
7675
|
+
throw usageError("Usage: canonry agent memory forget <project> --key <k>", {
|
|
7676
|
+
message: "project name is required"
|
|
7677
|
+
});
|
|
7678
|
+
}
|
|
7679
|
+
const key = getString(input.values, "key");
|
|
7680
|
+
if (!key) {
|
|
7681
|
+
throw usageError("--key is required.", {
|
|
7682
|
+
message: "--key is required"
|
|
7683
|
+
});
|
|
7684
|
+
}
|
|
7685
|
+
await agentMemoryForget({ project, key, format: input.format });
|
|
8051
7686
|
}
|
|
8052
7687
|
}
|
|
8053
7688
|
];
|