@ainyc/canonry 2.13.2 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/assets/{index-CKzK0os-.js → index-BwFUCV6e.js} +116 -116
- package/assets/assets/{index-CAewPdsZ.css → index-U2SLimrz.css} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-DHMCIJMQ.js → chunk-LD7Y4K4G.js} +118 -9
- package/dist/{chunk-XJS7NALL.js → chunk-RNMMN2WI.js} +4 -1
- package/dist/cli.js +42 -9
- package/dist/index.js +2 -2
- package/dist/mcp.js +12 -1
- package/package.json +6 -6
package/assets/index.html
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
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-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-BwFUCV6e.js"></script>
|
|
16
|
+
<link rel="stylesheet" crossorigin href="./assets/index-U2SLimrz.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
visibilityStateFromAnswerMentioned,
|
|
60
60
|
windowCutoff,
|
|
61
61
|
wordpressEnvSchema
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-RNMMN2WI.js";
|
|
63
63
|
import {
|
|
64
64
|
IntelligenceService,
|
|
65
65
|
agentMemory,
|
|
@@ -5371,15 +5371,14 @@ var routeCatalog = [
|
|
|
5371
5371
|
method: "post",
|
|
5372
5372
|
path: "/api/v1/backlinks/syncs",
|
|
5373
5373
|
summary: "Queue a workspace-wide Common Crawl release sync",
|
|
5374
|
-
description: "Creates a `cc_release_syncs` row and fires the sync callback. Idempotent: an existing in-flight row for the same release is returned.",
|
|
5374
|
+
description: "Creates a `cc_release_syncs` row and fires the sync callback. Idempotent: an existing in-flight row for the same release is returned. When `release` is omitted, the server auto-discovers the latest available Common Crawl release.",
|
|
5375
5375
|
tags: ["backlinks"],
|
|
5376
5376
|
requestBody: {
|
|
5377
|
-
required:
|
|
5377
|
+
required: false,
|
|
5378
5378
|
content: {
|
|
5379
5379
|
"application/json": {
|
|
5380
5380
|
schema: {
|
|
5381
5381
|
type: "object",
|
|
5382
|
-
required: ["release"],
|
|
5383
5382
|
properties: {
|
|
5384
5383
|
release: stringSchema
|
|
5385
5384
|
}
|
|
@@ -5422,6 +5421,17 @@ var routeCatalog = [
|
|
|
5422
5421
|
200: { description: "Cached release metadata returned." }
|
|
5423
5422
|
}
|
|
5424
5423
|
},
|
|
5424
|
+
{
|
|
5425
|
+
method: "get",
|
|
5426
|
+
path: "/api/v1/backlinks/latest-release",
|
|
5427
|
+
summary: "Auto-discover the latest available Common Crawl hyperlinkgraph release",
|
|
5428
|
+
description: "Probes Common Crawl by HEAD-checking quarterly release slugs and returns the newest one published. The local server caches the result for ~5 minutes so repeated calls do not hammer Common Crawl.",
|
|
5429
|
+
tags: ["backlinks"],
|
|
5430
|
+
responses: {
|
|
5431
|
+
200: { description: "Latest available release, or null when no candidate slug responded." },
|
|
5432
|
+
422: { description: "Backlinks feature is not available on this deployment." }
|
|
5433
|
+
}
|
|
5434
|
+
},
|
|
5425
5435
|
{
|
|
5426
5436
|
method: "delete",
|
|
5427
5437
|
path: "/api/v1/backlinks/cache/{release}",
|
|
@@ -10712,6 +10722,60 @@ function forwardDomain(revDomain) {
|
|
|
10712
10722
|
function isValidReleaseId(id) {
|
|
10713
10723
|
return RELEASE_ID_REGEX.test(id);
|
|
10714
10724
|
}
|
|
10725
|
+
function formatReleaseId(year, quarter) {
|
|
10726
|
+
return `cc-main-${year}-${quarter}`;
|
|
10727
|
+
}
|
|
10728
|
+
|
|
10729
|
+
// ../integration-commoncrawl/src/release-discovery.ts
|
|
10730
|
+
var QUARTERS = [
|
|
10731
|
+
"oct-nov-dec",
|
|
10732
|
+
"jul-aug-sep",
|
|
10733
|
+
"apr-may-jun",
|
|
10734
|
+
"jan-feb-mar"
|
|
10735
|
+
];
|
|
10736
|
+
function probeCandidates(now, maxBack) {
|
|
10737
|
+
const year = now.getUTCFullYear();
|
|
10738
|
+
const out = [];
|
|
10739
|
+
for (let y = year; y >= year - maxBack; y--) {
|
|
10740
|
+
for (const q of QUARTERS) {
|
|
10741
|
+
out.push({ year: y, quarter: q });
|
|
10742
|
+
}
|
|
10743
|
+
}
|
|
10744
|
+
return out;
|
|
10745
|
+
}
|
|
10746
|
+
async function probeRelease(release, fetchImpl = fetch) {
|
|
10747
|
+
const paths = ccReleasePaths(release);
|
|
10748
|
+
const [vertex, edges] = await Promise.all([
|
|
10749
|
+
fetchImpl(paths.vertexUrl, { method: "HEAD" }),
|
|
10750
|
+
fetchImpl(paths.edgesUrl, { method: "HEAD" })
|
|
10751
|
+
]);
|
|
10752
|
+
if (!vertex.ok || !edges.ok) return null;
|
|
10753
|
+
return {
|
|
10754
|
+
release,
|
|
10755
|
+
vertexUrl: paths.vertexUrl,
|
|
10756
|
+
edgesUrl: paths.edgesUrl,
|
|
10757
|
+
vertexBytes: parseContentLength(vertex.headers.get("content-length")),
|
|
10758
|
+
edgesBytes: parseContentLength(edges.headers.get("content-length")),
|
|
10759
|
+
lastModified: vertex.headers.get("last-modified")
|
|
10760
|
+
};
|
|
10761
|
+
}
|
|
10762
|
+
async function probeLatestRelease(opts = {}) {
|
|
10763
|
+
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
10764
|
+
const maxBack = opts.maxQuartersBack ?? 3;
|
|
10765
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
10766
|
+
const candidates = probeCandidates(now, maxBack);
|
|
10767
|
+
for (const { year, quarter } of candidates) {
|
|
10768
|
+
const release = formatReleaseId(year, quarter);
|
|
10769
|
+
const result = await probeRelease(release, fetchImpl);
|
|
10770
|
+
if (result) return result;
|
|
10771
|
+
}
|
|
10772
|
+
return null;
|
|
10773
|
+
}
|
|
10774
|
+
function parseContentLength(value) {
|
|
10775
|
+
if (!value) return null;
|
|
10776
|
+
const n = Number.parseInt(value, 10);
|
|
10777
|
+
return Number.isFinite(n) ? n : null;
|
|
10778
|
+
}
|
|
10715
10779
|
|
|
10716
10780
|
// ../integration-commoncrawl/src/downloader.ts
|
|
10717
10781
|
import { createHash } from "crypto";
|
|
@@ -10739,7 +10803,7 @@ async function downloadFile(opts) {
|
|
|
10739
10803
|
if (!res.ok || !res.body) {
|
|
10740
10804
|
throw new Error(`HTTP ${res.status} ${res.statusText} for ${opts.url}`);
|
|
10741
10805
|
}
|
|
10742
|
-
const total =
|
|
10806
|
+
const total = parseContentLength2(res.headers.get("content-length"));
|
|
10743
10807
|
const hasher = createHash("sha256");
|
|
10744
10808
|
let bytes = 0;
|
|
10745
10809
|
const hashAndCount = new Transform({
|
|
@@ -10790,7 +10854,7 @@ async function unlinkIfExists(p) {
|
|
|
10790
10854
|
} catch {
|
|
10791
10855
|
}
|
|
10792
10856
|
}
|
|
10793
|
-
function
|
|
10857
|
+
function parseContentLength2(value) {
|
|
10794
10858
|
if (!value) return null;
|
|
10795
10859
|
const n = Number.parseInt(value, 10);
|
|
10796
10860
|
return Number.isFinite(n) ? n : null;
|
|
@@ -11093,8 +11157,22 @@ async function backlinksRoutes(app, opts) {
|
|
|
11093
11157
|
return reply.status(200).send(result);
|
|
11094
11158
|
});
|
|
11095
11159
|
app.post("/backlinks/syncs", async (request, reply) => {
|
|
11096
|
-
|
|
11097
|
-
if (!release
|
|
11160
|
+
let release = request.body?.release;
|
|
11161
|
+
if (!release) {
|
|
11162
|
+
if (!opts.discoverLatestRelease) {
|
|
11163
|
+
throw validationError(
|
|
11164
|
+
"No `release` provided and auto-discovery is unavailable on this deployment. Pass an explicit release id (e.g., cc-main-2026-jan-feb-mar)."
|
|
11165
|
+
);
|
|
11166
|
+
}
|
|
11167
|
+
const discovered = await opts.discoverLatestRelease();
|
|
11168
|
+
if (!discovered) {
|
|
11169
|
+
throw validationError(
|
|
11170
|
+
"Could not auto-discover the latest Common Crawl release. Pass an explicit `release` body parameter."
|
|
11171
|
+
);
|
|
11172
|
+
}
|
|
11173
|
+
release = discovered.release;
|
|
11174
|
+
}
|
|
11175
|
+
if (!isValidReleaseId(release)) {
|
|
11098
11176
|
throw validationError("Invalid release id. Expected form: cc-main-YYYY-{jan-feb-mar,apr-may-jun,jul-aug-sep,oct-nov-dec}");
|
|
11099
11177
|
}
|
|
11100
11178
|
if (!opts.getBacklinksStatus || !opts.onReleaseSyncRequested) {
|
|
@@ -11145,6 +11223,13 @@ async function backlinksRoutes(app, opts) {
|
|
|
11145
11223
|
const releases = opts.listCachedReleases?.() ?? [];
|
|
11146
11224
|
return reply.send(releases);
|
|
11147
11225
|
});
|
|
11226
|
+
app.get("/backlinks/latest-release", async (_request, reply) => {
|
|
11227
|
+
if (!opts.discoverLatestRelease) {
|
|
11228
|
+
throw missingDependency(BACKLINKS_UNSUPPORTED_MESSAGE);
|
|
11229
|
+
}
|
|
11230
|
+
const discovered = await opts.discoverLatestRelease();
|
|
11231
|
+
return reply.send(discovered);
|
|
11232
|
+
});
|
|
11148
11233
|
app.delete("/backlinks/cache/:release", async (request, reply) => {
|
|
11149
11234
|
const release = request.params.release;
|
|
11150
11235
|
if (!isValidReleaseId(release)) {
|
|
@@ -11941,7 +12026,8 @@ async function apiRoutes(app, opts) {
|
|
|
11941
12026
|
onReleaseSyncRequested: opts.onReleaseSyncRequested,
|
|
11942
12027
|
onBacklinkExtractRequested: opts.onBacklinkExtractRequested,
|
|
11943
12028
|
onBacklinksPruneCache: opts.onBacklinksPruneCache,
|
|
11944
|
-
listCachedReleases: opts.listCachedReleases
|
|
12029
|
+
listCachedReleases: opts.listCachedReleases,
|
|
12030
|
+
discoverLatestRelease: opts.discoverLatestRelease
|
|
11945
12031
|
});
|
|
11946
12032
|
await api.register(doctorRoutes, {
|
|
11947
12033
|
googleConnectionStore: opts.googleConnectionStore,
|
|
@@ -19112,6 +19198,28 @@ async function createServer(opts) {
|
|
|
19112
19198
|
}));
|
|
19113
19199
|
return reply.status(204).send();
|
|
19114
19200
|
});
|
|
19201
|
+
const LATEST_RELEASE_TTL_MS = 5 * 60 * 1e3;
|
|
19202
|
+
let latestReleaseCache = null;
|
|
19203
|
+
const discoverLatestRelease = async () => {
|
|
19204
|
+
const now = Date.now();
|
|
19205
|
+
if (latestReleaseCache && latestReleaseCache.expiresAt > now) {
|
|
19206
|
+
return latestReleaseCache.value;
|
|
19207
|
+
}
|
|
19208
|
+
const probed = await probeLatestRelease().catch((err) => {
|
|
19209
|
+
app.log.warn({ err }, "Common Crawl latest-release probe failed");
|
|
19210
|
+
return null;
|
|
19211
|
+
});
|
|
19212
|
+
const value = probed ? {
|
|
19213
|
+
release: probed.release,
|
|
19214
|
+
vertexUrl: probed.vertexUrl,
|
|
19215
|
+
edgesUrl: probed.edgesUrl,
|
|
19216
|
+
vertexBytes: probed.vertexBytes,
|
|
19217
|
+
edgesBytes: probed.edgesBytes,
|
|
19218
|
+
lastModified: probed.lastModified
|
|
19219
|
+
} : null;
|
|
19220
|
+
latestReleaseCache = { value, expiresAt: now + LATEST_RELEASE_TTL_MS };
|
|
19221
|
+
return value;
|
|
19222
|
+
};
|
|
19115
19223
|
await app.register(apiRoutes, {
|
|
19116
19224
|
db: opts.db,
|
|
19117
19225
|
routePrefix: apiPrefix,
|
|
@@ -19220,6 +19328,7 @@ async function createServer(opts) {
|
|
|
19220
19328
|
};
|
|
19221
19329
|
});
|
|
19222
19330
|
},
|
|
19331
|
+
discoverLatestRelease,
|
|
19223
19332
|
openApiInfo: {
|
|
19224
19333
|
title: "Canonry API",
|
|
19225
19334
|
version: PKG_VERSION,
|
|
@@ -2409,7 +2409,10 @@ var ApiClient = class {
|
|
|
2409
2409
|
return this.request("POST", "/backlinks/install");
|
|
2410
2410
|
}
|
|
2411
2411
|
async backlinksTriggerSync(release) {
|
|
2412
|
-
return this.request("POST", "/backlinks/syncs", { release });
|
|
2412
|
+
return this.request("POST", "/backlinks/syncs", release ? { release } : void 0);
|
|
2413
|
+
}
|
|
2414
|
+
async backlinksLatestRelease() {
|
|
2415
|
+
return this.request("GET", "/backlinks/latest-release");
|
|
2413
2416
|
}
|
|
2414
2417
|
async backlinksLatestSync() {
|
|
2415
2418
|
return this.request("GET", "/backlinks/syncs/latest");
|
package/dist/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
setGoogleAuthConfig,
|
|
18
18
|
showFirstRunNotice,
|
|
19
19
|
trackEvent
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-LD7Y4K4G.js";
|
|
21
21
|
import {
|
|
22
22
|
CcReleaseSyncStatuses,
|
|
23
23
|
CheckScopes,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
saveConfig,
|
|
45
45
|
saveConfigPatch,
|
|
46
46
|
usageError
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-RNMMN2WI.js";
|
|
48
48
|
import {
|
|
49
49
|
apiKeys,
|
|
50
50
|
competitors,
|
|
@@ -638,8 +638,38 @@ async function backlinksSync(opts) {
|
|
|
638
638
|
return;
|
|
639
639
|
}
|
|
640
640
|
if (opts.wait) process.stderr.write("\n");
|
|
641
|
+
if (!opts.release) {
|
|
642
|
+
process.stderr.write(`Auto-discovered release: ${sync.release}
|
|
643
|
+
`);
|
|
644
|
+
}
|
|
641
645
|
console.log(formatSync(final));
|
|
642
646
|
}
|
|
647
|
+
function formatBytesShort(n) {
|
|
648
|
+
if (n === null) return "\u2014";
|
|
649
|
+
if (n >= 1e9) return `${(n / 1e9).toFixed(1)} GB`;
|
|
650
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)} MB`;
|
|
651
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)} KB`;
|
|
652
|
+
return `${n} B`;
|
|
653
|
+
}
|
|
654
|
+
function formatLatestRelease(result) {
|
|
655
|
+
if (!result) return "No release discovered (Common Crawl probe returned no candidates).";
|
|
656
|
+
const lines = [];
|
|
657
|
+
lines.push(`Release: ${result.release}`);
|
|
658
|
+
lines.push(`Vertex: ${result.vertexUrl}`);
|
|
659
|
+
lines.push(` ${formatBytesShort(result.vertexBytes)}`);
|
|
660
|
+
lines.push(`Edges: ${result.edgesUrl}`);
|
|
661
|
+
lines.push(` ${formatBytesShort(result.edgesBytes)}`);
|
|
662
|
+
if (result.lastModified) lines.push(`Last modified: ${result.lastModified}`);
|
|
663
|
+
return lines.join("\n");
|
|
664
|
+
}
|
|
665
|
+
async function backlinksLatestRelease(opts = {}) {
|
|
666
|
+
const result = await getClient().backlinksLatestRelease();
|
|
667
|
+
if (opts.format === "json") {
|
|
668
|
+
printJson(result);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
console.log(formatLatestRelease(result));
|
|
672
|
+
}
|
|
643
673
|
async function backlinksStatus(opts = {}) {
|
|
644
674
|
const sync = await getClient().backlinksLatestSync();
|
|
645
675
|
if (opts.format === "json") {
|
|
@@ -715,19 +745,14 @@ var BACKLINKS_CLI_COMMANDS = [
|
|
|
715
745
|
},
|
|
716
746
|
{
|
|
717
747
|
path: ["backlinks", "sync"],
|
|
718
|
-
usage: "canonry backlinks sync --release <id> [--wait] [--format json]",
|
|
748
|
+
usage: "canonry backlinks sync [--release <id>] [--wait] [--format json]",
|
|
719
749
|
options: {
|
|
720
750
|
release: stringOption(),
|
|
721
751
|
wait: { type: "boolean" }
|
|
722
752
|
},
|
|
723
753
|
run: async (input) => {
|
|
724
|
-
const release = requireStringOption(input, "release", {
|
|
725
|
-
message: "--release is required",
|
|
726
|
-
usage: "canonry backlinks sync --release <id> [--wait]",
|
|
727
|
-
command: "backlinks sync"
|
|
728
|
-
});
|
|
729
754
|
await backlinksSync({
|
|
730
|
-
release,
|
|
755
|
+
release: getString(input.values, "release"),
|
|
731
756
|
wait: getBoolean(input.values, "wait"),
|
|
732
757
|
format: input.format
|
|
733
758
|
});
|
|
@@ -775,6 +800,14 @@ var BACKLINKS_CLI_COMMANDS = [
|
|
|
775
800
|
await backlinksReleases({ format: input.format });
|
|
776
801
|
}
|
|
777
802
|
},
|
|
803
|
+
{
|
|
804
|
+
path: ["backlinks", "releases", "latest"],
|
|
805
|
+
usage: "canonry backlinks releases latest [--format json]",
|
|
806
|
+
options: {},
|
|
807
|
+
run: async (input) => {
|
|
808
|
+
await backlinksLatestRelease({ format: input.format });
|
|
809
|
+
}
|
|
810
|
+
},
|
|
778
811
|
{
|
|
779
812
|
path: ["backlinks", "extract"],
|
|
780
813
|
usage: "canonry backlinks extract <project> [--release <id>] [--wait] [--format json]",
|
package/dist/index.js
CHANGED
package/dist/mcp.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
projectUpsertRequestSchema,
|
|
11
11
|
runTriggerRequestSchema,
|
|
12
12
|
scheduleUpsertRequestSchema
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-RNMMN2WI.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// src/mcp/cli.ts
|
|
@@ -412,6 +412,17 @@ var canonryMcpTools = [
|
|
|
412
412
|
openApiOperations: ["GET /api/v1/projects/{name}/schedule"],
|
|
413
413
|
handler: (client, input) => client.getSchedule(input.project)
|
|
414
414
|
}),
|
|
415
|
+
defineTool({
|
|
416
|
+
name: "canonry_backlinks_latest_release",
|
|
417
|
+
title: "Discover latest Common Crawl release",
|
|
418
|
+
description: "Probes Common Crawl to find the latest published hyperlinkgraph release. Returns the release id and file URLs/sizes ready to feed into a backlinks sync (or null if no candidate slug responded).",
|
|
419
|
+
access: "read",
|
|
420
|
+
tier: "setup",
|
|
421
|
+
inputSchema: emptyInputSchema,
|
|
422
|
+
annotations: readAnnotations(true),
|
|
423
|
+
openApiOperations: ["GET /api/v1/backlinks/latest-release"],
|
|
424
|
+
handler: (client) => client.backlinksLatestRelease()
|
|
425
|
+
}),
|
|
415
426
|
defineTool({
|
|
416
427
|
name: "canonry_settings_get",
|
|
417
428
|
title: "Get settings",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
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",
|
|
@@ -59,21 +59,21 @@
|
|
|
59
59
|
"@types/node-cron": "^3.0.11",
|
|
60
60
|
"tsup": "^8.5.1",
|
|
61
61
|
"tsx": "^4.19.0",
|
|
62
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
62
63
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
64
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
63
65
|
"@ainyc/canonry-db": "0.0.0",
|
|
64
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
65
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
66
66
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
67
68
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
69
70
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
70
71
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
71
72
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
72
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
73
73
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
75
74
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
76
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
75
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
76
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
79
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|