@canonry/canonry 4.167.0 → 4.168.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.
@@ -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-P5LR3NDQ.js";
12
+ } from "./chunk-C4UWZLQX.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-7M3QVRJD.js";
141
+ } from "./chunk-CDACTPTY.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,
@@ -585,13 +578,13 @@ function checkLatestVersionForServer(opts) {
585
578
 
586
579
  // src/server.ts
587
580
  import { createRequire as createRequire4 } from "module";
588
- import crypto25 from "crypto";
589
- import fs8 from "fs";
590
- import path9 from "path";
591
- import { fileURLToPath as fileURLToPath3 } from "url";
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 os5 from "os";
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(path10, queryPairs) {
5177
+ function buildUrl(path9, queryPairs) {
5185
5178
  const qs = queryPairs.join("&");
5186
- return qs ? `${OPENAI_ADS_API_BASE}/${path10}?${qs}` : `${OPENAI_ADS_API_BASE}/${path10}`;
5179
+ return qs ? `${OPENAI_ADS_API_BASE}/${path9}?${qs}` : `${OPENAI_ADS_API_BASE}/${path9}`;
5187
5180
  }
5188
- async function adsFetch(apiKey, path10, queryPairs = [], method = "GET", body) {
5189
- const url = buildUrl(path10, queryPairs);
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: path10, httpStatus: res.status, code });
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: path10, httpStatus: 429, code });
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: path10, httpStatus: res.status, code });
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, path10, queryPairs, maxPages = OPENAI_ADS_MAX_PAGES) {
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, path10, pairs);
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: path10, pages: OPENAI_ADS_MAX_PAGES, items: items.length });
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(path10) {
7398
- return path10.split("/").filter(Boolean)[0] ?? "__root__";
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 path10 = pagePath(page);
8030
- if (path10 === "/") return "/";
8031
- const trimmed = path10.endsWith("/") ? path10.slice(0, -1) : path10;
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
  }
@@ -8098,12 +8091,14 @@ function deadLinkCheckedCount(edges, pages) {
8098
8091
  }
8099
8092
  return new Set([...edges].filter((edge) => edge.type === "anchor" && edge.classification === "internal" && attemptedUrls.has(edge.to)).map((edge) => edge.to)).size;
8100
8093
  }
8094
+ var RATE_LIMITED_STATUS = 429;
8101
8095
  function partitionDeadLinks(deadLinks) {
8102
8096
  const reported = deadLinks.findings;
8103
8097
  const engineUnverified = deadLinks.unverified ?? [];
8104
- const dead = reported.filter((finding) => typeof finding.statusCode === "number" && finding.statusCode >= 400);
8098
+ const answeredWithError = (finding) => typeof finding.statusCode === "number" && finding.statusCode >= 400;
8099
+ const dead = reported.filter((finding) => answeredWithError(finding) && finding.statusCode !== RATE_LIMITED_STATUS);
8105
8100
  const unverified = [
8106
- ...reported.filter((finding) => typeof finding.statusCode !== "number"),
8101
+ ...reported.filter((finding) => !answeredWithError(finding) || finding.statusCode === RATE_LIMITED_STATUS),
8107
8102
  ...engineUnverified
8108
8103
  ];
8109
8104
  return { dead, unverified };
@@ -9092,7 +9087,7 @@ function readStoredGroundingSources(rawResponse) {
9092
9087
  return result;
9093
9088
  }
9094
9089
  async function backfillInsightsCommand(project, opts) {
9095
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ULDOVV5Y.js");
9090
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-KBSDKHED.js");
9096
9091
  const config = loadConfig();
9097
9092
  const db = createClient(config.database);
9098
9093
  migrate(db);
@@ -9616,352 +9611,6 @@ No DB writes performed. Re-run without --dry-run to apply.`);
9616
9611
  }
9617
9612
  }
9618
9613
 
9619
- // src/commands/skills.ts
9620
- import crypto18 from "crypto";
9621
- import fs4 from "fs";
9622
- import os4 from "os";
9623
- import path5 from "path";
9624
- import { fileURLToPath } from "url";
9625
- var BUNDLED_SKILL_NAMES = ["canonry", "aero"];
9626
- function resolveBundledSkillsRoot(pkgDir) {
9627
- const here = pkgDir ?? path5.dirname(fileURLToPath(import.meta.url));
9628
- const candidates = [
9629
- path5.join(here, "../assets/agent-workspace/skills"),
9630
- path5.join(here, "../../assets/agent-workspace/skills"),
9631
- path5.join(here, "../../../../skills")
9632
- ];
9633
- for (const candidate of candidates) {
9634
- if (BUNDLED_SKILL_NAMES.every((name) => fs4.existsSync(path5.join(candidate, name, "SKILL.md")))) {
9635
- return candidate;
9636
- }
9637
- }
9638
- throw new CliError({
9639
- code: "INTERNAL_ERROR",
9640
- message: `Bundled skills not found. Searched:
9641
- ${candidates.join("\n ")}`,
9642
- exitCode: 2
9643
- });
9644
- }
9645
- function parseDescription(content) {
9646
- const fmMatch = /^---\n([\s\S]*?)\n---/.exec(content);
9647
- if (!fmMatch) return "";
9648
- const descMatch = /^description:\s*(\S.*)$/m.exec(fmMatch[1]);
9649
- if (!descMatch) return "";
9650
- return descMatch[1].replace(/^["']|["']$/g, "").trim();
9651
- }
9652
- function getBundledSkills(pkgDir) {
9653
- const root = resolveBundledSkillsRoot(pkgDir);
9654
- return BUNDLED_SKILL_NAMES.map((name) => {
9655
- const skillDir = path5.join(root, name);
9656
- const skillFile = path5.join(skillDir, "SKILL.md");
9657
- const content = fs4.readFileSync(skillFile, "utf-8");
9658
- return { name, description: parseDescription(content), bundledPath: skillDir };
9659
- });
9660
- }
9661
- function walkRelative(dir, prefix = "") {
9662
- const out = [];
9663
- for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
9664
- const rel = prefix ? path5.join(prefix, entry.name) : entry.name;
9665
- const full = path5.join(dir, entry.name);
9666
- if (entry.isDirectory()) {
9667
- out.push(...walkRelative(full, rel));
9668
- } else if (entry.isFile()) {
9669
- out.push(rel);
9670
- }
9671
- }
9672
- return out.sort();
9673
- }
9674
- function sha256File(filePath) {
9675
- return crypto18.createHash("sha256").update(fs4.readFileSync(filePath)).digest("hex");
9676
- }
9677
- function readSkillManifest(skillDir) {
9678
- try {
9679
- return coerceSkillManifest(JSON.parse(fs4.readFileSync(path5.join(skillDir, SKILL_MANIFEST_FILENAME), "utf-8")));
9680
- } catch {
9681
- return null;
9682
- }
9683
- }
9684
- function writeSkillManifest(skillDir, manifest) {
9685
- fs4.writeFileSync(path5.join(skillDir, SKILL_MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}
9686
- `, "utf-8");
9687
- }
9688
- function reconcileSkillTree(srcDir, destDir, manifest, force) {
9689
- const result = { added: [], updated: [], unchanged: [], conflicts: [], bundledHashes: /* @__PURE__ */ new Map() };
9690
- for (const rel of walkRelative(srcDir)) {
9691
- const srcPath = path5.join(srcDir, rel);
9692
- const destPath = path5.join(destDir, rel);
9693
- const bundledHash = sha256File(srcPath);
9694
- result.bundledHashes.set(rel, bundledHash);
9695
- const installedHash = fs4.existsSync(destPath) ? sha256File(destPath) : void 0;
9696
- const state = classifySkillFile({ bundledHash, installedHash, manifestHash: manifest?.files[rel] });
9697
- switch (state) {
9698
- case "missing":
9699
- fs4.mkdirSync(path5.dirname(destPath), { recursive: true });
9700
- fs4.copyFileSync(srcPath, destPath);
9701
- result.added.push(rel);
9702
- break;
9703
- case "unchanged":
9704
- result.unchanged.push(rel);
9705
- break;
9706
- case "stale":
9707
- fs4.copyFileSync(srcPath, destPath);
9708
- result.updated.push(rel);
9709
- break;
9710
- case "edited":
9711
- if (force) {
9712
- fs4.copyFileSync(srcPath, destPath);
9713
- result.updated.push(rel);
9714
- } else {
9715
- result.conflicts.push(rel);
9716
- }
9717
- break;
9718
- }
9719
- }
9720
- return result;
9721
- }
9722
- function buildManifest(skillName, recon, prior) {
9723
- const conflicts = new Set(recon.conflicts);
9724
- const files = {};
9725
- for (const [rel, bundledHash] of recon.bundledHashes) {
9726
- files[rel] = conflicts.has(rel) ? prior?.files[rel] ?? bundledHash : bundledHash;
9727
- }
9728
- return { skill: skillName, version: PACKAGE_VERSION, files };
9729
- }
9730
- function describeChanges(recon) {
9731
- const parts = [];
9732
- if (recon.added.length > 0) parts.push(`${recon.added.length} added`);
9733
- if (recon.updated.length > 0) parts.push(`${recon.updated.length} refreshed`);
9734
- return parts.length > 0 ? parts.join(", ") : "no changes";
9735
- }
9736
- function buildClaudeMessage(name, status, recon) {
9737
- const rel = `.claude/skills/${name}`;
9738
- let message = status === "installed" ? `Installed ${rel}` : status === "updated" ? `Updated ${rel} (${describeChanges(recon)})` : `Already installed: ${rel}`;
9739
- if (recon.conflicts.length > 0) {
9740
- message += ` \u2014 ${recon.conflicts.length} file(s) differ from the bundle (local edits kept; pass --force to overwrite)`;
9741
- }
9742
- return message;
9743
- }
9744
- function installClaudeSkill(skill, targetDir, force) {
9745
- const targetPath = path5.join(targetDir, ".claude", "skills", skill.name);
9746
- const existedBefore = fs4.existsSync(path5.join(targetPath, "SKILL.md"));
9747
- const priorManifest = readSkillManifest(targetPath);
9748
- fs4.mkdirSync(targetPath, { recursive: true });
9749
- const recon = reconcileSkillTree(skill.bundledPath, targetPath, priorManifest, force);
9750
- writeSkillManifest(targetPath, buildManifest(skill.name, recon, priorManifest));
9751
- const changed = recon.added.length + recon.updated.length;
9752
- const status = !existedBefore ? "installed" : changed > 0 ? "updated" : "already-installed";
9753
- return {
9754
- skill: skill.name,
9755
- client: CodingAgents.claude,
9756
- targetPath,
9757
- status,
9758
- message: buildClaudeMessage(skill.name, status, recon),
9759
- added: recon.added,
9760
- updated: recon.updated,
9761
- unchanged: recon.unchanged,
9762
- conflicts: recon.conflicts
9763
- };
9764
- }
9765
- function installCodexSymlink(skill, targetDir, force) {
9766
- const codexPath = path5.join(targetDir, ".codex", "skills", skill.name);
9767
- const claudePath = path5.join(targetDir, ".claude", "skills", skill.name);
9768
- const linkTarget = path5.relative(path5.dirname(codexPath), claudePath);
9769
- fs4.mkdirSync(path5.dirname(codexPath), { recursive: true });
9770
- let stat;
9771
- try {
9772
- stat = fs4.lstatSync(codexPath);
9773
- } catch {
9774
- stat = void 0;
9775
- }
9776
- if (stat?.isSymbolicLink()) {
9777
- const existing = fs4.readlinkSync(codexPath);
9778
- if (existing === linkTarget) {
9779
- return {
9780
- skill: skill.name,
9781
- client: CodingAgents.codex,
9782
- targetPath: codexPath,
9783
- status: "already-linked",
9784
- message: `Already linked: .codex/skills/${skill.name}`
9785
- };
9786
- }
9787
- if (!force) {
9788
- throw new CliError({
9789
- code: "VALIDATION_ERROR",
9790
- message: `.codex/skills/${skill.name} is a symlink pointing elsewhere (${existing}). Pass --force to relink.`,
9791
- details: { skill: skill.name, targetPath: codexPath, existingTarget: existing },
9792
- exitCode: 1
9793
- });
9794
- }
9795
- fs4.unlinkSync(codexPath);
9796
- fs4.symlinkSync(linkTarget, codexPath);
9797
- return {
9798
- skill: skill.name,
9799
- client: CodingAgents.codex,
9800
- targetPath: codexPath,
9801
- status: "relinked",
9802
- message: `Relinked .codex/skills/${skill.name} \u2192 ${linkTarget}`
9803
- };
9804
- }
9805
- if (stat) {
9806
- if (!force) {
9807
- throw new CliError({
9808
- code: "VALIDATION_ERROR",
9809
- message: `.codex/skills/${skill.name} exists but is not a symlink. Pass --force to replace.`,
9810
- details: { skill: skill.name, targetPath: codexPath },
9811
- exitCode: 1
9812
- });
9813
- }
9814
- fs4.rmSync(codexPath, { recursive: true, force: true });
9815
- }
9816
- fs4.symlinkSync(linkTarget, codexPath);
9817
- return {
9818
- skill: skill.name,
9819
- client: CodingAgents.codex,
9820
- targetPath: codexPath,
9821
- status: stat ? "relinked" : "linked",
9822
- message: stat ? `Replaced and linked .codex/skills/${skill.name} \u2192 ${linkTarget}` : `Linked .codex/skills/${skill.name} \u2192 ${linkTarget}`
9823
- };
9824
- }
9825
- function buildSummaryMessage(results) {
9826
- const counts = {};
9827
- for (const r of results) counts[r.status] = (counts[r.status] ?? 0) + 1;
9828
- const parts = Object.entries(counts).map(([status, n]) => `${n} ${status}`);
9829
- let message = `Skills install summary: ${parts.join(", ")}.`;
9830
- const totalConflicts = results.reduce((sum, r) => sum + (r.conflicts?.length ?? 0), 0);
9831
- if (totalConflicts > 0) {
9832
- message += ` ${totalConflicts} file(s) differ from the bundle and were kept \u2014 pass --force to overwrite local edits.`;
9833
- }
9834
- return message;
9835
- }
9836
- function getBundledSkillSnapshots(pkgDir) {
9837
- return getBundledSkills(pkgDir).map((skill) => {
9838
- const files = {};
9839
- for (const rel of walkRelative(skill.bundledPath)) {
9840
- files[rel] = sha256File(path5.join(skill.bundledPath, rel));
9841
- }
9842
- return { name: skill.name, version: PACKAGE_VERSION, files };
9843
- });
9844
- }
9845
- async function installSkills(opts = {}) {
9846
- const targetDir = opts.user ? os4.homedir() : path5.resolve(opts.dir ?? process.cwd());
9847
- const client = opts.client ?? SkillsClients.all;
9848
- const force = opts.force ?? false;
9849
- const allSkills = getBundledSkills();
9850
- const requestedNames = opts.skills && opts.skills.length > 0 ? opts.skills : allSkills.map((s) => s.name);
9851
- const knownNames = new Set(allSkills.map((s) => s.name));
9852
- const unknown = requestedNames.filter((n) => !knownNames.has(n));
9853
- if (unknown.length > 0) {
9854
- throw new CliError({
9855
- code: "VALIDATION_ERROR",
9856
- message: `Unknown skill(s): ${unknown.join(", ")}. Available: ${[...knownNames].join(", ")}`,
9857
- details: { unknownSkills: unknown, availableSkills: [...knownNames] },
9858
- exitCode: 1
9859
- });
9860
- }
9861
- const skillsToInstall = allSkills.filter((s) => requestedNames.includes(s.name));
9862
- fs4.mkdirSync(targetDir, { recursive: true });
9863
- const results = [];
9864
- for (const skill of skillsToInstall) {
9865
- results.push(installClaudeSkill(skill, targetDir, force));
9866
- if (client !== SkillsClients.claude) {
9867
- results.push(installCodexSymlink(skill, targetDir, force));
9868
- }
9869
- }
9870
- return {
9871
- targetDir,
9872
- results,
9873
- message: buildSummaryMessage(results)
9874
- };
9875
- }
9876
- async function listSkills(opts = {}) {
9877
- const skills = getBundledSkills();
9878
- if (isMachineFormat(opts.format)) {
9879
- console.log(JSON.stringify({
9880
- skills: skills.map((s) => ({
9881
- name: s.name,
9882
- description: s.description,
9883
- claudePath: `.claude/skills/${s.name}`,
9884
- codexPath: `.codex/skills/${s.name}`
9885
- }))
9886
- }, null, 2));
9887
- return;
9888
- }
9889
- console.log("Bundled canonry skills:\n");
9890
- for (const skill of skills) {
9891
- console.log(` ${skill.name}`);
9892
- if (skill.description) console.log(` ${skill.description}`);
9893
- console.log(` Claude: .claude/skills/${skill.name}/`);
9894
- console.log(` Codex: .codex/skills/${skill.name} (symlink \u2192 ../../.claude/skills/${skill.name})`);
9895
- console.log();
9896
- }
9897
- }
9898
- function emitInstallSummary(summary, format) {
9899
- if (isMachineFormat(format)) {
9900
- console.log(JSON.stringify(summary, null, 2));
9901
- return;
9902
- }
9903
- for (const r of summary.results) console.log(r.message);
9904
- console.log(`
9905
- Target: ${summary.targetDir}`);
9906
- console.log(summary.message);
9907
- }
9908
- function getMissingUserSkillsNudge(home, agentPlugin) {
9909
- if (!home) return null;
9910
- const skillsBase = path5.join(home, ".claude", "skills");
9911
- const installed = [];
9912
- const missing = [];
9913
- for (const name of BUNDLED_SKILL_NAMES) {
9914
- const skillFile = path5.join(skillsBase, name, "SKILL.md");
9915
- if (existsSafe(skillFile)) installed.push(name);
9916
- else missing.push(name);
9917
- }
9918
- if (agentPlugin && agentPlugin.configuredClients.length > 0) {
9919
- const unverifiedClients = agentPlugin.configuredClients.filter((client) => !agentPlugin.verifiedClients.includes(client));
9920
- const mismatchedClients = agentPlugin.verifiedClients.filter((client) => agentPlugin.verifiedClientVersions?.[client] !== PACKAGE_VERSION);
9921
- if (unverifiedClients.length === 0 && mismatchedClients.length === 0) return null;
9922
- const displayClients = (clients) => clients.map((client) => client === "claude-code" ? "Claude Code" : "Codex").join(" + ");
9923
- const problems = [];
9924
- if (unverifiedClients.length > 0) {
9925
- problems.push(`The Canonry plugin is enabled for ${displayClients(unverifiedClients)}, but its cached manifest and skill assets could not be verified.`);
9926
- }
9927
- if (mismatchedClients.length > 0) {
9928
- const versions = mismatchedClients.map((client) => `${client === "claude-code" ? "Claude Code" : "Codex"} v${agentPlugin.verifiedClientVersions?.[client] ?? "unknown"}`).join(", ");
9929
- problems.push(`${versions} ${mismatchedClients.length === 1 ? "does" : "do"} not match the running Canonry v${PACKAGE_VERSION}.`);
9930
- }
9931
- return {
9932
- message: `Tip: ${problems.join(" ")} Update or reinstall \`canonry@canonry\` with the affected client plugin manager.`,
9933
- missing,
9934
- installed
9935
- };
9936
- }
9937
- if (missing.length === 0) return null;
9938
- const fix = missing.length === BUNDLED_SKILL_NAMES.length ? "canonry skills install --user" : `canonry skills install ${missing.join(" ")} --user`;
9939
- return {
9940
- 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.`,
9941
- missing,
9942
- installed
9943
- };
9944
- }
9945
- function existsSafe(p) {
9946
- try {
9947
- return fs4.existsSync(p);
9948
- } catch {
9949
- return false;
9950
- }
9951
- }
9952
- function parseSkillsClient(value) {
9953
- if (!value) return SkillsClients.all;
9954
- const parsed = skillsClientSchema.safeParse(value);
9955
- if (parsed.success) return parsed.data;
9956
- const allowed = skillsClientSchema.options;
9957
- throw new CliError({
9958
- code: "VALIDATION_ERROR",
9959
- message: `Invalid --client value "${value}". Must be one of: ${allowed.join(", ")}`,
9960
- details: { flag: "client", value, allowed },
9961
- exitCode: 1
9962
- });
9963
- }
9964
-
9965
9614
  // src/provider-registry.ts
9966
9615
  var ProviderRegistry = class {
9967
9616
  providers = /* @__PURE__ */ new Map();
@@ -10014,7 +9663,7 @@ var ProviderRegistry = class {
10014
9663
  };
10015
9664
 
10016
9665
  // src/scheduler.ts
10017
- import crypto19 from "crypto";
9666
+ import crypto18 from "crypto";
10018
9667
  import cron from "node-cron";
10019
9668
  import { and as and14, eq as eq17, inArray as inArray6, notExists, sql as sql8 } from "drizzle-orm";
10020
9669
  var log13 = createLogger("Scheduler");
@@ -10057,7 +9706,7 @@ var Scheduler = class {
10057
9706
  const now = (/* @__PURE__ */ new Date()).toISOString();
10058
9707
  for (const project of projectsWithoutHealth) {
10059
9708
  this.db.insert(schedules).values({
10060
- id: crypto19.randomUUID(),
9709
+ id: crypto18.randomUUID(),
10061
9710
  projectId: project.id,
10062
9711
  kind: SchedulableRunKinds.doctor,
10063
9712
  cronExpr: DEFAULT_HEALTH_CRON,
@@ -10216,7 +9865,7 @@ var Scheduler = class {
10216
9865
  log13.warn("gbp-sync.no-callback", { scheduleId, projectId, msg: "host did not register onGbpSyncRequested" });
10217
9866
  return;
10218
9867
  }
10219
- const runId2 = crypto19.randomUUID();
9868
+ const runId2 = crypto18.randomUUID();
10220
9869
  this.db.insert(runs).values({
10221
9870
  id: runId2,
10222
9871
  projectId,
@@ -10249,7 +9898,7 @@ var Scheduler = class {
10249
9898
  this.db.update(schedules).set({ nextRunAt, updatedAt: now }).where(eq17(schedules.id, currentSchedule.id)).run();
10250
9899
  return;
10251
9900
  }
10252
- const runId2 = crypto19.randomUUID();
9901
+ const runId2 = crypto18.randomUUID();
10253
9902
  this.db.insert(runs).values({
10254
9903
  id: runId2,
10255
9904
  projectId,
@@ -10324,7 +9973,7 @@ var Scheduler = class {
10324
9973
  this.db.update(schedules).set({ nextRunAt, updatedAt: now }).where(eq17(schedules.id, currentSchedule.id)).run();
10325
9974
  return;
10326
9975
  }
10327
- const runId2 = crypto19.randomUUID();
9976
+ const runId2 = crypto18.randomUUID();
10328
9977
  const effectiveRequest = normalizeSiteAuditRunRequest({});
10329
9978
  this.db.transaction((tx) => {
10330
9979
  tx.insert(runs).values({
@@ -10422,7 +10071,7 @@ async function refreshAllIntegrations(client, projectName) {
10422
10071
 
10423
10072
  // src/notifier.ts
10424
10073
  import { eq as eq18, desc as desc7, and as and15, inArray as inArray7, or as or2 } from "drizzle-orm";
10425
- import crypto20 from "crypto";
10074
+ import crypto19 from "crypto";
10426
10075
  var log15 = createLogger("Notifier");
10427
10076
  var Notifier = class {
10428
10077
  db;
@@ -10748,7 +10397,7 @@ var Notifier = class {
10748
10397
  }
10749
10398
  logDelivery(projectId, notificationId, event, status, error) {
10750
10399
  this.db.insert(auditLog).values({
10751
- id: crypto20.randomUUID(),
10400
+ id: crypto19.randomUUID(),
10752
10401
  projectId,
10753
10402
  actor: "scheduler",
10754
10403
  action: `notification.${status}`,
@@ -10910,12 +10559,12 @@ function analysisResultFromInsights(insights2) {
10910
10559
  }
10911
10560
 
10912
10561
  // src/agent/session-registry.ts
10913
- import crypto24 from "crypto";
10562
+ import crypto23 from "crypto";
10914
10563
  import { eq as eq21 } from "drizzle-orm";
10915
10564
 
10916
10565
  // src/agent/session.ts
10917
- import fs7 from "fs";
10918
- import path8 from "path";
10566
+ import fs6 from "fs";
10567
+ import path7 from "path";
10919
10568
  import { Agent } from "@mariozechner/pi-agent-core";
10920
10569
  import { registerBuiltInApiProviders } from "@mariozechner/pi-ai";
10921
10570
 
@@ -11158,26 +10807,26 @@ function buildAgentProvidersResponse(config) {
11158
10807
  }
11159
10808
 
11160
10809
  // src/agent/skill-paths.ts
11161
- import fs5 from "fs";
11162
- import path6 from "path";
11163
- import { fileURLToPath as fileURLToPath2 } from "url";
10810
+ import fs4 from "fs";
10811
+ import path5 from "path";
10812
+ import { fileURLToPath } from "url";
11164
10813
  function resolveAeroSkillDir(pkgDir) {
11165
- const here = pkgDir ?? path6.dirname(fileURLToPath2(import.meta.url));
10814
+ const here = pkgDir ?? path5.dirname(fileURLToPath(import.meta.url));
11166
10815
  const candidates = [
11167
- path6.join(here, "../assets/agent-workspace/skills/aero"),
11168
- path6.join(here, "../../assets/agent-workspace/skills/aero"),
11169
- path6.join(here, "../../../../skills/aero")
10816
+ path5.join(here, "../assets/agent-workspace/skills/aero"),
10817
+ path5.join(here, "../../assets/agent-workspace/skills/aero"),
10818
+ path5.join(here, "../../../../skills/aero")
11170
10819
  ];
11171
10820
  for (const candidate of candidates) {
11172
- if (fs5.existsSync(path6.join(candidate, "SKILL.md"))) return candidate;
10821
+ if (fs4.existsSync(path5.join(candidate, "SKILL.md"))) return candidate;
11173
10822
  }
11174
10823
  throw new Error(`Aero skill not found. Searched:
11175
10824
  ${candidates.join("\n ")}`);
11176
10825
  }
11177
10826
 
11178
10827
  // src/agent/skill-tools.ts
11179
- import fs6 from "fs";
11180
- import path7 from "path";
10828
+ import fs5 from "fs";
10829
+ import path6 from "path";
11181
10830
  import { Type } from "@sinclair/typebox";
11182
10831
  var MAX_DOC_CHARS = 2e4;
11183
10832
  function textResult(details) {
@@ -11186,7 +10835,7 @@ function textResult(details) {
11186
10835
  details
11187
10836
  };
11188
10837
  }
11189
- function parseDescription2(body) {
10838
+ function parseDescription(body) {
11190
10839
  if (!body.startsWith("---")) return "(no description)";
11191
10840
  const end = body.indexOf("\n---", 3);
11192
10841
  if (end === -1) return "(no description)";
@@ -11198,16 +10847,16 @@ function parseDescription2(body) {
11198
10847
  return "(no description)";
11199
10848
  }
11200
10849
  function scanSkillDocs(skillDir) {
11201
- const refsDir = path7.join(skillDir ?? resolveAeroSkillDir(), "references");
11202
- if (!fs6.existsSync(refsDir)) return [];
10850
+ const refsDir = path6.join(skillDir ?? resolveAeroSkillDir(), "references");
10851
+ if (!fs5.existsSync(refsDir)) return [];
11203
10852
  const entries = [];
11204
- for (const file of fs6.readdirSync(refsDir)) {
10853
+ for (const file of fs5.readdirSync(refsDir)) {
11205
10854
  if (!file.endsWith(".md")) continue;
11206
- const filePath = path7.join(refsDir, file);
11207
- const body = fs6.readFileSync(filePath, "utf-8");
10855
+ const filePath = path6.join(refsDir, file);
10856
+ const body = fs5.readFileSync(filePath, "utf-8");
11208
10857
  entries.push({
11209
10858
  slug: file.replace(/\.md$/, ""),
11210
- description: parseDescription2(body),
10859
+ description: parseDescription(body),
11211
10860
  bytes: Buffer.byteLength(body, "utf-8")
11212
10861
  });
11213
10862
  }
@@ -11247,8 +10896,8 @@ function buildReadSkillDocTool() {
11247
10896
  availableSlugs: docs.map((d) => d.slug)
11248
10897
  });
11249
10898
  }
11250
- const filePath = path7.join(skillDir, "references", `${match.slug}.md`);
11251
- const content = fs6.readFileSync(filePath, "utf-8");
10899
+ const filePath = path6.join(skillDir, "references", `${match.slug}.md`);
10900
+ const content = fs5.readFileSync(filePath, "utf-8");
11252
10901
  if (content.length > MAX_DOC_CHARS) {
11253
10902
  return textResult({
11254
10903
  slug: match.slug,
@@ -11654,7 +11303,7 @@ function buildAeroStateTools(ctx, opts = {}) {
11654
11303
  }
11655
11304
 
11656
11305
  // src/agent/llm-usage.ts
11657
- import crypto21 from "crypto";
11306
+ import crypto20 from "crypto";
11658
11307
  var AeroLlmUsageFeatures = {
11659
11308
  turn: "aero.turn"
11660
11309
  };
@@ -11673,7 +11322,7 @@ function recordLlmUsageEvent(args) {
11673
11322
  const usage = args.message.usage;
11674
11323
  const now = (/* @__PURE__ */ new Date()).toISOString();
11675
11324
  args.db.insert(llmUsageEvents).values({
11676
- id: crypto21.randomUUID(),
11325
+ id: crypto20.randomUUID(),
11677
11326
  projectId: args.projectId,
11678
11327
  runId: args.runId,
11679
11328
  agentSessionId: args.agentSessionId,
@@ -11749,7 +11398,7 @@ function splitAeroAnthropicSystemCachePayload(payload, model) {
11749
11398
  }
11750
11399
 
11751
11400
  // src/agent/tool-usage.ts
11752
- import crypto22 from "crypto";
11401
+ import crypto21 from "crypto";
11753
11402
  var AeroToolEventStatuses = {
11754
11403
  success: "success",
11755
11404
  error: "error"
@@ -11812,7 +11461,7 @@ function createAeroToolUsageHooks(args) {
11812
11461
  function recordAgentToolEvent(args) {
11813
11462
  try {
11814
11463
  args.db.insert(agentToolEvents).values({
11815
- id: crypto22.randomUUID(),
11464
+ id: crypto21.randomUUID(),
11816
11465
  projectId: args.projectId,
11817
11466
  agentSessionId: args.agentSessionId,
11818
11467
  toolCallId: args.toolCallId,
@@ -11843,9 +11492,9 @@ function ensureBuiltinsRegistered() {
11843
11492
  }
11844
11493
  function loadAeroSystemPrompt(pkgDir) {
11845
11494
  const skillDir = resolveAeroSkillDir(pkgDir);
11846
- const skillBody = fs7.readFileSync(path8.join(skillDir, "SKILL.md"), "utf-8");
11847
- const soulPath = path8.join(skillDir, "soul.md");
11848
- const base = fs7.existsSync(soulPath) ? `${fs7.readFileSync(soulPath, "utf-8").trimEnd()}
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()}
11849
11498
 
11850
11499
  ---
11851
11500
 
@@ -11858,7 +11507,7 @@ function appendSystemPromptExtras(base, env = process.env) {
11858
11507
  const filePath = env.AERO_SYSTEM_PROMPT_FILE?.trim();
11859
11508
  if (filePath) {
11860
11509
  try {
11861
- fileBody = fs7.readFileSync(filePath, "utf-8").trim();
11510
+ fileBody = fs6.readFileSync(filePath, "utf-8").trim();
11862
11511
  } catch {
11863
11512
  fileBody = "";
11864
11513
  }
@@ -12039,7 +11688,7 @@ async function loadExternalMcpTools(servers, opts = {}) {
12039
11688
  }
12040
11689
 
12041
11690
  // src/agent/memory-store.ts
12042
- import crypto23 from "crypto";
11691
+ import crypto22 from "crypto";
12043
11692
  import { and as and16, desc as desc8, eq as eq20, like, sql as sql9 } from "drizzle-orm";
12044
11693
  var COMPACTION_KEY_PREFIX = "compaction:";
12045
11694
  var COMPACTION_NOTES_PER_SESSION = 3;
@@ -12068,7 +11717,7 @@ function upsertMemoryEntry(db, args) {
12068
11717
  throw new Error(`memory key prefix "${COMPACTION_KEY_PREFIX}" is reserved for compaction notes`);
12069
11718
  }
12070
11719
  const now = (/* @__PURE__ */ new Date()).toISOString();
12071
- const id = crypto23.randomUUID();
11720
+ const id = crypto22.randomUUID();
12072
11721
  db.insert(agentMemory).values({
12073
11722
  id,
12074
11723
  projectId: args.projectId,
@@ -12105,7 +11754,7 @@ function writeCompactionNote(db, args) {
12105
11754
  }
12106
11755
  const now = (/* @__PURE__ */ new Date()).toISOString();
12107
11756
  const key = `${COMPACTION_KEY_PREFIX}${args.sessionId}:${now}`;
12108
- const id = crypto23.randomUUID();
11757
+ const id = crypto22.randomUUID();
12109
11758
  let inserted;
12110
11759
  db.transaction((tx) => {
12111
11760
  tx.insert(agentMemory).values({
@@ -12384,7 +12033,7 @@ var SessionRegistry = class {
12384
12033
  }
12385
12034
  const { provider, modelId } = resolveSessionProviderAndModel(this.opts.config, preferences);
12386
12035
  const systemPrompt = loadAeroSystemPrompt();
12387
- const sessionId = crypto24.randomUUID();
12036
+ const sessionId = crypto23.randomUUID();
12388
12037
  const agent = createAeroSession({
12389
12038
  projectName,
12390
12039
  client: this.opts.client,
@@ -12763,7 +12412,7 @@ ${lines.join("\n")}
12763
12412
  insertRow(params) {
12764
12413
  const now = (/* @__PURE__ */ new Date()).toISOString();
12765
12414
  this.opts.db.insert(agentSessions).values({
12766
- id: params.id ?? crypto24.randomUUID(),
12415
+ id: params.id ?? crypto23.randomUUID(),
12767
12416
  projectId: params.projectId,
12768
12417
  systemPrompt: params.systemPrompt,
12769
12418
  modelProvider: params.provider ?? params.modelProvider ?? AgentProviderIds.claude,
@@ -13151,13 +12800,13 @@ var USER_AGENT2 = "Canonry/1.0 (site-analysis)";
13151
12800
  function fetchWithPinnedAddress(target) {
13152
12801
  return new Promise((resolve) => {
13153
12802
  const port = target.url.port ? Number(target.url.port) : 443;
13154
- const path10 = target.url.pathname + target.url.search;
12803
+ const path9 = target.url.pathname + target.url.search;
13155
12804
  const req = https2.request(
13156
12805
  {
13157
12806
  hostname: target.address,
13158
12807
  family: target.family,
13159
12808
  port,
13160
- path: path10,
12809
+ path: path9,
13161
12810
  method: "GET",
13162
12811
  timeout: FETCH_TIMEOUT_MS2,
13163
12812
  servername: target.url.hostname,
@@ -13946,14 +13595,14 @@ function summarizeProviderConfig(config) {
13946
13595
  };
13947
13596
  }
13948
13597
  function hashApiKey(key) {
13949
- return crypto25.createHash("sha256").update(key).digest("hex");
13598
+ return crypto24.createHash("sha256").update(key).digest("hex");
13950
13599
  }
13951
13600
  var DASHBOARD_SCRYPT_KEYLEN = 64;
13952
13601
  var DASHBOARD_SCRYPT_COST = 1 << 15;
13953
13602
  var DASHBOARD_SCRYPT_MAXMEM = 64 * 1024 * 1024;
13954
13603
  function hashDashboardPassword(password) {
13955
- const salt = crypto25.randomBytes(16);
13956
- const derived = crypto25.scryptSync(password, salt, DASHBOARD_SCRYPT_KEYLEN, {
13604
+ const salt = crypto24.randomBytes(16);
13605
+ const derived = crypto24.scryptSync(password, salt, DASHBOARD_SCRYPT_KEYLEN, {
13957
13606
  N: DASHBOARD_SCRYPT_COST,
13958
13607
  maxmem: DASHBOARD_SCRYPT_MAXMEM
13959
13608
  });
@@ -13974,14 +13623,14 @@ function verifyDashboardPassword(password, storedHash) {
13974
13623
  } catch {
13975
13624
  return { ok: false, needsRehash: false };
13976
13625
  }
13977
- const derived = crypto25.scryptSync(password, salt, expected.length, {
13626
+ const derived = crypto24.scryptSync(password, salt, expected.length, {
13978
13627
  N: DASHBOARD_SCRYPT_COST,
13979
13628
  maxmem: DASHBOARD_SCRYPT_MAXMEM
13980
13629
  });
13981
13630
  if (derived.length !== expected.length)
13982
13631
  return { ok: false, needsRehash: false };
13983
13632
  return {
13984
- ok: crypto25.timingSafeEqual(derived, expected),
13633
+ ok: crypto24.timingSafeEqual(derived, expected),
13985
13634
  needsRehash: false
13986
13635
  };
13987
13636
  }
@@ -13990,7 +13639,7 @@ function verifyDashboardPassword(password, storedHash) {
13990
13639
  const expected = Buffer.from(storedHash, "hex");
13991
13640
  if (candidate.length !== expected.length)
13992
13641
  return { ok: false, needsRehash: false };
13993
- const ok = crypto25.timingSafeEqual(candidate, expected);
13642
+ const ok = crypto24.timingSafeEqual(candidate, expected);
13994
13643
  return { ok, needsRehash: ok };
13995
13644
  }
13996
13645
  return { ok: false, needsRehash: false };
@@ -14221,8 +13870,8 @@ async function createServer(opts) {
14221
13870
  );
14222
13871
  jobRunner.onRunCompleted = (runId, projectId) => runCoordinator.onRunCompleted(runId, projectId);
14223
13872
  const snapshotService = new SnapshotService(registry);
14224
- const orphanedOpenClawDir = path9.join(os5.homedir(), ".openclaw-aero");
14225
- if (fs8.existsSync(orphanedOpenClawDir)) {
13873
+ const orphanedOpenClawDir = path8.join(os4.homedir(), ".openclaw-aero");
13874
+ if (fs7.existsSync(orphanedOpenClawDir)) {
14226
13875
  app.log.warn(
14227
13876
  { path: orphanedOpenClawDir },
14228
13877
  "OpenClaw gateway is no longer used. Remove ~/.openclaw-aero/ manually to reclaim the directory."
@@ -14759,7 +14408,7 @@ async function createServer(opts) {
14759
14408
  return removed;
14760
14409
  }
14761
14410
  };
14762
- const googleStateSecret = process.env.GOOGLE_STATE_SECRET ?? crypto25.randomBytes(32).toString("hex");
14411
+ const googleStateSecret = process.env.GOOGLE_STATE_SECRET ?? crypto24.randomBytes(32).toString("hex");
14763
14412
  const googleConnectionStore = {
14764
14413
  listConnections: (domain) => listGoogleConnections(opts.config, domain),
14765
14414
  getConnection: (domain, connectionType) => getGoogleConnection(opts.config, domain, connectionType),
@@ -14839,7 +14488,7 @@ async function createServer(opts) {
14839
14488
  if (!existing) {
14840
14489
  const prefix = opts.config.apiKey.slice(0, 12);
14841
14490
  opts.db.insert(apiKeys).values({
14842
- id: `key_${crypto25.randomBytes(8).toString("hex")}`,
14491
+ id: `key_${crypto24.randomBytes(8).toString("hex")}`,
14843
14492
  name: "default",
14844
14493
  keyHash,
14845
14494
  keyPrefix: prefix,
@@ -14863,7 +14512,7 @@ async function createServer(opts) {
14863
14512
  };
14864
14513
  const createSession = (apiKeyId) => {
14865
14514
  pruneExpiredSessions();
14866
- const sessionId = crypto25.randomBytes(32).toString("hex");
14515
+ const sessionId = crypto24.randomBytes(32).toString("hex");
14867
14516
  sessions.set(sessionId, {
14868
14517
  apiKeyId,
14869
14518
  expiresAt: Date.now() + SESSION_TTL_MS
@@ -15111,7 +14760,7 @@ async function createServer(opts) {
15111
14760
  const configPath = getConfigPath();
15112
14761
  return {
15113
14762
  databasePath: opts.config.database,
15114
- configPath: fs8.existsSync(configPath) ? configPath : null
14763
+ configPath: fs7.existsSync(configPath) ? configPath : null
15115
14764
  };
15116
14765
  })(),
15117
14766
  // Snapshot the bundled skill trees (version + file hashes) so the
@@ -15223,7 +14872,7 @@ async function createServer(opts) {
15223
14872
  deps: {
15224
14873
  enqueueAutoExtract: ({ projectId, release: r }) => {
15225
14874
  const now = (/* @__PURE__ */ new Date()).toISOString();
15226
- const runId = crypto25.randomUUID();
14875
+ const runId = crypto24.randomUUID();
15227
14876
  opts.db.insert(runs).values({
15228
14877
  id: runId,
15229
14878
  projectId,
@@ -15458,7 +15107,7 @@ async function createServer(opts) {
15458
15107
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
15459
15108
  opts.db.insert(auditLog).values(
15460
15109
  targetProjectIds.map((projectId) => ({
15461
- id: crypto25.randomUUID(),
15110
+ id: crypto24.randomUUID(),
15462
15111
  projectId,
15463
15112
  actor: "api",
15464
15113
  action: existing ? "provider.updated" : "provider.created",
@@ -15617,10 +15266,10 @@ async function createServer(opts) {
15617
15266
  return snapshotService.createReport(input);
15618
15267
  }
15619
15268
  });
15620
- const dirname = path9.dirname(fileURLToPath3(import.meta.url));
15621
- const assetsDir = opts.assetsDir ?? path9.join(dirname, "..", "assets");
15622
- if (fs8.existsSync(assetsDir)) {
15623
- const indexPath = path9.join(assetsDir, "index.html");
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");
15624
15273
  const injectConfig = (html, projectTabsOverride, themeOverride, renderTokenOverride) => {
15625
15274
  const clientConfig = {};
15626
15275
  if (basePath) clientConfig.basePath = basePath;
@@ -15675,8 +15324,8 @@ async function createServer(opts) {
15675
15324
  // Without this, the browser hits the server for every JS chunk on
15676
15325
  // every page load, defeating most of the dashboard's first-paint
15677
15326
  // budget.
15678
- setHeaders: (res, path10) => {
15679
- if (path10.endsWith(".html")) {
15327
+ setHeaders: (res, path9) => {
15328
+ if (path9.endsWith(".html")) {
15680
15329
  res.setHeader("Cache-Control", "no-cache, must-revalidate");
15681
15330
  } else {
15682
15331
  res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
@@ -15684,8 +15333,8 @@ async function createServer(opts) {
15684
15333
  }
15685
15334
  });
15686
15335
  const serveIndex = (_request, reply) => {
15687
- if (fs8.existsSync(indexPath)) {
15688
- const html = fs8.readFileSync(indexPath, "utf-8");
15336
+ if (fs7.existsSync(indexPath)) {
15337
+ const html = fs7.readFileSync(indexPath, "utf-8");
15689
15338
  return sendSpaDocument(reply, html);
15690
15339
  }
15691
15340
  return reply.status(404).send({ error: "Dashboard not built" });
@@ -15706,8 +15355,8 @@ async function createServer(opts) {
15706
15355
  if (basePath && !url.startsWith(basePath)) {
15707
15356
  return reply.status(404).send({ error: "Not found", path: request.url });
15708
15357
  }
15709
- if (fs8.existsSync(indexPath)) {
15710
- const html = fs8.readFileSync(indexPath, "utf-8");
15358
+ if (fs7.existsSync(indexPath)) {
15359
+ const html = fs7.readFileSync(indexPath, "utf-8");
15711
15360
  return sendSpaDocument(reply, html);
15712
15361
  }
15713
15362
  return reply.status(404).send({ error: "Not found" });
@@ -15814,11 +15463,6 @@ export {
15814
15463
  backfillTrafficClassificationCommand,
15815
15464
  getCloudflareTrafficConnectionBySourceId,
15816
15465
  setGoogleAuthConfig,
15817
- installSkills,
15818
- listSkills,
15819
- emitInstallSummary,
15820
- getMissingUserSkillsNudge,
15821
- parseSkillsClient,
15822
15466
  formatAuditFactorScore,
15823
15467
  checkLatestVersionForCli,
15824
15468
  listAgentProviders,