@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
package/assets/assets/{react-sigma_core.esm.min-DLRh4X_G.js → react-sigma_core.esm.min-BOZ1RPZp.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as Bt,t as S,r as C}from"./vendor-tanstack-Dock0eH1.js";import{e as Ht,G as Wt}from"./SiteHealthSection-
|
|
1
|
+
import{g as Bt,t as S,r as C}from"./vendor-tanstack-Dock0eH1.js";import{e as Ht,G as Wt}from"./SiteHealthSection-rCrAk98W.js";import"./index-Nk2MzD2d.js";import"./vendor-radix-4UOaVWza.js";import"./vendor-recharts-D8rt5lKn.js";import"./vendor-lucide-nYKv-BB7.js";import"./vendor-markdown-Bn7fRwrx.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-BoYe2M-i.js";function Vt(r,n){if(typeof r!="object"||!r)return r;var i=r[Symbol.toPrimitive];if(i!==void 0){var e=i.call(r,n);if(typeof e!="object")return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}function ae(r){var n=Vt(r,"string");return typeof n=="symbol"?n:n+""}function A(r,n){if(!(r instanceof n))throw new TypeError("Cannot call a class as a function")}function He(r,n){for(var i=0;i<n.length;i++){var e=n[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(r,ae(e.key),e)}}function L(r,n,i){return n&&He(r.prototype,n),i&&He(r,i),Object.defineProperty(r,"prototype",{writable:!1}),r}function Q(r){return Q=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(n){return n.__proto__||Object.getPrototypeOf(n)},Q(r)}function yt(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(yt=function(){return!!r})()}function jt(r){if(r===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}function Zt(r,n){if(n&&(typeof n=="object"||typeof n=="function"))return n;if(n!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return jt(r)}function I(r,n,i){return n=Q(n),Zt(r,yt()?Reflect.construct(n,i||[],Q(r).constructor):n.apply(r,i))}function xe(r,n){return xe=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,e){return i.__proto__=e,i},xe(r,n)}function G(r,n){if(typeof n!="function"&&n!==null)throw new TypeError("Super expression must either be null or a function");r.prototype=Object.create(n&&n.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),Object.defineProperty(r,"prototype",{writable:!1}),n&&xe(r,n)}function qt(r){if(Array.isArray(r))return r}function Yt(r,n){var i=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(i!=null){var e,t,a,o,s=[],l=!0,h=!1;try{if(a=(i=i.call(r)).next,n===0){if(Object(i)!==i)return;l=!1}else for(;!(l=(e=a.call(i)).done)&&(s.push(e.value),s.length!==n);l=!0);}catch(u){h=!0,t=u}finally{try{if(!l&&i.return!=null&&(o=i.return(),Object(o)!==o))return}finally{if(h)throw t}}return s}}function Se(r,n){(n==null||n>r.length)&&(n=r.length);for(var i=0,e=Array(n);i<n;i++)e[i]=r[i];return e}function Tt(r,n){if(r){if(typeof r=="string")return Se(r,n);var i={}.toString.call(r).slice(8,-1);return i==="Object"&&r.constructor&&(i=r.constructor.name),i==="Map"||i==="Set"?Array.from(r):i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Se(r,n):void 0}}function Xt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
2
2
|
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ee(r,n){return qt(r)||Yt(r,n)||Tt(r,n)||Xt()}var pe={black:"#000000",silver:"#C0C0C0",gray:"#808080",grey:"#808080",white:"#FFFFFF",maroon:"#800000",red:"#FF0000",purple:"#800080",fuchsia:"#FF00FF",green:"#008000",lime:"#00FF00",olive:"#808000",yellow:"#FFFF00",navy:"#000080",blue:"#0000FF",teal:"#008080",aqua:"#00FFFF",darkblue:"#00008B",mediumblue:"#0000CD",darkgreen:"#006400",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",springgreen:"#00FF7F",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",rebeccapurple:"#663399",mediumaquamarine:"#66CDAA",dimgray:"#696969",dimgrey:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",slategrey:"#708090",lightslategray:"#778899",lightslategrey:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370DB",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",darkgrey:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgray:"#D3D3D3",lightgrey:"#D3D3D3",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",palevioletred:"#DB7093",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",lightyellow:"#FFFFE0",ivory:"#FFFFF0"},Ct=new Int8Array(4),be=new Int32Array(Ct.buffer,0,1),$t=new Float32Array(Ct.buffer,0,1),Kt=/^\s*rgba?\s*\(/,Jt=/^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/;function Qt(r){var n=0,i=0,e=0,t=1;if(r[0]==="#")r.length===4?(n=parseInt(r.charAt(1)+r.charAt(1),16),i=parseInt(r.charAt(2)+r.charAt(2),16),e=parseInt(r.charAt(3)+r.charAt(3),16)):(n=parseInt(r.charAt(1)+r.charAt(2),16),i=parseInt(r.charAt(3)+r.charAt(4),16),e=parseInt(r.charAt(5)+r.charAt(6),16)),r.length===9&&(t=parseInt(r.charAt(7)+r.charAt(8),16)/255);else if(Kt.test(r)){var a=r.match(Jt);a&&(n=+a[1],i=+a[2],e=+a[3],a[4]&&(t=+a[4]))}return{r:n,g:i,b:e,a:t}}var J={};for(var le in pe)J[le]=oe(pe[le]),J[pe[le]]=J[le];function Rt(r,n,i,e,t){return be[0]=e<<24|i<<16|n<<8|r,be[0]=be[0]&4278190079,$t[0]}function oe(r){if(r=r.toLowerCase(),typeof J[r]<"u")return J[r];var n=Qt(r),i=n.r,e=n.g,t=n.b,a=n.a;a=a*255|0;var o=Rt(i,e,t,a);return J[r]=o,o}var Ee={};function _t(r){if(typeof Ee[r]<"u")return Ee[r];var n=(r&16711680)>>>16,i=(r&65280)>>>8,e=r&255,t=255,a=Rt(n,i,e,t);return Ee[r]=a,a}function We(r,n,i,e){return i+(n<<8)+(r<<16)}function Ve(r,n,i,e,t,a){var o=Math.floor(i/a*t),s=Math.floor(r.drawingBufferHeight/a-e/a*t),l=new Uint8Array(4);r.bindFramebuffer(r.FRAMEBUFFER,n),r.readPixels(o,s,1,1,r.RGBA,r.UNSIGNED_BYTE,l);var h=ee(l,4),u=h[0],d=h[1],f=h[2],g=h[3];return[u,d,f,g]}function c(r,n,i){return(n=ae(n))in r?Object.defineProperty(r,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):r[n]=i,r}function je(r,n){var i=Object.keys(r);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(r);n&&(e=e.filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})),i.push.apply(i,e)}return i}function b(r){for(var n=1;n<arguments.length;n++){var i=arguments[n]!=null?arguments[n]:{};n%2?je(Object(i),!0).forEach(function(e){c(r,e,i[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):je(Object(i)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))})}return r}function ei(r,n){for(;!{}.hasOwnProperty.call(r,n)&&(r=Q(r))!==null;);return r}function Ae(){return Ae=typeof Reflect<"u"&&Reflect.get?Reflect.get.bind():function(r,n,i){var e=ei(r,n);if(e){var t=Object.getOwnPropertyDescriptor(e,n);return t.get?t.get.call(arguments.length<3?r:i):t.value}},Ae.apply(null,arguments)}function wt(r,n,i,e){var t=Ae(Q(r.prototype),n,i);return typeof t=="function"?function(a){return t.apply(i,a)}:t}function ti(r){return r.normalized?1:r.size}function ye(r){var n=0;return r.forEach(function(i){return n+=ti(i)}),n}function xt(r,n,i){var e=r==="VERTEX"?n.VERTEX_SHADER:n.FRAGMENT_SHADER,t=n.createShader(e);if(t===null)throw new Error("loadShader: error while creating the shader");n.shaderSource(t,i),n.compileShader(t);var a=n.getShaderParameter(t,n.COMPILE_STATUS);if(!a){var o=n.getShaderInfoLog(t);throw n.deleteShader(t),new Error(`loadShader: error while compiling the shader:
|
|
3
3
|
`.concat(o,`
|
|
4
4
|
`).concat(i))}return t}function ii(r,n){return xt("VERTEX",r,n)}function ri(r,n){return xt("FRAGMENT",r,n)}function ni(r,n){var i=r.createProgram();if(i===null)throw new Error("loadProgram: error while creating the program.");var e,t;for(e=0,t=n.length;e<t;e++)r.attachShader(i,n[e]);r.linkProgram(i);var a=r.getProgramParameter(i,r.LINK_STATUS);if(!a){var o=r.getProgramInfoLog(i);throw r.deleteProgram(i),new Error("loadProgram: error while linking the program: ".concat(o))}return i}function Ze(r){var n=r.gl,i=r.buffer,e=r.program,t=r.vertexShader,a=r.fragmentShader;n.deleteShader(t),n.deleteShader(a),n.deleteProgram(e),n.deleteBuffer(i)}var qe=`#define PICKING_MODE
|
package/assets/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-Nk2MzD2d.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dock0eH1.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-4UOaVWza.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-D8rt5lKn.js">
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BUNDLED_SKILL_NAMES,
|
|
3
|
+
PACKAGE_VERSION,
|
|
4
|
+
configExists,
|
|
5
|
+
installSkills,
|
|
6
|
+
loadConfigRaw,
|
|
7
|
+
saveConfigPatch
|
|
8
|
+
} from "./chunk-HVBAGSQC.js";
|
|
9
|
+
import {
|
|
10
|
+
SKILL_MANIFEST_FILENAME,
|
|
11
|
+
SkillsClients
|
|
12
|
+
} from "./chunk-K7XXDKYY.js";
|
|
13
|
+
|
|
14
|
+
// src/skills-autosync.ts
|
|
15
|
+
import fs from "fs";
|
|
16
|
+
import os from "os";
|
|
17
|
+
import path from "path";
|
|
18
|
+
var DEFAULT_SYNC_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
19
|
+
function peekVersionChange() {
|
|
20
|
+
if (!configExists()) return { state: "unknown" };
|
|
21
|
+
const raw = loadConfigRaw();
|
|
22
|
+
if (raw === null) return { state: "unknown" };
|
|
23
|
+
const lastSeen = raw.lastSkillsSyncedVersion;
|
|
24
|
+
if (lastSeen === PACKAGE_VERSION) return { state: "unchanged" };
|
|
25
|
+
return { state: "changed", lastSeen };
|
|
26
|
+
}
|
|
27
|
+
function syncIntervalSeconds(env = process.env) {
|
|
28
|
+
const raw = env.CANONRY_SKILLS_SYNC_SECS;
|
|
29
|
+
if (!raw) return DEFAULT_SYNC_INTERVAL_SECONDS;
|
|
30
|
+
const parsed = Number(raw);
|
|
31
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_SYNC_INTERVAL_SECONDS;
|
|
32
|
+
}
|
|
33
|
+
function isDisabled(env = process.env) {
|
|
34
|
+
const raw = env.CANONRY_NO_AUTO_SKILLS_SYNC;
|
|
35
|
+
return raw === "1" || raw === "true";
|
|
36
|
+
}
|
|
37
|
+
function ownedInstallTargets(cwd = process.cwd(), home = os.homedir()) {
|
|
38
|
+
const seen = /* @__PURE__ */ new Set();
|
|
39
|
+
const candidates = [
|
|
40
|
+
{ dir: path.resolve(home), user: true },
|
|
41
|
+
{ dir: path.resolve(cwd), user: false }
|
|
42
|
+
];
|
|
43
|
+
const targets = [];
|
|
44
|
+
for (const { dir, user } of candidates) {
|
|
45
|
+
if (seen.has(dir)) continue;
|
|
46
|
+
seen.add(dir);
|
|
47
|
+
const skills = BUNDLED_SKILL_NAMES.filter(
|
|
48
|
+
(name) => fs.existsSync(path.join(dir, ".claude", "skills", name, SKILL_MANIFEST_FILENAME))
|
|
49
|
+
);
|
|
50
|
+
if (skills.length === 0) continue;
|
|
51
|
+
const hasCodex = skills.some((name) => {
|
|
52
|
+
try {
|
|
53
|
+
return fs.lstatSync(path.join(dir, ".codex", "skills", name)).isSymbolicLink();
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
targets.push({ dir, user, skills, client: hasCodex ? SkillsClients.all : SkillsClients.claude });
|
|
59
|
+
}
|
|
60
|
+
return targets;
|
|
61
|
+
}
|
|
62
|
+
async function autoSyncSkills(env = process.env) {
|
|
63
|
+
const skipped = { ran: false, reason: "skipped", updated: [], conflicts: [], targets: [] };
|
|
64
|
+
if (isDisabled(env)) return skipped;
|
|
65
|
+
const probe = peekVersionChange();
|
|
66
|
+
if (probe.state === "unknown") return skipped;
|
|
67
|
+
let reason;
|
|
68
|
+
if (probe.state === "changed") {
|
|
69
|
+
reason = "version-changed";
|
|
70
|
+
} else {
|
|
71
|
+
const intervalSeconds = syncIntervalSeconds(env);
|
|
72
|
+
if (intervalSeconds === 0) return skipped;
|
|
73
|
+
const raw = loadConfigRaw();
|
|
74
|
+
if (raw === null) return skipped;
|
|
75
|
+
const last = raw.lastSkillsVerifiedAt ? Date.parse(raw.lastSkillsVerifiedAt) : 0;
|
|
76
|
+
const elapsed = (Date.now() - (Number.isFinite(last) ? last : 0)) / 1e3;
|
|
77
|
+
if (elapsed < intervalSeconds) return skipped;
|
|
78
|
+
reason = "interval-elapsed";
|
|
79
|
+
}
|
|
80
|
+
const targets = ownedInstallTargets();
|
|
81
|
+
if (targets.length === 0) {
|
|
82
|
+
return skipped;
|
|
83
|
+
}
|
|
84
|
+
const updated = [];
|
|
85
|
+
const conflicts = [];
|
|
86
|
+
for (const target of targets) {
|
|
87
|
+
for (const skill of target.skills) {
|
|
88
|
+
try {
|
|
89
|
+
const summary = await installSkills({
|
|
90
|
+
...target.user ? { user: true } : { dir: target.dir },
|
|
91
|
+
skills: [skill],
|
|
92
|
+
client: target.client
|
|
93
|
+
});
|
|
94
|
+
for (const result of summary.results) {
|
|
95
|
+
for (const p of result.updated ?? []) updated.push(p);
|
|
96
|
+
for (const p of result.conflicts ?? []) conflicts.push(p);
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
recordVerified();
|
|
103
|
+
return { ran: true, reason, updated, conflicts, targets: targets.map((t) => t.dir) };
|
|
104
|
+
}
|
|
105
|
+
function recordVerified() {
|
|
106
|
+
try {
|
|
107
|
+
saveConfigPatch({
|
|
108
|
+
lastSkillsSyncedVersion: PACKAGE_VERSION,
|
|
109
|
+
lastSkillsVerifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
110
|
+
});
|
|
111
|
+
} catch {
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function formatAutoSyncNotice(result) {
|
|
115
|
+
if (!result.ran || result.conflicts.length === 0) return null;
|
|
116
|
+
const count = result.conflicts.length;
|
|
117
|
+
return `canonry: ${count} locally edited skill file${count === 1 ? "" : "s"} kept as-is (engine is now v${PACKAGE_VERSION}). Run "canonry skills install --force" to take the new version.`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
autoSyncSkills,
|
|
122
|
+
formatAutoSyncNotice
|
|
123
|
+
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_MEMORY_KEY_MAX_LENGTH,
|
|
3
3
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
4
|
+
CodingAgents,
|
|
4
5
|
DISCOVERY_MAX_PROBES_CAP,
|
|
5
6
|
DISCOVERY_PROBE_CONCURRENCY_CAP,
|
|
7
|
+
SKILL_MANIFEST_FILENAME,
|
|
8
|
+
SkillsClients,
|
|
6
9
|
adsActivateTreeRequestSchema,
|
|
7
10
|
adsAdCreateRequestSchema,
|
|
8
11
|
adsAdGroupCreateRequestSchema,
|
|
@@ -16,6 +19,8 @@ import {
|
|
|
16
19
|
adsPauseRequestSchema,
|
|
17
20
|
adsUnresolvedOperationListQuerySchema,
|
|
18
21
|
backlinkSourceSchema,
|
|
22
|
+
classifySkillFile,
|
|
23
|
+
coerceSkillManifest,
|
|
19
24
|
competitorBatchRequestSchema,
|
|
20
25
|
describeError,
|
|
21
26
|
discoveryBucketSchema,
|
|
@@ -77,12 +82,13 @@ import {
|
|
|
77
82
|
runTriggerRequestSchema,
|
|
78
83
|
schedulableRunKindSchema,
|
|
79
84
|
scheduleUpsertRequestSchema,
|
|
85
|
+
skillsClientSchema,
|
|
80
86
|
trafficConnectCloudRunRequestSchema,
|
|
81
87
|
trafficConnectVercelRequestSchema,
|
|
82
88
|
trafficConnectWordpressRequestSchema,
|
|
83
89
|
trafficEventKindSchema,
|
|
84
90
|
trafficSeriesGranularitySchema
|
|
85
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-K7XXDKYY.js";
|
|
86
92
|
|
|
87
93
|
// src/config.ts
|
|
88
94
|
import fs from "fs";
|
|
@@ -626,7 +632,7 @@ var serializeObjectParam = ({
|
|
|
626
632
|
|
|
627
633
|
// ../api-client-generated/src/generated/core/utils.gen.ts
|
|
628
634
|
var PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
629
|
-
var defaultPathSerializer = ({ path:
|
|
635
|
+
var defaultPathSerializer = ({ path: path3, url: _url }) => {
|
|
630
636
|
let url = _url;
|
|
631
637
|
const matches = _url.match(PATH_PARAM_RE);
|
|
632
638
|
if (matches) {
|
|
@@ -645,7 +651,7 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
|
|
|
645
651
|
name = name.substring(1);
|
|
646
652
|
style = "matrix";
|
|
647
653
|
}
|
|
648
|
-
const value =
|
|
654
|
+
const value = path3[name];
|
|
649
655
|
if (value === void 0 || value === null) {
|
|
650
656
|
continue;
|
|
651
657
|
}
|
|
@@ -689,15 +695,15 @@ var defaultPathSerializer = ({ path: path2, url: _url }) => {
|
|
|
689
695
|
};
|
|
690
696
|
var getUrl = ({
|
|
691
697
|
baseUrl,
|
|
692
|
-
path:
|
|
698
|
+
path: path3,
|
|
693
699
|
query,
|
|
694
700
|
querySerializer,
|
|
695
701
|
url: _url
|
|
696
702
|
}) => {
|
|
697
703
|
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
698
704
|
let url = (baseUrl ?? "") + pathUrl;
|
|
699
|
-
if (
|
|
700
|
-
url = defaultPathSerializer({ path:
|
|
705
|
+
if (path3) {
|
|
706
|
+
url = defaultPathSerializer({ path: path3, url });
|
|
701
707
|
}
|
|
702
708
|
let search = query ? querySerializer(query) : "";
|
|
703
709
|
if (search.startsWith("?")) {
|
|
@@ -5376,9 +5382,9 @@ var ApiClient = class {
|
|
|
5376
5382
|
* structured-error behavior of `request()`; the caller reads `res.body`
|
|
5377
5383
|
* and releases the response when done.
|
|
5378
5384
|
*/
|
|
5379
|
-
async streamPost(
|
|
5385
|
+
async streamPost(path3, body, signal) {
|
|
5380
5386
|
await this.probeBasePath();
|
|
5381
|
-
const url = `${this.originUrl}/api/v1${
|
|
5387
|
+
const url = `${this.originUrl}/api/v1${path3}`;
|
|
5382
5388
|
const headers = {
|
|
5383
5389
|
Authorization: `Bearer ${this.apiKey}`,
|
|
5384
5390
|
"Content-Type": "application/json",
|
|
@@ -7809,6 +7815,384 @@ import { createRequire } from "module";
|
|
|
7809
7815
|
var _require = createRequire(import.meta.url);
|
|
7810
7816
|
var PACKAGE_VERSION = _require("../package.json").version;
|
|
7811
7817
|
|
|
7818
|
+
// src/commands/skills.ts
|
|
7819
|
+
import crypto from "crypto";
|
|
7820
|
+
import fs2 from "fs";
|
|
7821
|
+
import os2 from "os";
|
|
7822
|
+
import path2 from "path";
|
|
7823
|
+
import { fileURLToPath } from "url";
|
|
7824
|
+
var BUNDLED_SKILL_NAMES = ["canonry", "aero"];
|
|
7825
|
+
function resolveBundledSkillsRoot(pkgDir) {
|
|
7826
|
+
const here = pkgDir ?? path2.dirname(fileURLToPath(import.meta.url));
|
|
7827
|
+
const candidates = [
|
|
7828
|
+
path2.join(here, "../assets/agent-workspace/skills"),
|
|
7829
|
+
path2.join(here, "../../assets/agent-workspace/skills"),
|
|
7830
|
+
path2.join(here, "../../../../skills")
|
|
7831
|
+
];
|
|
7832
|
+
for (const candidate of candidates) {
|
|
7833
|
+
if (BUNDLED_SKILL_NAMES.every((name) => fs2.existsSync(path2.join(candidate, name, "SKILL.md")))) {
|
|
7834
|
+
return candidate;
|
|
7835
|
+
}
|
|
7836
|
+
}
|
|
7837
|
+
throw new CliError({
|
|
7838
|
+
code: "INTERNAL_ERROR",
|
|
7839
|
+
message: `Bundled skills not found. Searched:
|
|
7840
|
+
${candidates.join("\n ")}`,
|
|
7841
|
+
exitCode: 2
|
|
7842
|
+
});
|
|
7843
|
+
}
|
|
7844
|
+
function parseDescription(content) {
|
|
7845
|
+
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(content);
|
|
7846
|
+
if (!fmMatch) return "";
|
|
7847
|
+
const descMatch = /^description:\s*(\S.*)$/m.exec(fmMatch[1]);
|
|
7848
|
+
if (!descMatch) return "";
|
|
7849
|
+
return descMatch[1].replace(/^["']|["']$/g, "").trim();
|
|
7850
|
+
}
|
|
7851
|
+
function getBundledSkills(pkgDir) {
|
|
7852
|
+
const root = resolveBundledSkillsRoot(pkgDir);
|
|
7853
|
+
return BUNDLED_SKILL_NAMES.map((name) => {
|
|
7854
|
+
const skillDir = path2.join(root, name);
|
|
7855
|
+
const skillFile = path2.join(skillDir, "SKILL.md");
|
|
7856
|
+
const content = fs2.readFileSync(skillFile, "utf-8");
|
|
7857
|
+
return { name, description: parseDescription(content), bundledPath: skillDir };
|
|
7858
|
+
});
|
|
7859
|
+
}
|
|
7860
|
+
function walkRelative(dir, prefix = "") {
|
|
7861
|
+
const out = [];
|
|
7862
|
+
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
7863
|
+
const rel = prefix ? path2.join(prefix, entry.name) : entry.name;
|
|
7864
|
+
const full = path2.join(dir, entry.name);
|
|
7865
|
+
if (entry.isDirectory()) {
|
|
7866
|
+
out.push(...walkRelative(full, rel));
|
|
7867
|
+
} else if (entry.isFile()) {
|
|
7868
|
+
out.push(rel);
|
|
7869
|
+
}
|
|
7870
|
+
}
|
|
7871
|
+
return out.sort();
|
|
7872
|
+
}
|
|
7873
|
+
function sha256File(filePath) {
|
|
7874
|
+
return crypto.createHash("sha256").update(fs2.readFileSync(filePath)).digest("hex");
|
|
7875
|
+
}
|
|
7876
|
+
function readSkillManifest(skillDir) {
|
|
7877
|
+
try {
|
|
7878
|
+
return coerceSkillManifest(JSON.parse(fs2.readFileSync(path2.join(skillDir, SKILL_MANIFEST_FILENAME), "utf-8")));
|
|
7879
|
+
} catch {
|
|
7880
|
+
return null;
|
|
7881
|
+
}
|
|
7882
|
+
}
|
|
7883
|
+
function writeSkillManifest(skillDir, manifest) {
|
|
7884
|
+
fs2.writeFileSync(path2.join(skillDir, SKILL_MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}
|
|
7885
|
+
`, "utf-8");
|
|
7886
|
+
}
|
|
7887
|
+
function reconcileSkillTree(srcDir, destDir, manifest, force) {
|
|
7888
|
+
const result = { added: [], updated: [], unchanged: [], conflicts: [], bundledHashes: /* @__PURE__ */ new Map() };
|
|
7889
|
+
for (const rel of walkRelative(srcDir)) {
|
|
7890
|
+
const srcPath = path2.join(srcDir, rel);
|
|
7891
|
+
const destPath = path2.join(destDir, rel);
|
|
7892
|
+
const bundledHash = sha256File(srcPath);
|
|
7893
|
+
result.bundledHashes.set(rel, bundledHash);
|
|
7894
|
+
const installedHash = fs2.existsSync(destPath) ? sha256File(destPath) : void 0;
|
|
7895
|
+
const state = classifySkillFile({ bundledHash, installedHash, manifestHash: manifest?.files[rel] });
|
|
7896
|
+
switch (state) {
|
|
7897
|
+
case "missing":
|
|
7898
|
+
fs2.mkdirSync(path2.dirname(destPath), { recursive: true });
|
|
7899
|
+
fs2.copyFileSync(srcPath, destPath);
|
|
7900
|
+
result.added.push(rel);
|
|
7901
|
+
break;
|
|
7902
|
+
case "unchanged":
|
|
7903
|
+
result.unchanged.push(rel);
|
|
7904
|
+
break;
|
|
7905
|
+
case "stale":
|
|
7906
|
+
fs2.copyFileSync(srcPath, destPath);
|
|
7907
|
+
result.updated.push(rel);
|
|
7908
|
+
break;
|
|
7909
|
+
case "edited":
|
|
7910
|
+
if (force) {
|
|
7911
|
+
fs2.copyFileSync(srcPath, destPath);
|
|
7912
|
+
result.updated.push(rel);
|
|
7913
|
+
} else {
|
|
7914
|
+
result.conflicts.push(rel);
|
|
7915
|
+
}
|
|
7916
|
+
break;
|
|
7917
|
+
}
|
|
7918
|
+
}
|
|
7919
|
+
return result;
|
|
7920
|
+
}
|
|
7921
|
+
function buildManifest(skillName, recon, prior) {
|
|
7922
|
+
const conflicts = new Set(recon.conflicts);
|
|
7923
|
+
const files = {};
|
|
7924
|
+
for (const [rel, bundledHash] of recon.bundledHashes) {
|
|
7925
|
+
files[rel] = conflicts.has(rel) ? prior?.files[rel] ?? bundledHash : bundledHash;
|
|
7926
|
+
}
|
|
7927
|
+
return { skill: skillName, version: PACKAGE_VERSION, files };
|
|
7928
|
+
}
|
|
7929
|
+
function describeChanges(recon) {
|
|
7930
|
+
const parts = [];
|
|
7931
|
+
if (recon.added.length > 0) parts.push(`${recon.added.length} added`);
|
|
7932
|
+
if (recon.updated.length > 0) parts.push(`${recon.updated.length} refreshed`);
|
|
7933
|
+
return parts.length > 0 ? parts.join(", ") : "no changes";
|
|
7934
|
+
}
|
|
7935
|
+
function buildClaudeMessage(name, status, recon) {
|
|
7936
|
+
const rel = `.claude/skills/${name}`;
|
|
7937
|
+
let message = status === "installed" ? `Installed ${rel}` : status === "updated" ? `Updated ${rel} (${describeChanges(recon)})` : `Already installed: ${rel}`;
|
|
7938
|
+
if (recon.conflicts.length > 0) {
|
|
7939
|
+
message += ` \u2014 ${recon.conflicts.length} file(s) differ from the bundle (local edits kept; pass --force to overwrite)`;
|
|
7940
|
+
}
|
|
7941
|
+
return message;
|
|
7942
|
+
}
|
|
7943
|
+
function installClaudeSkill(skill, targetDir, force) {
|
|
7944
|
+
const targetPath = path2.join(targetDir, ".claude", "skills", skill.name);
|
|
7945
|
+
const existedBefore = fs2.existsSync(path2.join(targetPath, "SKILL.md"));
|
|
7946
|
+
const priorManifest = readSkillManifest(targetPath);
|
|
7947
|
+
fs2.mkdirSync(targetPath, { recursive: true });
|
|
7948
|
+
const recon = reconcileSkillTree(skill.bundledPath, targetPath, priorManifest, force);
|
|
7949
|
+
writeSkillManifest(targetPath, buildManifest(skill.name, recon, priorManifest));
|
|
7950
|
+
const changed = recon.added.length + recon.updated.length;
|
|
7951
|
+
const status = !existedBefore ? "installed" : changed > 0 ? "updated" : "already-installed";
|
|
7952
|
+
return {
|
|
7953
|
+
skill: skill.name,
|
|
7954
|
+
client: CodingAgents.claude,
|
|
7955
|
+
targetPath,
|
|
7956
|
+
status,
|
|
7957
|
+
message: buildClaudeMessage(skill.name, status, recon),
|
|
7958
|
+
added: recon.added,
|
|
7959
|
+
updated: recon.updated,
|
|
7960
|
+
unchanged: recon.unchanged,
|
|
7961
|
+
conflicts: recon.conflicts
|
|
7962
|
+
};
|
|
7963
|
+
}
|
|
7964
|
+
function installCodexSymlink(skill, targetDir, force) {
|
|
7965
|
+
const codexPath = path2.join(targetDir, ".codex", "skills", skill.name);
|
|
7966
|
+
const claudePath = path2.join(targetDir, ".claude", "skills", skill.name);
|
|
7967
|
+
const linkTarget = path2.relative(path2.dirname(codexPath), claudePath);
|
|
7968
|
+
fs2.mkdirSync(path2.dirname(codexPath), { recursive: true });
|
|
7969
|
+
let stat;
|
|
7970
|
+
try {
|
|
7971
|
+
stat = fs2.lstatSync(codexPath);
|
|
7972
|
+
} catch {
|
|
7973
|
+
stat = void 0;
|
|
7974
|
+
}
|
|
7975
|
+
if (stat?.isSymbolicLink()) {
|
|
7976
|
+
const existing = fs2.readlinkSync(codexPath);
|
|
7977
|
+
if (existing === linkTarget) {
|
|
7978
|
+
return {
|
|
7979
|
+
skill: skill.name,
|
|
7980
|
+
client: CodingAgents.codex,
|
|
7981
|
+
targetPath: codexPath,
|
|
7982
|
+
status: "already-linked",
|
|
7983
|
+
message: `Already linked: .codex/skills/${skill.name}`
|
|
7984
|
+
};
|
|
7985
|
+
}
|
|
7986
|
+
if (!force) {
|
|
7987
|
+
throw new CliError({
|
|
7988
|
+
code: "VALIDATION_ERROR",
|
|
7989
|
+
message: `.codex/skills/${skill.name} is a symlink pointing elsewhere (${existing}). Pass --force to relink.`,
|
|
7990
|
+
details: { skill: skill.name, targetPath: codexPath, existingTarget: existing },
|
|
7991
|
+
exitCode: 1
|
|
7992
|
+
});
|
|
7993
|
+
}
|
|
7994
|
+
fs2.unlinkSync(codexPath);
|
|
7995
|
+
fs2.symlinkSync(linkTarget, codexPath);
|
|
7996
|
+
return {
|
|
7997
|
+
skill: skill.name,
|
|
7998
|
+
client: CodingAgents.codex,
|
|
7999
|
+
targetPath: codexPath,
|
|
8000
|
+
status: "relinked",
|
|
8001
|
+
message: `Relinked .codex/skills/${skill.name} \u2192 ${linkTarget}`
|
|
8002
|
+
};
|
|
8003
|
+
}
|
|
8004
|
+
if (stat) {
|
|
8005
|
+
if (!force) {
|
|
8006
|
+
throw new CliError({
|
|
8007
|
+
code: "VALIDATION_ERROR",
|
|
8008
|
+
message: `.codex/skills/${skill.name} exists but is not a symlink. Pass --force to replace.`,
|
|
8009
|
+
details: { skill: skill.name, targetPath: codexPath },
|
|
8010
|
+
exitCode: 1
|
|
8011
|
+
});
|
|
8012
|
+
}
|
|
8013
|
+
fs2.rmSync(codexPath, { recursive: true, force: true });
|
|
8014
|
+
}
|
|
8015
|
+
fs2.symlinkSync(linkTarget, codexPath);
|
|
8016
|
+
return {
|
|
8017
|
+
skill: skill.name,
|
|
8018
|
+
client: CodingAgents.codex,
|
|
8019
|
+
targetPath: codexPath,
|
|
8020
|
+
status: stat ? "relinked" : "linked",
|
|
8021
|
+
message: stat ? `Replaced and linked .codex/skills/${skill.name} \u2192 ${linkTarget}` : `Linked .codex/skills/${skill.name} \u2192 ${linkTarget}`
|
|
8022
|
+
};
|
|
8023
|
+
}
|
|
8024
|
+
function buildSummaryMessage(results) {
|
|
8025
|
+
const counts = {};
|
|
8026
|
+
for (const r of results) counts[r.status] = (counts[r.status] ?? 0) + 1;
|
|
8027
|
+
const parts = Object.entries(counts).map(([status, n]) => `${n} ${status}`);
|
|
8028
|
+
let message = `Skills install summary: ${parts.join(", ")}.`;
|
|
8029
|
+
const totalConflicts = results.reduce((sum, r) => sum + (r.conflicts?.length ?? 0), 0);
|
|
8030
|
+
if (totalConflicts > 0) {
|
|
8031
|
+
message += ` ${totalConflicts} file(s) differ from the bundle and were kept \u2014 pass --force to overwrite local edits.`;
|
|
8032
|
+
}
|
|
8033
|
+
return message;
|
|
8034
|
+
}
|
|
8035
|
+
function getBundledSkillSnapshots(pkgDir) {
|
|
8036
|
+
return getBundledSkills(pkgDir).map((skill) => {
|
|
8037
|
+
const files = {};
|
|
8038
|
+
for (const rel of walkRelative(skill.bundledPath)) {
|
|
8039
|
+
files[rel] = sha256File(path2.join(skill.bundledPath, rel));
|
|
8040
|
+
}
|
|
8041
|
+
return {
|
|
8042
|
+
name: skill.name,
|
|
8043
|
+
version: PACKAGE_VERSION,
|
|
8044
|
+
files,
|
|
8045
|
+
description: readBundledSkillDescription(skill.bundledPath)
|
|
8046
|
+
};
|
|
8047
|
+
});
|
|
8048
|
+
}
|
|
8049
|
+
function readBundledSkillDescription(skillDir) {
|
|
8050
|
+
let raw;
|
|
8051
|
+
try {
|
|
8052
|
+
raw = fs2.readFileSync(path2.join(skillDir, "SKILL.md"), "utf-8");
|
|
8053
|
+
} catch {
|
|
8054
|
+
return void 0;
|
|
8055
|
+
}
|
|
8056
|
+
const parts = raw.split("---");
|
|
8057
|
+
if (parts.length < 3) return void 0;
|
|
8058
|
+
const lines = (parts[1] ?? "").split("\n");
|
|
8059
|
+
const collected = [];
|
|
8060
|
+
let inside = false;
|
|
8061
|
+
for (const line of lines) {
|
|
8062
|
+
const isTopLevelKey = /^[a-z][\w-]*:/i.test(line);
|
|
8063
|
+
if (inside && isTopLevelKey) break;
|
|
8064
|
+
if (isTopLevelKey && line.startsWith("description:")) {
|
|
8065
|
+
inside = true;
|
|
8066
|
+
collected.push(line.slice("description:".length).trim());
|
|
8067
|
+
continue;
|
|
8068
|
+
}
|
|
8069
|
+
if (inside) collected.push(line.trim());
|
|
8070
|
+
}
|
|
8071
|
+
if (!inside) return void 0;
|
|
8072
|
+
const value = collected.join(" ").trim();
|
|
8073
|
+
const unquoted = value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
|
|
8074
|
+
return unquoted.length > 0 ? unquoted : void 0;
|
|
8075
|
+
}
|
|
8076
|
+
async function installSkills(opts = {}) {
|
|
8077
|
+
const targetDir = opts.user ? os2.homedir() : path2.resolve(opts.dir ?? process.cwd());
|
|
8078
|
+
const client2 = opts.client ?? SkillsClients.all;
|
|
8079
|
+
const force = opts.force ?? false;
|
|
8080
|
+
const allSkills = getBundledSkills();
|
|
8081
|
+
const requestedNames = opts.skills && opts.skills.length > 0 ? opts.skills : allSkills.map((s) => s.name);
|
|
8082
|
+
const knownNames = new Set(allSkills.map((s) => s.name));
|
|
8083
|
+
const unknown = requestedNames.filter((n) => !knownNames.has(n));
|
|
8084
|
+
if (unknown.length > 0) {
|
|
8085
|
+
throw new CliError({
|
|
8086
|
+
code: "VALIDATION_ERROR",
|
|
8087
|
+
message: `Unknown skill(s): ${unknown.join(", ")}. Available: ${[...knownNames].join(", ")}`,
|
|
8088
|
+
details: { unknownSkills: unknown, availableSkills: [...knownNames] },
|
|
8089
|
+
exitCode: 1
|
|
8090
|
+
});
|
|
8091
|
+
}
|
|
8092
|
+
const skillsToInstall = allSkills.filter((s) => requestedNames.includes(s.name));
|
|
8093
|
+
fs2.mkdirSync(targetDir, { recursive: true });
|
|
8094
|
+
const results = [];
|
|
8095
|
+
for (const skill of skillsToInstall) {
|
|
8096
|
+
results.push(installClaudeSkill(skill, targetDir, force));
|
|
8097
|
+
if (client2 !== SkillsClients.claude) {
|
|
8098
|
+
results.push(installCodexSymlink(skill, targetDir, force));
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
8101
|
+
return {
|
|
8102
|
+
targetDir,
|
|
8103
|
+
results,
|
|
8104
|
+
message: buildSummaryMessage(results)
|
|
8105
|
+
};
|
|
8106
|
+
}
|
|
8107
|
+
async function listSkills(opts = {}) {
|
|
8108
|
+
const skills = getBundledSkills();
|
|
8109
|
+
if (isMachineFormat(opts.format)) {
|
|
8110
|
+
console.log(JSON.stringify({
|
|
8111
|
+
skills: skills.map((s) => ({
|
|
8112
|
+
name: s.name,
|
|
8113
|
+
description: s.description,
|
|
8114
|
+
claudePath: `.claude/skills/${s.name}`,
|
|
8115
|
+
codexPath: `.codex/skills/${s.name}`
|
|
8116
|
+
}))
|
|
8117
|
+
}, null, 2));
|
|
8118
|
+
return;
|
|
8119
|
+
}
|
|
8120
|
+
console.log("Bundled canonry skills:\n");
|
|
8121
|
+
for (const skill of skills) {
|
|
8122
|
+
console.log(` ${skill.name}`);
|
|
8123
|
+
if (skill.description) console.log(` ${skill.description}`);
|
|
8124
|
+
console.log(` Claude: .claude/skills/${skill.name}/`);
|
|
8125
|
+
console.log(` Codex: .codex/skills/${skill.name} (symlink \u2192 ../../.claude/skills/${skill.name})`);
|
|
8126
|
+
console.log();
|
|
8127
|
+
}
|
|
8128
|
+
}
|
|
8129
|
+
function emitInstallSummary(summary, format) {
|
|
8130
|
+
if (isMachineFormat(format)) {
|
|
8131
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
8132
|
+
return;
|
|
8133
|
+
}
|
|
8134
|
+
for (const r of summary.results) console.log(r.message);
|
|
8135
|
+
console.log(`
|
|
8136
|
+
Target: ${summary.targetDir}`);
|
|
8137
|
+
console.log(summary.message);
|
|
8138
|
+
}
|
|
8139
|
+
function getMissingUserSkillsNudge(home, agentPlugin) {
|
|
8140
|
+
if (!home) return null;
|
|
8141
|
+
const skillsBase = path2.join(home, ".claude", "skills");
|
|
8142
|
+
const installed = [];
|
|
8143
|
+
const missing = [];
|
|
8144
|
+
for (const name of BUNDLED_SKILL_NAMES) {
|
|
8145
|
+
const skillFile = path2.join(skillsBase, name, "SKILL.md");
|
|
8146
|
+
if (existsSafe(skillFile)) installed.push(name);
|
|
8147
|
+
else missing.push(name);
|
|
8148
|
+
}
|
|
8149
|
+
if (agentPlugin && agentPlugin.configuredClients.length > 0) {
|
|
8150
|
+
const unverifiedClients = agentPlugin.configuredClients.filter((client2) => !agentPlugin.verifiedClients.includes(client2));
|
|
8151
|
+
const mismatchedClients = agentPlugin.verifiedClients.filter((client2) => agentPlugin.verifiedClientVersions?.[client2] !== PACKAGE_VERSION);
|
|
8152
|
+
if (unverifiedClients.length === 0 && mismatchedClients.length === 0) return null;
|
|
8153
|
+
const displayClients = (clients) => clients.map((client2) => client2 === "claude-code" ? "Claude Code" : "Codex").join(" + ");
|
|
8154
|
+
const problems = [];
|
|
8155
|
+
if (unverifiedClients.length > 0) {
|
|
8156
|
+
problems.push(`The Canonry plugin is enabled for ${displayClients(unverifiedClients)}, but its cached manifest and skill assets could not be verified.`);
|
|
8157
|
+
}
|
|
8158
|
+
if (mismatchedClients.length > 0) {
|
|
8159
|
+
const versions = mismatchedClients.map((client2) => `${client2 === "claude-code" ? "Claude Code" : "Codex"} v${agentPlugin.verifiedClientVersions?.[client2] ?? "unknown"}`).join(", ");
|
|
8160
|
+
problems.push(`${versions} ${mismatchedClients.length === 1 ? "does" : "do"} not match the running Canonry v${PACKAGE_VERSION}.`);
|
|
8161
|
+
}
|
|
8162
|
+
return {
|
|
8163
|
+
message: `Tip: ${problems.join(" ")} Update or reinstall \`canonry@canonry\` with the affected client plugin manager.`,
|
|
8164
|
+
missing,
|
|
8165
|
+
installed
|
|
8166
|
+
};
|
|
8167
|
+
}
|
|
8168
|
+
if (missing.length === 0) return null;
|
|
8169
|
+
const fix = missing.length === BUNDLED_SKILL_NAMES.length ? "canonry skills install --user" : `canonry skills install ${missing.join(" ")} --user`;
|
|
8170
|
+
return {
|
|
8171
|
+
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.`,
|
|
8172
|
+
missing,
|
|
8173
|
+
installed
|
|
8174
|
+
};
|
|
8175
|
+
}
|
|
8176
|
+
function existsSafe(p) {
|
|
8177
|
+
try {
|
|
8178
|
+
return fs2.existsSync(p);
|
|
8179
|
+
} catch {
|
|
8180
|
+
return false;
|
|
8181
|
+
}
|
|
8182
|
+
}
|
|
8183
|
+
function parseSkillsClient(value) {
|
|
8184
|
+
if (!value) return SkillsClients.all;
|
|
8185
|
+
const parsed = skillsClientSchema.safeParse(value);
|
|
8186
|
+
if (parsed.success) return parsed.data;
|
|
8187
|
+
const allowed = skillsClientSchema.options;
|
|
8188
|
+
throw new CliError({
|
|
8189
|
+
code: "VALIDATION_ERROR",
|
|
8190
|
+
message: `Invalid --client value "${value}". Must be one of: ${allowed.join(", ")}`,
|
|
8191
|
+
details: { flag: "client", value, allowed },
|
|
8192
|
+
exitCode: 1
|
|
8193
|
+
});
|
|
8194
|
+
}
|
|
8195
|
+
|
|
7812
8196
|
// src/mcp/tool-registry.ts
|
|
7813
8197
|
import { z as z3 } from "zod";
|
|
7814
8198
|
|
|
@@ -11064,9 +11448,16 @@ export {
|
|
|
11064
11448
|
isEndpointMissing,
|
|
11065
11449
|
systemError,
|
|
11066
11450
|
printCliError,
|
|
11451
|
+
PACKAGE_VERSION,
|
|
11452
|
+
BUNDLED_SKILL_NAMES,
|
|
11453
|
+
getBundledSkillSnapshots,
|
|
11454
|
+
installSkills,
|
|
11455
|
+
listSkills,
|
|
11456
|
+
emitInstallSummary,
|
|
11457
|
+
getMissingUserSkillsNudge,
|
|
11458
|
+
parseSkillsClient,
|
|
11067
11459
|
createApiClient,
|
|
11068
11460
|
ApiClient,
|
|
11069
|
-
PACKAGE_VERSION,
|
|
11070
11461
|
measurementDraftOperationSchema,
|
|
11071
11462
|
runMeasurementDraftAction,
|
|
11072
11463
|
canonryMcpTools,
|