@canonry/canonry 4.167.1 → 4.169.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/agent-workspace/skills/aero/SKILL.md +1 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +1 -1
- package/assets/assets/{AuditHistoryPanel-Dvz6QFtW.js → AuditHistoryPanel-B3APGWB4.js} +1 -1
- package/assets/assets/{BacklinksPage-BHOtOIr5.js → BacklinksPage-C-7KAx5g.js} +1 -1
- package/assets/assets/{HistoryPage-Bc5Nx6dX.js → HistoryPage-Cf-dJuPA.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-D4FIFiWv.js → MeasurementPropertyPage-C1W-BG81.js} +1 -1
- package/assets/assets/{ProjectPage-CT5ZD7_A.js → ProjectPage-CnZC8AA7.js} +1 -1
- package/assets/assets/{RunRow-CB2oG45_.js → RunRow-DJQ4Up9f.js} +1 -1
- package/assets/assets/{RunsPage-OLbocIOY.js → RunsPage-BbtbYLgP.js} +1 -1
- package/assets/assets/{SettingsPage-DVdPBrap.js → SettingsPage-DG-6IuO1.js} +1 -1
- package/assets/assets/{SiteHealthSection-B1bjMCqY.js → SiteHealthSection-rCrAk98W.js} +3 -3
- package/assets/assets/{TrafficPage-BUWXjHhw.js → TrafficPage-CpS4K8eT.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DwoFzTu7.js → TrafficSourceDetailPage-D_zPmdUz.js} +1 -1
- package/assets/assets/{extract-error-message-CNH2-nPH.js → extract-error-message-40mUXcbq.js} +1 -1
- package/assets/assets/{index-DdXb59Rg.js → index-Nk2MzD2d.js} +29 -29
- package/assets/assets/{react-sigma_core.esm.min-DLRh4X_G.js → react-sigma_core.esm.min-BOZ1RPZp.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/chunk-ANA3GJSC.js +123 -0
- package/dist/{chunk-P5LR3NDQ.js → chunk-HVBAGSQC.js} +400 -9
- package/dist/{chunk-TP4KXU3E.js → chunk-K7XXDKYY.js} +3916 -3068
- package/dist/{chunk-NFG2BPQP.js → chunk-T2UJAYTX.js} +93 -451
- package/dist/{chunk-7M3QVRJD.js → chunk-U2X42SKN.js} +80 -2
- package/dist/cli.js +17 -9
- package/dist/index.d.ts +19 -0
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-ULDOVV5Y.js → intelligence-service-6ZYTEFXX.js} +2 -2
- package/dist/mcp.js +24 -2
- package/package.json +11 -9
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiClient,
|
|
3
3
|
CanonryMcpToolNames,
|
|
4
|
-
CliError,
|
|
5
|
-
PACKAGE_VERSION,
|
|
6
4
|
canonryMcpTools,
|
|
7
5
|
configExists,
|
|
6
|
+
getBundledSkillSnapshots,
|
|
8
7
|
getConfigPath,
|
|
9
8
|
isMachineFormat,
|
|
10
9
|
loadConfig,
|
|
11
10
|
loadConfigRaw,
|
|
12
11
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HVBAGSQC.js";
|
|
14
13
|
import {
|
|
15
14
|
CC_CACHE_DIR,
|
|
16
15
|
DUCKDB_SPEC,
|
|
@@ -139,7 +138,7 @@ import {
|
|
|
139
138
|
siteCrawlSnapshots,
|
|
140
139
|
toAlertView,
|
|
141
140
|
usageCounters
|
|
142
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-U2X42SKN.js";
|
|
143
142
|
import {
|
|
144
143
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
145
144
|
AGENT_PROVIDER_IDS,
|
|
@@ -151,7 +150,6 @@ import {
|
|
|
151
150
|
BacklinkSources,
|
|
152
151
|
CITED_URL_CAPTURE_VERSION,
|
|
153
152
|
CcReleaseSyncStatuses,
|
|
154
|
-
CodingAgents,
|
|
155
153
|
DiscoveryCompetitorTypes,
|
|
156
154
|
LLM_CAPABILITIES,
|
|
157
155
|
LlmCapabilities,
|
|
@@ -170,10 +168,8 @@ import {
|
|
|
170
168
|
SITE_AUDIT_MAX_PAGE_LIMIT,
|
|
171
169
|
SITE_CRAWL_GRAPH_MAX_EDGES,
|
|
172
170
|
SITE_CRAWL_GRAPH_MAX_NODES,
|
|
173
|
-
SKILL_MANIFEST_FILENAME,
|
|
174
171
|
SchedulableRunKinds,
|
|
175
172
|
SiteHealthLinkClassificationSources,
|
|
176
|
-
SkillsClients,
|
|
177
173
|
TEMPLATE_LINK_RATIO_THRESHOLD,
|
|
178
174
|
TrafficEventConfidences,
|
|
179
175
|
TrafficEventKinds,
|
|
@@ -192,10 +188,8 @@ import {
|
|
|
192
188
|
authRequired,
|
|
193
189
|
bucketOnboardingCount,
|
|
194
190
|
buildRunErrorFromMessages,
|
|
195
|
-
classifySkillFile,
|
|
196
191
|
classifyTemplateLinkEdge,
|
|
197
192
|
cloudflareQueueNameSchema,
|
|
198
|
-
coerceSkillManifest,
|
|
199
193
|
computeBacklinkSummaryMetrics,
|
|
200
194
|
contentActionLabel,
|
|
201
195
|
contentBriefDtoSchema,
|
|
@@ -243,7 +237,6 @@ import {
|
|
|
243
237
|
serializeRunError,
|
|
244
238
|
shiftIsoCalendarDate,
|
|
245
239
|
siteAuditRequestIdentity,
|
|
246
|
-
skillsClientSchema,
|
|
247
240
|
splitList,
|
|
248
241
|
startOfDayHourInTimeZone,
|
|
249
242
|
templateLinkDetection,
|
|
@@ -254,7 +247,7 @@ import {
|
|
|
254
247
|
validationError,
|
|
255
248
|
winnabilityClassLabel,
|
|
256
249
|
withRetry
|
|
257
|
-
} from "./chunk-
|
|
250
|
+
} from "./chunk-K7XXDKYY.js";
|
|
258
251
|
|
|
259
252
|
// src/telemetry.ts
|
|
260
253
|
import crypto from "crypto";
|
|
@@ -585,13 +578,13 @@ function checkLatestVersionForServer(opts) {
|
|
|
585
578
|
|
|
586
579
|
// src/server.ts
|
|
587
580
|
import { createRequire as createRequire4 } from "module";
|
|
588
|
-
import
|
|
589
|
-
import
|
|
590
|
-
import
|
|
591
|
-
import { fileURLToPath as
|
|
581
|
+
import crypto24 from "crypto";
|
|
582
|
+
import fs7 from "fs";
|
|
583
|
+
import path8 from "path";
|
|
584
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
592
585
|
import { and as and18, eq as eq24 } from "drizzle-orm";
|
|
593
586
|
import Fastify from "fastify";
|
|
594
|
-
import
|
|
587
|
+
import os4 from "os";
|
|
595
588
|
|
|
596
589
|
// ../provider-gemini/src/normalize.ts
|
|
597
590
|
import { GoogleGenAI } from "@google/genai";
|
|
@@ -5181,12 +5174,12 @@ function adsClientLog(level, action, ctx) {
|
|
|
5181
5174
|
const stream = level === "error" ? process.stderr : process.stdout;
|
|
5182
5175
|
stream.write(JSON.stringify(entry) + "\n");
|
|
5183
5176
|
}
|
|
5184
|
-
function buildUrl(
|
|
5177
|
+
function buildUrl(path9, queryPairs) {
|
|
5185
5178
|
const qs = queryPairs.join("&");
|
|
5186
|
-
return qs ? `${OPENAI_ADS_API_BASE}/${
|
|
5179
|
+
return qs ? `${OPENAI_ADS_API_BASE}/${path9}?${qs}` : `${OPENAI_ADS_API_BASE}/${path9}`;
|
|
5187
5180
|
}
|
|
5188
|
-
async function adsFetch(apiKey,
|
|
5189
|
-
const url = buildUrl(
|
|
5181
|
+
async function adsFetch(apiKey, path9, queryPairs = [], method = "GET", body) {
|
|
5182
|
+
const url = buildUrl(path9, queryPairs);
|
|
5190
5183
|
const res = await fetch(url, {
|
|
5191
5184
|
method,
|
|
5192
5185
|
headers: {
|
|
@@ -5198,18 +5191,18 @@ async function adsFetch(apiKey, path10, queryPairs = [], method = "GET", body) {
|
|
|
5198
5191
|
});
|
|
5199
5192
|
if (res.status === 401 || res.status === 403) {
|
|
5200
5193
|
const { code } = parseErrorEnvelope(await res.text());
|
|
5201
|
-
adsClientLog("error", "http.auth-failed", { path:
|
|
5194
|
+
adsClientLog("error", "http.auth-failed", { path: path9, httpStatus: res.status, code });
|
|
5202
5195
|
throw new OpenAiAdsApiError("OpenAI Ads API key is invalid or unauthorized", res.status, code);
|
|
5203
5196
|
}
|
|
5204
5197
|
if (res.status === 429) {
|
|
5205
5198
|
const { code } = parseErrorEnvelope(await res.text());
|
|
5206
|
-
adsClientLog("error", "http.rate-limited", { path:
|
|
5199
|
+
adsClientLog("error", "http.rate-limited", { path: path9, httpStatus: 429, code });
|
|
5207
5200
|
throw new OpenAiAdsApiError("OpenAI Ads API rate limit exceeded", 429, code);
|
|
5208
5201
|
}
|
|
5209
5202
|
if (!res.ok) {
|
|
5210
5203
|
const body2 = await res.text();
|
|
5211
5204
|
const { message, code } = parseErrorEnvelope(body2);
|
|
5212
|
-
adsClientLog("error", "http.error", { path:
|
|
5205
|
+
adsClientLog("error", "http.error", { path: path9, httpStatus: res.status, code });
|
|
5213
5206
|
const detail = message ?? (body2.length <= 500 ? body2 : `${body2.slice(0, 500)}... [truncated]`);
|
|
5214
5207
|
throw new OpenAiAdsApiError(`OpenAI Ads API error (${res.status}): ${detail}`, res.status, code);
|
|
5215
5208
|
}
|
|
@@ -5220,12 +5213,12 @@ async function adsFetch(apiKey, path10, queryPairs = [], method = "GET", body) {
|
|
|
5220
5213
|
throw new OpenAiAdsApiError("OpenAI Ads API returned invalid JSON", 502);
|
|
5221
5214
|
}
|
|
5222
5215
|
}
|
|
5223
|
-
async function fetchAllPages(apiKey,
|
|
5216
|
+
async function fetchAllPages(apiKey, path9, queryPairs, maxPages = OPENAI_ADS_MAX_PAGES) {
|
|
5224
5217
|
const items = [];
|
|
5225
5218
|
let after = null;
|
|
5226
5219
|
for (let page = 0; page < maxPages; page++) {
|
|
5227
5220
|
const pairs = after ? [...queryPairs, `after=${encodeURIComponent(after)}`] : [...queryPairs];
|
|
5228
|
-
const response = await adsFetch(apiKey,
|
|
5221
|
+
const response = await adsFetch(apiKey, path9, pairs);
|
|
5229
5222
|
items.push(...response.data);
|
|
5230
5223
|
if (!response.has_more || !response.last_id) {
|
|
5231
5224
|
return items;
|
|
@@ -5233,7 +5226,7 @@ async function fetchAllPages(apiKey, path10, queryPairs, maxPages = OPENAI_ADS_M
|
|
|
5233
5226
|
after = response.last_id;
|
|
5234
5227
|
}
|
|
5235
5228
|
if (maxPages < OPENAI_ADS_MAX_PAGES) return items;
|
|
5236
|
-
adsClientLog("error", "pagination.cap-reached", { path:
|
|
5229
|
+
adsClientLog("error", "pagination.cap-reached", { path: path9, pages: OPENAI_ADS_MAX_PAGES, items: items.length });
|
|
5237
5230
|
throw new OpenAiAdsApiError(
|
|
5238
5231
|
`OpenAI Ads API collection remained incomplete after the ${OPENAI_ADS_MAX_PAGES}-page safety cap`,
|
|
5239
5232
|
502,
|
|
@@ -7394,8 +7387,8 @@ function hashUnit(value) {
|
|
|
7394
7387
|
}
|
|
7395
7388
|
return (hash >>> 0) / 4294967296;
|
|
7396
7389
|
}
|
|
7397
|
-
function pathSection(
|
|
7398
|
-
return
|
|
7390
|
+
function pathSection(path9) {
|
|
7391
|
+
return path9.split("/").filter(Boolean)[0] ?? "__root__";
|
|
7399
7392
|
}
|
|
7400
7393
|
function seedSiteCrawlGraphNodes(nodes, rootNodeKey, priorPositions) {
|
|
7401
7394
|
return [...nodes].sort((a, b) => a.sampleRank - b.sampleRank || a.nodeKey.localeCompare(b.nodeKey)).map((node) => {
|
|
@@ -8026,9 +8019,9 @@ function pagePath(page) {
|
|
|
8026
8019
|
}
|
|
8027
8020
|
}
|
|
8028
8021
|
function parentPath(page) {
|
|
8029
|
-
const
|
|
8030
|
-
if (
|
|
8031
|
-
const trimmed =
|
|
8022
|
+
const path9 = pagePath(page);
|
|
8023
|
+
if (path9 === "/") return "/";
|
|
8024
|
+
const trimmed = path9.endsWith("/") ? path9.slice(0, -1) : path9;
|
|
8032
8025
|
const slash = trimmed.lastIndexOf("/");
|
|
8033
8026
|
return slash <= 0 ? "/" : trimmed.slice(0, slash) || "/";
|
|
8034
8027
|
}
|
|
@@ -9094,7 +9087,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
9094
9087
|
return result;
|
|
9095
9088
|
}
|
|
9096
9089
|
async function backfillInsightsCommand(project, opts) {
|
|
9097
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
9090
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-6ZYTEFXX.js");
|
|
9098
9091
|
const config = loadConfig();
|
|
9099
9092
|
const db = createClient(config.database);
|
|
9100
9093
|
migrate(db);
|
|
@@ -9618,352 +9611,6 @@ No DB writes performed. Re-run without --dry-run to apply.`);
|
|
|
9618
9611
|
}
|
|
9619
9612
|
}
|
|
9620
9613
|
|
|
9621
|
-
// src/commands/skills.ts
|
|
9622
|
-
import crypto18 from "crypto";
|
|
9623
|
-
import fs4 from "fs";
|
|
9624
|
-
import os4 from "os";
|
|
9625
|
-
import path5 from "path";
|
|
9626
|
-
import { fileURLToPath } from "url";
|
|
9627
|
-
var BUNDLED_SKILL_NAMES = ["canonry", "aero"];
|
|
9628
|
-
function resolveBundledSkillsRoot(pkgDir) {
|
|
9629
|
-
const here = pkgDir ?? path5.dirname(fileURLToPath(import.meta.url));
|
|
9630
|
-
const candidates = [
|
|
9631
|
-
path5.join(here, "../assets/agent-workspace/skills"),
|
|
9632
|
-
path5.join(here, "../../assets/agent-workspace/skills"),
|
|
9633
|
-
path5.join(here, "../../../../skills")
|
|
9634
|
-
];
|
|
9635
|
-
for (const candidate of candidates) {
|
|
9636
|
-
if (BUNDLED_SKILL_NAMES.every((name) => fs4.existsSync(path5.join(candidate, name, "SKILL.md")))) {
|
|
9637
|
-
return candidate;
|
|
9638
|
-
}
|
|
9639
|
-
}
|
|
9640
|
-
throw new CliError({
|
|
9641
|
-
code: "INTERNAL_ERROR",
|
|
9642
|
-
message: `Bundled skills not found. Searched:
|
|
9643
|
-
${candidates.join("\n ")}`,
|
|
9644
|
-
exitCode: 2
|
|
9645
|
-
});
|
|
9646
|
-
}
|
|
9647
|
-
function parseDescription(content) {
|
|
9648
|
-
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(content);
|
|
9649
|
-
if (!fmMatch) return "";
|
|
9650
|
-
const descMatch = /^description:\s*(\S.*)$/m.exec(fmMatch[1]);
|
|
9651
|
-
if (!descMatch) return "";
|
|
9652
|
-
return descMatch[1].replace(/^["']|["']$/g, "").trim();
|
|
9653
|
-
}
|
|
9654
|
-
function getBundledSkills(pkgDir) {
|
|
9655
|
-
const root = resolveBundledSkillsRoot(pkgDir);
|
|
9656
|
-
return BUNDLED_SKILL_NAMES.map((name) => {
|
|
9657
|
-
const skillDir = path5.join(root, name);
|
|
9658
|
-
const skillFile = path5.join(skillDir, "SKILL.md");
|
|
9659
|
-
const content = fs4.readFileSync(skillFile, "utf-8");
|
|
9660
|
-
return { name, description: parseDescription(content), bundledPath: skillDir };
|
|
9661
|
-
});
|
|
9662
|
-
}
|
|
9663
|
-
function walkRelative(dir, prefix = "") {
|
|
9664
|
-
const out = [];
|
|
9665
|
-
for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
|
|
9666
|
-
const rel = prefix ? path5.join(prefix, entry.name) : entry.name;
|
|
9667
|
-
const full = path5.join(dir, entry.name);
|
|
9668
|
-
if (entry.isDirectory()) {
|
|
9669
|
-
out.push(...walkRelative(full, rel));
|
|
9670
|
-
} else if (entry.isFile()) {
|
|
9671
|
-
out.push(rel);
|
|
9672
|
-
}
|
|
9673
|
-
}
|
|
9674
|
-
return out.sort();
|
|
9675
|
-
}
|
|
9676
|
-
function sha256File(filePath) {
|
|
9677
|
-
return crypto18.createHash("sha256").update(fs4.readFileSync(filePath)).digest("hex");
|
|
9678
|
-
}
|
|
9679
|
-
function readSkillManifest(skillDir) {
|
|
9680
|
-
try {
|
|
9681
|
-
return coerceSkillManifest(JSON.parse(fs4.readFileSync(path5.join(skillDir, SKILL_MANIFEST_FILENAME), "utf-8")));
|
|
9682
|
-
} catch {
|
|
9683
|
-
return null;
|
|
9684
|
-
}
|
|
9685
|
-
}
|
|
9686
|
-
function writeSkillManifest(skillDir, manifest) {
|
|
9687
|
-
fs4.writeFileSync(path5.join(skillDir, SKILL_MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}
|
|
9688
|
-
`, "utf-8");
|
|
9689
|
-
}
|
|
9690
|
-
function reconcileSkillTree(srcDir, destDir, manifest, force) {
|
|
9691
|
-
const result = { added: [], updated: [], unchanged: [], conflicts: [], bundledHashes: /* @__PURE__ */ new Map() };
|
|
9692
|
-
for (const rel of walkRelative(srcDir)) {
|
|
9693
|
-
const srcPath = path5.join(srcDir, rel);
|
|
9694
|
-
const destPath = path5.join(destDir, rel);
|
|
9695
|
-
const bundledHash = sha256File(srcPath);
|
|
9696
|
-
result.bundledHashes.set(rel, bundledHash);
|
|
9697
|
-
const installedHash = fs4.existsSync(destPath) ? sha256File(destPath) : void 0;
|
|
9698
|
-
const state = classifySkillFile({ bundledHash, installedHash, manifestHash: manifest?.files[rel] });
|
|
9699
|
-
switch (state) {
|
|
9700
|
-
case "missing":
|
|
9701
|
-
fs4.mkdirSync(path5.dirname(destPath), { recursive: true });
|
|
9702
|
-
fs4.copyFileSync(srcPath, destPath);
|
|
9703
|
-
result.added.push(rel);
|
|
9704
|
-
break;
|
|
9705
|
-
case "unchanged":
|
|
9706
|
-
result.unchanged.push(rel);
|
|
9707
|
-
break;
|
|
9708
|
-
case "stale":
|
|
9709
|
-
fs4.copyFileSync(srcPath, destPath);
|
|
9710
|
-
result.updated.push(rel);
|
|
9711
|
-
break;
|
|
9712
|
-
case "edited":
|
|
9713
|
-
if (force) {
|
|
9714
|
-
fs4.copyFileSync(srcPath, destPath);
|
|
9715
|
-
result.updated.push(rel);
|
|
9716
|
-
} else {
|
|
9717
|
-
result.conflicts.push(rel);
|
|
9718
|
-
}
|
|
9719
|
-
break;
|
|
9720
|
-
}
|
|
9721
|
-
}
|
|
9722
|
-
return result;
|
|
9723
|
-
}
|
|
9724
|
-
function buildManifest(skillName, recon, prior) {
|
|
9725
|
-
const conflicts = new Set(recon.conflicts);
|
|
9726
|
-
const files = {};
|
|
9727
|
-
for (const [rel, bundledHash] of recon.bundledHashes) {
|
|
9728
|
-
files[rel] = conflicts.has(rel) ? prior?.files[rel] ?? bundledHash : bundledHash;
|
|
9729
|
-
}
|
|
9730
|
-
return { skill: skillName, version: PACKAGE_VERSION, files };
|
|
9731
|
-
}
|
|
9732
|
-
function describeChanges(recon) {
|
|
9733
|
-
const parts = [];
|
|
9734
|
-
if (recon.added.length > 0) parts.push(`${recon.added.length} added`);
|
|
9735
|
-
if (recon.updated.length > 0) parts.push(`${recon.updated.length} refreshed`);
|
|
9736
|
-
return parts.length > 0 ? parts.join(", ") : "no changes";
|
|
9737
|
-
}
|
|
9738
|
-
function buildClaudeMessage(name, status, recon) {
|
|
9739
|
-
const rel = `.claude/skills/${name}`;
|
|
9740
|
-
let message = status === "installed" ? `Installed ${rel}` : status === "updated" ? `Updated ${rel} (${describeChanges(recon)})` : `Already installed: ${rel}`;
|
|
9741
|
-
if (recon.conflicts.length > 0) {
|
|
9742
|
-
message += ` \u2014 ${recon.conflicts.length} file(s) differ from the bundle (local edits kept; pass --force to overwrite)`;
|
|
9743
|
-
}
|
|
9744
|
-
return message;
|
|
9745
|
-
}
|
|
9746
|
-
function installClaudeSkill(skill, targetDir, force) {
|
|
9747
|
-
const targetPath = path5.join(targetDir, ".claude", "skills", skill.name);
|
|
9748
|
-
const existedBefore = fs4.existsSync(path5.join(targetPath, "SKILL.md"));
|
|
9749
|
-
const priorManifest = readSkillManifest(targetPath);
|
|
9750
|
-
fs4.mkdirSync(targetPath, { recursive: true });
|
|
9751
|
-
const recon = reconcileSkillTree(skill.bundledPath, targetPath, priorManifest, force);
|
|
9752
|
-
writeSkillManifest(targetPath, buildManifest(skill.name, recon, priorManifest));
|
|
9753
|
-
const changed = recon.added.length + recon.updated.length;
|
|
9754
|
-
const status = !existedBefore ? "installed" : changed > 0 ? "updated" : "already-installed";
|
|
9755
|
-
return {
|
|
9756
|
-
skill: skill.name,
|
|
9757
|
-
client: CodingAgents.claude,
|
|
9758
|
-
targetPath,
|
|
9759
|
-
status,
|
|
9760
|
-
message: buildClaudeMessage(skill.name, status, recon),
|
|
9761
|
-
added: recon.added,
|
|
9762
|
-
updated: recon.updated,
|
|
9763
|
-
unchanged: recon.unchanged,
|
|
9764
|
-
conflicts: recon.conflicts
|
|
9765
|
-
};
|
|
9766
|
-
}
|
|
9767
|
-
function installCodexSymlink(skill, targetDir, force) {
|
|
9768
|
-
const codexPath = path5.join(targetDir, ".codex", "skills", skill.name);
|
|
9769
|
-
const claudePath = path5.join(targetDir, ".claude", "skills", skill.name);
|
|
9770
|
-
const linkTarget = path5.relative(path5.dirname(codexPath), claudePath);
|
|
9771
|
-
fs4.mkdirSync(path5.dirname(codexPath), { recursive: true });
|
|
9772
|
-
let stat;
|
|
9773
|
-
try {
|
|
9774
|
-
stat = fs4.lstatSync(codexPath);
|
|
9775
|
-
} catch {
|
|
9776
|
-
stat = void 0;
|
|
9777
|
-
}
|
|
9778
|
-
if (stat?.isSymbolicLink()) {
|
|
9779
|
-
const existing = fs4.readlinkSync(codexPath);
|
|
9780
|
-
if (existing === linkTarget) {
|
|
9781
|
-
return {
|
|
9782
|
-
skill: skill.name,
|
|
9783
|
-
client: CodingAgents.codex,
|
|
9784
|
-
targetPath: codexPath,
|
|
9785
|
-
status: "already-linked",
|
|
9786
|
-
message: `Already linked: .codex/skills/${skill.name}`
|
|
9787
|
-
};
|
|
9788
|
-
}
|
|
9789
|
-
if (!force) {
|
|
9790
|
-
throw new CliError({
|
|
9791
|
-
code: "VALIDATION_ERROR",
|
|
9792
|
-
message: `.codex/skills/${skill.name} is a symlink pointing elsewhere (${existing}). Pass --force to relink.`,
|
|
9793
|
-
details: { skill: skill.name, targetPath: codexPath, existingTarget: existing },
|
|
9794
|
-
exitCode: 1
|
|
9795
|
-
});
|
|
9796
|
-
}
|
|
9797
|
-
fs4.unlinkSync(codexPath);
|
|
9798
|
-
fs4.symlinkSync(linkTarget, codexPath);
|
|
9799
|
-
return {
|
|
9800
|
-
skill: skill.name,
|
|
9801
|
-
client: CodingAgents.codex,
|
|
9802
|
-
targetPath: codexPath,
|
|
9803
|
-
status: "relinked",
|
|
9804
|
-
message: `Relinked .codex/skills/${skill.name} \u2192 ${linkTarget}`
|
|
9805
|
-
};
|
|
9806
|
-
}
|
|
9807
|
-
if (stat) {
|
|
9808
|
-
if (!force) {
|
|
9809
|
-
throw new CliError({
|
|
9810
|
-
code: "VALIDATION_ERROR",
|
|
9811
|
-
message: `.codex/skills/${skill.name} exists but is not a symlink. Pass --force to replace.`,
|
|
9812
|
-
details: { skill: skill.name, targetPath: codexPath },
|
|
9813
|
-
exitCode: 1
|
|
9814
|
-
});
|
|
9815
|
-
}
|
|
9816
|
-
fs4.rmSync(codexPath, { recursive: true, force: true });
|
|
9817
|
-
}
|
|
9818
|
-
fs4.symlinkSync(linkTarget, codexPath);
|
|
9819
|
-
return {
|
|
9820
|
-
skill: skill.name,
|
|
9821
|
-
client: CodingAgents.codex,
|
|
9822
|
-
targetPath: codexPath,
|
|
9823
|
-
status: stat ? "relinked" : "linked",
|
|
9824
|
-
message: stat ? `Replaced and linked .codex/skills/${skill.name} \u2192 ${linkTarget}` : `Linked .codex/skills/${skill.name} \u2192 ${linkTarget}`
|
|
9825
|
-
};
|
|
9826
|
-
}
|
|
9827
|
-
function buildSummaryMessage(results) {
|
|
9828
|
-
const counts = {};
|
|
9829
|
-
for (const r of results) counts[r.status] = (counts[r.status] ?? 0) + 1;
|
|
9830
|
-
const parts = Object.entries(counts).map(([status, n]) => `${n} ${status}`);
|
|
9831
|
-
let message = `Skills install summary: ${parts.join(", ")}.`;
|
|
9832
|
-
const totalConflicts = results.reduce((sum, r) => sum + (r.conflicts?.length ?? 0), 0);
|
|
9833
|
-
if (totalConflicts > 0) {
|
|
9834
|
-
message += ` ${totalConflicts} file(s) differ from the bundle and were kept \u2014 pass --force to overwrite local edits.`;
|
|
9835
|
-
}
|
|
9836
|
-
return message;
|
|
9837
|
-
}
|
|
9838
|
-
function getBundledSkillSnapshots(pkgDir) {
|
|
9839
|
-
return getBundledSkills(pkgDir).map((skill) => {
|
|
9840
|
-
const files = {};
|
|
9841
|
-
for (const rel of walkRelative(skill.bundledPath)) {
|
|
9842
|
-
files[rel] = sha256File(path5.join(skill.bundledPath, rel));
|
|
9843
|
-
}
|
|
9844
|
-
return { name: skill.name, version: PACKAGE_VERSION, files };
|
|
9845
|
-
});
|
|
9846
|
-
}
|
|
9847
|
-
async function installSkills(opts = {}) {
|
|
9848
|
-
const targetDir = opts.user ? os4.homedir() : path5.resolve(opts.dir ?? process.cwd());
|
|
9849
|
-
const client = opts.client ?? SkillsClients.all;
|
|
9850
|
-
const force = opts.force ?? false;
|
|
9851
|
-
const allSkills = getBundledSkills();
|
|
9852
|
-
const requestedNames = opts.skills && opts.skills.length > 0 ? opts.skills : allSkills.map((s) => s.name);
|
|
9853
|
-
const knownNames = new Set(allSkills.map((s) => s.name));
|
|
9854
|
-
const unknown = requestedNames.filter((n) => !knownNames.has(n));
|
|
9855
|
-
if (unknown.length > 0) {
|
|
9856
|
-
throw new CliError({
|
|
9857
|
-
code: "VALIDATION_ERROR",
|
|
9858
|
-
message: `Unknown skill(s): ${unknown.join(", ")}. Available: ${[...knownNames].join(", ")}`,
|
|
9859
|
-
details: { unknownSkills: unknown, availableSkills: [...knownNames] },
|
|
9860
|
-
exitCode: 1
|
|
9861
|
-
});
|
|
9862
|
-
}
|
|
9863
|
-
const skillsToInstall = allSkills.filter((s) => requestedNames.includes(s.name));
|
|
9864
|
-
fs4.mkdirSync(targetDir, { recursive: true });
|
|
9865
|
-
const results = [];
|
|
9866
|
-
for (const skill of skillsToInstall) {
|
|
9867
|
-
results.push(installClaudeSkill(skill, targetDir, force));
|
|
9868
|
-
if (client !== SkillsClients.claude) {
|
|
9869
|
-
results.push(installCodexSymlink(skill, targetDir, force));
|
|
9870
|
-
}
|
|
9871
|
-
}
|
|
9872
|
-
return {
|
|
9873
|
-
targetDir,
|
|
9874
|
-
results,
|
|
9875
|
-
message: buildSummaryMessage(results)
|
|
9876
|
-
};
|
|
9877
|
-
}
|
|
9878
|
-
async function listSkills(opts = {}) {
|
|
9879
|
-
const skills = getBundledSkills();
|
|
9880
|
-
if (isMachineFormat(opts.format)) {
|
|
9881
|
-
console.log(JSON.stringify({
|
|
9882
|
-
skills: skills.map((s) => ({
|
|
9883
|
-
name: s.name,
|
|
9884
|
-
description: s.description,
|
|
9885
|
-
claudePath: `.claude/skills/${s.name}`,
|
|
9886
|
-
codexPath: `.codex/skills/${s.name}`
|
|
9887
|
-
}))
|
|
9888
|
-
}, null, 2));
|
|
9889
|
-
return;
|
|
9890
|
-
}
|
|
9891
|
-
console.log("Bundled canonry skills:\n");
|
|
9892
|
-
for (const skill of skills) {
|
|
9893
|
-
console.log(` ${skill.name}`);
|
|
9894
|
-
if (skill.description) console.log(` ${skill.description}`);
|
|
9895
|
-
console.log(` Claude: .claude/skills/${skill.name}/`);
|
|
9896
|
-
console.log(` Codex: .codex/skills/${skill.name} (symlink \u2192 ../../.claude/skills/${skill.name})`);
|
|
9897
|
-
console.log();
|
|
9898
|
-
}
|
|
9899
|
-
}
|
|
9900
|
-
function emitInstallSummary(summary, format) {
|
|
9901
|
-
if (isMachineFormat(format)) {
|
|
9902
|
-
console.log(JSON.stringify(summary, null, 2));
|
|
9903
|
-
return;
|
|
9904
|
-
}
|
|
9905
|
-
for (const r of summary.results) console.log(r.message);
|
|
9906
|
-
console.log(`
|
|
9907
|
-
Target: ${summary.targetDir}`);
|
|
9908
|
-
console.log(summary.message);
|
|
9909
|
-
}
|
|
9910
|
-
function getMissingUserSkillsNudge(home, agentPlugin) {
|
|
9911
|
-
if (!home) return null;
|
|
9912
|
-
const skillsBase = path5.join(home, ".claude", "skills");
|
|
9913
|
-
const installed = [];
|
|
9914
|
-
const missing = [];
|
|
9915
|
-
for (const name of BUNDLED_SKILL_NAMES) {
|
|
9916
|
-
const skillFile = path5.join(skillsBase, name, "SKILL.md");
|
|
9917
|
-
if (existsSafe(skillFile)) installed.push(name);
|
|
9918
|
-
else missing.push(name);
|
|
9919
|
-
}
|
|
9920
|
-
if (agentPlugin && agentPlugin.configuredClients.length > 0) {
|
|
9921
|
-
const unverifiedClients = agentPlugin.configuredClients.filter((client) => !agentPlugin.verifiedClients.includes(client));
|
|
9922
|
-
const mismatchedClients = agentPlugin.verifiedClients.filter((client) => agentPlugin.verifiedClientVersions?.[client] !== PACKAGE_VERSION);
|
|
9923
|
-
if (unverifiedClients.length === 0 && mismatchedClients.length === 0) return null;
|
|
9924
|
-
const displayClients = (clients) => clients.map((client) => client === "claude-code" ? "Claude Code" : "Codex").join(" + ");
|
|
9925
|
-
const problems = [];
|
|
9926
|
-
if (unverifiedClients.length > 0) {
|
|
9927
|
-
problems.push(`The Canonry plugin is enabled for ${displayClients(unverifiedClients)}, but its cached manifest and skill assets could not be verified.`);
|
|
9928
|
-
}
|
|
9929
|
-
if (mismatchedClients.length > 0) {
|
|
9930
|
-
const versions = mismatchedClients.map((client) => `${client === "claude-code" ? "Claude Code" : "Codex"} v${agentPlugin.verifiedClientVersions?.[client] ?? "unknown"}`).join(", ");
|
|
9931
|
-
problems.push(`${versions} ${mismatchedClients.length === 1 ? "does" : "do"} not match the running Canonry v${PACKAGE_VERSION}.`);
|
|
9932
|
-
}
|
|
9933
|
-
return {
|
|
9934
|
-
message: `Tip: ${problems.join(" ")} Update or reinstall \`canonry@canonry\` with the affected client plugin manager.`,
|
|
9935
|
-
missing,
|
|
9936
|
-
installed
|
|
9937
|
-
};
|
|
9938
|
-
}
|
|
9939
|
-
if (missing.length === 0) return null;
|
|
9940
|
-
const fix = missing.length === BUNDLED_SKILL_NAMES.length ? "canonry skills install --user" : `canonry skills install ${missing.join(" ")} --user`;
|
|
9941
|
-
return {
|
|
9942
|
-
message: `Tip: ${missing.join(" + ")} skill${missing.length === 1 ? "" : "s"} not installed in ~/.claude/skills/. Run \`${fix}\` so Claude/Codex sessions on this host auto-load the canonry reference docs.`,
|
|
9943
|
-
missing,
|
|
9944
|
-
installed
|
|
9945
|
-
};
|
|
9946
|
-
}
|
|
9947
|
-
function existsSafe(p) {
|
|
9948
|
-
try {
|
|
9949
|
-
return fs4.existsSync(p);
|
|
9950
|
-
} catch {
|
|
9951
|
-
return false;
|
|
9952
|
-
}
|
|
9953
|
-
}
|
|
9954
|
-
function parseSkillsClient(value) {
|
|
9955
|
-
if (!value) return SkillsClients.all;
|
|
9956
|
-
const parsed = skillsClientSchema.safeParse(value);
|
|
9957
|
-
if (parsed.success) return parsed.data;
|
|
9958
|
-
const allowed = skillsClientSchema.options;
|
|
9959
|
-
throw new CliError({
|
|
9960
|
-
code: "VALIDATION_ERROR",
|
|
9961
|
-
message: `Invalid --client value "${value}". Must be one of: ${allowed.join(", ")}`,
|
|
9962
|
-
details: { flag: "client", value, allowed },
|
|
9963
|
-
exitCode: 1
|
|
9964
|
-
});
|
|
9965
|
-
}
|
|
9966
|
-
|
|
9967
9614
|
// src/provider-registry.ts
|
|
9968
9615
|
var ProviderRegistry = class {
|
|
9969
9616
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -10016,7 +9663,7 @@ var ProviderRegistry = class {
|
|
|
10016
9663
|
};
|
|
10017
9664
|
|
|
10018
9665
|
// src/scheduler.ts
|
|
10019
|
-
import
|
|
9666
|
+
import crypto18 from "crypto";
|
|
10020
9667
|
import cron from "node-cron";
|
|
10021
9668
|
import { and as and14, eq as eq17, inArray as inArray6, notExists, sql as sql8 } from "drizzle-orm";
|
|
10022
9669
|
var log13 = createLogger("Scheduler");
|
|
@@ -10059,7 +9706,7 @@ var Scheduler = class {
|
|
|
10059
9706
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10060
9707
|
for (const project of projectsWithoutHealth) {
|
|
10061
9708
|
this.db.insert(schedules).values({
|
|
10062
|
-
id:
|
|
9709
|
+
id: crypto18.randomUUID(),
|
|
10063
9710
|
projectId: project.id,
|
|
10064
9711
|
kind: SchedulableRunKinds.doctor,
|
|
10065
9712
|
cronExpr: DEFAULT_HEALTH_CRON,
|
|
@@ -10218,7 +9865,7 @@ var Scheduler = class {
|
|
|
10218
9865
|
log13.warn("gbp-sync.no-callback", { scheduleId, projectId, msg: "host did not register onGbpSyncRequested" });
|
|
10219
9866
|
return;
|
|
10220
9867
|
}
|
|
10221
|
-
const runId2 =
|
|
9868
|
+
const runId2 = crypto18.randomUUID();
|
|
10222
9869
|
this.db.insert(runs).values({
|
|
10223
9870
|
id: runId2,
|
|
10224
9871
|
projectId,
|
|
@@ -10251,7 +9898,7 @@ var Scheduler = class {
|
|
|
10251
9898
|
this.db.update(schedules).set({ nextRunAt, updatedAt: now }).where(eq17(schedules.id, currentSchedule.id)).run();
|
|
10252
9899
|
return;
|
|
10253
9900
|
}
|
|
10254
|
-
const runId2 =
|
|
9901
|
+
const runId2 = crypto18.randomUUID();
|
|
10255
9902
|
this.db.insert(runs).values({
|
|
10256
9903
|
id: runId2,
|
|
10257
9904
|
projectId,
|
|
@@ -10326,7 +9973,7 @@ var Scheduler = class {
|
|
|
10326
9973
|
this.db.update(schedules).set({ nextRunAt, updatedAt: now }).where(eq17(schedules.id, currentSchedule.id)).run();
|
|
10327
9974
|
return;
|
|
10328
9975
|
}
|
|
10329
|
-
const runId2 =
|
|
9976
|
+
const runId2 = crypto18.randomUUID();
|
|
10330
9977
|
const effectiveRequest = normalizeSiteAuditRunRequest({});
|
|
10331
9978
|
this.db.transaction((tx) => {
|
|
10332
9979
|
tx.insert(runs).values({
|
|
@@ -10424,7 +10071,7 @@ async function refreshAllIntegrations(client, projectName) {
|
|
|
10424
10071
|
|
|
10425
10072
|
// src/notifier.ts
|
|
10426
10073
|
import { eq as eq18, desc as desc7, and as and15, inArray as inArray7, or as or2 } from "drizzle-orm";
|
|
10427
|
-
import
|
|
10074
|
+
import crypto19 from "crypto";
|
|
10428
10075
|
var log15 = createLogger("Notifier");
|
|
10429
10076
|
var Notifier = class {
|
|
10430
10077
|
db;
|
|
@@ -10750,7 +10397,7 @@ var Notifier = class {
|
|
|
10750
10397
|
}
|
|
10751
10398
|
logDelivery(projectId, notificationId, event, status, error) {
|
|
10752
10399
|
this.db.insert(auditLog).values({
|
|
10753
|
-
id:
|
|
10400
|
+
id: crypto19.randomUUID(),
|
|
10754
10401
|
projectId,
|
|
10755
10402
|
actor: "scheduler",
|
|
10756
10403
|
action: `notification.${status}`,
|
|
@@ -10912,12 +10559,12 @@ function analysisResultFromInsights(insights2) {
|
|
|
10912
10559
|
}
|
|
10913
10560
|
|
|
10914
10561
|
// src/agent/session-registry.ts
|
|
10915
|
-
import
|
|
10562
|
+
import crypto23 from "crypto";
|
|
10916
10563
|
import { eq as eq21 } from "drizzle-orm";
|
|
10917
10564
|
|
|
10918
10565
|
// src/agent/session.ts
|
|
10919
|
-
import
|
|
10920
|
-
import
|
|
10566
|
+
import fs6 from "fs";
|
|
10567
|
+
import path7 from "path";
|
|
10921
10568
|
import { Agent } from "@mariozechner/pi-agent-core";
|
|
10922
10569
|
import { registerBuiltInApiProviders } from "@mariozechner/pi-ai";
|
|
10923
10570
|
|
|
@@ -11160,26 +10807,26 @@ function buildAgentProvidersResponse(config) {
|
|
|
11160
10807
|
}
|
|
11161
10808
|
|
|
11162
10809
|
// src/agent/skill-paths.ts
|
|
11163
|
-
import
|
|
11164
|
-
import
|
|
11165
|
-
import { fileURLToPath
|
|
10810
|
+
import fs4 from "fs";
|
|
10811
|
+
import path5 from "path";
|
|
10812
|
+
import { fileURLToPath } from "url";
|
|
11166
10813
|
function resolveAeroSkillDir(pkgDir) {
|
|
11167
|
-
const here = pkgDir ??
|
|
10814
|
+
const here = pkgDir ?? path5.dirname(fileURLToPath(import.meta.url));
|
|
11168
10815
|
const candidates = [
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
10816
|
+
path5.join(here, "../assets/agent-workspace/skills/aero"),
|
|
10817
|
+
path5.join(here, "../../assets/agent-workspace/skills/aero"),
|
|
10818
|
+
path5.join(here, "../../../../skills/aero")
|
|
11172
10819
|
];
|
|
11173
10820
|
for (const candidate of candidates) {
|
|
11174
|
-
if (
|
|
10821
|
+
if (fs4.existsSync(path5.join(candidate, "SKILL.md"))) return candidate;
|
|
11175
10822
|
}
|
|
11176
10823
|
throw new Error(`Aero skill not found. Searched:
|
|
11177
10824
|
${candidates.join("\n ")}`);
|
|
11178
10825
|
}
|
|
11179
10826
|
|
|
11180
10827
|
// src/agent/skill-tools.ts
|
|
11181
|
-
import
|
|
11182
|
-
import
|
|
10828
|
+
import fs5 from "fs";
|
|
10829
|
+
import path6 from "path";
|
|
11183
10830
|
import { Type } from "@sinclair/typebox";
|
|
11184
10831
|
var MAX_DOC_CHARS = 2e4;
|
|
11185
10832
|
function textResult(details) {
|
|
@@ -11188,7 +10835,7 @@ function textResult(details) {
|
|
|
11188
10835
|
details
|
|
11189
10836
|
};
|
|
11190
10837
|
}
|
|
11191
|
-
function
|
|
10838
|
+
function parseDescription(body) {
|
|
11192
10839
|
if (!body.startsWith("---")) return "(no description)";
|
|
11193
10840
|
const end = body.indexOf("\n---", 3);
|
|
11194
10841
|
if (end === -1) return "(no description)";
|
|
@@ -11200,16 +10847,16 @@ function parseDescription2(body) {
|
|
|
11200
10847
|
return "(no description)";
|
|
11201
10848
|
}
|
|
11202
10849
|
function scanSkillDocs(skillDir) {
|
|
11203
|
-
const refsDir =
|
|
11204
|
-
if (!
|
|
10850
|
+
const refsDir = path6.join(skillDir ?? resolveAeroSkillDir(), "references");
|
|
10851
|
+
if (!fs5.existsSync(refsDir)) return [];
|
|
11205
10852
|
const entries = [];
|
|
11206
|
-
for (const file of
|
|
10853
|
+
for (const file of fs5.readdirSync(refsDir)) {
|
|
11207
10854
|
if (!file.endsWith(".md")) continue;
|
|
11208
|
-
const filePath =
|
|
11209
|
-
const body =
|
|
10855
|
+
const filePath = path6.join(refsDir, file);
|
|
10856
|
+
const body = fs5.readFileSync(filePath, "utf-8");
|
|
11210
10857
|
entries.push({
|
|
11211
10858
|
slug: file.replace(/\.md$/, ""),
|
|
11212
|
-
description:
|
|
10859
|
+
description: parseDescription(body),
|
|
11213
10860
|
bytes: Buffer.byteLength(body, "utf-8")
|
|
11214
10861
|
});
|
|
11215
10862
|
}
|
|
@@ -11249,8 +10896,8 @@ function buildReadSkillDocTool() {
|
|
|
11249
10896
|
availableSlugs: docs.map((d) => d.slug)
|
|
11250
10897
|
});
|
|
11251
10898
|
}
|
|
11252
|
-
const filePath =
|
|
11253
|
-
const content =
|
|
10899
|
+
const filePath = path6.join(skillDir, "references", `${match.slug}.md`);
|
|
10900
|
+
const content = fs5.readFileSync(filePath, "utf-8");
|
|
11254
10901
|
if (content.length > MAX_DOC_CHARS) {
|
|
11255
10902
|
return textResult({
|
|
11256
10903
|
slug: match.slug,
|
|
@@ -11656,7 +11303,7 @@ function buildAeroStateTools(ctx, opts = {}) {
|
|
|
11656
11303
|
}
|
|
11657
11304
|
|
|
11658
11305
|
// src/agent/llm-usage.ts
|
|
11659
|
-
import
|
|
11306
|
+
import crypto20 from "crypto";
|
|
11660
11307
|
var AeroLlmUsageFeatures = {
|
|
11661
11308
|
turn: "aero.turn"
|
|
11662
11309
|
};
|
|
@@ -11675,7 +11322,7 @@ function recordLlmUsageEvent(args) {
|
|
|
11675
11322
|
const usage = args.message.usage;
|
|
11676
11323
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11677
11324
|
args.db.insert(llmUsageEvents).values({
|
|
11678
|
-
id:
|
|
11325
|
+
id: crypto20.randomUUID(),
|
|
11679
11326
|
projectId: args.projectId,
|
|
11680
11327
|
runId: args.runId,
|
|
11681
11328
|
agentSessionId: args.agentSessionId,
|
|
@@ -11751,7 +11398,7 @@ function splitAeroAnthropicSystemCachePayload(payload, model) {
|
|
|
11751
11398
|
}
|
|
11752
11399
|
|
|
11753
11400
|
// src/agent/tool-usage.ts
|
|
11754
|
-
import
|
|
11401
|
+
import crypto21 from "crypto";
|
|
11755
11402
|
var AeroToolEventStatuses = {
|
|
11756
11403
|
success: "success",
|
|
11757
11404
|
error: "error"
|
|
@@ -11814,7 +11461,7 @@ function createAeroToolUsageHooks(args) {
|
|
|
11814
11461
|
function recordAgentToolEvent(args) {
|
|
11815
11462
|
try {
|
|
11816
11463
|
args.db.insert(agentToolEvents).values({
|
|
11817
|
-
id:
|
|
11464
|
+
id: crypto21.randomUUID(),
|
|
11818
11465
|
projectId: args.projectId,
|
|
11819
11466
|
agentSessionId: args.agentSessionId,
|
|
11820
11467
|
toolCallId: args.toolCallId,
|
|
@@ -11845,9 +11492,9 @@ function ensureBuiltinsRegistered() {
|
|
|
11845
11492
|
}
|
|
11846
11493
|
function loadAeroSystemPrompt(pkgDir) {
|
|
11847
11494
|
const skillDir = resolveAeroSkillDir(pkgDir);
|
|
11848
|
-
const skillBody =
|
|
11849
|
-
const soulPath =
|
|
11850
|
-
const base =
|
|
11495
|
+
const skillBody = fs6.readFileSync(path7.join(skillDir, "SKILL.md"), "utf-8");
|
|
11496
|
+
const soulPath = path7.join(skillDir, "soul.md");
|
|
11497
|
+
const base = fs6.existsSync(soulPath) ? `${fs6.readFileSync(soulPath, "utf-8").trimEnd()}
|
|
11851
11498
|
|
|
11852
11499
|
---
|
|
11853
11500
|
|
|
@@ -11860,7 +11507,7 @@ function appendSystemPromptExtras(base, env = process.env) {
|
|
|
11860
11507
|
const filePath = env.AERO_SYSTEM_PROMPT_FILE?.trim();
|
|
11861
11508
|
if (filePath) {
|
|
11862
11509
|
try {
|
|
11863
|
-
fileBody =
|
|
11510
|
+
fileBody = fs6.readFileSync(filePath, "utf-8").trim();
|
|
11864
11511
|
} catch {
|
|
11865
11512
|
fileBody = "";
|
|
11866
11513
|
}
|
|
@@ -12041,7 +11688,7 @@ async function loadExternalMcpTools(servers, opts = {}) {
|
|
|
12041
11688
|
}
|
|
12042
11689
|
|
|
12043
11690
|
// src/agent/memory-store.ts
|
|
12044
|
-
import
|
|
11691
|
+
import crypto22 from "crypto";
|
|
12045
11692
|
import { and as and16, desc as desc8, eq as eq20, like, sql as sql9 } from "drizzle-orm";
|
|
12046
11693
|
var COMPACTION_KEY_PREFIX = "compaction:";
|
|
12047
11694
|
var COMPACTION_NOTES_PER_SESSION = 3;
|
|
@@ -12070,7 +11717,7 @@ function upsertMemoryEntry(db, args) {
|
|
|
12070
11717
|
throw new Error(`memory key prefix "${COMPACTION_KEY_PREFIX}" is reserved for compaction notes`);
|
|
12071
11718
|
}
|
|
12072
11719
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12073
|
-
const id =
|
|
11720
|
+
const id = crypto22.randomUUID();
|
|
12074
11721
|
db.insert(agentMemory).values({
|
|
12075
11722
|
id,
|
|
12076
11723
|
projectId: args.projectId,
|
|
@@ -12107,7 +11754,7 @@ function writeCompactionNote(db, args) {
|
|
|
12107
11754
|
}
|
|
12108
11755
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12109
11756
|
const key = `${COMPACTION_KEY_PREFIX}${args.sessionId}:${now}`;
|
|
12110
|
-
const id =
|
|
11757
|
+
const id = crypto22.randomUUID();
|
|
12111
11758
|
let inserted;
|
|
12112
11759
|
db.transaction((tx) => {
|
|
12113
11760
|
tx.insert(agentMemory).values({
|
|
@@ -12386,7 +12033,7 @@ var SessionRegistry = class {
|
|
|
12386
12033
|
}
|
|
12387
12034
|
const { provider, modelId } = resolveSessionProviderAndModel(this.opts.config, preferences);
|
|
12388
12035
|
const systemPrompt = loadAeroSystemPrompt();
|
|
12389
|
-
const sessionId =
|
|
12036
|
+
const sessionId = crypto23.randomUUID();
|
|
12390
12037
|
const agent = createAeroSession({
|
|
12391
12038
|
projectName,
|
|
12392
12039
|
client: this.opts.client,
|
|
@@ -12765,7 +12412,7 @@ ${lines.join("\n")}
|
|
|
12765
12412
|
insertRow(params) {
|
|
12766
12413
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12767
12414
|
this.opts.db.insert(agentSessions).values({
|
|
12768
|
-
id: params.id ??
|
|
12415
|
+
id: params.id ?? crypto23.randomUUID(),
|
|
12769
12416
|
projectId: params.projectId,
|
|
12770
12417
|
systemPrompt: params.systemPrompt,
|
|
12771
12418
|
modelProvider: params.provider ?? params.modelProvider ?? AgentProviderIds.claude,
|
|
@@ -13153,13 +12800,13 @@ var USER_AGENT2 = "Canonry/1.0 (site-analysis)";
|
|
|
13153
12800
|
function fetchWithPinnedAddress(target) {
|
|
13154
12801
|
return new Promise((resolve) => {
|
|
13155
12802
|
const port = target.url.port ? Number(target.url.port) : 443;
|
|
13156
|
-
const
|
|
12803
|
+
const path9 = target.url.pathname + target.url.search;
|
|
13157
12804
|
const req = https2.request(
|
|
13158
12805
|
{
|
|
13159
12806
|
hostname: target.address,
|
|
13160
12807
|
family: target.family,
|
|
13161
12808
|
port,
|
|
13162
|
-
path:
|
|
12809
|
+
path: path9,
|
|
13163
12810
|
method: "GET",
|
|
13164
12811
|
timeout: FETCH_TIMEOUT_MS2,
|
|
13165
12812
|
servername: target.url.hostname,
|
|
@@ -13948,14 +13595,14 @@ function summarizeProviderConfig(config) {
|
|
|
13948
13595
|
};
|
|
13949
13596
|
}
|
|
13950
13597
|
function hashApiKey(key) {
|
|
13951
|
-
return
|
|
13598
|
+
return crypto24.createHash("sha256").update(key).digest("hex");
|
|
13952
13599
|
}
|
|
13953
13600
|
var DASHBOARD_SCRYPT_KEYLEN = 64;
|
|
13954
13601
|
var DASHBOARD_SCRYPT_COST = 1 << 15;
|
|
13955
13602
|
var DASHBOARD_SCRYPT_MAXMEM = 64 * 1024 * 1024;
|
|
13956
13603
|
function hashDashboardPassword(password) {
|
|
13957
|
-
const salt =
|
|
13958
|
-
const derived =
|
|
13604
|
+
const salt = crypto24.randomBytes(16);
|
|
13605
|
+
const derived = crypto24.scryptSync(password, salt, DASHBOARD_SCRYPT_KEYLEN, {
|
|
13959
13606
|
N: DASHBOARD_SCRYPT_COST,
|
|
13960
13607
|
maxmem: DASHBOARD_SCRYPT_MAXMEM
|
|
13961
13608
|
});
|
|
@@ -13976,14 +13623,14 @@ function verifyDashboardPassword(password, storedHash) {
|
|
|
13976
13623
|
} catch {
|
|
13977
13624
|
return { ok: false, needsRehash: false };
|
|
13978
13625
|
}
|
|
13979
|
-
const derived =
|
|
13626
|
+
const derived = crypto24.scryptSync(password, salt, expected.length, {
|
|
13980
13627
|
N: DASHBOARD_SCRYPT_COST,
|
|
13981
13628
|
maxmem: DASHBOARD_SCRYPT_MAXMEM
|
|
13982
13629
|
});
|
|
13983
13630
|
if (derived.length !== expected.length)
|
|
13984
13631
|
return { ok: false, needsRehash: false };
|
|
13985
13632
|
return {
|
|
13986
|
-
ok:
|
|
13633
|
+
ok: crypto24.timingSafeEqual(derived, expected),
|
|
13987
13634
|
needsRehash: false
|
|
13988
13635
|
};
|
|
13989
13636
|
}
|
|
@@ -13992,7 +13639,7 @@ function verifyDashboardPassword(password, storedHash) {
|
|
|
13992
13639
|
const expected = Buffer.from(storedHash, "hex");
|
|
13993
13640
|
if (candidate.length !== expected.length)
|
|
13994
13641
|
return { ok: false, needsRehash: false };
|
|
13995
|
-
const ok =
|
|
13642
|
+
const ok = crypto24.timingSafeEqual(candidate, expected);
|
|
13996
13643
|
return { ok, needsRehash: ok };
|
|
13997
13644
|
}
|
|
13998
13645
|
return { ok: false, needsRehash: false };
|
|
@@ -14223,8 +13870,8 @@ async function createServer(opts) {
|
|
|
14223
13870
|
);
|
|
14224
13871
|
jobRunner.onRunCompleted = (runId, projectId) => runCoordinator.onRunCompleted(runId, projectId);
|
|
14225
13872
|
const snapshotService = new SnapshotService(registry);
|
|
14226
|
-
const orphanedOpenClawDir =
|
|
14227
|
-
if (
|
|
13873
|
+
const orphanedOpenClawDir = path8.join(os4.homedir(), ".openclaw-aero");
|
|
13874
|
+
if (fs7.existsSync(orphanedOpenClawDir)) {
|
|
14228
13875
|
app.log.warn(
|
|
14229
13876
|
{ path: orphanedOpenClawDir },
|
|
14230
13877
|
"OpenClaw gateway is no longer used. Remove ~/.openclaw-aero/ manually to reclaim the directory."
|
|
@@ -14761,7 +14408,7 @@ async function createServer(opts) {
|
|
|
14761
14408
|
return removed;
|
|
14762
14409
|
}
|
|
14763
14410
|
};
|
|
14764
|
-
const googleStateSecret = process.env.GOOGLE_STATE_SECRET ??
|
|
14411
|
+
const googleStateSecret = process.env.GOOGLE_STATE_SECRET ?? crypto24.randomBytes(32).toString("hex");
|
|
14765
14412
|
const googleConnectionStore = {
|
|
14766
14413
|
listConnections: (domain) => listGoogleConnections(opts.config, domain),
|
|
14767
14414
|
getConnection: (domain, connectionType) => getGoogleConnection(opts.config, domain, connectionType),
|
|
@@ -14841,7 +14488,7 @@ async function createServer(opts) {
|
|
|
14841
14488
|
if (!existing) {
|
|
14842
14489
|
const prefix = opts.config.apiKey.slice(0, 12);
|
|
14843
14490
|
opts.db.insert(apiKeys).values({
|
|
14844
|
-
id: `key_${
|
|
14491
|
+
id: `key_${crypto24.randomBytes(8).toString("hex")}`,
|
|
14845
14492
|
name: "default",
|
|
14846
14493
|
keyHash,
|
|
14847
14494
|
keyPrefix: prefix,
|
|
@@ -14865,7 +14512,7 @@ async function createServer(opts) {
|
|
|
14865
14512
|
};
|
|
14866
14513
|
const createSession = (apiKeyId) => {
|
|
14867
14514
|
pruneExpiredSessions();
|
|
14868
|
-
const sessionId =
|
|
14515
|
+
const sessionId = crypto24.randomBytes(32).toString("hex");
|
|
14869
14516
|
sessions.set(sessionId, {
|
|
14870
14517
|
apiKeyId,
|
|
14871
14518
|
expiresAt: Date.now() + SESSION_TTL_MS
|
|
@@ -15113,7 +14760,7 @@ async function createServer(opts) {
|
|
|
15113
14760
|
const configPath = getConfigPath();
|
|
15114
14761
|
return {
|
|
15115
14762
|
databasePath: opts.config.database,
|
|
15116
|
-
configPath:
|
|
14763
|
+
configPath: fs7.existsSync(configPath) ? configPath : null
|
|
15117
14764
|
};
|
|
15118
14765
|
})(),
|
|
15119
14766
|
// Snapshot the bundled skill trees (version + file hashes) so the
|
|
@@ -15225,7 +14872,7 @@ async function createServer(opts) {
|
|
|
15225
14872
|
deps: {
|
|
15226
14873
|
enqueueAutoExtract: ({ projectId, release: r }) => {
|
|
15227
14874
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
15228
|
-
const runId =
|
|
14875
|
+
const runId = crypto24.randomUUID();
|
|
15229
14876
|
opts.db.insert(runs).values({
|
|
15230
14877
|
id: runId,
|
|
15231
14878
|
projectId,
|
|
@@ -15460,7 +15107,7 @@ async function createServer(opts) {
|
|
|
15460
15107
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15461
15108
|
opts.db.insert(auditLog).values(
|
|
15462
15109
|
targetProjectIds.map((projectId) => ({
|
|
15463
|
-
id:
|
|
15110
|
+
id: crypto24.randomUUID(),
|
|
15464
15111
|
projectId,
|
|
15465
15112
|
actor: "api",
|
|
15466
15113
|
action: existing ? "provider.updated" : "provider.created",
|
|
@@ -15619,10 +15266,10 @@ async function createServer(opts) {
|
|
|
15619
15266
|
return snapshotService.createReport(input);
|
|
15620
15267
|
}
|
|
15621
15268
|
});
|
|
15622
|
-
const dirname =
|
|
15623
|
-
const assetsDir = opts.assetsDir ??
|
|
15624
|
-
if (
|
|
15625
|
-
const indexPath =
|
|
15269
|
+
const dirname = path8.dirname(fileURLToPath2(import.meta.url));
|
|
15270
|
+
const assetsDir = opts.assetsDir ?? path8.join(dirname, "..", "assets");
|
|
15271
|
+
if (fs7.existsSync(assetsDir)) {
|
|
15272
|
+
const indexPath = path8.join(assetsDir, "index.html");
|
|
15626
15273
|
const injectConfig = (html, projectTabsOverride, themeOverride, renderTokenOverride) => {
|
|
15627
15274
|
const clientConfig = {};
|
|
15628
15275
|
if (basePath) clientConfig.basePath = basePath;
|
|
@@ -15677,8 +15324,8 @@ async function createServer(opts) {
|
|
|
15677
15324
|
// Without this, the browser hits the server for every JS chunk on
|
|
15678
15325
|
// every page load, defeating most of the dashboard's first-paint
|
|
15679
15326
|
// budget.
|
|
15680
|
-
setHeaders: (res,
|
|
15681
|
-
if (
|
|
15327
|
+
setHeaders: (res, path9) => {
|
|
15328
|
+
if (path9.endsWith(".html")) {
|
|
15682
15329
|
res.setHeader("Cache-Control", "no-cache, must-revalidate");
|
|
15683
15330
|
} else {
|
|
15684
15331
|
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
@@ -15686,8 +15333,8 @@ async function createServer(opts) {
|
|
|
15686
15333
|
}
|
|
15687
15334
|
});
|
|
15688
15335
|
const serveIndex = (_request, reply) => {
|
|
15689
|
-
if (
|
|
15690
|
-
const html =
|
|
15336
|
+
if (fs7.existsSync(indexPath)) {
|
|
15337
|
+
const html = fs7.readFileSync(indexPath, "utf-8");
|
|
15691
15338
|
return sendSpaDocument(reply, html);
|
|
15692
15339
|
}
|
|
15693
15340
|
return reply.status(404).send({ error: "Dashboard not built" });
|
|
@@ -15708,8 +15355,8 @@ async function createServer(opts) {
|
|
|
15708
15355
|
if (basePath && !url.startsWith(basePath)) {
|
|
15709
15356
|
return reply.status(404).send({ error: "Not found", path: request.url });
|
|
15710
15357
|
}
|
|
15711
|
-
if (
|
|
15712
|
-
const html =
|
|
15358
|
+
if (fs7.existsSync(indexPath)) {
|
|
15359
|
+
const html = fs7.readFileSync(indexPath, "utf-8");
|
|
15713
15360
|
return sendSpaDocument(reply, html);
|
|
15714
15361
|
}
|
|
15715
15362
|
return reply.status(404).send({ error: "Not found" });
|
|
@@ -15816,11 +15463,6 @@ export {
|
|
|
15816
15463
|
backfillTrafficClassificationCommand,
|
|
15817
15464
|
getCloudflareTrafficConnectionBySourceId,
|
|
15818
15465
|
setGoogleAuthConfig,
|
|
15819
|
-
installSkills,
|
|
15820
|
-
listSkills,
|
|
15821
|
-
emitInstallSummary,
|
|
15822
|
-
getMissingUserSkillsNudge,
|
|
15823
|
-
parseSkillsClient,
|
|
15824
15466
|
formatAuditFactorScore,
|
|
15825
15467
|
checkLatestVersionForCli,
|
|
15826
15468
|
listAgentProviders,
|