@ainyc/canonry 4.186.7 → 4.186.9

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.
Files changed (27) hide show
  1. package/assets/assets/{AuditHistoryPanel-9q5v4zHj.js → AuditHistoryPanel-aXPOAK7n.js} +1 -1
  2. package/assets/assets/{BacklinksPage-C2QVWfQf.js → BacklinksPage-Bim-7fNk.js} +1 -1
  3. package/assets/assets/{HistoryPage-oLCQA7-T.js → HistoryPage-B8RyIjRC.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-DUYt5ceA.js → MeasurementPropertyPage-BlxY3qHW.js} +1 -1
  5. package/assets/assets/ProjectPage-BMZrEjBE.js +9 -0
  6. package/assets/assets/{RunRow-kaFXI_VP.js → RunRow-B28gp-6g.js} +1 -1
  7. package/assets/assets/{RunsPage-CQizRJxf.js → RunsPage-BXm6DVdt.js} +1 -1
  8. package/assets/assets/{SettingsPage-BHh4Y7Qg.js → SettingsPage-CJX7c5HH.js} +1 -1
  9. package/assets/assets/{SiteHealthSection-DjmPK0Tg.js → SiteHealthSection-Ys8sVumO.js} +3 -3
  10. package/assets/assets/{TrafficPage-B3N0r5gW.js → TrafficPage-wPdIYn8H.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-C27GkPF4.js → TrafficSourceDetailPage-C813qZsA.js} +1 -1
  12. package/assets/assets/{extract-error-message-DlmIEdy_.js → extract-error-message-C3RpUAm_.js} +1 -1
  13. package/assets/assets/{index-DVa1lkiE.js → index-Dr_-IUJz.js} +23 -23
  14. package/assets/assets/{react-sigma_core.esm.min-BBOzBU_n.js → react-sigma_core.esm.min-LmiGNvR6.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-7CG3QE4N.js → chunk-EMSDPSQM.js} +130 -68
  17. package/dist/{chunk-CFJHRXZ3.js → chunk-LNBX7RTN.js} +556 -536
  18. package/dist/{chunk-FGEHMYIW.js → chunk-O26JKJXV.js} +41 -6
  19. package/dist/{chunk-42P3CXIH.js → chunk-U3M2VALC.js} +20 -3
  20. package/dist/{chunk-7TYSFZEG.js → chunk-XD2ZD2BP.js} +2 -2
  21. package/dist/cli.js +5 -5
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-KBHLNDGO.js → intelligence-service-UZGA24EF.js} +2 -2
  25. package/dist/mcp.js +3 -3
  26. package/package.json +11 -11
  27. package/assets/assets/ProjectPage-Dsao_AiN.js +0 -9
@@ -11,7 +11,7 @@ import {
11
11
  loadConfig,
12
12
  loadConfigRaw,
13
13
  saveConfigPatch
14
- } from "./chunk-42P3CXIH.js";
14
+ } from "./chunk-U3M2VALC.js";
15
15
  import {
16
16
  CC_CACHE_DIR,
17
17
  DUCKDB_SPEC,
@@ -158,7 +158,7 @@ import {
158
158
  siteCrawlSnapshots,
159
159
  toAlertView,
160
160
  usageCounters
161
- } from "./chunk-7CG3QE4N.js";
161
+ } from "./chunk-EMSDPSQM.js";
162
162
  import {
163
163
  AGENT_MEMORY_VALUE_MAX_BYTES,
164
164
  AGENT_PROVIDER_IDS,
@@ -170,6 +170,7 @@ import {
170
170
  BacklinkSources,
171
171
  CITED_URL_CAPTURE_VERSION,
172
172
  CcReleaseSyncStatuses,
173
+ DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT,
173
174
  DiscoveryCompetitorTypes,
174
175
  GOOGLE_ADS_CAMPAIGN_METRICS_MAX_CAMPAIGNS,
175
176
  GOOGLE_ADS_CAMPAIGN_METRICS_MAX_DAYS,
@@ -299,7 +300,7 @@ import {
299
300
  validationError,
300
301
  winnabilityClassLabel,
301
302
  withRetry
302
- } from "./chunk-CFJHRXZ3.js";
303
+ } from "./chunk-LNBX7RTN.js";
303
304
 
304
305
  // src/telemetry.ts
305
306
  import crypto from "crypto";
@@ -10778,6 +10779,16 @@ var log13 = createLogger("SiteAudit");
10778
10779
  var SiteAuditCancelledError = class extends Error {
10779
10780
  name = "SiteAuditCancelledError";
10780
10781
  };
10782
+ var NON_PAGE_MEDIA_EXTENSIONS = /\.(?:jpe?g|png|gif|webp|avif|bmp|ico|tiff?|svg|mp4|webm|mov|avi|mp3|wav|ogg|woff2?|ttf|otf|eot)(?:$|\?)/i;
10783
+ var NON_PAGE_MEDIA_CONTENT_TYPE = /^(?:image|video|audio|font)\//i;
10784
+ function isNonPageMedia(page) {
10785
+ if (page.contentType && NON_PAGE_MEDIA_CONTENT_TYPE.test(page.contentType.trim())) return true;
10786
+ try {
10787
+ return NON_PAGE_MEDIA_EXTENSIONS.test(new URL(page.requestedUrl).pathname);
10788
+ } catch {
10789
+ return NON_PAGE_MEDIA_EXTENSIONS.test(page.requestedUrl);
10790
+ }
10791
+ }
10781
10792
  function toHomepageUrl(canonicalDomain) {
10782
10793
  const trimmed = canonicalDomain.trim().replace(/\/+$/, "");
10783
10794
  return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
@@ -11083,8 +11094,10 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
11083
11094
  };
11084
11095
  const persistPages = (tx, pages, now) => {
11085
11096
  const changedUrls = /* @__PURE__ */ new Set();
11086
- for (const page of pages) registerPageNode(page, changedUrls);
11087
- for (const page of pages) persistPage(tx, page, now);
11097
+ for (const page of pages) observedPages.set(page.key, page);
11098
+ const pageNodes = pages.filter((page) => !isNonPageMedia(page));
11099
+ for (const page of pageNodes) registerPageNode(page, changedUrls);
11100
+ for (const page of pageNodes) persistPage(tx, page, now);
11088
11101
  bindReferences(tx, changedUrls, now);
11089
11102
  };
11090
11103
  const edgePlacementColumns = (edge) => ({
@@ -11909,7 +11922,7 @@ function readStoredGroundingSources(rawResponse) {
11909
11922
  return result;
11910
11923
  }
11911
11924
  async function backfillInsightsCommand(project, opts) {
11912
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-KBHLNDGO.js");
11925
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-UZGA24EF.js");
11913
11926
  const config = loadConfig();
11914
11927
  const db = createClient(config.database);
11915
11928
  migrate(db);
@@ -16917,6 +16930,12 @@ function parseBooleanEnv(value) {
16917
16930
  if (normalized === "0" || normalized === "false" || normalized === "no") return false;
16918
16931
  return void 0;
16919
16932
  }
16933
+ function parsePositiveIntegerEnv(value) {
16934
+ const normalized = value?.trim();
16935
+ if (!normalized || !/^\d+$/.test(normalized)) return void 0;
16936
+ const parsed = Number(normalized);
16937
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
16938
+ }
16920
16939
  function resolveDashboardRequirePassword(env, config) {
16921
16940
  return parseBooleanEnv(env.CANONRY_DASHBOARD_REQUIRE_PASSWORD) ?? config.dashboard?.requirePassword ?? true;
16922
16941
  }
@@ -16926,6 +16945,12 @@ function resolveDashboardShowResourceLinks(env, config) {
16926
16945
  function resolveDashboardManagedSweeps(env, config) {
16927
16946
  return parseBooleanEnv(env.CANONRY_DASHBOARD_MANAGED_SWEEPS) ?? config.dashboard?.managedSweeps ?? false;
16928
16947
  }
16948
+ function resolveResearchAllowViewers(env, config) {
16949
+ return parseBooleanEnv(env.CANONRY_RESEARCH_ALLOW_VIEWERS) ?? config.research?.allowViewers ?? false;
16950
+ }
16951
+ function resolveResearchViewerDailyRunLimit(env, config) {
16952
+ return parsePositiveIntegerEnv(env.CANONRY_RESEARCH_VIEWER_DAILY_RUN_LIMIT) ?? config.research?.viewerDailyRunLimit ?? DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT;
16953
+ }
16929
16954
  function resolveDashboardShowUpdateNotification(env, config) {
16930
16955
  return parseBooleanEnv(env.CANONRY_DASHBOARD_SHOW_UPDATE_NOTIFICATION) ?? config.dashboard?.showUpdateNotification ?? true;
16931
16956
  }
@@ -18059,6 +18084,8 @@ async function createServer(opts) {
18059
18084
  const dashboardShowUpdateNotification = resolveDashboardShowUpdateNotification(process.env, opts.config);
18060
18085
  const dashboardManagedSweeps = resolveDashboardManagedSweeps(process.env, opts.config);
18061
18086
  const dashboardOnboardingMode = resolveDashboardOnboardingMode(process.env, opts.config);
18087
+ const researchAllowViewers = resolveResearchAllowViewers(process.env, opts.config);
18088
+ const researchViewerDailyRunLimit = resolveResearchViewerDailyRunLimit(process.env, opts.config);
18062
18089
  app.log.info(
18063
18090
  { dashboardRequirePassword },
18064
18091
  "Dashboard password gate resolved"
@@ -18381,6 +18408,8 @@ async function createServer(opts) {
18381
18408
  // was previously reachable only from tests, so a source losing ground could
18382
18409
  // not be rescued without shipping code. Unset keeps the built-in default.
18383
18410
  vercelSyncDeadlineMs: resolveVercelSyncDeadlineMs(process.env),
18411
+ researchAllowViewers,
18412
+ researchViewerDailyRunLimit,
18384
18413
  // Local-only Aero agent routes. Registered here so they inherit api-routes'
18385
18414
  // auth plugin — bare `registerAgentRoutes(app, ...)` would skip auth.
18386
18415
  credentials: credentialChecker,
@@ -18957,6 +18986,12 @@ async function createServer(opts) {
18957
18986
  if (Object.keys(dashboardConfig).length > 0) {
18958
18987
  clientConfig.dashboard = dashboardConfig;
18959
18988
  }
18989
+ if (researchAllowViewers) {
18990
+ clientConfig.research = {
18991
+ allowViewers: true,
18992
+ viewerDailyRunLimit: researchViewerDailyRunLimit
18993
+ };
18994
+ }
18960
18995
  if (embed.enabled) {
18961
18996
  const embedClient = embedClientConfigForRequest(embed, projectTabsOverride, themeOverride, renderTokenOverride);
18962
18997
  if (embedClient) clientConfig.embed = embedClient;
@@ -2,6 +2,7 @@ import {
2
2
  AGENT_MEMORY_KEY_MAX_LENGTH,
3
3
  AGENT_MEMORY_VALUE_MAX_BYTES,
4
4
  CodingAgents,
5
+ DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT,
5
6
  DISCOVERY_MAX_PROBES_CAP,
6
7
  DISCOVERY_PROBE_CONCURRENCY_CAP,
7
8
  GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX,
@@ -97,7 +98,7 @@ import {
97
98
  trafficEventKindSchema,
98
99
  trafficSeriesGranularitySchema,
99
100
  visibilityReportRequestSchema
100
- } from "./chunk-CFJHRXZ3.js";
101
+ } from "./chunk-LNBX7RTN.js";
101
102
 
102
103
  // src/cli-error.ts
103
104
  function isMachineFormat(format) {
@@ -169,6 +170,8 @@ import { parse, stringify } from "yaml";
169
170
  // ../config/src/index.ts
170
171
  import { z } from "zod";
171
172
  var dashboardManagedSweepsSchema = z.boolean().nullish();
173
+ var researchAllowViewersSchema = z.boolean().nullish();
174
+ var researchViewerDailyRunLimitSchema = z.number().int().positive().nullish();
172
175
  var envSchema = z.object({
173
176
  DATABASE_URL: z.string().default("postgresql://aeo:aeo@postgres:5432/aeo_platform"),
174
177
  API_PORT: z.coerce.number().int().positive().default(3e3),
@@ -209,7 +212,9 @@ var envSchema = z.object({
209
212
  // Secret for HMAC-signing Google OAuth state parameters. Required for
210
213
  // cloud deployments that mount googleRoutes; the plugin refuses to register
211
214
  // without it (see packages/api-routes/src/google.ts).
212
- GOOGLE_STATE_SECRET: z.string().optional()
215
+ GOOGLE_STATE_SECRET: z.string().optional(),
216
+ CANONRY_RESEARCH_ALLOW_VIEWERS: z.string().optional(),
217
+ CANONRY_RESEARCH_VIEWER_DAILY_RUN_LIMIT: z.coerce.number().int().positive().default(DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT)
213
218
  });
214
219
  var bootstrapEnvSchema = z.object({
215
220
  CANONRY_API_KEY: z.string().optional(),
@@ -396,6 +401,18 @@ Do not use "canonry init --force" for recovery. It replaces credentials without
396
401
  message: `Invalid config at ${configPath}: dashboard.managedSweeps must be true, false, or left blank.`
397
402
  });
398
403
  }
404
+ if (!researchAllowViewersSchema.safeParse(parsed.research?.allowViewers).success) {
405
+ throw new CliError({
406
+ code: "CONFIG_INVALID",
407
+ message: `Invalid config at ${configPath}: research.allowViewers must be true, false, or left blank.`
408
+ });
409
+ }
410
+ if (!researchViewerDailyRunLimitSchema.safeParse(parsed.research?.viewerDailyRunLimit).success) {
411
+ throw new CliError({
412
+ code: "CONFIG_INVALID",
413
+ message: `Invalid config at ${configPath}: research.viewerDailyRunLimit must be a positive integer or left blank.`
414
+ });
415
+ }
399
416
  if (parsed.geminiApiKey && !parsed.providers?.gemini) {
400
417
  parsed.providers = {
401
418
  ...parsed.providers,
@@ -12544,7 +12561,7 @@ Two signals, never interchangeable:
12544
12561
  - cited = the domain appears in the SOURCE links behind the answer.
12545
12562
  A model can do either, both or neither. Never compute one from the other, and never report a number for one under the other's name.
12546
12563
 
12547
- Sweeps and probes spend provider quota and write rows. Get explicit approval before any run, apply, or other mutation.
12564
+ Sweeps, probes, and research runs spend provider quota and write rows. Get explicit approval before any run, apply, or other mutation.
12548
12565
 
12549
12566
  Most reads are free. Five ads reads are NOT: canonry_ads_account, canonry_ads_geo_search, canonry_ads_live_delivery, canonry_ads_conversion_pixels and canonry_ads_conversion_event_settings call the provider live and spend against the advertiser account. They are marked read, so nothing in the tool list warns you. Get approval for those exactly as for a mutation.
12550
12567
 
@@ -5,11 +5,11 @@ import {
5
5
  installSkills,
6
6
  loadConfigRaw,
7
7
  saveConfigPatch
8
- } from "./chunk-42P3CXIH.js";
8
+ } from "./chunk-U3M2VALC.js";
9
9
  import {
10
10
  SKILL_MANIFEST_FILENAME,
11
11
  SkillsClients
12
- } from "./chunk-CFJHRXZ3.js";
12
+ } from "./chunk-LNBX7RTN.js";
13
13
 
14
14
  // src/skills-autosync.ts
15
15
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -28,11 +28,11 @@ import {
28
28
  trackCliCommandFinished,
29
29
  trackEvent,
30
30
  waitForServerRuntimeStartup
31
- } from "./chunk-FGEHMYIW.js";
31
+ } from "./chunk-O26JKJXV.js";
32
32
  import {
33
33
  autoSyncSkills,
34
34
  formatAutoSyncNotice
35
- } from "./chunk-7TYSFZEG.js";
35
+ } from "./chunk-XD2ZD2BP.js";
36
36
  import {
37
37
  CliError,
38
38
  EXIT_SYSTEM_ERROR,
@@ -58,7 +58,7 @@ import {
58
58
  saveConfigPatch,
59
59
  systemError,
60
60
  usageError
61
- } from "./chunk-42P3CXIH.js";
61
+ } from "./chunk-U3M2VALC.js";
62
62
  import {
63
63
  CLOUDFLARE_WORKER_BINDINGS,
64
64
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -72,7 +72,7 @@ import {
72
72
  projects,
73
73
  queries,
74
74
  renderReportHtml
75
- } from "./chunk-7CG3QE4N.js";
75
+ } from "./chunk-EMSDPSQM.js";
76
76
  import {
77
77
  AdsDeliverySnapshotStatuses,
78
78
  AdsHistoricalCampaignRollupStatuses,
@@ -145,7 +145,7 @@ import {
145
145
  shareOfVoiceReason,
146
146
  visibilityReportRequestSchema,
147
147
  winnabilityClassSchema
148
- } from "./chunk-CFJHRXZ3.js";
148
+ } from "./chunk-LNBX7RTN.js";
149
149
 
150
150
  // src/cli.ts
151
151
  import { pathToFileURL } from "url";
package/dist/index.d.ts CHANGED
@@ -309,6 +309,12 @@ interface DashboardConfigEntry {
309
309
  /** Hide dashboard sweep controls; operators can still use `canonry run`. Defaults to false. */
310
310
  managedSweeps?: boolean | null;
311
311
  }
312
+ interface ResearchConfigEntry {
313
+ /** Allow signed-in viewers to run paid research queries. Defaults to false. */
314
+ allowViewers?: boolean | null;
315
+ /** Viewer-created research runs allowed per project and UTC day. Defaults to 20. */
316
+ viewerDailyRunLimit?: number | null;
317
+ }
312
318
  /**
313
319
  * Google Places API config — supplemental rendered-listing data for GBP
314
320
  * lodging locations (#648). The API key authenticates Place Details calls
@@ -350,6 +356,8 @@ interface CanonryConfig {
350
356
  gtm?: GtmConfigEntry;
351
357
  dashboardPasswordHash?: string;
352
358
  dashboard?: DashboardConfigEntry;
359
+ /** Paid research access and budget controls. */
360
+ research?: ResearchConfigEntry;
353
361
  telemetry?: boolean;
354
362
  anonymousId?: string;
355
363
  lastSeenVersion?: string;
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-FGEHMYIW.js";
6
+ } from "./chunk-O26JKJXV.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-42P3CXIH.js";
10
- import "./chunk-7CG3QE4N.js";
11
- import "./chunk-CFJHRXZ3.js";
9
+ } from "./chunk-U3M2VALC.js";
10
+ import "./chunk-EMSDPSQM.js";
11
+ import "./chunk-LNBX7RTN.js";
12
12
  export {
13
13
  GoogleMarketingRuntimeError,
14
14
  createGoogleMarketingCredentialStore,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-7CG3QE4N.js";
4
- import "./chunk-CFJHRXZ3.js";
3
+ } from "./chunk-EMSDPSQM.js";
4
+ import "./chunk-LNBX7RTN.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-7TYSFZEG.js";
3
+ } from "./chunk-XD2ZD2BP.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-42P3CXIH.js";
7
+ } from "./chunk-U3M2VALC.js";
8
8
  import {
9
9
  isReadOnlyKey
10
- } from "./chunk-CFJHRXZ3.js";
10
+ } from "./chunk-LNBX7RTN.js";
11
11
 
12
12
  // src/mcp/cli.ts
13
13
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.186.7",
3
+ "version": "4.186.9",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "license": "FSL-1.1-ALv2",
@@ -70,18 +70,18 @@
70
70
  "@types/node-cron": "^3.0.11",
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
- "@ainyc/canonry-web": "0.0.0",
74
- "@ainyc/canonry-api-routes": "0.0.0",
75
73
  "@ainyc/canonry-api-client": "0.0.0",
76
- "@ainyc/canonry-contracts": "0.0.0",
74
+ "@ainyc/canonry-api-routes": "0.0.0",
75
+ "@ainyc/canonry-web": "0.0.0",
77
76
  "@ainyc/canonry-config": "0.0.0",
77
+ "@ainyc/canonry-contracts": "0.0.0",
78
78
  "@ainyc/canonry-db": "0.0.0",
79
79
  "@ainyc/canonry-integration-bing": "0.0.0",
80
- "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
81
80
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
81
+ "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
82
82
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
83
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
84
83
  "@ainyc/canonry-integration-google": "0.0.0",
84
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
85
85
  "@ainyc/canonry-integration-google-ads": "0.0.0",
86
86
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
87
87
  "@ainyc/canonry-integration-google-places": "0.0.0",
@@ -89,13 +89,13 @@
89
89
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
90
90
  "@ainyc/canonry-integration-traffic": "0.0.0",
91
91
  "@ainyc/canonry-integration-wordpress": "0.0.0",
92
- "@ainyc/canonry-provider-claude": "0.0.0",
93
- "@ainyc/canonry-provider-gemini": "0.0.0",
94
- "@ainyc/canonry-provider-cdp": "0.0.0",
95
92
  "@ainyc/canonry-intelligence": "0.0.0",
96
- "@ainyc/canonry-provider-local": "0.0.0",
93
+ "@ainyc/canonry-provider-cdp": "0.0.0",
94
+ "@ainyc/canonry-provider-claude": "0.0.0",
97
95
  "@ainyc/canonry-provider-openai": "0.0.0",
98
- "@ainyc/canonry-provider-perplexity": "0.0.0"
96
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
97
+ "@ainyc/canonry-provider-local": "0.0.0",
98
+ "@ainyc/canonry-provider-gemini": "0.0.0"
99
99
  },
100
100
  "scripts": {
101
101
  "build": "pnpm run build:cli && pnpm run build:web",