@ainyc/canonry 4.90.0 → 4.91.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.
Files changed (23) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +4 -2
  2. package/assets/assets/{BacklinksPage-CzZbUMMc.js → BacklinksPage-DHC1po5Q.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-BBcVCGyK.js → ChartPrimitives-Cu2xEVle.js} +1 -1
  4. package/assets/assets/{ProjectPage-BZwzpRBL.js → ProjectPage-DXYcaMVO.js} +1 -1
  5. package/assets/assets/{RunRow-B-Xzc9el.js → RunRow-BPqbBlXl.js} +1 -1
  6. package/assets/assets/{RunsPage-idZt03Qs.js → RunsPage-BJx3_Nel.js} +1 -1
  7. package/assets/assets/{SettingsPage-BGMJxf9N.js → SettingsPage-CXTIHdsv.js} +1 -1
  8. package/assets/assets/{TrafficPage-UpFu1vki.js → TrafficPage-iibCIBqX.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-m0OEVrkk.js → TrafficSourceDetailPage-WU30E_59.js} +1 -1
  10. package/assets/assets/{arrow-left-Cgp2_UfR.js → arrow-left-Ds_f14R8.js} +1 -1
  11. package/assets/assets/{extract-error-message-BiiNM-57.js → extract-error-message-D250utEX.js} +1 -1
  12. package/assets/assets/{index-DPPOgIIL.js → index-qiysJOcG.js} +3 -3
  13. package/assets/assets/{trash-2-Bm_IgAE2.js → trash-2-CcVWAeec.js} +1 -1
  14. package/assets/index.html +1 -1
  15. package/dist/{chunk-KO3T36E5.js → chunk-4KQYRCVC.js} +57 -7
  16. package/dist/{chunk-XG7JKKTC.js → chunk-6RVUSM4Y.js} +2 -2
  17. package/dist/{chunk-I4FR66PU.js → chunk-KFJPJBW3.js} +4 -4
  18. package/dist/{chunk-PL2ODHUC.js → chunk-WMBOHP7E.js} +13 -0
  19. package/dist/cli.js +6 -4
  20. package/dist/index.js +4 -4
  21. package/dist/{intelligence-service-DZK4FOAJ.js → intelligence-service-QB6HQRWU.js} +2 -2
  22. package/dist/mcp.js +2 -2
  23. package/package.json +9 -9
@@ -1 +1 @@
1
- import{c}from"./index-DPPOgIIL.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
1
+ import{c}from"./index-qiysJOcG.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-DPPOgIIL.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-qiysJOcG.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dq7p98wZ.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-B57xfQbP.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-ClRVR6aX.js">
@@ -258,7 +258,7 @@ import {
258
258
  wordpressSchemaDeployResultDtoSchema,
259
259
  wordpressSchemaStatusResultDtoSchema,
260
260
  wordpressStatusDtoSchema
261
- } from "./chunk-PL2ODHUC.js";
261
+ } from "./chunk-WMBOHP7E.js";
262
262
 
263
263
  // src/intelligence-service.ts
264
264
  import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
@@ -18628,6 +18628,38 @@ function summarizeLodging(rows) {
18628
18628
  emptyLodgingCount: rows.length - populatedLodgingCount
18629
18629
  };
18630
18630
  }
18631
+ function summarizeProfileCompleteness(rows) {
18632
+ let withSecondaryCategories = 0;
18633
+ let secondaryCategoryTotal = 0;
18634
+ let withDescription = 0;
18635
+ let withServiceArea = 0;
18636
+ let withHours = 0;
18637
+ let withPrimaryPhone = 0;
18638
+ let permanentlyClosed = 0;
18639
+ let temporarilyClosed = 0;
18640
+ for (const r of rows) {
18641
+ const secondaryCount = r.additionalCategories?.length ?? 0;
18642
+ if (secondaryCount > 0) withSecondaryCategories++;
18643
+ secondaryCategoryTotal += secondaryCount;
18644
+ if ((r.description ?? "").trim().length > 0) withDescription++;
18645
+ if (r.serviceArea != null) withServiceArea++;
18646
+ if (r.regularHours != null) withHours++;
18647
+ if ((r.primaryPhone ?? "").trim().length > 0) withPrimaryPhone++;
18648
+ if (r.openStatus === "CLOSED_PERMANENTLY") permanentlyClosed++;
18649
+ if (r.openStatus === "CLOSED_TEMPORARILY") temporarilyClosed++;
18650
+ }
18651
+ return {
18652
+ locationCount: rows.length,
18653
+ withSecondaryCategories,
18654
+ secondaryCategoryTotal,
18655
+ withDescription,
18656
+ withServiceArea,
18657
+ withHours,
18658
+ withPrimaryPhone,
18659
+ permanentlyClosed,
18660
+ temporarilyClosed
18661
+ };
18662
+ }
18631
18663
  function buildGbpSummary(input) {
18632
18664
  const freshness = computeFreshness(input.dailyMetrics, input.asOfDate);
18633
18665
  const anchor = freshness.dataThroughDate ?? input.asOfDate;
@@ -18644,7 +18676,8 @@ function buildGbpSummary(input) {
18644
18676
  timeseries: buildTimeseries(input.dailyMetrics, freshness),
18645
18677
  keywords: computeKeywordCoverage(input.keywords),
18646
18678
  placeActions: summarizePlaceActions(input.placeActions),
18647
- lodging: summarizeLodging(input.lodging)
18679
+ lodging: summarizeLodging(input.lodging),
18680
+ profileCompleteness: summarizeProfileCompleteness(input.locationProfiles)
18648
18681
  };
18649
18682
  }
18650
18683
 
@@ -19741,11 +19774,15 @@ var GBP_LOCATIONS_DEFAULT_READ_MASK = [
19741
19774
  "title",
19742
19775
  "storefrontAddress",
19743
19776
  "websiteUri",
19744
- "categories.primaryCategory.displayName",
19777
+ // Request `categories` WHOLE, not a nested sub-path. The Business Information
19778
+ // locations.list readMask rejects a nested path into the REPEATED
19779
+ // `additionalCategories` array ("Invalid field mask provided", HTTP 400 —
19780
+ // verified against the live API), so we ask for the full `categories` object
19781
+ // (it carries primaryCategory + additionalCategories displayNames + serviceTypes).
19782
+ "categories",
19745
19783
  // Owner-authored profile content — the entity-anchor and qualifier signals AI
19746
19784
  // answer engines weight most. All ride the same Business Information v1
19747
19785
  // Location resource canonry already reads (no new auth / API enablement).
19748
- "categories.additionalCategories.displayName",
19749
19786
  "profile.description",
19750
19787
  "serviceArea",
19751
19788
  "regularHours",
@@ -21275,7 +21312,8 @@ async function googleRoutes(app, opts) {
21275
21312
  dailyMetrics: [],
21276
21313
  keywords: [],
21277
21314
  placeActions: [],
21278
- lodging: []
21315
+ lodging: [],
21316
+ locationProfiles: []
21279
21317
  });
21280
21318
  }
21281
21319
  const metricRows = app.db.select().from(gbpDailyMetrics).where(and14(eq21(gbpDailyMetrics.projectId, project.id), inArray10(gbpDailyMetrics.locationName, locationNames))).all();
@@ -21288,6 +21326,14 @@ async function googleRoutes(app, opts) {
21288
21326
  latestLodgingByLocation.set(row.locationName, { locationName: row.locationName, populatedGroupCount: row.populatedGroupCount });
21289
21327
  }
21290
21328
  }
21329
+ const profileRows = app.db.select({
21330
+ additionalCategories: gbpLocations.additionalCategories,
21331
+ description: gbpLocations.description,
21332
+ serviceArea: gbpLocations.serviceArea,
21333
+ regularHours: gbpLocations.regularHours,
21334
+ primaryPhone: gbpLocations.primaryPhone,
21335
+ openStatus: gbpLocations.openStatus
21336
+ }).from(gbpLocations).where(and14(eq21(gbpLocations.projectId, project.id), inArray10(gbpLocations.locationName, locationNames))).all();
21291
21337
  return buildGbpSummary({
21292
21338
  locationName,
21293
21339
  locationCount: locationNames.length,
@@ -21295,7 +21341,8 @@ async function googleRoutes(app, opts) {
21295
21341
  dailyMetrics: metricRows.map((r) => ({ metric: r.metric, date: r.date, value: r.value })),
21296
21342
  keywords: keywordRows.map((r) => ({ valueCount: r.valueCount ?? null, valueThreshold: r.valueThreshold ?? null })),
21297
21343
  placeActions: placeActionRows.map((r) => ({ placeActionType: r.placeActionType, providerType: r.providerType ?? null })),
21298
- lodging: [...latestLodgingByLocation.values()]
21344
+ lodging: [...latestLodgingByLocation.values()],
21345
+ locationProfiles: profileRows
21299
21346
  });
21300
21347
  });
21301
21348
  }
@@ -34434,7 +34481,10 @@ var IntelligenceService = class {
34434
34481
  keywords: [],
34435
34482
  // keyword coverage is unused here; the trend uses the monthly series below
34436
34483
  placeActions: placeActionRows.map((r) => ({ placeActionType: r.placeActionType, providerType: r.providerType ?? null })),
34437
- lodging: lodgingRow ? [{ locationName, populatedGroupCount: lodgingRow.populatedGroupCount }] : []
34484
+ lodging: lodgingRow ? [{ locationName, populatedGroupCount: lodgingRow.populatedGroupCount }] : [],
34485
+ // The analyzer consumes metric/keyword/place-action/lodging signals, not
34486
+ // the profile-completeness scorecard, so it is left empty here.
34487
+ locationProfiles: []
34438
34488
  });
34439
34489
  const trend = this.buildGbpKeywordTrend(projectId, locationName);
34440
34490
  return {
@@ -23,7 +23,7 @@ import {
23
23
  trafficConnectVercelRequestSchema,
24
24
  trafficConnectWordpressRequestSchema,
25
25
  trafficEventKindSchema
26
- } from "./chunk-PL2ODHUC.js";
26
+ } from "./chunk-WMBOHP7E.js";
27
27
 
28
28
  // src/config.ts
29
29
  import fs from "fs";
@@ -6313,7 +6313,7 @@ var canonryMcpTools = [
6313
6313
  defineTool({
6314
6314
  name: "canonry_gbp_summary",
6315
6315
  title: "Get GBP local-AEO summary",
6316
- description: "Composite Google Business Profile summary for a project: performance totals + 7d deltas, keyword thresholded %, place-action CTA presence, and lodging coverage. All derived numbers computed server-side.",
6316
+ description: "Composite Google Business Profile summary for a project: performance totals + 7d deltas, keyword thresholded %, place-action CTA presence, lodging coverage, and owner-content profile completeness (how many selected locations populate secondary categories / description / service area / hours / phone, plus closed-status counts). All derived numbers computed server-side.",
6317
6317
  access: "read",
6318
6318
  tier: "gbp",
6319
6319
  inputSchema: gbpLocationScopedInputSchema,
@@ -9,7 +9,7 @@ import {
9
9
  loadConfig,
10
10
  loadConfigRaw,
11
11
  saveConfigPatch
12
- } from "./chunk-XG7JKKTC.js";
12
+ } from "./chunk-6RVUSM4Y.js";
13
13
  import {
14
14
  CC_CACHE_DIR,
15
15
  DUCKDB_SPEC,
@@ -104,7 +104,7 @@ import {
104
104
  siteAuditPages,
105
105
  siteAuditSnapshots,
106
106
  usageCounters
107
- } from "./chunk-KO3T36E5.js";
107
+ } from "./chunk-4KQYRCVC.js";
108
108
  import {
109
109
  AGENT_MEMORY_VALUE_MAX_BYTES,
110
110
  AGENT_PROVIDER_IDS,
@@ -164,7 +164,7 @@ import {
164
164
  validationError,
165
165
  winnabilityClassLabel,
166
166
  withRetry
167
- } from "./chunk-PL2ODHUC.js";
167
+ } from "./chunk-WMBOHP7E.js";
168
168
 
169
169
  // src/telemetry.ts
170
170
  import crypto from "crypto";
@@ -6323,7 +6323,7 @@ function readStoredGroundingSources(rawResponse) {
6323
6323
  return result;
6324
6324
  }
6325
6325
  async function backfillInsightsCommand(project, opts) {
6326
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-DZK4FOAJ.js");
6326
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-QB6HQRWU.js");
6327
6327
  const config = loadConfig();
6328
6328
  const db = createClient(config.database);
6329
6329
  migrate(db);
@@ -1069,6 +1069,19 @@ var gbpSummaryDtoSchema = z8.object({
1069
1069
  lodgingLocationCount: z8.number().int().nonnegative(),
1070
1070
  populatedLodgingCount: z8.number().int().nonnegative(),
1071
1071
  emptyLodgingCount: z8.number().int().nonnegative()
1072
+ }),
1073
+ // Owner-content completeness over the in-scope locations: how many populate
1074
+ // each entity-anchor / qualifier field AI answer engines weight.
1075
+ profileCompleteness: z8.object({
1076
+ locationCount: z8.number().int().nonnegative(),
1077
+ withSecondaryCategories: z8.number().int().nonnegative(),
1078
+ secondaryCategoryTotal: z8.number().int().nonnegative(),
1079
+ withDescription: z8.number().int().nonnegative(),
1080
+ withServiceArea: z8.number().int().nonnegative(),
1081
+ withHours: z8.number().int().nonnegative(),
1082
+ withPrimaryPhone: z8.number().int().nonnegative(),
1083
+ permanentlyClosed: z8.number().int().nonnegative(),
1084
+ temporarilyClosed: z8.number().int().nonnegative()
1072
1085
  })
1073
1086
  });
1074
1087
  var GBP_METRIC_LABELS = {
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-I4FR66PU.js";
30
+ } from "./chunk-KFJPJBW3.js";
31
31
  import {
32
32
  CliError,
33
33
  EXIT_SYSTEM_ERROR,
@@ -44,7 +44,7 @@ import {
44
44
  saveConfig,
45
45
  saveConfigPatch,
46
46
  usageError
47
- } from "./chunk-XG7JKKTC.js";
47
+ } from "./chunk-6RVUSM4Y.js";
48
48
  import {
49
49
  apiKeys,
50
50
  createClient,
@@ -52,7 +52,7 @@ import {
52
52
  projects,
53
53
  queries,
54
54
  renderReportHtml
55
- } from "./chunk-KO3T36E5.js";
55
+ } from "./chunk-4KQYRCVC.js";
56
56
  import {
57
57
  BacklinkSources,
58
58
  CcReleaseSyncStatuses,
@@ -77,7 +77,7 @@ import {
77
77
  providerQuotaPolicySchema,
78
78
  resolveProviderInput,
79
79
  winnabilityClassSchema
80
- } from "./chunk-PL2ODHUC.js";
80
+ } from "./chunk-WMBOHP7E.js";
81
81
 
82
82
  // src/cli.ts
83
83
  import { pathToFileURL } from "url";
@@ -3566,6 +3566,8 @@ async function gbpSummary(project, opts) {
3566
3566
  Keywords: ${s.keywords.total} tracked, ${s.keywords.thresholdedPct}% privacy-thresholded`);
3567
3567
  console.log(`Place actions: ${s.placeActions.total} CTA(s) \u2014 reservation:${s.placeActions.hasReservationCta ? "yes" : "no"} booking:${s.placeActions.hasBookingCta ? "yes" : "no"} direct-merchant:${s.placeActions.hasDirectMerchantCta ? "yes" : "no"}`);
3568
3568
  console.log(`Lodging: ${s.lodging.lodgingLocationCount} profile(s), ${s.lodging.populatedLodgingCount} populated, ${s.lodging.emptyLodgingCount} empty`);
3569
+ const pc = s.profileCompleteness;
3570
+ console.log(`Profile completeness (${pc.locationCount} location(s)): ${pc.withSecondaryCategories} w/ secondary categories (${pc.secondaryCategoryTotal} total), ${pc.withDescription} w/ description, ${pc.withServiceArea} w/ service area, ${pc.withHours} w/ hours, ${pc.withPrimaryPhone} w/ phone` + (pc.permanentlyClosed || pc.temporarilyClosed ? `; closed: ${pc.permanentlyClosed} permanently, ${pc.temporarilyClosed} temporarily` : ""));
3569
3571
  }
3570
3572
 
3571
3573
  // src/cli-commands/gbp.ts
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-I4FR66PU.js";
3
+ } from "./chunk-KFJPJBW3.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-XG7JKKTC.js";
7
- import "./chunk-KO3T36E5.js";
8
- import "./chunk-PL2ODHUC.js";
6
+ } from "./chunk-6RVUSM4Y.js";
7
+ import "./chunk-4KQYRCVC.js";
8
+ import "./chunk-WMBOHP7E.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-KO3T36E5.js";
4
- import "./chunk-PL2ODHUC.js";
3
+ } from "./chunk-4KQYRCVC.js";
4
+ import "./chunk-WMBOHP7E.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-XG7JKKTC.js";
6
+ } from "./chunk-6RVUSM4Y.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-PL2ODHUC.js";
9
+ } from "./chunk-WMBOHP7E.js";
10
10
 
11
11
  // src/mcp/cli.ts
12
12
  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.90.0",
3
+ "version": "4.91.1",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -63,26 +63,26 @@
63
63
  "tsup": "^8.5.1",
64
64
  "tsx": "^4.19.0",
65
65
  "@ainyc/canonry-api-client": "0.0.0",
66
- "@ainyc/canonry-api-routes": "0.0.0",
67
66
  "@ainyc/canonry-config": "0.0.0",
68
- "@ainyc/canonry-integration-bing": "0.0.0",
69
67
  "@ainyc/canonry-db": "0.0.0",
70
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
68
+ "@ainyc/canonry-api-routes": "0.0.0",
69
+ "@ainyc/canonry-integration-bing": "0.0.0",
71
70
  "@ainyc/canonry-contracts": "0.0.0",
72
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
71
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
73
72
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
74
74
  "@ainyc/canonry-integration-google": "0.0.0",
75
75
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
76
76
  "@ainyc/canonry-integration-google-places": "0.0.0",
77
77
  "@ainyc/canonry-integration-traffic": "0.0.0",
78
- "@ainyc/canonry-integration-wordpress": "0.0.0",
79
78
  "@ainyc/canonry-intelligence": "0.0.0",
79
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
80
80
  "@ainyc/canonry-provider-cdp": "0.0.0",
81
- "@ainyc/canonry-provider-claude": "0.0.0",
82
81
  "@ainyc/canonry-provider-gemini": "0.0.0",
82
+ "@ainyc/canonry-provider-claude": "0.0.0",
83
83
  "@ainyc/canonry-provider-local": "0.0.0",
84
- "@ainyc/canonry-provider-openai": "0.0.0",
85
- "@ainyc/canonry-provider-perplexity": "0.0.0"
84
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
85
+ "@ainyc/canonry-provider-openai": "0.0.0"
86
86
  },
87
87
  "scripts": {
88
88
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",