@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/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
- attachAgentWebhookDirect,
11
- buildAgentWebhookUrl,
7
+ coerceAgentProvider,
12
8
  computeCompetitorOverlap,
13
9
  configExists,
14
- configureOpenClawGateway,
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
- writeAgentEnv
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-ZZ57GRV6.js";
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, path7) {
71
- if (args.length < path7.length) return false;
72
- return path7.every((segment, index) => args[index] === segment);
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-MZ7SXEGE.js");
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 path7 = await import("path");
6872
- const filePath = path7.resolve(opts.from);
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 path7 = await import("path");
6507
+ const path6 = await import("path");
6974
6508
  const yaml = await import("yaml").catch(() => null);
6975
- const filePath = path7.resolve(opts.profile);
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 path7 = await import("path");
6618
+ const path6 = await import("path");
7085
6619
  const yaml = await import("yaml").catch(() => null);
7086
- const filePath = path7.resolve(opts.profile);
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: agentUrl,
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
- async function autoInstallOrFail(format) {
7922
- if (format !== "json") {
7923
- console.log("OpenClaw not found, installing pinned openclaw@2026.4.14 via npm...");
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
- const install = await installOpenClaw({ silent: format === "json" });
7926
- if (!install.success) {
7927
- const msg = `Failed to install OpenClaw: ${install.error}`;
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.error(JSON.stringify({ error: { code: "AGENT_INSTALL_FAILED", message: msg } }));
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.error(msg);
7434
+ console.log(`Aero conversation reset for "${opts.project}".`);
7932
7435
  }
7933
- process.exitCode = 1;
7934
- throw new Error(msg);
7436
+ } catch (err) {
7437
+ printCliError(err, format);
7438
+ if (err instanceof CliError) process.exitCode = err.exitCode;
7439
+ else process.exitCode = 2;
7935
7440
  }
7936
- if (format !== "json") {
7937
- console.log(`Installed OpenClaw ${install.detection.version}`);
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 suppressStdout(fn) {
7942
- const original = console.log;
7943
- console.log = () => {
7944
- };
7472
+ async function agentMemorySet(opts) {
7473
+ const format = toFormat2(opts.format);
7945
7474
  try {
7946
- return await fn();
7947
- } finally {
7948
- console.log = original;
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", "status"],
7956
- usage: "canonry agent status [--format json]",
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
- await agentStatus({ format: input.format });
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", "start"],
7964
- usage: "canonry agent start [--format json]",
7551
+ path: ["agent", "providers"],
7552
+ usage: "canonry agent providers <project> [--format json]",
7965
7553
  options: {},
7966
7554
  run: async (input) => {
7967
- await agentStart({ format: input.format });
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", "stop"],
7972
- usage: "canonry agent stop [--format json]",
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
- await agentStop({ format: input.format });
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", "reset"],
7980
- usage: "canonry agent reset [--format json]",
7587
+ path: ["agent", "detach"],
7588
+ usage: "canonry agent detach <project> [--format json]",
7981
7589
  options: {},
7982
7590
  run: async (input) => {
7983
- await agentReset({ format: input.format });
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", "attach"],
7988
- usage: "canonry agent attach <project> [--format json]",
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 attach <project>");
7607
+ console.error("Usage: canonry agent transcript <project>");
7994
7608
  process.exitCode = 1;
7995
7609
  return;
7996
7610
  }
7997
- await agentAttach({ project, format: input.format });
7611
+ await agentTranscript({ project, format: input.format });
7998
7612
  }
7999
7613
  },
8000
7614
  {
8001
- path: ["agent", "detach"],
8002
- usage: "canonry agent detach <project> [--format json]",
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 detach <project>");
7621
+ console.error("Usage: canonry agent reset <project>");
8008
7622
  process.exitCode = 1;
8009
7623
  return;
8010
7624
  }
8011
- await agentDetach({ project, format: input.format });
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", "setup"],
8016
- usage: "canonry agent setup [--agent-provider <id>] [--agent-key <key>] [--agent-model <model>] [--gateway-port <port>] [--gemini-key <key>] [--openai-key <key>] [--claude-key <key>] [--perplexity-key <key>] [--format json]",
7643
+ path: ["agent", "memory", "set"],
7644
+ usage: "canonry agent memory set <project> --key <k> --value <v> [--format json]",
8017
7645
  options: {
8018
- "agent-provider": stringOption(),
8019
- "agent-key": stringOption(),
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 portStr = input.values["gateway-port"];
8034
- const gatewayPort = typeof portStr === "string" ? Number.parseInt(portStr, 10) : void 0;
8035
- await agentSetup({
8036
- agentProvider: getString(input.values, "agent-provider"),
8037
- agentKey: getString(input.values, "agent-key"),
8038
- agentModel: getString(input.values, "agent-model"),
8039
- gatewayPort,
8040
- format: input.format,
8041
- geminiKey: getString(input.values, "gemini-key"),
8042
- openaiKey: getString(input.values, "openai-key"),
8043
- claudeKey: getString(input.values, "claude-key"),
8044
- perplexityKey: getString(input.values, "perplexity-key"),
8045
- localUrl: getString(input.values, "local-url"),
8046
- localModel: getString(input.values, "local-model"),
8047
- localKey: getString(input.values, "local-key"),
8048
- googleClientId: getString(input.values, "google-client-id"),
8049
- googleClientSecret: getString(input.values, "google-client-secret")
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
  ];