@kanonak-protocol/cli 2.0.0 → 2.2.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/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2024-2026 Genval LLC
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -23,10 +23,19 @@ export declare class GenericCapabilityHandler {
23
23
  private readonly objectParser;
24
24
  constructor(fileCache: FileCache, parser: KanonakParser, publisherIndex: PublisherIndex, fetchFn: AuthenticatedFetchFn, handlerRegistry: DeploymentHandlerRegistry, repository: IKanonakDocumentRepository);
25
25
  /**
26
- * Fetch a package and deploy every instance of the capability's
27
- * managed type.
26
+ * Fetch a package and deploy instances of the capability's managed
27
+ * type. If the parsed reference includes an `instanceName`, only
28
+ * that one instance is deployed; otherwise every matching instance
29
+ * in the package is deployed.
28
30
  */
29
31
  add(capability: LoadedCapability, packageRef: string, options: Record<string, string>): Promise<void>;
32
+ /**
33
+ * On a "package not found" error, scan the publisher index for
34
+ * approximate name matches and print up to 5 suggestions. Helps
35
+ * users recover from typos and from passing a 3-segment URI to
36
+ * `add` against an old CLI that lacked instance support.
37
+ */
38
+ private printPackageSuggestions;
30
39
  remove(capability: LoadedCapability, name: string, options: Record<string, string>): Promise<void>;
31
40
  list(capability: LoadedCapability, options: Record<string, string>): Promise<void>;
32
41
  update(capability: LoadedCapability, name: string | undefined, options: Record<string, string>): Promise<void>;
package/dist/index.js CHANGED
@@ -1,99 +1,98 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Ws}from"commander";import{readFileSync as Xs}from"fs";import{fileURLToPath as Js}from"url";import{dirname as Ys,join as Zs}from"path";import{KanonakParser as Qs,PublisherIndex as ei,CredentialStore as ni,createAuthenticatedFetch as ti}from"@kanonak-protocol/sdk";import{readFileSync as Qt,statSync as er}from"fs";import{resolve as nr,dirname as tr}from"path";import{KanonakParser as rr,KanonakObjectValidator as or,ValidationSeverity as mn}from"@kanonak-protocol/sdk";import{readFileSync as zt,readdirSync as qt}from"fs";import{join as Gt,dirname as Wt,basename as pn}from"path";import{InMemoryKanonakDocumentRepository as Xt,FileSystemKanonakDocumentRepository as Jt,HttpKanonakDocumentRepository as Yt,getGlobalCachePath as Zt}from"@kanonak-protocol/sdk";import{mkdirSync as Nt,readFileSync as un,writeFileSync as dn,existsSync as Me,appendFileSync as Ft}from"fs";import{join as Mt,dirname as Bt,isAbsolute as Vt}from"path";import{getGlobalCachePath as Ht}from"@kanonak-protocol/sdk";var T=class{constructor(e=Ht()){this.cacheDir=e;this.isProjectLocal=!Vt(e)}cacheDir;gitignoreChecked=!1;isProjectLocal;get(e,t,r){let o=this.getPath(e,t,r);return Me(o)?un(o,"utf-8"):null}put(e,t,r,o){let a=this.getPath(e,t,r);Nt(Bt(a),{recursive:!0}),dn(a,o,"utf-8"),this.isProjectLocal&&this.ensureGitignore()}has(e,t,r){return Me(this.getPath(e,t,r))}ensureGitignore(){if(this.gitignoreChecked)return;this.gitignoreChecked=!0;let e=".gitignore",t=this.cacheDir;if(Me(e)){if(un(e,"utf-8").split(`
3
- `).some(o=>o.trim()===t||o.trim()===t+"/"))return;Ft(e,`
2
+ import{Command as Js}from"commander";import{readFileSync as Ys}from"fs";import{fileURLToPath as Zs}from"url";import{dirname as Qs,join as ei}from"path";import{KanonakParser as ni,PublisherIndex as ti,CredentialStore as oi,createAuthenticatedFetch as ri}from"@kanonak-protocol/sdk";import{readFileSync as Qt,statSync as eo}from"fs";import{resolve as no,dirname as to}from"path";import{KanonakParser as oo,KanonakObjectValidator as ro,ValidationSeverity as fn}from"@kanonak-protocol/sdk";import{readFileSync as zt,readdirSync as qt}from"fs";import{join as Gt,dirname as Wt,basename as pn}from"path";import{InMemoryKanonakDocumentRepository as Xt,FileSystemKanonakDocumentRepository as Jt,HttpKanonakDocumentRepository as Yt,getGlobalCachePath as Zt}from"@kanonak-protocol/sdk";import{mkdirSync as Lt,readFileSync as dn,writeFileSync as mn,existsSync as Me,appendFileSync as Ft}from"fs";import{join as Mt,dirname as Bt,isAbsolute as Vt}from"path";import{getGlobalCachePath as Ht}from"@kanonak-protocol/sdk";var T=class{constructor(e=Ht()){this.cacheDir=e;this.isProjectLocal=!Vt(e)}cacheDir;gitignoreChecked=!1;isProjectLocal;get(e,t,o){let r=this.getPath(e,t,o);return Me(r)?dn(r,"utf-8"):null}put(e,t,o,r){let a=this.getPath(e,t,o);Lt(Bt(a),{recursive:!0}),mn(a,r,"utf-8"),this.isProjectLocal&&this.ensureGitignore()}has(e,t,o){return Me(this.getPath(e,t,o))}ensureGitignore(){if(this.gitignoreChecked)return;this.gitignoreChecked=!0;let e=".gitignore",t=this.cacheDir;if(Me(e)){if(dn(e,"utf-8").split(`
3
+ `).some(r=>r.trim()===t||r.trim()===t+"/"))return;Ft(e,`
4
4
  ${t}/
5
- `)}else dn(e,`${t}/
6
- `)}getPath(e,t,r){return Mt(this.cacheDir,e,`${t}@${r}.kan.yml`)}};function ie(n){let e=n;for(;;){let t=Wt(e);if(t===e)break;if(pn(e).includes(".")||pn(t).includes(".")){e=t;continue}break}return e}function ge(n,e){for(let t of qt(n,{withFileTypes:!0})){let r=Gt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?ge(r,e):t.name.endsWith(".kan.yml")&&e.push(r)}}var Be=class{repos;constructor(...e){this.repos=e}async getHighestCompatibleVersionAsync(e,t){for(let r of this.repos)try{let o=await r.getHighestCompatibleVersionAsync(e,t);if(o)return o}catch{}return null}async getAllDocumentsAsync(){let e=[];for(let t of this.repos)try{e.push(...await t.getAllDocumentsAsync())}catch{}return e}async getDocumentAsync(e){for(let t of this.repos)try{let r=await t.getDocumentAsync(e);if(r)return r}catch{}return null}async getDocumentsByNamespaceAsync(e,t){for(let r of this.repos)try{let o=await r.getDocumentsByNamespaceAsync(e,t);if(o.length>0)return o}catch{}return[]}async saveDocumentAsync(e,t){await this.repos[0].saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.repos[0].deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.repos[0].clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){return this.repos[0].getAllDocumentReferencesAsync()}async getDocumentContentAsync(e){for(let t of this.repos)try{let r=await t.getDocumentContentAsync(e);if(r)return r}catch{}return null}async getDocumentUriAsync(e){for(let t of this.repos)try{let r=await t.getDocumentUriAsync(e);if(r)return r}catch{}return null}};async function j(n,e){let t=[];ge(n,t);let r=new Xt(e);for(let c of t)try{let i=zt(c,"utf-8"),l=e.parse(i),u=l.metadata.namespace_;if(u){let d=`${u.publisher}/${u.package_}@${u.version}`;await r.saveDocumentAsync(l,d)}}catch{}let o=new Jt(Zt(),!0,e),a=new T,s=new Yt({getFromCache:(c,i,l)=>a.get(c,i,l),onFetch:(c,i,l,u)=>a.put(c,i,l,u)});return new Be(r,o,s)}async function fn(n){let e=nr(n),t=er(e),r=t.isDirectory()?ie(e):ie(tr(e)),o=new rr,a=new or(o),s=await j(r,o),c=[];if(t.isDirectory()?ge(e,c):c.push(e),c.length===0){console.log("No .kan.yml files found.");return}let i=0,l=0;for(let u of c){let d=Qt(u,"utf-8"),m=o.parseWithErrors(d);if(m.errors&&m.errors.length>0){console.log(`
7
- ${u}:`);for(let h of m.errors)console.log(` ERROR (parse): ${h.message} [line ${h.line}:${h.column}]`),i++;continue}let y=m.document;if(!y){console.log(`
8
- ${u}:`),console.log(" ERROR: Failed to parse document"),i++;continue}let g=await a.validateAsync(y,s),k=g.errors.filter(h=>h.severity===mn.Error),b=g.errors.filter(h=>h.severity===mn.Warning);if(k.length>0||b.length>0){let h=y.metadata.namespace_,$=h?`${h.publisher}/${h.package_}@${h.version}`:u;console.log(`
9
- ${$}:`);for(let S of k)console.log(` ERROR: ${S.message}`),S.suggestion&&console.log(` -> ${S.suggestion}`);for(let S of b)console.log(` WARN: ${S.message}`)}i+=k.length,l+=b.length}console.log(`
10
- ${c.length} file(s) validated. ${i} error(s), ${l} warning(s).`),i>0&&process.exit(1)}import{KanonakParser as ur,PublisherIndex as dr,CredentialStore as pr,createAuthenticatedFetch as mr}from"@kanonak-protocol/sdk";import{readFileSync as ar,writeFileSync as sr,existsSync as ir}from"fs";import{createHash as cr}from"crypto";import gn from"js-yaml";var Ve="kanonak.lock",lr=`# This file is generated by Kanonak CLI. Do not edit manually.
11
- `;function hn(){if(!ir(Ve))return null;let n=ar(Ve,"utf-8"),e=gn.load(n);return!e||typeof e!="object"||e.version!=="1"?null:{version:"1",lastUpdated:e.lastUpdated??new Date().toISOString(),packages:e.packages??{}}}function kn(n){n.lastUpdated=new Date().toISOString();let e={};for(let r of Object.keys(n.packages).sort())e[r]=n.packages[r];n.packages=e;let t=gn.dump(n,{lineWidth:-1,sortKeys:!1,quotingType:'"'});sr(Ve,lr+t,"utf-8")}function N(n){return`sha256:${cr("sha256").update(n).digest("hex")}`}function W(n){let e=n.indexOf("@"),t,r=null;e!==-1?(t=n.substring(0,e),r=n.substring(e+1)||null):t=n;let o=t.indexOf("/");if(o===-1)return null;let a=t.substring(0,o),s=t.substring(o+1);return!a||!s?null:{publisher:a,packageName:s,version:r}}async function yn(n){let e=new T,t=new ur,r=new pr,o=mr(r),a=new dr({fetchFn:o}),s=hn()??{version:"1",lastUpdated:new Date().toISOString(),packages:{}};if(!n){Object.keys(s.packages).length===0&&(console.error("No kanonak.lock file found or lock file is empty."),console.error("Usage: kanonak install {publisher}/{package}[@{version}]"),process.exit(1)),console.log(`Installing ${Object.keys(s.packages).length} package(s) from kanonak.lock...`);for(let[y,g]of Object.entries(s.packages)){let k=y.indexOf("/"),b=y.substring(0,k),h=y.substring(k+1),$=e.get(b,h,g.version);if($)console.log(` ${y}@${g.version} (cached)`);else{let S=g.resolved,A=await o(S,b);if(!A.ok)throw new Error(`Failed to fetch ${S} (${A.status} ${A.statusText})`);$=await A.text(),e.put(b,h,g.version,$),console.log(` ${y}@${g.version}`)}}console.log(`
12
- Installed ${Object.keys(s.packages).length} package(s) from lock file.`);return}let c=W(n);c||(console.error(`Invalid package reference: ${n}`),console.error("Expected format: {publisher}/{package}@{version} or {publisher}/{package}"),process.exit(1));let{publisher:i,packageName:l,version:u}=c,d=u??await a.getHighestVersion(i,l);d||(console.error(`Could not resolve version for ${i}/${l}`),process.exit(1)),console.log(`Installing ${i}/${l}@${d}...`);let m=new Set;await bn(i,l,d,e,t,a,o,m,s),kn(s),console.log(`
13
- Installed ${m.size} package(s).`)}async function bn(n,e,t,r,o,a,s,c,i){let l=`${n}/${e}@${t}`;if(c.has(l))return;c.add(l);let u=`${n}/${e}`,d=r.get(n,e,t),m;if(d)console.log(` ${l} (cached)`),m=await a.getPackageUrl(n,e,t);else{m=await a.getPackageUrl(n,e,t);let k=await s(m,n);if(!k.ok)throw new Error(`Failed to fetch ${m} (${k.status} ${k.statusText})`);d=await k.text(),r.put(n,e,t,d),console.log(` ${l}`)}let y={},g=o.parse(d);if(g.metadata.imports)for(let[k,b]of Object.entries(g.metadata.imports))for(let h of b){let $=await a.resolveVersion(k,h);$?(y[`${k}/${h.packageName}`]=$,await bn(k,h.packageName,$,r,o,a,s,c,i)):console.error(` WARNING: Could not resolve ${k}/${h.packageName} ${h.package_}`)}i.packages[u]={version:t,resolved:m,integrity:N(d),dependencies:y}}import{readFileSync as fr}from"fs";import{resolve as gr,dirname as hr}from"path";import{KanonakParser as kr}from"@kanonak-protocol/sdk";async function wn(n){let e=gr(n),t=fr(e,"utf-8"),r=new kr,o=r.parse(t),a=o.metadata.namespace_,s=a?`${a.publisher}/${a.package_}@${a.version}`:n;if(console.log(s),!o.metadata.imports){console.log(" (no imports)");return}let c=ie(hr(e)),i=await j(c,r),l=new Set;for(let[u,d]of Object.entries(o.metadata.imports))for(let m of d)await Sn(u,m,i,l," ")}async function Sn(n,e,t,r,o){let a=`${n}/${e.packageName}`;if(r.has(a)){console.log(`${o}${a} (${e.package_}) [circular]`);return}r.add(a);let s;try{s=await t.getHighestCompatibleVersionAsync(n,e)}catch{console.log(`${o}${a} (${e.package_}) [fetch failed]`);return}if(!s){console.log(`${o}${a} (${e.package_}) [not found]`);return}let c=s.metadata.namespace_?.version?.toString()??"?";if(console.log(`${o}${n}/${e.packageName}@${c}`),s.metadata.imports)for(let[i,l]of Object.entries(s.metadata.imports))for(let u of l)await Sn(i,u,t,r,o+" ")}import{createHash as br,randomBytes as Dn}from"crypto";import{createServer as wr}from"http";import{execFile as He}from"child_process";import{CredentialStore as Sr,generateDPoPKeyPair as $r,createDPoPProof as $n,serverSupportsDPoP as vr}from"@kanonak-protocol/sdk";import{normalizeHost as yr}from"@kanonak-protocol/sdk";var F=class{cache=new Map;async discover(e){let t=yr(e);if(this.cache.has(t))return this.cache.get(t);let r=`https://${t}/.well-known/oauth-authorization-server`,o=await this.tryEndpoint(r);if(!o){let a=`https://${t}/.well-known/openid-configuration`;o=await this.tryEndpoint(a)}return this.cache.set(t,o),o}async supportsOAuth(e){return await this.discover(e)!==null}static supportsPkceS256(e){return e.codeChallengeMethodsSupported?.some(t=>t.toUpperCase()==="S256")??!1}static supportsDynamicRegistration(e){return!!e.registrationEndpoint}static supportsAuthorizationCode(e){return e.responseTypesSupported?.some(t=>t.toLowerCase()==="code")??!1}async tryEndpoint(e){let t;try{t=await fetch(e)}catch(o){let a=o instanceof Error?o.message:String(o);return a.includes("ENOTFOUND")||a.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${a})`),console.error(" If the server is behind a VPN, ensure you are connected.")):a.includes("CERT")||a.includes("SSL")||a.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${a})`),console.error(" If using a custom CA certificate, set NODE_EXTRA_CA_CERTS=/path/to/ca.pem")):console.error(` OAuth discovery: ${e} \u2014 network error: ${a}`),null}if(!t.ok)return t.status===404||(t.status===403?(console.error(` OAuth discovery: ${e} \u2014 HTTP 403 Forbidden`),console.error(" Access may be blocked by a firewall, proxy, or WAF.")):t.status>=500&&(console.error(` OAuth discovery: ${e} \u2014 HTTP ${t.status} server error`),console.error(" The authorization server returned an internal error. Contact your IDP administrator."))),null;let r;try{r=await t.json()}catch{return console.error(` OAuth discovery: ${e} \u2014 response is not valid JSON`),console.error(" The endpoint may be returning HTML instead of JSON. Check IDP configuration."),null}return{issuer:ce(r.issuer),authorizationEndpoint:ce(r.authorization_endpoint),tokenEndpoint:ce(r.token_endpoint),registrationEndpoint:ce(r.registration_endpoint),revocationEndpoint:ce(r.revocation_endpoint),scopesSupported:X(r.scopes_supported),responseTypesSupported:X(r.response_types_supported),grantTypesSupported:X(r.grant_types_supported),codeChallengeMethodsSupported:X(r.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:X(r.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:X(r.dpop_signing_alg_values_supported)}}};function ce(n){return typeof n=="string"?n:null}function X(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):null}var Y=class{discovery;credentialStore;constructor(e,t){this.discovery=e??new F,this.credentialStore=t??new Sr}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let r=await this.discovery.discover(e);if(!r)return I(`No OAuth discovery endpoint found for '${e}'.
5
+ `)}else mn(e,`${t}/
6
+ `)}getPath(e,t,o){return Mt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function se(n){let e=n;for(;;){let t=Wt(e);if(t===e)break;if(pn(e).includes(".")||pn(t).includes(".")){e=t;continue}break}return e}function fe(n,e){for(let t of qt(n,{withFileTypes:!0})){let o=Gt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?fe(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}var Be=class{repos;constructor(...e){this.repos=e}async getHighestCompatibleVersionAsync(e,t){for(let o of this.repos)try{let r=await o.getHighestCompatibleVersionAsync(e,t);if(r)return r}catch{}return null}async getAllDocumentsAsync(){let e=[];for(let t of this.repos)try{e.push(...await t.getAllDocumentsAsync())}catch{}return e}async getDocumentAsync(e){for(let t of this.repos)try{let o=await t.getDocumentAsync(e);if(o)return o}catch{}return null}async getDocumentsByNamespaceAsync(e,t){for(let o of this.repos)try{let r=await o.getDocumentsByNamespaceAsync(e,t);if(r.length>0)return r}catch{}return[]}async saveDocumentAsync(e,t){await this.repos[0].saveDocumentAsync(e,t)}async deleteDocumentAsync(e){await this.repos[0].deleteDocumentAsync(e)}async clearNamespaceAsync(e,t){await this.repos[0].clearNamespaceAsync(e,t)}async getAllDocumentReferencesAsync(){return this.repos[0].getAllDocumentReferencesAsync()}async getDocumentContentAsync(e){for(let t of this.repos)try{let o=await t.getDocumentContentAsync(e);if(o)return o}catch{}return null}async getDocumentUriAsync(e){for(let t of this.repos)try{let o=await t.getDocumentUriAsync(e);if(o)return o}catch{}return null}};async function x(n,e){let t=[];fe(n,t);let o=new Xt(e);for(let c of t)try{let i=zt(c,"utf-8"),l=e.parse(i),u=l.metadata.namespace_;if(u){let d=`${u.publisher}/${u.package_}@${u.version}`;await o.saveDocumentAsync(l,d)}}catch{}let r=new Jt(Zt(),!0,e),a=new T,s=new Yt({getFromCache:(c,i,l)=>a.get(c,i,l),onFetch:(c,i,l,u)=>a.put(c,i,l,u)});return new Be(o,r,s)}async function gn(n){let e=no(n),t=eo(e),o=t.isDirectory()?se(e):se(to(e)),r=new oo,a=new ro(r),s=await x(o,r),c=[];if(t.isDirectory()?fe(e,c):c.push(e),c.length===0){console.log("No .kan.yml files found.");return}let i=0,l=0;for(let u of c){let d=Qt(u,"utf-8"),m=r.parseWithErrors(d);if(m.errors&&m.errors.length>0){console.log(`
7
+ ${u}:`);for(let g of m.errors)console.log(` ERROR (parse): ${g.message} [line ${g.line}:${g.column}]`),i++;continue}let k=m.document;if(!k){console.log(`
8
+ ${u}:`),console.log(" ERROR: Failed to parse document"),i++;continue}let b=await a.validateAsync(k,s),f=b.errors.filter(g=>g.severity===fn.Error),h=b.errors.filter(g=>g.severity===fn.Warning);if(f.length>0||h.length>0){let g=k.metadata.namespace_,w=g?`${g.publisher}/${g.package_}@${g.version}`:u;console.log(`
9
+ ${w}:`);for(let $ of f)console.log(` ERROR: ${$.message}`),$.suggestion&&console.log(` -> ${$.suggestion}`);for(let $ of h)console.log(` WARN: ${$.message}`)}i+=f.length,l+=h.length}console.log(`
10
+ ${c.length} file(s) validated. ${i} error(s), ${l} warning(s).`),i>0&&process.exit(1)}import{KanonakParser as ao,PublisherIndex as so,CredentialStore as io,createAuthenticatedFetch as co}from"@kanonak-protocol/sdk";import{loadLockFile as lo,saveLockFile as uo,computeIntegrity as mo}from"@kanonak-protocol/sdk";function G(n){if(!n)return null;let e=n.indexOf("/");if(e===-1)return null;let t=n.substring(0,e),o=n.substring(e+1);if(!t||!o)return null;let r,a=null,s=null,c=o.indexOf("@");if(c!==-1){r=o.substring(0,c);let i=o.substring(c+1),l=i.indexOf("/");l===-1?a=i||null:(a=i.substring(0,l)||null,s=i.substring(l+1)||null)}else{let i=o.indexOf("/");i===-1?r=o:(r=o.substring(0,i),s=o.substring(i+1)||null)}return!r||s&&s.includes("/")||a&&a.includes("@")?null:{publisher:t,packageName:r,version:a,instanceName:s}}async function hn(n){let e=new T,t=new ao,o=new io,r=co(o),a=new so({fetchFn:r}),s=lo()??{version:"1",lastUpdated:new Date().toISOString(),packages:{}};if(!n){Object.keys(s.packages).length===0&&(console.error("No kanonak.lock file found or lock file is empty."),console.error("Usage: kanonak install {publisher}/{package}[@{version}]"),process.exit(1)),console.log(`Installing ${Object.keys(s.packages).length} package(s) from kanonak.lock...`);for(let[b,f]of Object.entries(s.packages)){let h=b.indexOf("/"),g=b.substring(0,h),w=b.substring(h+1),$=e.get(g,w,f.version);if($)console.log(` ${b}@${f.version} (cached)`);else{let v=f.resolved,D=await r(v,g);if(!D.ok)throw new Error(`Failed to fetch ${v} (${D.status} ${D.statusText})`);$=await D.text(),e.put(g,w,f.version,$),console.log(` ${b}@${f.version}`)}}console.log(`
11
+ Installed ${Object.keys(s.packages).length} package(s) from lock file.`);return}let c=G(n);c||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:i,packageName:l,version:u,instanceName:d}=c;d&&(console.error(`\`kanonak install\` works on whole packages \u2014 got an instance suffix "/${d}".`),console.error(`Try: kanonak install ${i}/${l}${u?"@"+u:""}`),console.error("(Use `kanonak <capability> add` if you want to install one named instance.)"),process.exit(1));let m=u??await a.getHighestVersion(i,l);m||(console.error(`Could not resolve version for "${i}/${l}".`),console.error("Check the spelling, or run a search to see what the publisher offers."),process.exit(1)),console.log(`Installing ${i}/${l}@${m}...`);let k=new Set;await kn(i,l,m,e,t,a,r,k,s),uo(s),console.log(`
12
+ Installed ${k.size} package(s).`)}async function kn(n,e,t,o,r,a,s,c,i){let l=`${n}/${e}@${t}`;if(c.has(l))return;c.add(l);let u=`${n}/${e}`,d=o.get(n,e,t),m;if(d)console.log(` ${l} (cached)`),m=await a.getPackageUrl(n,e,t);else{m=await a.getPackageUrl(n,e,t);let f=await s(m,n);if(!f.ok)throw new Error(`Failed to fetch ${m} (${f.status} ${f.statusText})`);d=await f.text(),o.put(n,e,t,d),console.log(` ${l}`)}let k={},b=r.parse(d);if(b.metadata.imports)for(let[f,h]of Object.entries(b.metadata.imports))for(let g of h){let w=await a.resolveVersion(f,g);w?(k[`${f}/${g.packageName}`]=w,await kn(f,g.packageName,w,o,r,a,s,c,i)):console.error(` WARNING: Could not resolve ${f}/${g.packageName} ${g.package_}`)}i.packages[u]={version:t,resolved:m,integrity:mo(d),dependencies:k}}import{readFileSync as po}from"fs";import{resolve as fo,dirname as go}from"path";import{KanonakParser as ho}from"@kanonak-protocol/sdk";async function yn(n){let e=fo(n),t=po(e,"utf-8"),o=new ho,r=o.parse(t),a=r.metadata.namespace_,s=a?`${a.publisher}/${a.package_}@${a.version}`:n;if(console.log(s),!r.metadata.imports){console.log(" (no imports)");return}let c=se(go(e)),i=await x(c,o),l=new Set;for(let[u,d]of Object.entries(r.metadata.imports))for(let m of d)await bn(u,m,i,l," ")}async function bn(n,e,t,o,r){let a=`${n}/${e.packageName}`;if(o.has(a)){console.log(`${r}${a} (${e.package_}) [circular]`);return}o.add(a);let s;try{s=await t.getHighestCompatibleVersionAsync(n,e)}catch{console.log(`${r}${a} (${e.package_}) [fetch failed]`);return}if(!s){console.log(`${r}${a} (${e.package_}) [not found]`);return}let c=s.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${c}`),s.metadata.imports)for(let[i,l]of Object.entries(s.metadata.imports))for(let u of l)await bn(i,u,t,o,r+" ")}import{createHash as yo,randomBytes as Sn}from"crypto";import{createServer as bo}from"http";import{execFile as Ve}from"child_process";import{CredentialStore as wo,generateDPoPKeyPair as $o,createDPoPProof as wn,serverSupportsDPoP as So}from"@kanonak-protocol/sdk";import{normalizeHost as ko}from"@kanonak-protocol/sdk";var L=class{cache=new Map;async discover(e){let t=ko(e);if(this.cache.has(t))return this.cache.get(t);let o=`https://${t}/.well-known/oauth-authorization-server`,r=await this.tryEndpoint(o);if(!r){let a=`https://${t}/.well-known/openid-configuration`;r=await this.tryEndpoint(a)}return this.cache.set(t,r),r}async supportsOAuth(e){return await this.discover(e)!==null}static supportsPkceS256(e){return e.codeChallengeMethodsSupported?.some(t=>t.toUpperCase()==="S256")??!1}static supportsDynamicRegistration(e){return!!e.registrationEndpoint}static supportsAuthorizationCode(e){return e.responseTypesSupported?.some(t=>t.toLowerCase()==="code")??!1}async tryEndpoint(e){let t;try{t=await fetch(e)}catch(r){let a=r instanceof Error?r.message:String(r);return a.includes("ENOTFOUND")||a.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${a})`),console.error(" If the server is behind a VPN, ensure you are connected.")):a.includes("CERT")||a.includes("SSL")||a.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${a})`),console.error(" If using a custom CA certificate, set NODE_EXTRA_CA_CERTS=/path/to/ca.pem")):console.error(` OAuth discovery: ${e} \u2014 network error: ${a}`),null}if(!t.ok)return t.status===404||(t.status===403?(console.error(` OAuth discovery: ${e} \u2014 HTTP 403 Forbidden`),console.error(" Access may be blocked by a firewall, proxy, or WAF.")):t.status>=500&&(console.error(` OAuth discovery: ${e} \u2014 HTTP ${t.status} server error`),console.error(" The authorization server returned an internal error. Contact your IDP administrator."))),null;let o;try{o=await t.json()}catch{return console.error(` OAuth discovery: ${e} \u2014 response is not valid JSON`),console.error(" The endpoint may be returning HTML instead of JSON. Check IDP configuration."),null}return{issuer:ie(o.issuer),authorizationEndpoint:ie(o.authorization_endpoint),tokenEndpoint:ie(o.token_endpoint),registrationEndpoint:ie(o.registration_endpoint),revocationEndpoint:ie(o.revocation_endpoint),scopesSupported:W(o.scopes_supported),responseTypesSupported:W(o.response_types_supported),grantTypesSupported:W(o.grant_types_supported),codeChallengeMethodsSupported:W(o.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:W(o.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:W(o.dpop_signing_alg_values_supported)}}};function ie(n){return typeof n=="string"?n:null}function W(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):null}var J=class{discovery;credentialStore;constructor(e,t){this.discovery=e??new L,this.credentialStore=t??new wo}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let o=await this.discovery.discover(e);if(!o)return R(`No OAuth discovery endpoint found for '${e}'.
14
13
  The server must expose one of:
15
14
  - https://${e}/.well-known/oauth-authorization-server (RFC 8414)
16
15
  - https://${e}/.well-known/openid-configuration (OpenID Connect)
17
16
  Verify the hostname is correct and HTTPS is configured.
18
- If using a corporate proxy, ensure it is not blocking the discovery request.`);let o=[];if(r.authorizationEndpoint||o.push("authorization_endpoint"),r.tokenEndpoint||o.push("token_endpoint"),o.length>0)return I(`OAuth metadata for '${e}' is missing required fields: ${o.join(", ")}.
19
- Contact the IDP administrator to ensure these are included in the discovery document.`);let a=vr(r.dpopSigningAlgValuesSupported),s=null;if(a){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{s=$r()}catch(P){return I(`Failed to generate DPoP key pair: ${J(P)}
20
- Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:c,port:i,waitForCallback:l,close:u}=await _r(),d=await this.credentialStore.getCredential(e),m=d?.clientId??null,y=d?.clientSecret??null;if(!m&&r.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let P=await this.registerClient(r.registrationEndpoint,c);if(!P.success)return u(),I(P.error);m=P.clientId,y=P.clientSecret??null}if(!m)return u(),I(`No OAuth client credentials for '${e}' and the server does not support dynamic client registration (no registration_endpoint in metadata).
17
+ If using a corporate proxy, ensure it is not blocking the discovery request.`);let r=[];if(o.authorizationEndpoint||r.push("authorization_endpoint"),o.tokenEndpoint||r.push("token_endpoint"),r.length>0)return R(`OAuth metadata for '${e}' is missing required fields: ${r.join(", ")}.
18
+ Contact the IDP administrator to ensure these are included in the discovery document.`);let a=So(o.dpopSigningAlgValuesSupported),s=null;if(a){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{s=$o()}catch(D){return R(`Failed to generate DPoP key pair: ${X(D)}
19
+ Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:c,port:i,waitForCallback:l,close:u}=await Eo(),d=await this.credentialStore.getCredential(e),m=d?.clientId??null,k=d?.clientSecret??null;if(!m&&o.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let D=await this.registerClient(o.registrationEndpoint,c);if(!D.success)return u(),R(D.error);m=D.clientId,k=D.clientSecret??null}if(!m)return u(),R(`No OAuth client credentials for '${e}' and the server does not support dynamic client registration (no registration_endpoint in metadata).
21
20
  You must pre-register a client with your IDP and configure the client_id.
22
21
  Ask your IDP administrator to enable dynamic client registration (RFC 7591),
23
- or add a registration_endpoint to the OAuth metadata.`);let g=Ar(),k=Kr(g),b=Cr(),h=Pr(r.authorizationEndpoint,m,c,t,b,k);console.log(` Opening browser for authorization on port ${i}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${h}`),Ir(h);let $=await l();if(u(),!$)return I(`Authorization timed out after 5 minutes.
22
+ or add a registration_endpoint to the OAuth metadata.`);let b=Do(),f=Ko(b),h=Ao(),g=Co(o.authorizationEndpoint,m,c,t,h,f);console.log(` Opening browser for authorization on port ${i}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${g}`),Io(g);let w=await l();if(u(),!w)return R(`Authorization timed out after 5 minutes.
24
23
  The browser authorization was not completed in time.
25
- Re-run 'kanonak login ${e}' and complete the browser authorization promptly.`);if(!$.code){let P=$.error?`: ${$.error}`:"";return I(`No authorization code received${P}.
24
+ Re-run 'kanonak login ${e}' and complete the browser authorization promptly.`);if(!w.code){let D=w.error?`: ${w.error}`:"";return R(`No authorization code received${D}.
26
25
  The IDP may have rejected the authorization request.
27
- Check the IDP admin console for error details.`)}if($.state!==b)return I(`Authorization state mismatch \u2014 possible CSRF attack.
26
+ Check the IDP admin console for error details.`)}if(w.state!==h)return R(`Authorization state mismatch \u2014 possible CSRF attack.
28
27
  The response did not match the expected session.
29
- Re-run 'kanonak login ${e}' to start a fresh authorization flow.`);console.log(" Exchanging authorization code for tokens...");let S=await this.exchangeCode(r.tokenEndpoint,m,y,$.code,c,g,s);if(!S.success)return I(S.error);let A={clientId:m,clientSecret:y,accessToken:S.tokens.accessToken,refreshToken:S.tokens.refreshToken,expiresAt:S.tokens.expiresIn?new Date(Date.now()+S.tokens.expiresIn*1e3).toISOString():null,tokenEndpoint:r.tokenEndpoint,dpopKeyPair:s};return await this.credentialStore.store(e,A),console.log(` Successfully authenticated with ${e}`),a&&console.log(" DPoP proof-of-possession is active"),{success:!0,host:e}}async refresh(e){let t=await this.credentialStore.getCredential(e);if(!t)return I(`No stored credentials for '${e}'. Run 'kanonak login ${e}' to authenticate first.`);if(!t.refreshToken)return I(`No refresh token available for '${e}'.
28
+ Re-run 'kanonak login ${e}' to start a fresh authorization flow.`);console.log(" Exchanging authorization code for tokens...");let $=await this.exchangeCode(o.tokenEndpoint,m,k,w.code,c,b,s);if(!$.success)return R($.error);let v={clientId:m,clientSecret:k,accessToken:$.tokens.accessToken,refreshToken:$.tokens.refreshToken,expiresAt:$.tokens.expiresIn?new Date(Date.now()+$.tokens.expiresIn*1e3).toISOString():null,tokenEndpoint:o.tokenEndpoint,dpopKeyPair:s};return await this.credentialStore.store(e,v),console.log(` Successfully authenticated with ${e}`),a&&console.log(" DPoP proof-of-possession is active"),{success:!0,host:e}}async refresh(e){let t=await this.credentialStore.getCredential(e);if(!t)return R(`No stored credentials for '${e}'. Run 'kanonak login ${e}' to authenticate first.`);if(!t.refreshToken)return R(`No refresh token available for '${e}'.
30
29
  The authorization server may not issue refresh tokens for this client.
31
- Run 'kanonak login ${e}' to re-authenticate.`);if(!t.clientId)return I(`No client ID in stored credentials for '${e}'.
32
- The stored credential may be corrupted. Run 'kanonak logout ${e}' then 'kanonak login ${e}'.`);let r=t.tokenEndpoint;if(!r){let a=await this.discovery.discover(e);if(!a?.tokenEndpoint)return I(`Cannot find token endpoint for '${e}'.
30
+ Run 'kanonak login ${e}' to re-authenticate.`);if(!t.clientId)return R(`No client ID in stored credentials for '${e}'.
31
+ The stored credential may be corrupted. Run 'kanonak logout ${e}' then 'kanonak login ${e}'.`);let o=t.tokenEndpoint;if(!o){let a=await this.discovery.discover(e);if(!a?.tokenEndpoint)return R(`Cannot find token endpoint for '${e}'.
33
32
  The OAuth discovery endpoint may be unreachable.
34
- Check network connectivity and run 'kanonak login ${e}' to re-authenticate.`);r=a.tokenEndpoint}let o=await this.refreshTokenRequest(r,t.clientId,t.clientSecret,t.refreshToken,t.dpopKeyPair);return o.success?(t.accessToken=o.tokens.accessToken,o.tokens.refreshToken&&(t.refreshToken=o.tokens.refreshToken),t.expiresAt=o.tokens.expiresIn?new Date(Date.now()+o.tokens.expiresIn*1e3).toISOString():null,t.tokenEndpoint=r,await this.credentialStore.store(e,t),{success:!0,host:e}):I(`${o.error}
35
- The refresh token may have expired. Run 'kanonak login ${e}' to re-authenticate.`)}async logout(e){let t=await this.credentialStore.getCredential(e);if(!t)return I(`No stored credentials for '${e}'.
36
- You may not be logged in, or credentials may be stored in a different backend.`);let r=await this.discovery.discover(e);if(r?.revocationEndpoint&&t.accessToken&&t.clientId)try{await this.revokeToken(r.revocationEndpoint,t.accessToken,t.clientId)}catch{console.warn(` Warning: Token revocation failed for '${e}'. The token has been removed locally but may still be valid on the server until it expires.`)}return await this.credentialStore.remove(e),{success:!0,host:e}}async registerClient(e,t){let r;try{r=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak CLI",redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})})}catch(s){return{success:!1,error:`Dynamic client registration request to ${e} failed: ${J(s)}
33
+ Check network connectivity and run 'kanonak login ${e}' to re-authenticate.`);o=a.tokenEndpoint}let r=await this.refreshTokenRequest(o,t.clientId,t.clientSecret,t.refreshToken,t.dpopKeyPair);return r.success?(t.accessToken=r.tokens.accessToken,r.tokens.refreshToken&&(t.refreshToken=r.tokens.refreshToken),t.expiresAt=r.tokens.expiresIn?new Date(Date.now()+r.tokens.expiresIn*1e3).toISOString():null,t.tokenEndpoint=o,await this.credentialStore.store(e,t),{success:!0,host:e}):R(`${r.error}
34
+ The refresh token may have expired. Run 'kanonak login ${e}' to re-authenticate.`)}async logout(e){let t=await this.credentialStore.getCredential(e);if(!t)return R(`No stored credentials for '${e}'.
35
+ You may not be logged in, or credentials may be stored in a different backend.`);let o=await this.discovery.discover(e);if(o?.revocationEndpoint&&t.accessToken&&t.clientId)try{await this.revokeToken(o.revocationEndpoint,t.accessToken,t.clientId)}catch{console.warn(` Warning: Token revocation failed for '${e}'. The token has been removed locally but may still be valid on the server until it expires.`)}return await this.credentialStore.remove(e),{success:!0,host:e}}async registerClient(e,t){let o;try{o=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak CLI",redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})})}catch(s){return{success:!1,error:`Dynamic client registration request to ${e} failed: ${X(s)}
37
36
  Ensure the IDP is reachable and HTTPS is properly configured.
38
- If using a corporate proxy or custom CA, set NODE_EXTRA_CA_CERTS.`}}if(!r.ok){let s=await ze(r);return{success:!1,error:`Dynamic client registration (RFC 7591) failed.
37
+ If using a corporate proxy or custom CA, set NODE_EXTRA_CA_CERTS.`}}if(!o.ok){let s=await He(o);return{success:!1,error:`Dynamic client registration (RFC 7591) failed.
39
38
  Endpoint: ${e}
40
- HTTP ${r.status}: ${s}
39
+ HTTP ${o.status}: ${s}
41
40
  The IDP may not support dynamic registration for public clients.
42
- Ask your IDP administrator to enable RFC 7591 support, or pre-register a client manually.`}}let o=await r.json(),a=o.client_id;return a?{success:!0,clientId:a,clientSecret:o.client_secret}:{success:!1,error:`Dynamic client registration response from ${e} did not contain a client_id.
43
- The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,r,o,a,s,c){let i=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:o,redirect_uri:a,code_verifier:s});r&&i.set("client_secret",r);let l={"Content-Type":"application/x-www-form-urlencoded"};if(c)try{l.DPoP=$n(c.privateKey,c.publicKey,"POST",e)}catch(d){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${J(d)}
44
- The stored key pair may be corrupted. Run 'kanonak login' to re-authenticate.`}}let u;try{u=await fetch(e,{method:"POST",headers:l,body:i.toString()})}catch(d){return{success:!1,error:`Token exchange request to ${e} failed: ${J(d)}
45
- Ensure the token endpoint is reachable.`}}if(!u.ok){let d=await ze(u),m=Dr(d);return{success:!1,error:`Token exchange failed.
41
+ Ask your IDP administrator to enable RFC 7591 support, or pre-register a client manually.`}}let r=await o.json(),a=r.client_id;return a?{success:!0,clientId:a,clientSecret:r.client_secret}:{success:!1,error:`Dynamic client registration response from ${e} did not contain a client_id.
42
+ The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,o,r,a,s,c){let i=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:a,code_verifier:s});o&&i.set("client_secret",o);let l={"Content-Type":"application/x-www-form-urlencoded"};if(c)try{l.DPoP=wn(c.privateKey,c.publicKey,"POST",e)}catch(d){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${X(d)}
43
+ The stored key pair may be corrupted. Run 'kanonak login' to re-authenticate.`}}let u;try{u=await fetch(e,{method:"POST",headers:l,body:i.toString()})}catch(d){return{success:!1,error:`Token exchange request to ${e} failed: ${X(d)}
44
+ Ensure the token endpoint is reachable.`}}if(!u.ok){let d=await He(u),m=vo(d);return{success:!1,error:`Token exchange failed.
46
45
  Endpoint: ${e}
47
46
  HTTP ${u.status}: ${d}`+(m?`
48
- ${m}`:"")}}return{success:!0,tokens:vn(await u.json())}}async refreshTokenRequest(e,t,r,o,a){let s=new URLSearchParams({grant_type:"refresh_token",client_id:t,refresh_token:o});r&&s.set("client_secret",r);let c={"Content-Type":"application/x-www-form-urlencoded"};if(a)try{c.DPoP=$n(a.privateKey,a.publicKey,"POST",e)}catch(l){return{success:!1,error:`Failed to create DPoP proof for token refresh: ${J(l)}`}}let i;try{i=await fetch(e,{method:"POST",headers:c,body:s.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${J(l)}`}}if(!i.ok){let l=await ze(i);return{success:!1,error:`Token refresh failed \u2014 HTTP ${i.status}: ${l}`}}return{success:!0,tokens:vn(await i.json())}}async revokeToken(e,t,r){await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({token:t,client_id:r}).toString()})}};function I(n){return{success:!1,error:n}}function vn(n){return{accessToken:n.access_token,refreshToken:n.refresh_token,expiresIn:typeof n.expires_in=="number"?n.expires_in:void 0}}function J(n){return n instanceof Error?n.message:String(n)}async function ze(n){try{return await n.text()}catch{return"(could not read response body)"}}function Dr(n){try{let e=JSON.parse(n);switch(e.error){case"invalid_grant":return"Hint: The authorization code may have expired or already been used. Re-run the login flow.";case"invalid_client":return"Hint: The client credentials were rejected. The client_id may be invalid or the client_secret may be wrong.";case"redirect_uri_mismatch":return"Hint: The redirect_uri does not match what was registered with the IDP.";case"unsupported_grant_type":return"Hint: The IDP does not support authorization_code grants. Contact your IDP administrator.";case"invalid_scope":return"Hint: One or more requested scopes are not allowed. Check the scopes configured on the IDP.";case"use_dpop_nonce":return"Hint: The server requires a DPoP nonce. This should be handled automatically \u2014 please report this as a bug.";default:return e.error_description?`IDP says: ${e.error_description}`:null}}catch{return null}}function Ar(){return Dn(32).toString("base64url")}function Kr(n){return br("sha256").update(n).digest("base64url")}function Cr(){return Dn(16).toString("base64url")}function Pr(n,e,t,r,o,a){let s=new URLSearchParams({client_id:e,response_type:"code",redirect_uri:t,scope:r.join(" "),state:o,code_challenge:a,code_challenge_method:"S256"});return`${n}?${s}`}var Er=300*1e3;async function _r(){return new Promise(n=>{let e=wr((o,a)=>{let s=new URL(o.url,"http://localhost"),c=s.searchParams.get("code")??void 0,i=s.searchParams.get("state")??void 0,l=s.searchParams.get("error")??s.searchParams.get("error_description")??void 0,u=l?Rr(l):null,d=u?`<html><body><h1>Authorization failed</h1><p>${u}</p></body></html>`:"<html><body><h1>Authorization successful!</h1><p>You can close this window.</p></body></html>";a.writeHead(200,{"Content-Type":"text/html"}),a.end(d),t({code:c,state:i,error:l})}),t,r=new Promise(o=>{t=o,setTimeout(()=>{o(null),e.close()},Er)});e.listen(0,"127.0.0.1",()=>{let o=e.address();n({redirectUri:`http://localhost:${o.port}/callback`,port:o.port,waitForCallback:()=>r,close:()=>e.close()})})})}function Rr(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Ir(n){try{process.platform==="win32"?He("cmd",["/c","start","",n]):process.platform==="darwin"?He("open",[n]):He("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as Tr}from"@kanonak-protocol/sdk";async function An(n){try{let e=new F,t=new Tr,o=await new Y(e,t).authorize(n);o.success?console.log(`
47
+ ${m}`:"")}}return{success:!0,tokens:$n(await u.json())}}async refreshTokenRequest(e,t,o,r,a){let s=new URLSearchParams({grant_type:"refresh_token",client_id:t,refresh_token:r});o&&s.set("client_secret",o);let c={"Content-Type":"application/x-www-form-urlencoded"};if(a)try{c.DPoP=wn(a.privateKey,a.publicKey,"POST",e)}catch(l){return{success:!1,error:`Failed to create DPoP proof for token refresh: ${X(l)}`}}let i;try{i=await fetch(e,{method:"POST",headers:c,body:s.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${X(l)}`}}if(!i.ok){let l=await He(i);return{success:!1,error:`Token refresh failed \u2014 HTTP ${i.status}: ${l}`}}return{success:!0,tokens:$n(await i.json())}}async revokeToken(e,t,o){await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({token:t,client_id:o}).toString()})}};function R(n){return{success:!1,error:n}}function $n(n){return{accessToken:n.access_token,refreshToken:n.refresh_token,expiresIn:typeof n.expires_in=="number"?n.expires_in:void 0}}function X(n){return n instanceof Error?n.message:String(n)}async function He(n){try{return await n.text()}catch{return"(could not read response body)"}}function vo(n){try{let e=JSON.parse(n);switch(e.error){case"invalid_grant":return"Hint: The authorization code may have expired or already been used. Re-run the login flow.";case"invalid_client":return"Hint: The client credentials were rejected. The client_id may be invalid or the client_secret may be wrong.";case"redirect_uri_mismatch":return"Hint: The redirect_uri does not match what was registered with the IDP.";case"unsupported_grant_type":return"Hint: The IDP does not support authorization_code grants. Contact your IDP administrator.";case"invalid_scope":return"Hint: One or more requested scopes are not allowed. Check the scopes configured on the IDP.";case"use_dpop_nonce":return"Hint: The server requires a DPoP nonce. This should be handled automatically \u2014 please report this as a bug.";default:return e.error_description?`IDP says: ${e.error_description}`:null}}catch{return null}}function Do(){return Sn(32).toString("base64url")}function Ko(n){return yo("sha256").update(n).digest("base64url")}function Ao(){return Sn(16).toString("base64url")}function Co(n,e,t,o,r,a){let s=new URLSearchParams({client_id:e,response_type:"code",redirect_uri:t,scope:o.join(" "),state:r,code_challenge:a,code_challenge_method:"S256"});return`${n}?${s}`}var Po=300*1e3;async function Eo(){return new Promise(n=>{let e=bo((r,a)=>{let s=new URL(r.url,"http://localhost"),c=s.searchParams.get("code")??void 0,i=s.searchParams.get("state")??void 0,l=s.searchParams.get("error")??s.searchParams.get("error_description")??void 0,u=l?_o(l):null,d=u?`<html><body><h1>Authorization failed</h1><p>${u}</p></body></html>`:"<html><body><h1>Authorization successful!</h1><p>You can close this window.</p></body></html>";a.writeHead(200,{"Content-Type":"text/html"}),a.end(d),t({code:c,state:i,error:l})}),t,o=new Promise(r=>{t=r,setTimeout(()=>{r(null),e.close()},Po)});e.listen(0,"127.0.0.1",()=>{let r=e.address();n({redirectUri:`http://localhost:${r.port}/callback`,port:r.port,waitForCallback:()=>o,close:()=>e.close()})})})}function _o(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Io(n){try{process.platform==="win32"?Ve("cmd",["/c","start","",n]):process.platform==="darwin"?Ve("open",[n]):Ve("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as Ro}from"@kanonak-protocol/sdk";async function vn(n){try{let e=new L,t=new Ro,r=await new J(e,t).authorize(n);r.success?console.log(`
49
48
  Authenticated with ${n}.`):(console.error(`
50
49
  Authentication failed:
51
- ${o.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
50
+ ${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
52
51
  Authentication failed unexpectedly:
53
52
  ${t}`),console.error(`
54
- If this persists, file an issue at https://github.com/kanonak-protocol/typescript/issues`),process.exit(1)}}import{CredentialStore as jr}from"@kanonak-protocol/sdk";async function Kn(n){try{let e=new F,t=new jr,o=await new Y(e,t).logout(n);o.success?console.log(`Logged out from ${n}.`):(console.error(`
53
+ If this persists, see https://github.com/kanonak-protocol for support channels.`),process.exit(1)}}import{CredentialStore as To}from"@kanonak-protocol/sdk";async function Dn(n){try{let e=new L,t=new To,r=await new J(e,t).logout(n);r.success?console.log(`Logged out from ${n}.`):(console.error(`
55
54
  Logout failed:
56
- ${o.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
55
+ ${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
57
56
  Logout failed unexpectedly:
58
- ${t}`),process.exit(1)}}import{Command as io}from"commander";import{KanonakParser as co,KanonakObjectParser as lo,PublisherIndex as uo,CredentialStore as po,createAuthenticatedFetch as mo}from"@kanonak-protocol/sdk";import{readFileSync as xr,writeFileSync as Ur,existsSync as Or}from"fs";import{join as Lr}from"path";import Cn from"js-yaml";import{getGlobalCachePath as Nr}from"@kanonak-protocol/sdk";var Fr=`# This file is generated by Kanonak CLI. Do not edit manually.
59
- `;function Pn(){let n=Nr();return Lr(n,"..","capabilities.lock")}function Z(){let n=Pn();if(!Or(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=xr(n,"utf-8"),t=Cn.load(e);return!t||typeof t!="object"||t.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}}:{version:"1",lastUpdated:t.lastUpdated??new Date().toISOString(),capabilities:t.capabilities??{}}}function qe(n){n.lastUpdated=new Date().toISOString();let e={};for(let r of Object.keys(n.capabilities).sort())e[r]=n.capabilities[r];n.capabilities=e;let t=Cn.dump(n,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ur(Pn(),Fr+t,"utf-8")}var D=class{constructor(e,t){this.doc=e;this.broader=t}doc;broader;async getAllDocumentsAsync(){return[this.doc]}async getDocumentAsync(e){return this.broader.getDocumentAsync(e)}async getDocumentsByNamespaceAsync(e,t){return this.broader.getDocumentsByNamespaceAsync(e,t)}async getHighestCompatibleVersionAsync(e,t){return this.broader.getHighestCompatibleVersionAsync(e,t)}async saveDocumentAsync(){throw new Error("SingleDocumentRepository is read-only")}async deleteDocumentAsync(){throw new Error("SingleDocumentRepository is read-only")}async clearNamespaceAsync(){throw new Error("SingleDocumentRepository is read-only")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(e){return this.broader.getDocumentContentAsync(e)}async getDocumentUriAsync(e){return this.broader.getDocumentUriAsync(e)}};import{KanonakObjectParser as Wr,EmbeddedKanonak as jn,ReferenceKanonak as xn}from"@kanonak-protocol/sdk";import{SubjectKanonak as En,DefinedKanonak as Mr,StringStatement as Br,NumberStatement as Vr,BooleanStatement as Hr,ReferenceStatement as _n,EmbeddedStatement as zr,ListStatement as qr}from"@kanonak-protocol/sdk";function L(n){return`${n.publisher}/${n.package_}/${n.name}`}function M(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}function Gr(n,e){if(!(n instanceof Mr))return!1;for(let t of n.statement)if(t.predicate?.subject?.name==="type"&&t instanceof _n){let o=t.object;if(M(o.subject,e))return!0}return!1}function K(n,e){let t=[];for(let r of n)r instanceof En&&Gr(r,e)&&t.push(r);return t}function he(n,e){for(let t of n){if(!(t instanceof En)||t.name!==e.name)continue;if((t.namespace||"").startsWith(`${e.publisher}/${e.package_}@`))return t}}function ke(n,e){for(let t of n.statement){let r=t.predicate;if(r?.subject&&M(r.subject,e))return t}}function le(n,e){let t=ke(n,e);if(t&&(t instanceof Br||t instanceof Vr||t instanceof Hr))return t.object}function C(n,e){let t=le(n,e);return typeof t=="string"?t:void 0}function B(n,e){let t=ke(n,e);if(t instanceof _n)return t.object.subject}function H(n,e){let t=ke(n,e);if(t instanceof zr)return t.object}function Q(n,e){let t=ke(n,e);return t instanceof qr?t.object??[]:[]}var E="kanonak.org",_="capabilities",Ge={publisher:E,package_:_,name:"Capability"},Xr={publisher:E,package_:_,name:"commandName"},Un={publisher:E,package_:_,name:"description"},Jr={publisher:E,package_:_,name:"managesType"},Yr={publisher:E,package_:_,name:"deploymentTarget"},Zr={publisher:E,package_:_,name:"hasCommand"},Qr={publisher:E,package_:_,name:"subcommandName"},eo={publisher:E,package_:_,name:"performs"},no={publisher:E,package_:_,name:"hasArgument"},to={publisher:E,package_:_,name:"argumentName"},Rn={publisher:E,package_:_,name:"isRequired"},In={publisher:E,package_:_,name:"isOption"},ro={publisher:E,package_:_,name:"defaultValue"};async function On(n,e,t){let r=Z(),o=new Wr,a=[];for(let[s,c]of Object.entries(r.capabilities)){let i=n.get(c.publisher,c.package_,c.version);if(!i){console.error(` WARNING: Cached content missing for capability "${s}" (${c.publisher}/${c.package_}@${c.version})`);continue}try{let l=e.parse(i),u=new D(l,t),d=await o.parseKanonaks(u),m=oo(d,c.publisher,c.package_,c.version);m?a.push(m):console.error(` WARNING: No Capability instance found in "${s}" (${c.publisher}/${c.package_}@${c.version})`)}catch(l){console.error(` WARNING: Failed to parse capability "${s}": ${l}`)}}return a}function oo(n,e,t,r){let o=K(n,Ge);if(o.length===0)return;let a=o[0],s=C(a,Xr)??"",c=C(a,Un)??"",i=B(a,Jr),l=B(a,Yr),u=[];for(let d of Q(a,Zr)){let m=ao(d,n);m&&u.push(m)}return{commandName:s,description:c,managesTypeKey:i?L(i):"",deploymentTargetKey:l?L(l):"",commands:u,publisher:e,package_:t,version:r}}function ao(n,e){let t;if(n instanceof jn)t=n;else if(n instanceof xn){let i=Ln(e,n.subject.publisher,n.subject.package_,n.subject.name);i&&(t=i)}if(!t)return;let r=C(t,Qr)??"",o=C(t,Un)??"",a=B(t,eo),s=Q(t,no),c=[];for(let i of s){let l=so(i,e);l&&c.push(l)}return{subcommandName:r,description:o,arguments:c,actionKey:a?L(a):""}}function so(n,e){let t;if(n instanceof jn)t=n;else if(n instanceof xn){let i=Ln(e,n.subject.publisher,n.subject.package_,n.subject.name);i&&(t=i)}if(!t)return;let r=C(t,to)??"",o=C(t,Rn)==="true"||Tn(t,Rn)===!0,a=C(t,In)==="true"||Tn(t,In)===!0,s=C(t,ro),c={argumentName:r,required:o,isOption:a};return s!==void 0&&(c.defaultValue=s),c}function Tn(n,e){for(let t of n.statement){let r=t,o=r.predicate;if(o?.subject&&o.subject.publisher===e.publisher&&o.subject.package_===e.package_&&o.subject.name===e.name)return typeof r.object=="boolean"?r.object:void 0}}function Ln(n,e,t,r){for(let o of n){if(!("name"in o)||!("namespace"in o))continue;let a=o;if(a.name===r&&!(!a.namespace||typeof a.namespace!="string")&&a.namespace.startsWith(`${e}/${t}@`))return o}}var fo={publisher:E,package_:_,name:"commandName"};function Nn(){let n=new io("capability").description("Manage Kanonak CLI capabilities (pluggable command groups)");return n.command("add <package>").description("Install a capability from a Kanonak publisher").action(async e=>{await go(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await ho(e)}),n.command("list").description("List installed capabilities").action(async()=>{await ko()}),n}async function go(n){let e=W(n);e||(console.error(`Invalid package reference: ${n}`),console.error("Expected format: {publisher}/{package}@{version} or {publisher}/{package}"),process.exit(1));let{publisher:t,packageName:r,version:o}=e,a=new T,s=new co,c=new lo,i=new po,l=mo(i),u=new uo({fetchFn:l}),d=o??await u.getHighestVersion(t,r);d||(console.error(`Could not resolve version for ${t}/${r}`),process.exit(1)),console.log(`Installing capability ${t}/${r}@${d}...`);let m=a.get(t,r,d);if(!m){let P=await u.getPackageUrl(t,r,d),G=await l(P,t);if(!G.ok)throw new Error(`Failed to fetch ${P} (${G.status} ${G.statusText})`);m=await G.text(),a.put(t,r,d,m)}let y=s.parse(m),g=await j(process.cwd(),s),k=new D(y,g),b=await c.parseKanonaks(k),h=K(b,Ge);h.length===0&&(console.error(`Package ${t}/${r}@${d} does not contain a ${E}/${_}/Capability instance.`),process.exit(1));let $=h[0],S=C($,fo);S||(console.error(`Capability instance in ${t}/${r}@${d} has no commandName property.`),process.exit(1));let A=Z();A.capabilities[S]={publisher:t,package_:r,version:d,resolved:await u.getPackageUrl(t,r,d),integrity:N(m)},qe(A),console.log(`
60
- Installed capability "${S}".`),console.log(`Run "kanonak ${S} --help" to get started.`)}async function ho(n){let e=Z();e.capabilities[n]||(console.error(`Capability "${n}" is not installed.`),process.exit(1));let t=e.capabilities[n];delete e.capabilities[n],qe(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function ko(){let n=Z(),e=Object.entries(n.capabilities);if(e.length===0){console.log("No capabilities installed."),console.log("Install one with: kanonak capability add {publisher}/{package}");return}console.log(`Installed capabilities:
61
- `);for(let[t,r]of e)console.log(` ${t} ${r.publisher}/${r.package_}@${r.version}`)}import{Command as me}from"commander";import{readFileSync as Sa,writeFileSync as $a,mkdirSync as va,existsSync as st,statSync as Da}from"fs";import{join as Aa,resolve as Ka}from"path";import{KanonakParser as en,KanonakObjectParser as nn,SubjectKanonak as Ca,Reasoner as Pa,KanonakVocabulary as Ea,makeUriKey as it}from"@kanonak-protocol/sdk";var yo="kanonak.org",bo="document-ast",w=n=>({publisher:yo,package_:bo,name:n}),x={Document:w("Document"),Block:w("Block"),Inline:w("Inline"),StructuredValue:w("StructuredValue"),Heading:w("Heading"),Paragraph:w("Paragraph"),RawBlock:w("RawBlock"),Text:w("Text"),StructuredMap:w("StructuredMap"),StructuredEntry:w("StructuredEntry"),StructuredList:w("StructuredList"),StringScalar:w("StringScalar"),IntegerScalar:w("IntegerScalar"),EscapeHint:w("EscapeHint"),MediaType:w("MediaType"),metadata:w("metadata"),children:w("children"),level:w("level"),inlines:w("inlines"),text:w("text"),entries:w("entries"),key:w("key"),value:w("value"),escapeHint:w("escapeHint"),items:w("items"),stringValue:w("stringValue"),integerValue:w("integerValue"),rawContent:w("rawContent"),mediaType:w("mediaType"),mimeType:w("mimeType"),ESC_RAW:w("esc-raw"),ESC_YAML_SAFE:w("esc-yaml-safe"),ESC_TOML_STRING:w("esc-toml-string"),ESC_TOML_MULTILINE:w("esc-toml-multiline"),ESC_JSON:w("esc-json"),TEXT_PLAIN:w("text-plain"),TEXT_MARKDOWN:w("text-markdown"),TEXT_HTML:w("text-html"),APPLICATION_JSON:w("application-json"),TEXT_YAML:w("text-yaml"),IMAGE_SVG_XML:w("image-svg-xml")},wo="kanonak.org",So="transformations",p=n=>({publisher:wo,package_:So,name:n}),f={Transformation:p("Transformation"),InputPattern:p("InputPattern"),Expression:p("Expression"),ExpressionKind:p("ExpressionKind"),ExpressionFragment:p("ExpressionFragment"),AstFieldBinding:p("AstFieldBinding"),OutputFormat:p("OutputFormat"),FormatOverride:p("FormatOverride"),RenameEntry:p("RenameEntry"),Artifact:p("Artifact"),NormalizeKind:p("NormalizeKind"),inputPattern:p("inputPattern"),rule:p("rule"),artifactName:p("artifactName"),outputs:p("outputs"),formatOverrides:p("formatOverrides"),matchesClass:p("matchesClass"),requires:p("requires"),kind:p("kind"),astClass:p("astClass"),set:p("set"),iterate:p("iterate"),loopVar:p("loopVar"),emit:p("emit"),condition:p("condition"),thenBuild:p("thenBuild"),elseBuild:p("elseBuild"),parts:p("parts"),stringLiteral:p("stringLiteral"),integerLiteral:p("integerLiteral"),booleanLiteral:p("booleanLiteral"),varName:p("varName"),readSource:p("readSource"),readProp:p("readProp"),traverseSource:p("traverseSource"),through:p("through"),step:p("step"),primary:p("primary"),alternate:p("alternate"),uriNameOf:p("uriNameOf"),listMapSource:p("listMapSource"),mapBody:p("mapBody"),separator:p("separator"),items:p("items"),normSource:p("normSource"),normKind:p("normKind"),checkExpr:p("checkExpr"),refTo:p("refTo"),fragmentRef:p("fragmentRef"),expr:p("expr"),labelTarget:p("labelTarget"),labelSource:p("labelSource"),resolveSource:p("resolveSource"),field:p("field"),bindValue:p("bindValue"),backendUri:p("backendUri"),formatTarget:p("formatTarget"),metadataKeys:p("metadataKeys"),metadataRenames:p("metadataRenames"),trailingNewline:p("trailingNewline"),fromKey:p("fromKey"),toKey:p("toKey"),KIND_BUILD_AST_NODE:p("build-ast-node"),KIND_FOR_EACH:p("for-each"),KIND_WHEN:p("when"),KIND_CONCAT:p("concat"),KIND_STRING_LITERAL:p("string-literal"),KIND_INTEGER_LITERAL:p("integer-literal"),KIND_BOOLEAN_LITERAL:p("boolean-literal"),KIND_VAR_REF:p("var-ref"),KIND_PROPERTY_READ:p("property-read"),KIND_TRAVERSE:p("traverse"),KIND_FALLBACK:p("fallback"),KIND_URI_NAME:p("uri-name"),KIND_LIST_MAP:p("list-map"),KIND_JOIN:p("join"),KIND_NORMALIZE:p("normalize"),KIND_IS_SET:p("is-set"),KIND_URI_LITERAL:p("uri-literal"),KIND_CALL_FRAGMENT:p("call-fragment"),KIND_DISPLAY_LABEL:p("display-label"),KIND_RESOLVE_REF:p("resolve-ref"),NORM_TRIM_END:p("trim-end"),FMT_MARKDOWN_FRONTMATTER:p("markdown-with-frontmatter"),FMT_TOML:p("toml"),FMT_JSON:p("json"),FMT_PLAIN_MARKDOWN:p("plain-markdown")};import{SubjectKanonak as Fn}from"@kanonak-protocol/sdk";var ye=class{constructor(e,t,r){this.repository=e;this.parser=t;this.objectParser=r}repository;parser;objectParser;cache=new Map;async resolveSubject(e,t){let r=he(t,e);if(r)return r;let o=`${e.publisher}/${e.package_}`,a=this.cache.get(o);if(!a){let s=await this.repository.getDocumentsByNamespaceAsync(e.publisher,e.package_);if(s.length===0)return;let c=s[0],i=new D(c,this.repository);a=await this.objectParser.parseKanonaks(i),this.cache.set(o,a)}for(let s of a)if(s instanceof Fn&&s.name===e.name&&s.namespace&&s.namespace.startsWith(`${e.publisher}/${e.package_}@`))return s;for(let s of a)if(s instanceof Fn&&s.name===e.name)return s}};import{DefinedKanonak as Mn,LiteralKanonak as $o,ReferenceKanonak as be,StringStatement as vo,NumberStatement as Do,BooleanStatement as Ao,ReferenceStatement as Ko,EmbeddedStatement as Co,ListStatement as Po}from"@kanonak-protocol/sdk";var we=class extends Error{constructor(e){super(e)}},Se=class{constructor(e,t){this.resolver=e;this.allKanonaks=t}resolver;allKanonaks;async evaluate(e,t){switch(e.kind){case"var-ref":{if(!t.has(e.varName))throw new we(`Unbound variable "${e.varName}"`);return t.get(e.varName)}case"string-literal":return e.value;case"integer-literal":return e.value;case"boolean-literal":return e.value;case"uri-literal":return{...e.refTo};case"property-read":{let r=await this.evaluate(e.source,t);return r instanceof Mn?We(r,e.readProp):void 0}case"traverse":{let r=await this.evaluate(e.source,t);if(!(r instanceof Mn))return;let o=We(r,e.through),a;if(o instanceof be?a=o.subject:Array.isArray(o)&&o.length>0&&o[0]instanceof be&&(a=o[0].subject),!a)return;let s=await this.resolver.resolveSubject(a,this.allKanonaks);if(!s)return;let c=new Map(t);return c.set("input",s),this.evaluate(e.step,c)}case"fallback":{let r=await this.evaluate(e.primary,t);return Vn(r)?r:this.evaluate(e.alternate,t)}case"uri-name":{let r=await this.evaluate(e.of,t);return r instanceof be?r.subject.name:Hn(r)?r.name:void 0}case"list-map":{let r=await this.evaluate(e.source,t),o=Xe(r),a=[];for(let s of o){let c=new Map(t);c.set(e.loopVar,s),a.push(await this.evaluate(e.mapBody,c))}return a}case"join":{let r=await this.evaluate(e.items,t),o=Xe(r),a=[];for(let s of o)s!=null&&a.push(String(s));return a.join(e.separator)}case"normalize":{let r=await this.evaluate(e.source,t);return typeof r!="string"?r:e.normKind==="trim-end"?r.trimEnd():r}case"is-set":{let r=await this.evaluate(e.check,t);return Vn(r)}case"when":{let r=await this.evaluate(e.condition,t);return Io(r)?this.evaluate(e.thenBuild,t):e.elseBuild?this.evaluate(e.elseBuild,t):void 0}case"concat":{let r=[];for(let o of e.parts){let a=await this.evaluate(o,t);if(a!=null)if(Array.isArray(a))for(let s of a)r.push(s);else r.push(a)}return r}case"for-each":{let r=await this.evaluate(e.iterate,t),o=Xe(r),a=[];for(let s of o){let c=new Map(t);c.set(e.loopVar,s);let i=await this.evaluate(e.emit,c);if(i!=null)if(Array.isArray(i))for(let l of i)a.push(l);else a.push(i)}return a}case"build-ast-node":return this.buildAstNode(e,t);case"resolve-ref":{let r=await this.evaluate(e.source,t),o;return r instanceof be?o=r.subject:Hn(r)&&(o=r),o?this.resolver.resolveSubject(o,this.allKanonaks):void 0}case"display-label":{let r={publisher:e.labelTarget.publisher,package_:e.labelTarget.package_,name:e.labelTarget.name},o=await this.resolver.resolveSubject(r,this.allKanonaks);if(o){let a=We(o,e.labelSource);if(typeof a=="string"&&a.length>0)return a}return e.labelTarget.name}default:{let r=e;throw new we(`Unhandled expression kind: ${JSON.stringify(r)}`)}}}async buildAstNode(e,t){let r={kind:e.astClass.name};for(let o of e.set){let a=await this.evaluate(o.value,t);if(a==null||Array.isArray(a)&&a.length===0)continue;let s=o.field.name;Array.isArray(a)&&Eo.has(s)&&a.every(c=>_o(c))&&(a=a.map(c=>String(c)).join("")),r[s]=a}return r}},Eo=new Set(["stringValue","text","rawContent","key"]);function _o(n){return typeof n=="string"||typeof n=="number"||typeof n=="boolean"}function We(n,e){let t=[];for(let o of n.statement){let a=o.predicate;a?.subject&&M(a.subject,e)&&t.push(o)}if(t.length===0)return;if(t.length===1&&t[0]instanceof Po)return Ro(t[0].object);if(t.length===1)return Bn(t[0]);let r=[];for(let o of t){let a=Bn(o);a!==void 0&&r.push(a)}return r}function Ro(n){let e=[];for(let t of n)t instanceof $o?e.push(t.value):e.push(t);return e}function Bn(n){if(n instanceof vo||n instanceof Do||n instanceof Ao||n instanceof Ko||n instanceof Co)return n.object}function Vn(n){return n==null?!1:typeof n=="string"||Array.isArray(n)?n.length>0:!0}function Io(n){return n==null?!1:typeof n=="boolean"?n:typeof n=="string"?n.length>0:typeof n=="number"?n!==0:Array.isArray(n)?n.length>0:!0}function Xe(n){return n==null?[]:Array.isArray(n)?n:[n]}function Hn(n){return n!==null&&typeof n=="object"&&"publisher"in n&&"package_"in n&&"name"in n}import{EmbeddedKanonak as To,ReferenceKanonak as Je,SubjectKanonak as jo,ListStatement as qn,StringStatement as xo,ReferenceStatement as Ye}from"@kanonak-protocol/sdk";var v=class extends Error{constructor(t,r){super(`${t} (at ${r})`);this.path=r}path},zn=16;function Uo(n){return n.predicate?.subject}function Gn(n,e){let t=[];for(let r of n.statement){let o=Uo(r);o&&M(o,e)&&t.push(r)}return t}function U(n,e){let t=B(n,e);if(t)return t;let r=Q(n,e);if(r.length===1&&r[0]instanceof Je)return r[0].subject}function $e(n,e){let t=Q(n,e),r=[];for(let o of t)o instanceof To&&r.push(o);return r}function Wn(n,e){let t=[];for(let r of Gn(n,e))if(r instanceof xo)t.push(r.object);else if(r instanceof qn)for(let o of r.object)typeof o=="string"?t.push(o):o instanceof Je&&t.push(o.subject.name);else r instanceof Ye&&t.push(r.object.subject.name);return t}function Oo(n,e){let t=n.split("/");if(t.length<3)throw new v(`Invalid property URI "${n}" \u2014 expected publisher/package/name`,e);let[r,o,...a]=t;return{publisher:r,package_:o,name:a.join("/")}}function ne(n,e){let t=n.name,r=`transformation[${t}]`,o={catalog:e,depth:0},a=H(n,f.inputPattern);if(!a)throw new v("Transformation has no inputPattern",r);let s=Lo(a,o,`${r}.inputPattern`),c=H(n,f.rule);if(!c)throw new v("Transformation has no rule",r);let i=ee(c,o,`${r}.rule`),l=H(n,f.artifactName);if(!l)throw new v("Transformation has no artifactName",r);let u=ee(l,o,`${r}.artifactName`),d=new Set;for(let y of Gn(n,f.outputs))if(y instanceof Ye)d.add(y.object.subject.name);else if(y instanceof qn)for(let g of y.object)g instanceof Je&&d.add(g.subject.name);if(d.size===0)throw new v("Transformation has no outputs",r);let m=new Map;for(let y of $e(n,f.formatOverrides)){let g=`${r}.formatOverrides[]`,k=U(y,f.formatTarget);if(!k)throw new v("FormatOverride missing formatTarget",g);m.set(k.name,No(y,g))}return{name:t,inputPattern:s,rule:i,artifactName:u,outputs:d,overrides:m}}function Lo(n,e,t){let r=U(n,f.matchesClass);if(!r)throw new v("InputPattern has no matchesClass",t);let o={publisher:r.publisher,package_:r.package_,name:r.name},s=Wn(n,f.requires).map((c,i)=>Oo(c,`${t}.requires[${i}]`));return{matchesClass:o,requires:s}}function No(n,e){let t=Wn(n,f.metadataKeys),r=t.length>0?t:void 0,o=new Map;for(let c of $e(n,f.metadataRenames)){let i=C(c,f.fromKey),l=C(c,f.toKey);i&&l&&o.set(i,l)}let a=le(n,f.trailingNewline);return{metadataKeys:r,metadataRenames:o,trailingNewline:typeof a=="boolean"?a:void 0}}function ee(n,e,t){let r=U(n,f.kind);if(!r)throw new v("Expression has no kind",t);let o=r.name;switch(o){case"build-ast-node":return Bo(n,e,t);case"for-each":return Vo(n,e,t);case"when":return Ho(n,e,t);case"concat":return zo(n,e,t);case"string-literal":return{kind:"string-literal",value:ue(n,f.stringLiteral,t)};case"integer-literal":return{kind:"integer-literal",value:Yo(n,f.integerLiteral,t)};case"boolean-literal":return{kind:"boolean-literal",value:Zo(n,f.booleanLiteral,t)};case"var-ref":return{kind:"var-ref",varName:ue(n,f.varName,t)};case"property-read":return qo(n,e,t);case"traverse":return Go(n,e,t);case"fallback":return Wo(n,e,t);case"uri-name":return{kind:"uri-name",of:R(n,f.uriNameOf,e,`${t}.uriNameOf`)};case"list-map":return Xo(n,e,t);case"join":return{kind:"join",separator:ue(n,f.separator,t),items:R(n,f.items,e,`${t}.items`)};case"normalize":return Jo(n,e,t);case"is-set":return{kind:"is-set",check:R(n,f.checkExpr,e,`${t}.checkExpr`)};case"uri-literal":{let a=U(n,f.refTo);if(!a)throw new v("uri-literal has no refTo",t);return{kind:"uri-literal",refTo:{publisher:a.publisher,package_:a.package_,name:a.name}}}case"display-label":{let a=U(n,f.labelTarget);if(!a)throw new v("display-label has no labelTarget",t);let s=U(n,f.labelSource);if(!s)throw new v("display-label has no labelSource",t);return{kind:"display-label",labelTarget:{publisher:a.publisher,package_:a.package_,name:a.name},labelSource:{publisher:s.publisher,package_:s.package_,name:s.name}}}case"resolve-ref":return{kind:"resolve-ref",source:R(n,f.resolveSource,e,`${t}.resolveSource`)};case"call-fragment":{if(e.depth>=zn)throw new v(`call-fragment recursion exceeded ${zn} levels (cycle?)`,t);let a=U(n,f.fragmentRef);if(!a)throw new v("call-fragment has no fragmentRef",t);let s=Fo(e.catalog,a);if(!s)throw new v(`call-fragment: no ExpressionFragment found matching ${a.publisher}/${a.package_}/${a.name} \u2014 either the fragment is missing or its package is not in the compilation catalog`,t);let c=H(s,f.expr);if(!c)throw new v(`ExpressionFragment "${s.name}" has no expr`,t);let i={catalog:e.catalog,depth:e.depth+1};return ee(c,i,`${t}\u2192fragment[${s.name}]`)}default:throw new v(`Unknown ExpressionKind "${o}"`,t)}}function Fo(n,e){for(let t of n)if(t instanceof jo&&t.name===e.name&&t.namespace&&t.namespace.startsWith(`${e.publisher}/${e.package_}@`)&&Mo(t))return t}function Mo(n){for(let e of n.statement){let t=e.predicate;if(!(!t||t.subject?.name!=="type")&&e instanceof Ye){let r=e.object.subject;if(r.publisher===f.ExpressionFragment.publisher&&r.package_===f.ExpressionFragment.package_&&r.name===f.ExpressionFragment.name)return!0}}return!1}function Bo(n,e,t){let r=U(n,f.astClass);if(!r)throw new v("build-ast-node has no astClass",t);let o={publisher:r.publisher,package_:r.package_,name:r.name},a=[];return $e(n,f.set).forEach((c,i)=>{let l=`${t}.set[${i}]`,u=U(c,f.field);if(!u)throw new v("AstFieldBinding has no field",l);let d=R(c,f.bindValue,e,`${l}.bindValue`);a.push({field:{publisher:u.publisher,package_:u.package_,name:u.name},value:d})}),{kind:"build-ast-node",astClass:o,set:a}}function Vo(n,e,t){return{kind:"for-each",iterate:R(n,f.iterate,e,`${t}.iterate`),loopVar:ue(n,f.loopVar,t),emit:R(n,f.emit,e,`${t}.emit`)}}function Ho(n,e,t){let r=H(n,f.elseBuild);return{kind:"when",condition:R(n,f.condition,e,`${t}.condition`),thenBuild:R(n,f.thenBuild,e,`${t}.thenBuild`),elseBuild:r?ee(r,e,`${t}.elseBuild`):void 0}}function zo(n,e,t){return{kind:"concat",parts:$e(n,f.parts).map((o,a)=>ee(o,e,`${t}.parts[${a}]`))}}function qo(n,e,t){let r=U(n,f.readProp);if(!r)throw new v("property-read has no readProp",t);return{kind:"property-read",source:R(n,f.readSource,e,`${t}.readSource`),readProp:{publisher:r.publisher,package_:r.package_,name:r.name}}}function Go(n,e,t){let r=U(n,f.through);if(!r)throw new v("traverse has no through",t);return{kind:"traverse",source:R(n,f.traverseSource,e,`${t}.traverseSource`),through:{publisher:r.publisher,package_:r.package_,name:r.name},step:R(n,f.step,e,`${t}.step`)}}function Wo(n,e,t){return{kind:"fallback",primary:R(n,f.primary,e,`${t}.primary`),alternate:R(n,f.alternate,e,`${t}.alternate`)}}function Xo(n,e,t){return{kind:"list-map",source:R(n,f.listMapSource,e,`${t}.listMapSource`),loopVar:ue(n,f.loopVar,t),mapBody:R(n,f.mapBody,e,`${t}.mapBody`)}}function Jo(n,e,t){let r=U(n,f.normKind);if(!r)throw new v("normalize has no normKind",t);let o=r.name;if(o!=="trim-end")throw new v(`Unknown NormalizeKind "${o}"`,t);return{kind:"normalize",source:R(n,f.normSource,e,`${t}.normSource`),normKind:o}}function R(n,e,t,r){let o=H(n,e);if(!o){let a=`${e.publisher}/${e.package_}/${e.name}`,s=n.statement.length,c=n.statement.some(u=>{let d=u.predicate?.subject;return d&&d.publisher==="kanonak.org"&&d.package_==="transformations"&&d.name==="kind"}),i=`${e.publisher}/${e.package_}`,l;throw s===0?l=" (parent Expression has no statements at all \u2014 the parser produced an empty node, which usually means the containing YAML block did not resolve to an Expression-typed embedded)":c&&s<3?l=` \u2014 expected property ${a} but the parent Expression only has ${s} statement(s) including its 'kind'. The most likely cause is a STALE local copy of the Kanonak package ${i} that declares the expression kind but not the '${e.name}' property. Refresh your workspace copy of ${i} and re-resolve imports so the runner picks up the current property definitions.`:l=` \u2014 expected property ${a}. Parent Expression has ${s} statement(s) but none match that predicate URI. Either the YAML is missing the '${e.name}' key for this expression kind, or your local copy of the Kanonak package ${i} is out of date.`,new v(`missing child expression${l}`,r)}return ee(o,t,r)}function ue(n,e,t){let r=C(n,e);if(typeof r!="string")throw new v(`missing required string property "${e.name}"`,t);return r}function Yo(n,e,t){let r=le(n,e);if(typeof r!="number")throw new v(`missing required integer property "${e.name}"`,t);return r}function Zo(n,e,t){let r=le(n,e);if(typeof r!="boolean")throw new v(`missing required boolean property "${e.name}"`,t);return r}function Xn(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var ve=class{backendUri="kanonak.org/transformations/markdown-with-frontmatter";render(e,t){let r=Qo(e.metadata,t),o=ta(e.children),s=["---",...r,"---","",o].join(`
57
+ ${t}`),process.exit(1)}}import{Command as sr}from"commander";import{KanonakParser as ir,KanonakObjectParser as cr,PublisherIndex as lr,CredentialStore as ur,createAuthenticatedFetch as dr,computeIntegrity as mr}from"@kanonak-protocol/sdk";import{readFileSync as xo,writeFileSync as jo,existsSync as Uo}from"fs";import{join as No}from"path";import Kn from"js-yaml";import{getGlobalCachePath as Oo}from"@kanonak-protocol/sdk";var Lo=`# This file is generated by Kanonak CLI. Do not edit manually.
58
+ `;function An(){let n=Oo();return No(n,"..","capabilities.lock")}function Y(){let n=An();if(!Uo(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=xo(n,"utf-8"),t=Kn.load(e);return!t||typeof t!="object"||t.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}}:{version:"1",lastUpdated:t.lastUpdated??new Date().toISOString(),capabilities:t.capabilities??{}}}function ze(n){n.lastUpdated=new Date().toISOString();let e={};for(let o of Object.keys(n.capabilities).sort())e[o]=n.capabilities[o];n.capabilities=e;let t=Kn.dump(n,{lineWidth:-1,sortKeys:!1,quotingType:'"'});jo(An(),Lo+t,"utf-8")}var A=class{constructor(e,t){this.doc=e;this.broader=t}doc;broader;async getAllDocumentsAsync(){return[this.doc]}async getDocumentAsync(e){return this.broader.getDocumentAsync(e)}async getDocumentsByNamespaceAsync(e,t){return this.broader.getDocumentsByNamespaceAsync(e,t)}async getHighestCompatibleVersionAsync(e,t){return this.broader.getHighestCompatibleVersionAsync(e,t)}async saveDocumentAsync(){throw new Error("SingleDocumentRepository is read-only")}async deleteDocumentAsync(){throw new Error("SingleDocumentRepository is read-only")}async clearNamespaceAsync(){throw new Error("SingleDocumentRepository is read-only")}async getAllDocumentReferencesAsync(){return[]}async getDocumentContentAsync(e){return this.broader.getDocumentContentAsync(e)}async getDocumentUriAsync(e){return this.broader.getDocumentUriAsync(e)}};import{KanonakObjectParser as Go,EmbeddedKanonak as Rn,ReferenceKanonak as Tn}from"@kanonak-protocol/sdk";import{SubjectKanonak as Cn,DefinedKanonak as Fo,StringStatement as Mo,NumberStatement as Bo,BooleanStatement as Vo,ReferenceStatement as Pn,EmbeddedStatement as Ho,ListStatement as zo}from"@kanonak-protocol/sdk";function N(n){return`${n.publisher}/${n.package_}/${n.name}`}function F(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}function qo(n,e){if(!(n instanceof Fo))return!1;for(let t of n.statement)if(t.predicate?.subject?.name==="type"&&t instanceof Pn){let r=t.object;if(F(r.subject,e))return!0}return!1}function C(n,e){let t=[];for(let o of n)o instanceof Cn&&qo(o,e)&&t.push(o);return t}function ge(n,e){for(let t of n){if(!(t instanceof Cn)||t.name!==e.name)continue;if((t.namespace||"").startsWith(`${e.publisher}/${e.package_}@`))return t}}function he(n,e){for(let t of n.statement){let o=t.predicate;if(o?.subject&&F(o.subject,e))return t}}function ce(n,e){let t=he(n,e);if(t&&(t instanceof Mo||t instanceof Bo||t instanceof Vo))return t.object}function P(n,e){let t=ce(n,e);return typeof t=="string"?t:void 0}function M(n,e){let t=he(n,e);if(t instanceof Pn)return t.object.subject}function V(n,e){let t=he(n,e);if(t instanceof Ho)return t.object}function Z(n,e){let t=he(n,e);return t instanceof zo?t.object??[]:[]}var E="kanonak.org",_="capabilities",qe={publisher:E,package_:_,name:"Capability"},Wo={publisher:E,package_:_,name:"commandName"},xn={publisher:E,package_:_,name:"description"},Xo={publisher:E,package_:_,name:"managesType"},Jo={publisher:E,package_:_,name:"deploymentTarget"},Yo={publisher:E,package_:_,name:"hasCommand"},Zo={publisher:E,package_:_,name:"subcommandName"},Qo={publisher:E,package_:_,name:"performs"},er={publisher:E,package_:_,name:"hasArgument"},nr={publisher:E,package_:_,name:"argumentName"},En={publisher:E,package_:_,name:"isRequired"},_n={publisher:E,package_:_,name:"isOption"},tr={publisher:E,package_:_,name:"defaultValue"};async function jn(n,e,t){let o=Y(),r=new Go,a=[];for(let[s,c]of Object.entries(o.capabilities)){let i=n.get(c.publisher,c.package_,c.version);if(!i){console.error(` WARNING: Cached content missing for capability "${s}" (${c.publisher}/${c.package_}@${c.version})`);continue}try{let l=e.parse(i),u=new A(l,t),d=await r.parseKanonaks(u),m=or(d,c.publisher,c.package_,c.version);m?a.push(m):console.error(` WARNING: No Capability instance found in "${s}" (${c.publisher}/${c.package_}@${c.version})`)}catch(l){console.error(` WARNING: Failed to parse capability "${s}": ${l}`)}}return a}function or(n,e,t,o){let r=C(n,qe);if(r.length===0)return;let a=r[0],s=P(a,Wo)??"",c=P(a,xn)??"",i=M(a,Xo),l=M(a,Jo),u=[];for(let d of Z(a,Yo)){let m=rr(d,n);m&&u.push(m)}return{commandName:s,description:c,managesTypeKey:i?N(i):"",deploymentTargetKey:l?N(l):"",commands:u,publisher:e,package_:t,version:o}}function rr(n,e){let t;if(n instanceof Rn)t=n;else if(n instanceof Tn){let i=Un(e,n.subject.publisher,n.subject.package_,n.subject.name);i&&(t=i)}if(!t)return;let o=P(t,Zo)??"",r=P(t,xn)??"",a=M(t,Qo),s=Z(t,er),c=[];for(let i of s){let l=ar(i,e);l&&c.push(l)}return{subcommandName:o,description:r,arguments:c,actionKey:a?N(a):""}}function ar(n,e){let t;if(n instanceof Rn)t=n;else if(n instanceof Tn){let i=Un(e,n.subject.publisher,n.subject.package_,n.subject.name);i&&(t=i)}if(!t)return;let o=P(t,nr)??"",r=P(t,En)==="true"||In(t,En)===!0,a=P(t,_n)==="true"||In(t,_n)===!0,s=P(t,tr),c={argumentName:o,required:r,isOption:a};return s!==void 0&&(c.defaultValue=s),c}function In(n,e){for(let t of n.statement){let o=t,r=o.predicate;if(r?.subject&&r.subject.publisher===e.publisher&&r.subject.package_===e.package_&&r.subject.name===e.name)return typeof o.object=="boolean"?o.object:void 0}}function Un(n,e,t,o){for(let r of n){if(!("name"in r)||!("namespace"in r))continue;let a=r;if(a.name===o&&!(!a.namespace||typeof a.namespace!="string")&&a.namespace.startsWith(`${e}/${t}@`))return r}}var pr={publisher:E,package_:_,name:"commandName"};function Nn(){let n=new sr("capability").description("Manage Kanonak CLI capabilities (pluggable command groups)");return n.command("add <package>").description("Install a capability from a Kanonak publisher").action(async e=>{await fr(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await gr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await hr()}),n}async function fr(n){let e=G(n);e||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:t,packageName:o,version:r,instanceName:a}=e;a&&(console.error(`\`kanonak capability add\` installs whole packages \u2014 got an instance suffix "/${a}".`),console.error(`Try: kanonak capability add ${t}/${o}${r?"@"+r:""}`),process.exit(1));let s=new T,c=new ir,i=new cr,l=new ur,u=dr(l),d=new lr({fetchFn:u}),m=r??await d.getHighestVersion(t,o);m||(console.error(`Could not resolve version for "${t}/${o}".`),process.exit(1)),console.log(`Installing capability ${t}/${o}@${m}...`);let k=s.get(t,o,m);if(!k){let q=await d.getPackageUrl(t,o,m),pe=await u(q,t);if(!pe.ok)throw new Error(`Failed to fetch ${q} (${pe.status} ${pe.statusText})`);k=await pe.text(),s.put(t,o,m,k)}let b=c.parse(k),f=await x(process.cwd(),c),h=new A(b,f),g=await i.parseKanonaks(h),w=C(g,qe);w.length===0&&(console.error(`Package ${t}/${o}@${m} does not contain a ${E}/${_}/Capability instance.`),process.exit(1));let $=w[0],v=P($,pr);v||(console.error(`Capability instance in ${t}/${o}@${m} has no commandName property.`),process.exit(1));let D=Y();D.capabilities[v]={publisher:t,package_:o,version:m,resolved:await d.getPackageUrl(t,o,m),integrity:mr(k)},ze(D),console.log(`
59
+ Installed capability "${v}".`),console.log(`Run "kanonak ${v} --help" to get started.`)}async function gr(n){let e=Y();e.capabilities[n]||(console.error(`Capability "${n}" is not installed.`),process.exit(1));let t=e.capabilities[n];delete e.capabilities[n],ze(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function hr(){let n=Y(),e=Object.entries(n.capabilities);if(e.length===0){console.log("No capabilities installed."),console.log("Install one with: kanonak capability add {publisher}/{package}");return}console.log(`Installed capabilities:
60
+ `);for(let[t,o]of e)console.log(` ${t} ${o.publisher}/${o.package_}@${o.version}`)}import{Command as de}from"commander";import{readFileSync as $a,writeFileSync as Sa,mkdirSync as va,existsSync as rt,statSync as Da}from"fs";import{join as Ka,resolve as Aa}from"path";import{KanonakParser as Qe,KanonakObjectParser as en,SubjectKanonak as Ca,Reasoner as Pa,KanonakVocabulary as Ea,makeUriKey as st,pickHighestDocument as nn,formatVersion as it}from"@kanonak-protocol/sdk";var kr="kanonak.org",yr="document-ast",S=n=>({publisher:kr,package_:yr,name:n}),j={Document:S("Document"),Block:S("Block"),Inline:S("Inline"),StructuredValue:S("StructuredValue"),Heading:S("Heading"),Paragraph:S("Paragraph"),RawBlock:S("RawBlock"),Text:S("Text"),StructuredMap:S("StructuredMap"),StructuredEntry:S("StructuredEntry"),StructuredList:S("StructuredList"),StringScalar:S("StringScalar"),IntegerScalar:S("IntegerScalar"),EscapeHint:S("EscapeHint"),MediaType:S("MediaType"),metadata:S("metadata"),children:S("children"),level:S("level"),inlines:S("inlines"),text:S("text"),entries:S("entries"),key:S("key"),value:S("value"),escapeHint:S("escapeHint"),items:S("items"),stringValue:S("stringValue"),integerValue:S("integerValue"),rawContent:S("rawContent"),mediaType:S("mediaType"),mimeType:S("mimeType"),ESC_RAW:S("esc-raw"),ESC_YAML_SAFE:S("esc-yaml-safe"),ESC_TOML_STRING:S("esc-toml-string"),ESC_TOML_MULTILINE:S("esc-toml-multiline"),ESC_JSON:S("esc-json"),TEXT_PLAIN:S("text-plain"),TEXT_MARKDOWN:S("text-markdown"),TEXT_HTML:S("text-html"),APPLICATION_JSON:S("application-json"),TEXT_YAML:S("text-yaml"),IMAGE_SVG_XML:S("image-svg-xml")},br="kanonak.org",wr="transformations",p=n=>({publisher:br,package_:wr,name:n}),y={Transformation:p("Transformation"),InputPattern:p("InputPattern"),Expression:p("Expression"),ExpressionKind:p("ExpressionKind"),ExpressionFragment:p("ExpressionFragment"),AstFieldBinding:p("AstFieldBinding"),OutputFormat:p("OutputFormat"),FormatOverride:p("FormatOverride"),RenameEntry:p("RenameEntry"),Artifact:p("Artifact"),NormalizeKind:p("NormalizeKind"),inputPattern:p("inputPattern"),rule:p("rule"),artifactName:p("artifactName"),outputs:p("outputs"),formatOverrides:p("formatOverrides"),matchesClass:p("matchesClass"),requires:p("requires"),kind:p("kind"),astClass:p("astClass"),set:p("set"),iterate:p("iterate"),loopVar:p("loopVar"),emit:p("emit"),condition:p("condition"),thenBuild:p("thenBuild"),elseBuild:p("elseBuild"),parts:p("parts"),stringLiteral:p("stringLiteral"),integerLiteral:p("integerLiteral"),booleanLiteral:p("booleanLiteral"),varName:p("varName"),readSource:p("readSource"),readProp:p("readProp"),traverseSource:p("traverseSource"),through:p("through"),step:p("step"),primary:p("primary"),alternate:p("alternate"),uriNameOf:p("uriNameOf"),listMapSource:p("listMapSource"),mapBody:p("mapBody"),separator:p("separator"),items:p("items"),normSource:p("normSource"),normKind:p("normKind"),checkExpr:p("checkExpr"),refTo:p("refTo"),fragmentRef:p("fragmentRef"),expr:p("expr"),labelTarget:p("labelTarget"),labelSource:p("labelSource"),resolveSource:p("resolveSource"),field:p("field"),bindValue:p("bindValue"),backendUri:p("backendUri"),formatTarget:p("formatTarget"),metadataKeys:p("metadataKeys"),metadataRenames:p("metadataRenames"),trailingNewline:p("trailingNewline"),fromKey:p("fromKey"),toKey:p("toKey"),KIND_BUILD_AST_NODE:p("build-ast-node"),KIND_FOR_EACH:p("for-each"),KIND_WHEN:p("when"),KIND_CONCAT:p("concat"),KIND_STRING_LITERAL:p("string-literal"),KIND_INTEGER_LITERAL:p("integer-literal"),KIND_BOOLEAN_LITERAL:p("boolean-literal"),KIND_VAR_REF:p("var-ref"),KIND_PROPERTY_READ:p("property-read"),KIND_TRAVERSE:p("traverse"),KIND_FALLBACK:p("fallback"),KIND_URI_NAME:p("uri-name"),KIND_LIST_MAP:p("list-map"),KIND_JOIN:p("join"),KIND_NORMALIZE:p("normalize"),KIND_IS_SET:p("is-set"),KIND_URI_LITERAL:p("uri-literal"),KIND_CALL_FRAGMENT:p("call-fragment"),KIND_DISPLAY_LABEL:p("display-label"),KIND_RESOLVE_REF:p("resolve-ref"),NORM_TRIM_END:p("trim-end"),FMT_MARKDOWN_FRONTMATTER:p("markdown-with-frontmatter"),FMT_TOML:p("toml"),FMT_JSON:p("json"),FMT_PLAIN_MARKDOWN:p("plain-markdown")};import{SubjectKanonak as On}from"@kanonak-protocol/sdk";var ke=class{constructor(e,t,o){this.repository=e;this.parser=t;this.objectParser=o}repository;parser;objectParser;cache=new Map;async resolveSubject(e,t){let o=ge(t,e);if(o)return o;let r=`${e.publisher}/${e.package_}`,a=this.cache.get(r);if(!a){let s=await this.repository.getDocumentsByNamespaceAsync(e.publisher,e.package_);if(s.length===0)return;let c=s[0],i=new A(c,this.repository);a=await this.objectParser.parseKanonaks(i),this.cache.set(r,a)}for(let s of a)if(s instanceof On&&s.name===e.name&&s.namespace&&s.namespace.startsWith(`${e.publisher}/${e.package_}@`))return s;for(let s of a)if(s instanceof On&&s.name===e.name)return s}};import{DefinedKanonak as Ln,LiteralKanonak as $r,ReferenceKanonak as ye,StringStatement as Sr,NumberStatement as vr,BooleanStatement as Dr,ReferenceStatement as Kr,EmbeddedStatement as Ar,ListStatement as Cr}from"@kanonak-protocol/sdk";var be=class extends Error{constructor(e){super(e)}},we=class{constructor(e,t){this.resolver=e;this.allKanonaks=t}resolver;allKanonaks;async evaluate(e,t){switch(e.kind){case"var-ref":{if(!t.has(e.varName))throw new be(`Unbound variable "${e.varName}"`);return t.get(e.varName)}case"string-literal":return e.value;case"integer-literal":return e.value;case"boolean-literal":return e.value;case"uri-literal":return{...e.refTo};case"property-read":{let o=await this.evaluate(e.source,t);return o instanceof Ln?Ge(o,e.readProp):void 0}case"traverse":{let o=await this.evaluate(e.source,t);if(!(o instanceof Ln))return;let r=Ge(o,e.through),a;if(r instanceof ye?a=r.subject:Array.isArray(r)&&r.length>0&&r[0]instanceof ye&&(a=r[0].subject),!a)return;let s=await this.resolver.resolveSubject(a,this.allKanonaks);if(!s)return;let c=new Map(t);return c.set("input",s),this.evaluate(e.step,c)}case"fallback":{let o=await this.evaluate(e.primary,t);return Mn(o)?o:this.evaluate(e.alternate,t)}case"uri-name":{let o=await this.evaluate(e.of,t);return o instanceof ye?o.subject.name:Bn(o)?o.name:void 0}case"list-map":{let o=await this.evaluate(e.source,t),r=We(o),a=[];for(let s of r){let c=new Map(t);c.set(e.loopVar,s),a.push(await this.evaluate(e.mapBody,c))}return a}case"join":{let o=await this.evaluate(e.items,t),r=We(o),a=[];for(let s of r)s!=null&&a.push(String(s));return a.join(e.separator)}case"normalize":{let o=await this.evaluate(e.source,t);return typeof o!="string"?o:e.normKind==="trim-end"?o.trimEnd():o}case"is-set":{let o=await this.evaluate(e.check,t);return Mn(o)}case"when":{let o=await this.evaluate(e.condition,t);return Ir(o)?this.evaluate(e.thenBuild,t):e.elseBuild?this.evaluate(e.elseBuild,t):void 0}case"concat":{let o=[];for(let r of e.parts){let a=await this.evaluate(r,t);if(a!=null)if(Array.isArray(a))for(let s of a)o.push(s);else o.push(a)}return o}case"for-each":{let o=await this.evaluate(e.iterate,t),r=We(o),a=[];for(let s of r){let c=new Map(t);c.set(e.loopVar,s);let i=await this.evaluate(e.emit,c);if(i!=null)if(Array.isArray(i))for(let l of i)a.push(l);else a.push(i)}return a}case"build-ast-node":return this.buildAstNode(e,t);case"resolve-ref":{let o=await this.evaluate(e.source,t),r;return o instanceof ye?r=o.subject:Bn(o)&&(r=o),r?this.resolver.resolveSubject(r,this.allKanonaks):void 0}case"display-label":{let o={publisher:e.labelTarget.publisher,package_:e.labelTarget.package_,name:e.labelTarget.name},r=await this.resolver.resolveSubject(o,this.allKanonaks);if(r){let a=Ge(r,e.labelSource);if(typeof a=="string"&&a.length>0)return a}return e.labelTarget.name}default:{let o=e;throw new be(`Unhandled expression kind: ${JSON.stringify(o)}`)}}}async buildAstNode(e,t){let o={kind:e.astClass.name};for(let r of e.set){let a=await this.evaluate(r.value,t);if(a==null||Array.isArray(a)&&a.length===0)continue;let s=r.field.name;Array.isArray(a)&&Pr.has(s)&&a.every(c=>Er(c))&&(a=a.map(c=>String(c)).join("")),o[s]=a}return o}},Pr=new Set(["stringValue","text","rawContent","key"]);function Er(n){return typeof n=="string"||typeof n=="number"||typeof n=="boolean"}function Ge(n,e){let t=[];for(let r of n.statement){let a=r.predicate;a?.subject&&F(a.subject,e)&&t.push(r)}if(t.length===0)return;if(t.length===1&&t[0]instanceof Cr)return _r(t[0].object);if(t.length===1)return Fn(t[0]);let o=[];for(let r of t){let a=Fn(r);a!==void 0&&o.push(a)}return o}function _r(n){let e=[];for(let t of n)t instanceof $r?e.push(t.value):e.push(t);return e}function Fn(n){if(n instanceof Sr||n instanceof vr||n instanceof Dr||n instanceof Kr||n instanceof Ar)return n.object}function Mn(n){return n==null?!1:typeof n=="string"||Array.isArray(n)?n.length>0:!0}function Ir(n){return n==null?!1:typeof n=="boolean"?n:typeof n=="string"?n.length>0:typeof n=="number"?n!==0:Array.isArray(n)?n.length>0:!0}function We(n){return n==null?[]:Array.isArray(n)?n:[n]}function Bn(n){return n!==null&&typeof n=="object"&&"publisher"in n&&"package_"in n&&"name"in n}import{EmbeddedKanonak as Rr,LiteralKanonak as Tr,ReferenceKanonak as Xe,SubjectKanonak as xr,ListStatement as Hn,StringStatement as jr,ReferenceStatement as Je}from"@kanonak-protocol/sdk";var K=class extends Error{constructor(t,o){super(`${t} (at ${o})`);this.path=o}path},Vn=16;function Ur(n){return n.predicate?.subject}function zn(n,e){let t=[];for(let o of n.statement){let r=Ur(o);r&&F(r,e)&&t.push(o)}return t}function U(n,e){let t=M(n,e);if(t)return t;let o=Z(n,e);if(o.length===1&&o[0]instanceof Xe)return o[0].subject}function $e(n,e){let t=Z(n,e),o=[];for(let r of t)r instanceof Rr&&o.push(r);return o}function qn(n,e){let t=[];for(let o of zn(n,e))if(o instanceof jr)t.push(o.object);else if(o instanceof Hn)for(let r of o.object)typeof r=="string"?t.push(r):r instanceof Tr?typeof r.value=="string"&&t.push(r.value):r instanceof Xe&&t.push(r.subject.name);else o instanceof Je&&t.push(o.object.subject.name);return t}function Nr(n,e){let t=n.split("/");if(t.length<3)throw new K(`Invalid property URI "${n}" \u2014 expected publisher/package/name`,e);let[o,r,...a]=t;return{publisher:o,package_:r,name:a.join("/")}}function ee(n,e){let t=n.name,o=`transformation[${t}]`,r={catalog:e,depth:0},a=V(n,y.inputPattern);if(!a)throw new K("Transformation has no inputPattern",o);let s=Or(a,r,`${o}.inputPattern`),c=V(n,y.rule);if(!c)throw new K("Transformation has no rule",o);let i=Q(c,r,`${o}.rule`),l=V(n,y.artifactName);if(!l)throw new K("Transformation has no artifactName",o);let u=Q(l,r,`${o}.artifactName`),d=new Set;for(let k of zn(n,y.outputs))if(k instanceof Je)d.add(k.object.subject.name);else if(k instanceof Hn)for(let b of k.object)b instanceof Xe&&d.add(b.subject.name);if(d.size===0)throw new K("Transformation has no outputs",o);let m=new Map;for(let k of $e(n,y.formatOverrides)){let b=`${o}.formatOverrides[]`,f=U(k,y.formatTarget);if(!f)throw new K("FormatOverride missing formatTarget",b);m.set(f.name,Lr(k,b))}return{name:t,inputPattern:s,rule:i,artifactName:u,outputs:d,overrides:m}}function Or(n,e,t){let o=U(n,y.matchesClass);if(!o)throw new K("InputPattern has no matchesClass",t);let r={publisher:o.publisher,package_:o.package_,name:o.name},s=qn(n,y.requires).map((c,i)=>Nr(c,`${t}.requires[${i}]`));return{matchesClass:r,requires:s}}function Lr(n,e){let t=qn(n,y.metadataKeys),o=t.length>0?t:void 0,r=new Map;for(let c of $e(n,y.metadataRenames)){let i=P(c,y.fromKey),l=P(c,y.toKey);i&&l&&r.set(i,l)}let a=ce(n,y.trailingNewline);return{metadataKeys:o,metadataRenames:r,trailingNewline:typeof a=="boolean"?a:void 0}}function Q(n,e,t){let o=U(n,y.kind);if(!o)throw new K("Expression has no kind",t);let r=o.name;switch(r){case"build-ast-node":return Br(n,e,t);case"for-each":return Vr(n,e,t);case"when":return Hr(n,e,t);case"concat":return zr(n,e,t);case"string-literal":return{kind:"string-literal",value:le(n,y.stringLiteral,t)};case"integer-literal":return{kind:"integer-literal",value:Yr(n,y.integerLiteral,t)};case"boolean-literal":return{kind:"boolean-literal",value:Zr(n,y.booleanLiteral,t)};case"var-ref":return{kind:"var-ref",varName:le(n,y.varName,t)};case"property-read":return qr(n,e,t);case"traverse":return Gr(n,e,t);case"fallback":return Wr(n,e,t);case"uri-name":return{kind:"uri-name",of:I(n,y.uriNameOf,e,`${t}.uriNameOf`)};case"list-map":return Xr(n,e,t);case"join":return{kind:"join",separator:le(n,y.separator,t),items:I(n,y.items,e,`${t}.items`)};case"normalize":return Jr(n,e,t);case"is-set":return{kind:"is-set",check:I(n,y.checkExpr,e,`${t}.checkExpr`)};case"uri-literal":{let a=U(n,y.refTo);if(!a)throw new K("uri-literal has no refTo",t);return{kind:"uri-literal",refTo:{publisher:a.publisher,package_:a.package_,name:a.name}}}case"display-label":{let a=U(n,y.labelTarget);if(!a)throw new K("display-label has no labelTarget",t);let s=U(n,y.labelSource);if(!s)throw new K("display-label has no labelSource",t);return{kind:"display-label",labelTarget:{publisher:a.publisher,package_:a.package_,name:a.name},labelSource:{publisher:s.publisher,package_:s.package_,name:s.name}}}case"resolve-ref":return{kind:"resolve-ref",source:I(n,y.resolveSource,e,`${t}.resolveSource`)};case"call-fragment":{if(e.depth>=Vn)throw new K(`call-fragment recursion exceeded ${Vn} levels (cycle?)`,t);let a=U(n,y.fragmentRef);if(!a)throw new K("call-fragment has no fragmentRef",t);let s=Fr(e.catalog,a);if(!s)throw new K(`call-fragment: no ExpressionFragment found matching ${a.publisher}/${a.package_}/${a.name} \u2014 either the fragment is missing or its package is not in the compilation catalog`,t);let c=V(s,y.expr);if(!c)throw new K(`ExpressionFragment "${s.name}" has no expr`,t);let i={catalog:e.catalog,depth:e.depth+1};return Q(c,i,`${t}\u2192fragment[${s.name}]`)}default:throw new K(`Unknown ExpressionKind "${r}"`,t)}}function Fr(n,e){for(let t of n)if(t instanceof xr&&t.name===e.name&&t.namespace&&t.namespace.startsWith(`${e.publisher}/${e.package_}@`)&&Mr(t))return t}function Mr(n){for(let e of n.statement){let t=e.predicate;if(!(!t||t.subject?.name!=="type")&&e instanceof Je){let o=e.object.subject;if(o.publisher===y.ExpressionFragment.publisher&&o.package_===y.ExpressionFragment.package_&&o.name===y.ExpressionFragment.name)return!0}}return!1}function Br(n,e,t){let o=U(n,y.astClass);if(!o)throw new K("build-ast-node has no astClass",t);let r={publisher:o.publisher,package_:o.package_,name:o.name},a=[];return $e(n,y.set).forEach((c,i)=>{let l=`${t}.set[${i}]`,u=U(c,y.field);if(!u)throw new K("AstFieldBinding has no field",l);let d=I(c,y.bindValue,e,`${l}.bindValue`);a.push({field:{publisher:u.publisher,package_:u.package_,name:u.name},value:d})}),{kind:"build-ast-node",astClass:r,set:a}}function Vr(n,e,t){return{kind:"for-each",iterate:I(n,y.iterate,e,`${t}.iterate`),loopVar:le(n,y.loopVar,t),emit:I(n,y.emit,e,`${t}.emit`)}}function Hr(n,e,t){let o=V(n,y.elseBuild);return{kind:"when",condition:I(n,y.condition,e,`${t}.condition`),thenBuild:I(n,y.thenBuild,e,`${t}.thenBuild`),elseBuild:o?Q(o,e,`${t}.elseBuild`):void 0}}function zr(n,e,t){return{kind:"concat",parts:$e(n,y.parts).map((r,a)=>Q(r,e,`${t}.parts[${a}]`))}}function qr(n,e,t){let o=U(n,y.readProp);if(!o)throw new K("property-read has no readProp",t);return{kind:"property-read",source:I(n,y.readSource,e,`${t}.readSource`),readProp:{publisher:o.publisher,package_:o.package_,name:o.name}}}function Gr(n,e,t){let o=U(n,y.through);if(!o)throw new K("traverse has no through",t);return{kind:"traverse",source:I(n,y.traverseSource,e,`${t}.traverseSource`),through:{publisher:o.publisher,package_:o.package_,name:o.name},step:I(n,y.step,e,`${t}.step`)}}function Wr(n,e,t){return{kind:"fallback",primary:I(n,y.primary,e,`${t}.primary`),alternate:I(n,y.alternate,e,`${t}.alternate`)}}function Xr(n,e,t){return{kind:"list-map",source:I(n,y.listMapSource,e,`${t}.listMapSource`),loopVar:le(n,y.loopVar,t),mapBody:I(n,y.mapBody,e,`${t}.mapBody`)}}function Jr(n,e,t){let o=U(n,y.normKind);if(!o)throw new K("normalize has no normKind",t);let r=o.name;if(r!=="trim-end")throw new K(`Unknown NormalizeKind "${r}"`,t);return{kind:"normalize",source:I(n,y.normSource,e,`${t}.normSource`),normKind:r}}function I(n,e,t,o){let r=V(n,e);if(!r){let a=`${e.publisher}/${e.package_}/${e.name}`,s=n.statement.length,c=n.statement.some(u=>{let d=u.predicate?.subject;return d&&d.publisher==="kanonak.org"&&d.package_==="transformations"&&d.name==="kind"}),i=`${e.publisher}/${e.package_}`,l;throw s===0?l=" (parent Expression has no statements at all \u2014 the parser produced an empty node, which usually means the containing YAML block did not resolve to an Expression-typed embedded)":c&&s<3?l=` \u2014 expected property ${a} but the parent Expression only has ${s} statement(s) including its 'kind'. The most likely cause is a STALE local copy of the Kanonak package ${i} that declares the expression kind but not the '${e.name}' property. Refresh your workspace copy of ${i} and re-resolve imports so the runner picks up the current property definitions.`:l=` \u2014 expected property ${a}. Parent Expression has ${s} statement(s) but none match that predicate URI. Either the YAML is missing the '${e.name}' key for this expression kind, or your local copy of the Kanonak package ${i} is out of date.`,new K(`missing child expression${l}`,o)}return Q(r,t,o)}function le(n,e,t){let o=P(n,e);if(typeof o!="string")throw new K(`missing required string property "${e.name}"`,t);return o}function Yr(n,e,t){let o=ce(n,e);if(typeof o!="number")throw new K(`missing required integer property "${e.name}"`,t);return o}function Zr(n,e,t){let o=ce(n,e);if(typeof o!="boolean")throw new K(`missing required boolean property "${e.name}"`,t);return o}function Gn(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var Se=class{backendUri="kanonak.org/transformations/markdown-with-frontmatter";render(e,t){let o=Qr(e.metadata,t),r=ta(e.children),s=["---",...o,"---","",r].join(`
62
61
  `);return t?.trailingNewline&&(s.endsWith(`
63
62
  `)||(s+=`
64
- `)),s}};function Qo(n,e){if(!n)return[];let t=new Map;for(let a of n.entries)t.set(a.key,a);let r=e?.metadataKeys??n.entries.map(a=>a.key),o=[];for(let a of r){let s=t.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=Yn(s.value,s.escapeHint);i!==void 0&&o.push(`${c}: ${i}`)}return o}function Yn(n,e){switch(n.kind){case"StringScalar":return ea(n.stringValue,e);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let t=[];for(let r of n.items){let o=Yn(r,e);o!==void 0&&t.push(o)}return t.join(", ")}case"StructuredMap":return;default:return}}function ea(n,e){return!e||Xn(e,x.ESC_RAW)?n:Xn(e,x.ESC_YAML_SAFE)?na(n):n}function na(n){return n.includes(`
63
+ `)),s}};function Qr(n,e){if(!n)return[];let t=new Map;for(let a of n.entries)t.set(a.key,a);let o=e?.metadataKeys??n.entries.map(a=>a.key),r=[];for(let a of o){let s=t.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=Xn(s.value,s.escapeHint);i!==void 0&&r.push(`${c}: ${i}`)}return r}function Xn(n,e){switch(n.kind){case"StringScalar":return ea(n.stringValue,e);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let t=[];for(let o of n.items){let r=Xn(o,e);r!==void 0&&t.push(r)}return t.join(", ")}case"StructuredMap":return;default:return}}function ea(n,e){return!e||Gn(e,j.ESC_RAW)?n:Gn(e,j.ESC_YAML_SAFE)?na(n):n}function na(n){return n.includes(`
65
64
  `)?`|-
66
65
  ${n.replace(/\n/g,`
67
- `).trimEnd()}`:/[:#\[\]{}&*!|>'"%@`,]/.test(n)?`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:n}function ta(n){let e=[];for(let t of n){let r=ra(t);r&&e.push(r)}return e.join(`
66
+ `).trimEnd()}`:/[:#\[\]{}&*!|>'"%@`,]/.test(n)?`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:n}function ta(n){let e=[];for(let t of n){let o=oa(t);o&&e.push(o)}return e.join(`
68
67
 
69
- `)}function ra(n){switch(n.kind){case"Heading":return`${"#".repeat(n.level)} ${Jn(n.inlines)}`;case"Paragraph":return Jn(n.inlines);case"RawBlock":return n.rawContent;default:return""}}function Jn(n){let e=[];for(let t of n)t.kind==="Text"&&e.push(t.text);return e.join("")}function oa(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var De=class{backendUri="kanonak.org/transformations/toml";render(e,t){let o=aa(e.metadata,t).join(`
70
- `);return t?.trailingNewline&&(o.endsWith(`
71
- `)||(o+=`
72
- `)),o}};function aa(n,e){if(!n)return[];let t=new Map;for(let a of n.entries)t.set(a.key,a);let r=e?.metadataKeys??n.entries.map(a=>a.key),o=[];for(let a of r){let s=t.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=Zn(s.value,s.escapeHint);i!==void 0&&o.push(`${c} = ${i}`)}return o}function Zn(n,e){switch(n.kind){case"StringScalar":return sa(n.stringValue,e);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let t=[];for(let r of n.items){let o=Zn(r,e);o!==void 0&&t.push(o)}return`[${t.join(", ")}]`}case"StructuredMap":return;default:return}}function sa(n,e){return e&&oa(e,x.ESC_TOML_MULTILINE)?ca(n):ia(n)}function ia(n){return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`}function ca(n){return`"""
68
+ `)}function oa(n){switch(n.kind){case"Heading":return`${"#".repeat(n.level)} ${Wn(n.inlines)}`;case"Paragraph":return Wn(n.inlines);case"RawBlock":return n.rawContent;default:return""}}function Wn(n){let e=[];for(let t of n)t.kind==="Text"&&e.push(t.text);return e.join("")}function ra(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var ve=class{backendUri="kanonak.org/transformations/toml";render(e,t){let r=aa(e.metadata,t).join(`
69
+ `);return t?.trailingNewline&&(r.endsWith(`
70
+ `)||(r+=`
71
+ `)),r}};function aa(n,e){if(!n)return[];let t=new Map;for(let a of n.entries)t.set(a.key,a);let o=e?.metadataKeys??n.entries.map(a=>a.key),r=[];for(let a of o){let s=t.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=Jn(s.value,s.escapeHint);i!==void 0&&r.push(`${c} = ${i}`)}return r}function Jn(n,e){switch(n.kind){case"StringScalar":return sa(n.stringValue,e);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let t=[];for(let o of n.items){let r=Jn(o,e);r!==void 0&&t.push(r)}return`[${t.join(", ")}]`}case"StructuredMap":return;default:return}}function sa(n,e){return e&&ra(e,j.ESC_TOML_MULTILINE)?ca(n):ia(n)}function ia(n){return`"${n.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n")}"`}function ca(n){return`"""
73
72
  ${n.replace(/"""/g,'\\"\\"\\"')}
74
- """`}var Ae=class{backendUri="kanonak.org/transformations/json";render(e,t){let r=JSON.stringify(e,null,2);return t?.trailingNewline&&!r.endsWith(`
75
- `)?r+`
76
- `:r}};function et(n){let e=n.replace(/\r\n/g,`
73
+ """`}var De=class{backendUri="kanonak.org/transformations/json";render(e,t){let o=JSON.stringify(e,null,2);return t?.trailingNewline&&!o.endsWith(`
74
+ `)?o+`
75
+ `:o}};function Zn(n){let e=n.replace(/\r\n/g,`
77
76
  `).split(`
78
- `),t=[],r=0;for(;r<e.length;){let o=e[r];if(o.trim()===""){r++;continue}let a=/^(\s*)```(\S*)\s*$/.exec(o);if(a){let i=a[2],l=[];for(r++;r<e.length&&!/^(\s*)```\s*$/.test(e[r]);)l.push(e[r]),r++;r++;let u=nt(l.join(`
79
- `)),d=i?` class="language-${tt(i)}"`:"";t.push(`<pre><code${d}>${u}</code></pre>`);continue}let s=/^(#{1,6})\s+(.*)$/.exec(o);if(s){let i=s[1].length,l=te(s[2].trim());t.push(`<h${i}>${l}</h${i}>`),r++;continue}if(o.includes("|")&&r+1<e.length&&Qn(e[r+1])){let i=Ze(o),l=la(e[r+1]);r+=2;let u=[];for(;r<e.length&&e[r].trim()!==""&&e[r].includes("|");)u.push(Ze(e[r])),r++;t.push(ua(i,l,u));continue}if(/^\s*[-*]\s+/.test(o)){let i=[];for(;r<e.length&&/^\s*[-*]\s+/.test(e[r]);){let l=[e[r].replace(/^\s*[-*]\s+/,"")];for(r++;r<e.length&&e[r].trim()!==""&&!/^\s*[-*]\s+/.test(e[r])&&!/^\s*\d+\.\s+/.test(e[r]);)l.push(e[r]),r++;r<e.length&&e[r].trim()===""&&r++,i.push(`<li>${te(l.join(" ").trim())}</li>`)}t.push(`<ul>
77
+ `),t=[],o=0;for(;o<e.length;){let r=e[o];if(r.trim()===""){o++;continue}let a=/^(\s*)```(\S*)\s*$/.exec(r);if(a){let i=a[2],l=[];for(o++;o<e.length&&!/^(\s*)```\s*$/.test(e[o]);)l.push(e[o]),o++;o++;let u=Qn(l.join(`
78
+ `)),d=i?` class="language-${et(i)}"`:"";t.push(`<pre><code${d}>${u}</code></pre>`);continue}let s=/^(#{1,6})\s+(.*)$/.exec(r);if(s){let i=s[1].length,l=ne(s[2].trim());t.push(`<h${i}>${l}</h${i}>`),o++;continue}if(r.includes("|")&&o+1<e.length&&Yn(e[o+1])){let i=Ye(r),l=la(e[o+1]);o+=2;let u=[];for(;o<e.length&&e[o].trim()!==""&&e[o].includes("|");)u.push(Ye(e[o])),o++;t.push(ua(i,l,u));continue}if(/^\s*[-*]\s+/.test(r)){let i=[];for(;o<e.length&&/^\s*[-*]\s+/.test(e[o]);){let l=[e[o].replace(/^\s*[-*]\s+/,"")];for(o++;o<e.length&&e[o].trim()!==""&&!/^\s*[-*]\s+/.test(e[o])&&!/^\s*\d+\.\s+/.test(e[o]);)l.push(e[o]),o++;o<e.length&&e[o].trim()===""&&o++,i.push(`<li>${ne(l.join(" ").trim())}</li>`)}t.push(`<ul>
80
79
  ${i.join(`
81
80
  `)}
82
- </ul>`);continue}if(/^\s*\d+\.\s+/.test(o)){let i=[];for(;r<e.length&&/^\s*\d+\.\s+/.test(e[r]);){let l=[e[r].replace(/^\s*\d+\.\s+/,"")];for(r++;r<e.length&&e[r].trim()!==""&&!/^\s*\d+\.\s+/.test(e[r])&&!/^\s*[-*]\s+/.test(e[r]);)l.push(e[r]),r++;r<e.length&&e[r].trim()===""&&r++,i.push(`<li>${te(l.join(" ").trim())}</li>`)}t.push(`<ol>
81
+ </ul>`);continue}if(/^\s*\d+\.\s+/.test(r)){let i=[];for(;o<e.length&&/^\s*\d+\.\s+/.test(e[o]);){let l=[e[o].replace(/^\s*\d+\.\s+/,"")];for(o++;o<e.length&&e[o].trim()!==""&&!/^\s*\d+\.\s+/.test(e[o])&&!/^\s*[-*]\s+/.test(e[o]);)l.push(e[o]),o++;o<e.length&&e[o].trim()===""&&o++,i.push(`<li>${ne(l.join(" ").trim())}</li>`)}t.push(`<ol>
83
82
  ${i.join(`
84
83
  `)}
85
- </ol>`);continue}let c=[o];for(r++;r<e.length&&e[r].trim()!==""&&!/^(#{1,6})\s+/.test(e[r])&&!/^(\s*)```/.test(e[r])&&!/^\s*[-*]\s+/.test(e[r])&&!/^\s*\d+\.\s+/.test(e[r])&&!(e[r].includes("|")&&r+1<e.length&&Qn(e[r+1]));)c.push(e[r]),r++;t.push(`<p>${te(c.join(" "))}</p>`)}return t.join(`
86
- `)}function Qn(n){return n.includes("-")?/^[\s|:-]+$/.test(n):!1}function Ze(n){let e=n.trim();return e.startsWith("|")&&(e=e.slice(1)),e.endsWith("|")&&(e=e.slice(0,-1)),e.split("|").map(t=>t.trim())}function la(n){return Ze(n).map(e=>{let t=e.startsWith(":"),r=e.endsWith(":");return t&&r?"center":r?"right":t?"left":null})}function ua(n,e,t){let r=s=>{let c=e[s];return c?` style="text-align:${c}"`:""},o=n.map((s,c)=>`<th${r(c)}>${te(s)}</th>`).join(""),a=t.map(s=>`<tr>${s.map((i,l)=>`<td${r(l)}>${te(i)}</td>`).join("")}</tr>`).join(`
84
+ </ol>`);continue}let c=[r];for(o++;o<e.length&&e[o].trim()!==""&&!/^(#{1,6})\s+/.test(e[o])&&!/^(\s*)```/.test(e[o])&&!/^\s*[-*]\s+/.test(e[o])&&!/^\s*\d+\.\s+/.test(e[o])&&!(e[o].includes("|")&&o+1<e.length&&Yn(e[o+1]));)c.push(e[o]),o++;t.push(`<p>${ne(c.join(" "))}</p>`)}return t.join(`
85
+ `)}function Yn(n){return n.includes("-")?/^[\s|:-]+$/.test(n):!1}function Ye(n){let e=n.trim();return e.startsWith("|")&&(e=e.slice(1)),e.endsWith("|")&&(e=e.slice(0,-1)),e.split("|").map(t=>t.trim())}function la(n){return Ye(n).map(e=>{let t=e.startsWith(":"),o=e.endsWith(":");return t&&o?"center":o?"right":t?"left":null})}function ua(n,e,t){let o=s=>{let c=e[s];return c?` style="text-align:${c}"`:""},r=n.map((s,c)=>`<th${o(c)}>${ne(s)}</th>`).join(""),a=t.map(s=>`<tr>${s.map((i,l)=>`<td${o(l)}>${ne(i)}</td>`).join("")}</tr>`).join(`
87
86
  `);return`<table>
88
- <thead><tr>${o}</tr></thead>
87
+ <thead><tr>${r}</tr></thead>
89
88
  <tbody>
90
89
  ${a}
91
90
  </tbody>
92
- </table>`}function te(n){let e=nt(n);return e=e.replace(/`([^`\n]+)`/g,(t,r)=>`<code>${r}</code>`),e=e.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(t,r,o)=>`<a href="${tt(o)}">${r}</a>`),e=e.replace(/\*\*([^*\n]+)\*\*/g,(t,r)=>`<strong>${r}</strong>`),e=e.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g,(t,r,o)=>`${r}<em>${o}</em>`),e=e.replace(/(^|[\s(])_([^_\n]+)_(?=[\s).,;:!?]|$)/g,(t,r,o)=>`${r}<em>${o}</em>`),e}function nt(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function tt(n){return n.replace(/"/g,"&quot;").replace(/&/g,"&amp;")}function Qe(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var Ke=class{backendUri="kanonak.org/transformations/html";render(e,t){let r=da(e.metadata)??"Untitled",o=pa(e.metadata,t),a=ma(e.children),s=`<!DOCTYPE html>
91
+ </table>`}function ne(n){let e=Qn(n);return e=e.replace(/`([^`\n]+)`/g,(t,o)=>`<code>${o}</code>`),e=e.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(t,o,r)=>`<a href="${et(r)}">${o}</a>`),e=e.replace(/\*\*([^*\n]+)\*\*/g,(t,o)=>`<strong>${o}</strong>`),e=e.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g,(t,o,r)=>`${o}<em>${r}</em>`),e=e.replace(/(^|[\s(])_([^_\n]+)_(?=[\s).,;:!?]|$)/g,(t,o,r)=>`${o}<em>${r}</em>`),e}function Qn(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function et(n){return n.replace(/"/g,"&quot;").replace(/&/g,"&amp;")}function Ze(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var Ke=class{backendUri="kanonak.org/transformations/html";render(e,t){let o=da(e.metadata)??"Untitled",r=ma(e.metadata,t),a=pa(e.children),s=`<!DOCTYPE html>
93
92
  <html lang="en">
94
93
  <head>
95
94
  <meta charset="utf-8">
96
- <title>${de(r)}</title>
95
+ <title>${ue(o)}</title>
97
96
  <style>
98
97
  body { font-family: -apple-system, Segoe UI, Helvetica, Arial, sans-serif; max-width: 860px; margin: 2rem auto; padding: 0 1rem; color: #222; line-height: 1.55; }
99
98
  h1, h2, h3, h4 { line-height: 1.2; }
@@ -115,21 +114,21 @@ figure.svg-figure svg { max-width: 100%; height: auto; }
115
114
  </style>
116
115
  </head>
117
116
  <body>
118
- ${o}${a}
117
+ ${r}${a}
119
118
  </body>
120
119
  </html>
121
120
  `;return t?.trailingNewline===!1&&s.endsWith(`
122
- `)?s.slice(0,-1):s}};function da(n){if(n){for(let e of n.entries)if((e.key==="title"||e.key==="name")&&e.value.kind==="StringScalar")return e.value.stringValue}}function pa(n,e){if(!n||n.entries.length===0)return"";let t=e?.metadataKeys??n.entries.map(a=>a.key),r=new Map(n.entries.map(a=>[a.key,a])),o=[];for(let a of t){let s=r.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=ot(s.value);i!==void 0&&o.push(` <dt>${de(c)}</dt>
123
- <dd>${i}</dd>`)}return o.length===0?"":`<dl class="metadata">
124
- ${o.join(`
121
+ `)?s.slice(0,-1):s}};function da(n){if(n){for(let e of n.entries)if((e.key==="title"||e.key==="name")&&e.value.kind==="StringScalar")return e.value.stringValue}}function ma(n,e){if(!n||n.entries.length===0)return"";let t=e?.metadataKeys??n.entries.map(a=>a.key),o=new Map(n.entries.map(a=>[a.key,a])),r=[];for(let a of t){let s=o.get(a);if(!s)continue;let c=e?.metadataRenames.get(a)??a,i=tt(s.value);i!==void 0&&r.push(` <dt>${ue(c)}</dt>
122
+ <dd>${i}</dd>`)}return r.length===0?"":`<dl class="metadata">
123
+ ${r.join(`
125
124
  `)}
126
125
  </dl>
127
- `}function ot(n){switch(n.kind){case"StringScalar":return de(n.stringValue);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let e=[];for(let t of n.items){let r=ot(t);r!==void 0&&e.push(`<code>${r}</code>`)}return e.join(", ")}case"StructuredMap":return;default:return}}function ma(n){let e=[];for(let t of n){let r=fa(t);r&&e.push(r)}return e.join(`
128
- `)}function fa(n){switch(n.kind){case"Heading":{let e=Math.max(1,Math.min(6,n.level));return`<h${e}>${rt(n.inlines)}</h${e}>`}case"Paragraph":return`<p>${rt(n.inlines)}</p>`;case"RawBlock":return ga(n);default:return""}}function ga(n){let e=n.mediaType;return e&&Qe(e,x.TEXT_MARKDOWN)?et(n.rawContent):e&&Qe(e,x.TEXT_HTML)?n.rawContent:e&&Qe(e,x.IMAGE_SVG_XML)?`<figure class="svg-figure">
126
+ `}function tt(n){switch(n.kind){case"StringScalar":return ue(n.stringValue);case"IntegerScalar":return String(n.integerValue);case"StructuredList":{let e=[];for(let t of n.items){let o=tt(t);o!==void 0&&e.push(`<code>${o}</code>`)}return e.join(", ")}case"StructuredMap":return;default:return}}function pa(n){let e=[];for(let t of n){let o=fa(t);o&&e.push(o)}return e.join(`
127
+ `)}function fa(n){switch(n.kind){case"Heading":{let e=Math.max(1,Math.min(6,n.level));return`<h${e}>${nt(n.inlines)}</h${e}>`}case"Paragraph":return`<p>${nt(n.inlines)}</p>`;case"RawBlock":return ga(n);default:return""}}function ga(n){let e=n.mediaType;return e&&Ze(e,j.TEXT_MARKDOWN)?Zn(n.rawContent):e&&Ze(e,j.TEXT_HTML)?n.rawContent:e&&Ze(e,j.IMAGE_SVG_XML)?`<figure class="svg-figure">
129
128
  ${n.rawContent}
130
- </figure>`:`<pre${e?` class="media-${ha(e.name)}"`:""}><code>${de(n.rawContent)}</code></pre>`}function rt(n){let e=[];for(let t of n)t.kind==="Text"&&e.push(de(t.text));return e.join("")}function de(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function ha(n){return n.replace(/"/g,"&quot;").replace(/&/g,"&amp;")}function ka(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var Ce=class{backendUri="kanonak.org/transformations/svg";render(e,t){for(let r of e.children)if(r.kind==="RawBlock"&&r.mediaType&&ka(r.mediaType,x.IMAGE_SVG_XML)){let o=r.rawContent;return t?.trailingNewline&&!o.endsWith(`
131
- `)&&(o+=`
132
- `),o}return'<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>'}};var Pe={"markdown-with-frontmatter":{formatUri:"kanonak.org/transformations/markdown-with-frontmatter",extension:".md"},toml:{formatUri:"kanonak.org/transformations/toml",extension:".toml"},json:{formatUri:"kanonak.org/transformations/json",extension:".json"},"plain-markdown":{formatUri:"kanonak.org/transformations/plain-markdown",extension:".md"},html:{formatUri:"kanonak.org/transformations/html",extension:".html"},svg:{formatUri:"kanonak.org/transformations/svg",extension:".svg"}},re=class extends Error{},V=class{backends=new Map;constructor(){this.register(new ve),this.register(new De),this.register(new Ae),this.register(new Ke),this.register(new Ce)}register(e){this.backends.set(e.backendUri,e)}async run(e){let t=e.transformationKanonaks??e.allKanonaks,r=ne(e.transformation,t);if(!r.outputs.has(e.outputFormat))throw new re(`Transformation "${r.name}" does not support output format "${e.outputFormat}". Declared outputs: ${Array.from(r.outputs).join(", ")}`);let o=new ye(e.repository,e.parser,e.objectParser),a=new Se(o,e.allKanonaks),s=e.instances.filter(u=>ya(u,r)),c=this.findBackendForFormat(e.outputFormat);if(!c)throw new re(`No backend registered for OutputFormat "${e.outputFormat}".`);let i=r.overrides.get(e.outputFormat),l=[];for(let u of s){let d=new Map;d.set("input",u);let m=await a.evaluate(r.rule,d);if(!wa(m))throw new re(`Transformation "${r.name}" rule did not yield a Document for input "${u.name}". Got: ${at(m)}`);let y=await a.evaluate(r.artifactName,d);if(typeof y!="string")throw new re(`Transformation "${r.name}" artifactName did not yield a string for input "${u.name}". Got: ${at(y)}`);let g=c.render(m,i);l.push({fileName:y,format:e.outputFormat,content:g,sourceName:u.name})}return l}findBackendForFormat(e){let t=Pe[e];if(t)return this.backends.get(t.formatUri)}};function ya(n,e){for(let t of e.inputPattern.requires)if(!ba(n,t))return!1;return!0}function ba(n,e){for(let t of n.statement){let r=t.predicate?.subject;if(r&&M(r,e)){let o=t.object;if(o==null||typeof o=="string"&&o.length===0||Array.isArray(o)&&o.length===0)continue;return!0}}return!1}function wa(n){return typeof n=="object"&&n!==null&&n.kind==="Document"&&Array.isArray(n.children)}function at(n){if(n===void 0)return"undefined";if(n===null)return"null";if(Array.isArray(n))return`array(${n.length})`;if(typeof n=="object"){let e=n.kind;return e?`object(kind=${e})`:"object"}return typeof n}function ct(){let n=new me("transform").description("Run ontology-driven transformations against Kanonak packages. Transformations are declarative YAML rules (instances of `kanonak.org/transformations/Transformation`) that convert ontology instances into output files. The runner produces one or more Artifacts per matched input; format backends serialize them to Markdown, HTML, SVG, TOML, JSON, or (with post-processing) PDF.").addHelpText("after",`
129
+ </figure>`:`<pre${e?` class="media-${ha(e.name)}"`:""}><code>${ue(n.rawContent)}</code></pre>`}function nt(n){let e=[];for(let t of n)t.kind==="Text"&&e.push(ue(t.text));return e.join("")}function ue(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function ha(n){return n.replace(/"/g,"&quot;").replace(/&/g,"&amp;")}function ka(n,e){return n.publisher===e.publisher&&n.package_===e.package_&&n.name===e.name}var Ae=class{backendUri="kanonak.org/transformations/svg";render(e,t){for(let o of e.children)if(o.kind==="RawBlock"&&o.mediaType&&ka(o.mediaType,j.IMAGE_SVG_XML)){let r=o.rawContent;return t?.trailingNewline&&!r.endsWith(`
130
+ `)&&(r+=`
131
+ `),r}return'<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>'}};var Ce={"markdown-with-frontmatter":{formatUri:"kanonak.org/transformations/markdown-with-frontmatter",extension:".md"},toml:{formatUri:"kanonak.org/transformations/toml",extension:".toml"},json:{formatUri:"kanonak.org/transformations/json",extension:".json"},"plain-markdown":{formatUri:"kanonak.org/transformations/plain-markdown",extension:".md"},html:{formatUri:"kanonak.org/transformations/html",extension:".html"},svg:{formatUri:"kanonak.org/transformations/svg",extension:".svg"}},te=class extends Error{},B=class{backends=new Map;constructor(){this.register(new Se),this.register(new ve),this.register(new De),this.register(new Ke),this.register(new Ae)}register(e){this.backends.set(e.backendUri,e)}async run(e){let t=e.transformationKanonaks??e.allKanonaks,o=ee(e.transformation,t);if(!o.outputs.has(e.outputFormat))throw new te(`Transformation "${o.name}" does not support output format "${e.outputFormat}". Declared outputs: ${Array.from(o.outputs).join(", ")}`);let r=new ke(e.repository,e.parser,e.objectParser),a=new we(r,e.allKanonaks),s=e.instances.filter(u=>ya(u,o)),c=this.findBackendForFormat(e.outputFormat);if(!c)throw new te(`No backend registered for OutputFormat "${e.outputFormat}".`);let i=o.overrides.get(e.outputFormat),l=[];for(let u of s){let d=new Map;d.set("input",u);let m=await a.evaluate(o.rule,d);if(!wa(m))throw new te(`Transformation "${o.name}" rule did not yield a Document for input "${u.name}". Got: ${ot(m)}`);let k=await a.evaluate(o.artifactName,d);if(typeof k!="string")throw new te(`Transformation "${o.name}" artifactName did not yield a string for input "${u.name}". Got: ${ot(k)}`);let b=c.render(m,i);l.push({fileName:k,format:e.outputFormat,content:b,sourceName:u.name})}return l}findBackendForFormat(e){let t=Ce[e];if(t)return this.backends.get(t.formatUri)}};function ya(n,e){for(let t of e.inputPattern.requires)if(!ba(n,t))return!1;return!0}function ba(n,e){for(let t of n.statement){let o=t.predicate?.subject;if(o&&F(o,e)){let r=t.object;if(r==null||typeof r=="string"&&r.length===0||Array.isArray(r)&&r.length===0)continue;return!0}}return!1}function wa(n){return typeof n=="object"&&n!==null&&n.kind==="Document"&&Array.isArray(n.children)}function ot(n){if(n===void 0)return"undefined";if(n===null)return"null";if(Array.isArray(n))return`array(${n.length})`;if(typeof n=="object"){let e=n.kind;return e?`object(kind=${e})`:"object"}return typeof n}function ct(){let n=new de("transform").description("Run ontology-driven transformations against Kanonak packages. Transformations are declarative YAML rules (instances of `kanonak.org/transformations/Transformation`) that convert ontology instances into output files. The runner produces one or more Artifacts per matched input; format backends serialize them to Markdown, HTML, SVG, TOML, JSON, or (with post-processing) PDF.").addHelpText("after",`
133
132
  Examples:
134
133
 
135
134
  # List every Transformation available in the local workspace
@@ -158,14 +157,14 @@ Examples:
158
157
 
159
158
  # List the registered format backends
160
159
  $ kanonak transform formats
161
- `);return n.addCommand(_a()),n.addCommand(Ta()),n.addCommand(xa()),n.addCommand(Oa()),n}function _a(){return new me("run").description("Run a transformation against an input scope and write the resulting Artifacts to disk.").argument("<transformation>","Transformation URI (`publisher/package/name`, optional `@version`) or just the local name if unique in the workspace.").requiredOption("--scope <scope>","Input source \u2014 either a package URI `publisher/package[@version]` (resolved via the local workspace + cache + HTTP tiers) or a file path to a `.kan.yml` document.").option("--format <name>","OutputFormat name to target (e.g. `markdown-with-frontmatter`, `html`, `svg`, `json`). If omitted and the transformation declares exactly one output, that single format is used.").option("--out <dir>","Directory to write artifacts into.",".").action(async(n,e)=>{try{await Ra(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function Ra(n,e){let t=new en,r=new nn,o=await j(process.cwd(),t),a=await lt(n,o,r),{transformation:s,transformationKanonaks:c}=a;console.log(`Transformation: ${pe(s)}`);let i=ne(s,c),l=await La(e.scope,o,t,r),u=await Ba(l,i.inputPattern.matchesClass,o);console.log(`Scope: ${e.scope} \u2014 found ${u.length} instance(s) of ${i.inputPattern.matchesClass.publisher}/${i.inputPattern.matchesClass.package_}/${i.inputPattern.matchesClass.name}`),u.length===0&&(console.error("No matching input instances in scope. Check the transformation's inputPattern.matchesClass vs. the scope package."),process.exit(1));let d=Ia(i.outputs,e.format);console.log(`Output format: ${d}`);let m=Pe[d];if(!m)throw new Error(`Unknown format "${d}". Run \`kanonak transform formats\` to see what the runner supports.`);let g=await new V().run({transformation:s,instances:u,allKanonaks:l,transformationKanonaks:c,repository:o,parser:t,objectParser:r,outputFormat:d}),k=Ka(e.out);va(k,{recursive:!0});for(let b of g){let h=Ma(b.fileName),$=Aa(k,`${h}${m.extension}`);$a($,b.content,"utf-8"),console.log(` wrote ${$}`)}console.log(`Done. ${g.length} artifact(s) written to ${k}`)}function Ia(n,e){if(e){if(!n.has(e))throw new Error(`Transformation does not declare --format "${e}" in its outputs. Declared outputs: ${Array.from(n).sort().join(", ")}`);return e}if(n.size===1)return Array.from(n)[0];throw new Error(`Transformation supports multiple output formats (${Array.from(n).sort().join(", ")}); pass --format <name> to select one.`)}function Ta(){return new me("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await ja()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function ja(){let n=new en,e=new nn,t=await j(process.cwd(),n),r=await t.getAllDocumentsAsync(),o=[];for(let a of r)try{let s=new D(a,t),c=await e.parseKanonaks(s),i=K(c,f.Transformation);for(let l of i)o.push(Fa(l,c))}catch{}if(o.length===0){console.log("No Transformation instances found in the current workspace.");return}o.sort((a,s)=>a.uri.localeCompare(s.uri));for(let a of o)console.log(`${a.uri}`),console.log(` matches: ${a.matchesClass}`),console.log(` outputs: ${a.outputs.join(", ")}`)}function xa(){return new me("show").description("Compile a transformation and print a human-readable summary (input pattern, outputs, format overrides, rule shape).").argument("<transformation>","Transformation URI or local name").action(async n=>{try{await Ua(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ua(n){let e=new en,t=new nn,r=await j(process.cwd(),e),{transformation:o,transformationKanonaks:a}=await lt(n,r,t),s=ne(o,a);if(console.log(`Transformation: ${pe(o)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${Ee(s.inputPattern.matchesClass)}`),s.inputPattern.requires.length>0){console.log(" Required properties:");for(let c of s.inputPattern.requires)console.log(` - ${Ee(c)}`)}else console.log(" Required properties: (none)");if(console.log(),console.log(`Outputs: ${Array.from(s.outputs).sort().join(", ")}`),console.log(),s.overrides.size>0){console.log("Format overrides:");for(let[c,i]of s.overrides){if(console.log(` ${c}:`),i.metadataKeys&&console.log(` metadata keys: ${i.metadataKeys.join(", ")}`),i.metadataRenames.size>0){let l=[];for(let[u,d]of i.metadataRenames)l.push(`${u} \u2192 ${d}`);console.log(` metadata renames: ${l.join(", ")}`)}i.trailingNewline!==void 0&&console.log(` trailing newline: ${i.trailingNewline}`)}console.log()}console.log(`Rule root kind: ${s.rule.kind}`),s.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${Ee(s.rule.astClass)}`),console.log(`Rule root bindings: ${s.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${s.artifactName.kind}`)}function Oa(){return new me("formats").description("List the OutputFormat names the runner can serialize to.").action(()=>{console.log("Registered format backends:");let n=Object.entries(Pe).sort(([e],[t])=>e.localeCompare(t));for(let[e,t]of n)console.log(` ${e.padEnd(28)} ${t.extension.padEnd(6)} ${t.formatUri}`)})}async function lt(n,e,t){let r,o,a;if(n.includes("/")){let i=n.indexOf("@"),l=n;if(i!==-1){let d=n.indexOf("/",i);if(d===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);l=n.substring(0,i)+n.substring(d)}let u=l.split("/");if(u.length<3)throw new Error(`Invalid transformation URI "${n}" \u2014 expected publisher/package/name or publisher/package@version/name`);r=u[0],o=u[1],a=u.slice(2).join("/")}else a=n;if(r&&o){let i=await e.getDocumentsByNamespaceAsync(r,o);if(i.length===0)throw new Error(`Package ${r}/${o} not found in the local workspace or cache.`);let l=Na(n),u=ut(i,l,`${r}/${o}`),d=new D(u,e),m=await t.parseKanonaks(d),y=he(m,{publisher:r,package_:o,name:a,version:""});if(!y){let g=K(m,f.Transformation),k=g.find(b=>b.name===a);if(!k)throw new Error(`Transformation "${a}" not found in package ${r}/${o}. Package contains ${g.length} Transformation(s): ${g.map(b=>b.name).join(", ")||"(none)"}`);return{transformation:k,transformationKanonaks:m}}return{transformation:y,transformationKanonaks:m}}let s=await e.getAllDocumentsAsync(),c=[];for(let i of s)try{let l=new D(i,e),u=await t.parseKanonaks(l),d=K(u,f.Transformation);for(let m of d)m.name===a&&c.push({tx:m,kanonaks:u})}catch{}if(c.length===0)throw new Error(`No Transformation named "${a}" found in the workspace. Try \`kanonak transform list\` to see available transformations.`);if(c.length>1){let i=c.map(l=>pe(l.tx)).join(`
160
+ `);return n.addCommand(_a()),n.addCommand(Ta()),n.addCommand(ja()),n.addCommand(Na()),n}function _a(){return new de("run").description("Run a transformation against an input scope and write the resulting Artifacts to disk.").argument("<transformation>","Transformation URI (`publisher/package/name`, optional `@version`) or just the local name if unique in the workspace.").requiredOption("--scope <scope>","Input source \u2014 either a package URI `publisher/package[@version]` (resolved via the local workspace + cache + HTTP tiers) or a file path to a `.kan.yml` document.").option("--format <name>","OutputFormat name to target (e.g. `markdown-with-frontmatter`, `html`, `svg`, `json`). If omitted and the transformation declares exactly one output, that single format is used.").option("--out <dir>","Directory to write artifacts into.",".").action(async(n,e)=>{try{await Ia(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function Ia(n,e){let t=new Qe,o=new en,r=await x(process.cwd(),t),a=await lt(n,r,o),{transformation:s,transformationKanonaks:c}=a;console.log(`Transformation: ${Ee(s)}`);let i=ee(s,c),l=await Oa(e.scope,r,t,o),u=await Ma(l,i.inputPattern.matchesClass,r);console.log(`Scope: ${e.scope} \u2014 found ${u.length} instance(s) of ${i.inputPattern.matchesClass.publisher}/${i.inputPattern.matchesClass.package_}/${i.inputPattern.matchesClass.name}`),u.length===0&&(console.error("No matching input instances in scope. Check the transformation's inputPattern.matchesClass vs. the scope package."),process.exit(1));let d=Ra(i.outputs,e.format);console.log(`Output format: ${d}`);let m=Ce[d];if(!m)throw new Error(`Unknown format "${d}". Run \`kanonak transform formats\` to see what the runner supports.`);let b=await new B().run({transformation:s,instances:u,allKanonaks:l,transformationKanonaks:c,repository:r,parser:t,objectParser:o,outputFormat:d}),f=Aa(e.out);va(f,{recursive:!0});for(let h of b){let g=Fa(h.fileName),w=Ka(f,`${g}${m.extension}`);Sa(w,h.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${b.length} artifact(s) written to ${f}`)}function Ra(n,e){if(e){if(!n.has(e))throw new Error(`Transformation does not declare --format "${e}" in its outputs. Declared outputs: ${Array.from(n).sort().join(", ")}`);return e}if(n.size===1)return Array.from(n)[0];throw new Error(`Transformation supports multiple output formats (${Array.from(n).sort().join(", ")}); pass --format <name> to select one.`)}function Ta(){return new de("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await xa()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function xa(){let n=new Qe,e=new en,t=await x(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let s of o)try{let c=new A(s,t),i=await e.parseKanonaks(c),l=C(i,y.Transformation);for(let u of l){let d=tn(u);if(!d)continue;let m=r.get(d)??[];m.push({tx:u,kanonaks:i,doc:s}),r.set(d,m)}}catch{}let a=[];for(let s of r.values()){if(s.length===1){a.push(at(s[0].tx,s[0].kanonaks));continue}let c=nn(s.map(l=>l.doc));if(!c.chosen)continue;let i=s.find(l=>l.doc===c.chosen);i&&a.push(at(i.tx,i.kanonaks))}if(a.length===0){console.log("No Transformation instances found in the current workspace.");return}a.sort((s,c)=>s.uri.localeCompare(c.uri));for(let s of a)console.log(`${s.uri}`),console.log(` matches: ${s.matchesClass}`),console.log(` outputs: ${s.outputs.join(", ")}`)}function ja(){return new de("show").description("Compile a transformation and print a human-readable summary (input pattern, outputs, format overrides, rule shape).").argument("<transformation>","Transformation URI or local name").action(async n=>{try{await Ua(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ua(n){let e=new Qe,t=new en,o=await x(process.cwd(),e),{transformation:r,transformationKanonaks:a}=await lt(n,o,t),s=ee(r,a);if(console.log(`Transformation: ${Ee(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${Pe(s.inputPattern.matchesClass)}`),s.inputPattern.requires.length>0){console.log(" Required properties:");for(let c of s.inputPattern.requires)console.log(` - ${Pe(c)}`)}else console.log(" Required properties: (none)");if(console.log(),console.log(`Outputs: ${Array.from(s.outputs).sort().join(", ")}`),console.log(),s.overrides.size>0){console.log("Format overrides:");for(let[c,i]of s.overrides){if(console.log(` ${c}:`),i.metadataKeys&&console.log(` metadata keys: ${i.metadataKeys.join(", ")}`),i.metadataRenames.size>0){let l=[];for(let[u,d]of i.metadataRenames)l.push(`${u} \u2192 ${d}`);console.log(` metadata renames: ${l.join(", ")}`)}i.trailingNewline!==void 0&&console.log(` trailing newline: ${i.trailingNewline}`)}console.log()}console.log(`Rule root kind: ${s.rule.kind}`),s.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${Pe(s.rule.astClass)}`),console.log(`Rule root bindings: ${s.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${s.artifactName.kind}`)}function Na(){return new de("formats").description("List the OutputFormat names the runner can serialize to.").action(()=>{console.log("Registered format backends:");let n=Object.entries(Ce).sort(([e],[t])=>e.localeCompare(t));for(let[e,t]of n)console.log(` ${e.padEnd(28)} ${t.extension.padEnd(6)} ${t.formatUri}`)})}async function lt(n,e,t){let o,r,a;if(n.includes("/")){let m=n.indexOf("@"),k=n;if(m!==-1){let f=n.indexOf("/",m);if(f===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);k=n.substring(0,m)+n.substring(f)}let b=k.split("/");if(b.length<3)throw new Error(`Invalid transformation URI "${n}" \u2014 expected publisher/package/name or publisher/package@version/name`);o=b[0],r=b[1],a=b.slice(2).join("/")}else a=n;if(o&&r){let m=await e.getDocumentsByNamespaceAsync(o,r);if(m.length===0)throw new Error(`Package ${o}/${r} not found in the local workspace or cache.`);let k=La(n),b=ut(m,k,`${o}/${r}`),f=new A(b,e),h=await t.parseKanonaks(f),g=ge(h,{publisher:o,package_:r,name:a,version:""});if(!g){let w=C(h,y.Transformation),$=w.find(v=>v.name===a);if(!$)throw new Error(`Transformation "${a}" not found in package ${o}/${r}. Package contains ${w.length} Transformation(s): ${w.map(v=>v.name).join(", ")||"(none)"}`);return{transformation:$,transformationKanonaks:h}}return{transformation:g,transformationKanonaks:h}}let s=await e.getAllDocumentsAsync(),c=new Map;for(let m of s)try{let k=new A(m,e),b=await t.parseKanonaks(k),f=C(b,y.Transformation);for(let h of f){if(h.name!==a)continue;let g=tn(h);if(!g)continue;let w=c.get(g)??[];w.push({tx:h,kanonaks:b,doc:m}),c.set(g,w)}}catch{}if(c.size===0)throw new Error(`No Transformation named "${a}" found in the workspace. Try \`kanonak transform list\` to see available transformations.`);if(c.size>1){let m=Array.from(c.keys()).sort().join(`
162
161
  `);throw new Error(`Multiple Transformations named "${a}" in the workspace \u2014 disambiguate with a full publisher/package/name URI:
163
- ${i}`)}return{transformation:c[0].tx,transformationKanonaks:c[0].kanonaks}}async function La(n,e,t,r){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||st(n)&&Da(n).isFile()){if(!st(n))throw new Error(`Scope file not found: ${n}`);let g=Sa(n,"utf-8"),k=t.parse(g),b=new D(k,e);return r.parseKanonaks(b)}let a=n.indexOf("@"),s=a===-1?n:n.substring(0,a),c=a===-1?void 0:n.substring(a+1),i=s.indexOf("/");if(i===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=s.substring(0,i),u=s.substring(i+1),d=await e.getDocumentsByNamespaceAsync(l,u);if(d.length===0)throw new Error(`Scope package ${l}/${u} not found in the local workspace or cache.`);let m=ut(d,c,`${l}/${u}`),y=new D(m,e);return r.parseKanonaks(y)}function Na(n){let e=n.indexOf("@");if(e===-1)return;let t=n.substring(e+1),r=t.indexOf("/");return r===-1?t:t.substring(0,r)}function ut(n,e,t){function r(s){let c=s.metadata.namespace_?.version;return c?`${c.major}.${c.minor}.${c.patch}`:""}if(e){let s=n.find(i=>r(i)===e);if(s)return s;let c=n.map(r).filter(Boolean).sort().join(", ");throw new Error(`${t}@${e} not found in the local workspace or cache. Available versions: ${c||"(none with parseable namespace)"}`)}if(n.length===1)return n[0];let a=[...n].sort((s,c)=>{let i=s.metadata.namespace_?.version,l=c.metadata.namespace_?.version;return!i||!l?0:i.major!==l.major?l.major-i.major:i.minor!==l.minor?l.minor-i.minor:l.patch-i.patch})[0];return console.warn(`Warning: ${t} has ${n.length} versions present (${n.map(r).filter(Boolean).join(", ")}); using @${r(a)}. Pin with ${t}@<version> to suppress this warning.`),a}function Fa(n,e){try{let t=ne(n,e);return{uri:pe(n),matchesClass:Ee(t.inputPattern.matchesClass),outputs:Array.from(t.outputs).sort()}}catch(t){return{uri:pe(n),matchesClass:`(compile error: ${t.message})`,outputs:[]}}}function pe(n){let e=n.namespace||"",t=e.indexOf("@");return`${t===-1?e:e.substring(0,t)}/${n.name}`}function Ee(n){return`${n.publisher}/${n.package_}/${n.name}`}function Ma(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Ba(n,e,t){let r=new Map;for(let s of n){if(!(s instanceof Ca))continue;let c=Va(s);c&&r.set(c,s)}let o=[];try{o=(await new Pa({vocabulary:new Ea}).reason(t)).getInstancesOfClass(it(e.publisher,e.package_,e.name))}catch{}let a=[];for(let s of o){let c=r.get(s);c&&a.push(c)}return a.length>0?a:K(n,e)}function Va(n){let e=n.namespace??"",t=e.indexOf("@"),r=t===-1?e:e.substring(0,t),o=r.indexOf("/");return o===-1||!n.name?null:it(r.substring(0,o),r.substring(o+1),n.name)}import{Command as Ha}from"commander";import{KanonakParser as za,PublisherIndex as dt,CredentialStore as pt,createAuthenticatedFetch as mt,FileSystemKanonakDocumentRepository as qa,Reasoner as Ga,KanonakVocabulary as Wa,getGlobalCachePath as Xa,makeUriKey as Ja}from"@kanonak-protocol/sdk";function Ya(n){let e=n.split("/");if(e.length!==3)return null;let[t,r,o]=e;return!t||!r||!o?null:{publisher:t,package_:r,name:o}}function ft(){return new Ha("search").description("Browse a publisher's catalogue or find instances of a class via the SDK reasoner").argument("<publisher>","Publisher domain (e.g. kanonak.org)").option("--type <uri>","Class URI to search for, in publisher/package/Name form").action(async(n,e)=>{e.type?await Qa(n,e.type):await Za(n)})}async function Za(n){let e=new pt,t=mt(e),r=new dt({fetchFn:t}),o;try{o=await r.listLatestPackages(n)}catch(s){console.error(`Failed to fetch publisher index for ${n}: ${s.message}`),process.exit(1)}if(o.length===0){console.log(`No packages found at ${n}.`);return}console.log(`Packages published by ${n}:
164
- `);let a=o.reduce((s,c)=>Math.max(s,c.packageName.length),0);for(let{packageName:s,version:c}of o)console.log(` ${s.padEnd(a)} @${c}`)}async function Qa(n,e){let t=Ya(e);t||(console.error(`Invalid --type value: ${e}`),console.error("Expected: publisher/package/Name (e.g. kanonak.org/capabilities/Capability)"),process.exit(1));let r=new za,o=new pt,a=mt(o),s=new dt({fetchFn:a}),c=new T,i=new Set,l=[];try{l=await s.listLatestPackages(n)}catch(b){console.error(`Failed to fetch publisher index for ${n}: ${b.message}`),process.exit(1)}for(let{packageName:b,version:h}of l)i.add(`${n}|${b}|${h}`);await tn(s,c,a,"kanonak.org","core-rdf",i),await tn(s,c,a,"kanonak.org","core-owl",i),await tn(s,c,a,t.publisher,t.package_,i);for(let b of i){let[h,$,S]=b.split("|");if(!c.has(h,$,S))try{let A=await s.getPackageUrl(h,$,S),P=await a(A,h);if(!P.ok){console.error(`Warning: failed to fetch ${h}/${$}@${S}: ${P.status} ${P.statusText}`);continue}let G=await P.text();c.put(h,$,S,G)}catch(A){console.error(`Warning: failed to fetch ${h}/${$}@${S}: ${A.message}`)}}let u=new qa(Xa(),!0,r),m=await new Ga({vocabulary:new Wa}).reason(u),y=Ja(t.publisher,t.package_,t.name),k=m.getInstancesOfClass(y).filter(b=>b!==y);if(k.length===0){console.log(`No instances of ${y} found in ${n}'s catalogue.`);return}console.log(`Instances of ${y} in ${n}'s catalogue:
165
- `),k.sort();for(let b of k)console.log(` ${b}`)}async function tn(n,e,t,r,o,a){try{let s=await n.getHighestVersion(r,o);if(!s)return;a.add(`${r}|${o}|${s}`)}catch{}}import{Command as gt}from"commander";function oe(n){return`${E}/${_}/${n}`}var rn={[oe("fetch-and-deploy")]:(n,e,t,r)=>n.add(e,t[0],r),[oe("remove-deployed")]:(n,e,t,r)=>n.remove(e,t[0],r),[oe("list-deployed")]:(n,e,t,r)=>n.list(e,r),[oe("update-deployed")]:(n,e,t,r)=>n.update(e,t[0],r),[oe("search-available")]:(n,e,t,r)=>n.search(e,r),[oe("show-info")]:(n,e,t,r)=>n.info(e,t[0],r)};function ht(n,e,t){for(let r of e){let o=new gt(r.commandName).description(r.description.trim());for(let a of r.commands){let s=o.command(es(a));s.description(a.description);for(let c of a.arguments)if(c.isOption){let i=c.defaultValue!=null?`--${c.argumentName} [value]`:`--${c.argumentName} <value>`;s.option(i,"",c.defaultValue)}s.action(async(...c)=>{let i=ns(c);await ts(t,r,a,c,i)})}n.addCommand(o)}}function es(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function ns(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof gt))return n[e];return{}}async function ts(n,e,t,r,o){let a=[];for(let c of r)if(typeof c=="string")a.push(c);else break;t.actionKey||(console.error(`Capability subcommand '${t.subcommandName}' has no resolved \`performs:\` Action. Every CapabilityCommand must declare a performs value pointing at a named Action instance from the capabilities ontology. Known actions: ${Object.keys(rn).join(", ")}.`),process.exit(1));let s=rn[t.actionKey];s||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(rn).join(", ")}.`),process.exit(1)),await s(n,e,a,o)}import{KanonakObjectParser as rs,PublisherIndex as on,PublisherConfigResolver as os}from"@kanonak-protocol/sdk";var _e=class{constructor(e,t,r,o,a,s){this.fileCache=e;this.parser=t;this.publisherIndex=r;this.fetchFn=o;this.handlerRegistry=a;this.repository=s}fileCache;parser;publisherIndex;fetchFn;handlerRegistry;repository;objectParser=new rs;async add(e,t,r){let o=W(t);o||(console.error(`Invalid package reference: ${t}`),console.error("Expected format: {publisher}/{package}@{version} or {publisher}/{package}"),process.exit(1));let{publisher:a,packageName:s,version:c}=o,i=c??await this.publisherIndex.getHighestVersion(a,s);i||(console.error(`Could not resolve version for ${a}/${s}`),process.exit(1));let l=this.fileCache.get(a,s,i);if(!l){let b=await this.publisherIndex.getPackageUrl(a,s,i),h=await this.fetchFn(b,a);if(!h.ok)throw new Error(`Failed to fetch ${b} (${h.status} ${h.statusText})`);l=await h.text(),this.fileCache.put(a,s,i,l)}let u=this.parser.parse(l),d=new D(u,this.repository),m=await this.objectParser.parseKanonaks(d),y=kt(e.managesTypeKey);y||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let g=K(m,y);g.length===0&&(console.error(`Package ${a}/${s}@${i} does not contain any ${L(y)} instances.`),process.exit(1));let k=this.handlerRegistry.get(e.deploymentTargetKey);k?await k.deploy({instances:g,allKanonaks:m,repository:this.repository,options:r}):console.log(`Cached ${a}/${s}@${i} (no deployment handler for "${e.deploymentTargetKey}")`)}async remove(e,t,r){await this.requireHandler(e).undeploy(t,{repository:this.repository,options:r})}async list(e,t){let o=await this.requireHandler(e).list({repository:this.repository,options:t}),a=e.managesTypeKey||"managed";if(o.length===0){console.log(`No ${a} instances installed.`);return}console.log(`Installed ${a} instances:
166
- `);for(let s of o){let c=s.publisher?`${s.publisher}/${s.package_}@${s.version}`:"unmanaged";console.log(` ${s.name} (${c}) ${s.path}`)}}async update(e,t,r){let a=await this.requireHandler(e).list({repository:this.repository,options:r}),s=t?a.filter(i=>i.name===t):a.filter(i=>i.publisher);if(s.length===0){console.log(t?`"${t}" not found.`:"No managed instances to update.");return}let c=0;for(let i of s){let l=await this.publisherIndex.getHighestVersion(i.publisher,i.package_);!l||l===i.version||(console.log(`Updating ${i.name}: ${i.version} \u2192 ${l}`),await this.add(e,`${i.publisher}/${i.package_}@${l}`,r),c++)}console.log(c===0?"All instances are up to date.":`
167
- Updated ${c} instance(s).`)}async search(e,t){let r=t.publisher??"kanonak.org",o=kt(e.managesTypeKey);if(!o){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${r} for ${L(o)} instances...
168
- `);let a=new os,s=await a.getConfig(r),c=a.resolveIndexUrl(r,s),i=await this.fetchFn(c,r);if(!i.ok){console.error(`Failed to fetch package index from ${r}.`);return}let l=await i.text(),u=on.parseIndex(l);if(u.size===0){console.error(`No packages found for publisher "${r}".`);return}let d=new Map;for(let[g,k]of u){let b=[...k].sort((h,$)=>{let S=on.parseVersion(h),A=on.parseVersion($);return!S||!A?0:S.major!==A.major?A.major-S.major:S.minor!==A.minor?A.minor-S.minor:A.patch-S.patch});d.set(g,b[0])}let m=[],y=0;for(let[g,k]of d){let b=this.fileCache.get(r,g,k);if(!b)try{let h=await this.publisherIndex.getPackageUrl(r,g,k),$=await this.fetchFn(h,r);if(!$.ok)continue;b=await $.text(),this.fileCache.put(r,g,k,b)}catch{continue}try{let h=this.parser.parse(b),$=new D(h,this.repository),S=await this.objectParser.parseKanonaks($),A=K(S,o);for(let P of A)m.push({publisher:r,package_:g,version:k,subject:P});y++}catch{continue}}if(m.length===0){console.log(`No ${L(o)} instances found across ${y} package(s).`);return}console.log(`Found ${m.length} ${L(o)} instance(s):
169
- `);for(let g of m)console.log(` ${g.publisher}/${g.package_}@${g.version}`),console.log(` ${g.subject.name}`),console.log()}async info(e,t,r){let s=(await this.requireHandler(e).list({repository:this.repository,options:r})).find(c=>c.name===t);s||(console.error(`"${t}" is not installed.`),process.exit(1)),console.log(`Name: ${s.name}`),console.log(`Type: ${e.managesTypeKey||"n/a"}`),console.log(`Publisher: ${s.publisher||"unmanaged"}`),console.log(`Package: ${s.package_||"n/a"}`),console.log(`Version: ${s.version||"n/a"}`),console.log(`Path: ${s.path}`)}requireHandler(e){let t=this.handlerRegistry.get(e.deploymentTargetKey);return t||(console.error(`No deployment handler registered for "${e.deploymentTargetKey}". Ensure the capability's deploymentTarget resolves to a DeploymentTarget instance whose URI is registered in the CLI at startup.`),process.exit(1)),t}};function kt(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}var Re=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as ks,rmSync as ys,existsSync as je,readdirSync as bs,writeFileSync as ws}from"fs";import{join as xe}from"path";import{KanonakObjectParser as Ss,KanonakParser as $s}from"@kanonak-protocol/sdk";import{join as an}from"path";import{homedir as yt}from"os";import{KanonakObjectParser as as}from"@kanonak-protocol/sdk";var ae="kanonak.org",se="agent-skills",wt={publisher:ae,package_:se,name:"Client"},St={publisher:ae,package_:se,name:"clientId"},ss={publisher:ae,package_:se,name:"projectSkillDir"},is={publisher:ae,package_:se,name:"userSkillDir"},cs="agents";async function fe(n,e){let t=(n.client??ls()??cs).toLowerCase(),r=n.scope??"project",o=await us(t,e);if(!o){let c=await ds(e);throw new Error(`Unknown client "${t}". Known clients: ${c.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=C(o,r==="user"?is:ss);if(!s)throw new Error(`Client "${t}" has no ${r==="user"?"userSkillDir":"projectSkillDir"} declared.`);return ps(s)}async function Ie(n,e,t){let r=await fe(e,t);return an(r,n)}function ls(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var bt=new WeakMap;async function $t(n){let e=bt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(ae,se);if(t.length===0)throw new Error(`Could not find ${ae}/${se} in the repository. Install a skill capability (which transitively imports agent-skills) or fetch agent-skills directly to populate the cache.`);let o=[...t].sort((i,l)=>{let u=i.metadata.namespace_?.version,d=l.metadata.namespace_?.version;return!u||!d?0:u.major!==d.major?d.major-u.major:u.minor!==d.minor?d.minor-u.minor:d.patch-u.patch})[0],a=new as,s=new D(o,n),c=await a.parseKanonaks(s);return bt.set(n,c),c}async function us(n,e){let t=await $t(e),r=K(t,wt);for(let o of r)if(C(o,St)===n)return o}async function ds(n){let e=await $t(n),t=K(e,wt),r=[];for(let o of t){let a=C(o,St);a&&r.push(a)}return r}function ps(n){return n.startsWith("~/")?an(yt(),n.slice(2)):n==="~"?yt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:an(process.cwd(),n)}import{readFileSync as ms,writeFileSync as fs,existsSync as gs}from"fs";import{join as vt}from"path";import Dt from"js-yaml";var At="skills.lock",hs=`# This file is generated by Kanonak CLI. Do not edit manually.
170
- `;function Te(n){let e=vt(n,At);if(!gs(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=ms(e,"utf-8"),r=Dt.load(t);return!r||typeof r!="object"||r.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),skills:{}}:{version:"1",lastUpdated:r.lastUpdated??new Date().toISOString(),skills:r.skills??{}}}function sn(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.skills).sort())t[a]=e.skills[a];e.skills=t;let r=vt(n,At),o=Dt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});fs(r,hs+o,"utf-8")}var Kt="kanonak.org",Ct="skill-to-skill-md",Ue=class{parser=new $s;objectParser=new Ss;runner=new V;async deploy(e){let{instances:t,allKanonaks:r,repository:o,options:a}=e;if(t.length===0){console.error("No Skill instances to deploy.");return}let s=await vs(o,this.objectParser);if(!s){console.error(`Cannot deploy: ${Kt}/${Ct}@1.0.0 is not installed in the workspace or cache.`);return}let c=await this.runner.run({transformation:s,instances:t,allKanonaks:r,repository:o,parser:this.parser,objectParser:this.objectParser,outputFormat:"markdown-with-frontmatter"});if(c.length===0){console.error("No skills could be transformed from the package.");return}let i=await fe(a,o),l=Te(i),u=t[0].namespace,{publisher:d,package_:m,version:y}=Ds(u);for(let g of c){let k=await Ie(g.fileName,a,o),b=je(xe(k,"SKILL.md"));ks(k,{recursive:!0}),ws(xe(k,"SKILL.md"),g.content,"utf-8"),l.skills[g.fileName]={publisher:d,package_:m,version:y,resolved:d?`kanonak://${d}/${m}@${y}`:"",integrity:N(g.content)},console.log(` ${b?"Updated":"Installed"} skill "${g.fileName}" \u2192 ${k}`)}sn(i,l)}async undeploy(e,t){let{repository:r,options:o}=t,a=await Ie(e,o,r);je(a)||(console.error(`Skill "${e}" is not installed at ${a}`),process.exit(1)),ys(a,{recursive:!0,force:!0});let s=await fe(o,r),c=Te(s);delete c.skills[e],sn(s,c),console.log(`Removed skill "${e}" from ${a}`)}async list(e){let{repository:t,options:r}=e,o=await fe(r,t),a=Te(o),s=[];for(let[c,i]of Object.entries(a.skills))s.push({name:c,publisher:i.publisher,package_:i.package_,version:i.version,path:await Ie(c,r,t)});if(je(o))try{let c=bs(o,{withFileTypes:!0});for(let i of c){if(!i.isDirectory()||a.skills[i.name])continue;let l=xe(o,i.name,"SKILL.md");je(l)&&s.push({name:i.name,publisher:"",package_:"",version:"",path:xe(o,i.name)})}}catch{}return s}};async function vs(n,e){let t=await n.getDocumentsByNamespaceAsync(Kt,Ct);if(t.length===0)return;let r=new D(t[0],n),o=await e.parseKanonaks(r);return K(o,f.Transformation)[0]}function Ds(n){if(!n)return{publisher:"",package_:"",version:""};let e=n.indexOf("@");if(e===-1)return{publisher:"",package_:"",version:""};let t=n.substring(0,e),r=n.substring(e+1),o=t.indexOf("/");return o===-1?{publisher:"",package_:"",version:""}:{publisher:t.substring(0,o),package_:t.substring(o+1),version:r}}import{mkdirSync as Ls,rmSync as Ns,existsSync as ln,readdirSync as Fs,writeFileSync as Ms,statSync as Bs}from"fs";import{join as Ne}from"path";import{KanonakObjectParser as Vs,KanonakParser as Hs}from"@kanonak-protocol/sdk";import{join as Pt}from"path";import{homedir as Et}from"os";import{KanonakObjectParser as As}from"@kanonak-protocol/sdk";var z="kanonak.org",q="agent-skills",Rt={publisher:z,package_:q,name:"Client"},It={publisher:z,package_:q,name:"clientId"},Ks={publisher:z,package_:q,name:"projectAgentDir"},Cs={publisher:z,package_:q,name:"userAgentDir"},Ps={publisher:z,package_:q,name:"agentFileFormat"},Es="agents";function _s(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Oe(n,e){let t=(n.client??_s()??Es).toLowerCase(),r=n.scope??"project",o=await Rs(t,e);if(!o){let u=await Is(e);throw new Error(`Unknown client "${t}". Known clients: ${u.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=C(o,r==="user"?Cs:Ks);if(!s)throw new Error(`Client "${t}" has no ${r==="user"?"userAgentDir":"projectAgentDir"} declared.`);let i=B(o,Ps)?.name==="toml"?"toml":"markdown-frontmatter",l=i==="toml"?".toml":".md";return{agentsDir:Ts(s),format:i,fileExtension:l}}var _t=new WeakMap;async function Tt(n){let e=_t.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(z,q);if(t.length===0)throw new Error(`Could not find ${z}/${q} in the repository. Install a capability that imports agent-skills to populate the cache.`);let o=[...t].sort((i,l)=>{let u=i.metadata.namespace_?.version,d=l.metadata.namespace_?.version;return!u||!d?0:u.major!==d.major?d.major-u.major:u.minor!==d.minor?d.minor-u.minor:d.patch-u.patch})[0],a=new As,s=new D(o,n),c=await a.parseKanonaks(s);return _t.set(n,c),c}async function Rs(n,e){let t=await Tt(e),r=K(t,Rt);for(let o of r)if(C(o,It)===n)return o}async function Is(n){let e=await Tt(n),t=K(e,Rt),r=[];for(let o of t){let a=C(o,It);a&&r.push(a)}return r}function Ts(n){return n.startsWith("~/")?Pt(Et(),n.slice(2)):n==="~"?Et():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Pt(process.cwd(),n)}import{readFileSync as js,writeFileSync as xs,existsSync as Us}from"fs";import{join as jt}from"path";import xt from"js-yaml";var Ut="agents.lock",Os=`# This file is generated by Kanonak CLI. Do not edit manually.
171
- `;function Le(n){let e=jt(n,Ut);if(!Us(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=js(e,"utf-8"),r=xt.load(t);return!r||typeof r!="object"||r.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),agents:{}}:{version:"1",lastUpdated:r.lastUpdated??new Date().toISOString(),agents:r.agents??{}}}function cn(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.agents).sort())t[a]=e.agents[a];e.agents=t;let r=jt(n,Ut),o=xt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});xs(r,Os+o,"utf-8")}var Ot="kanonak.org",Lt="agent-to-agent-file",Fe=class{parser=new Hs;objectParser=new Vs;runner=new V;async deploy(e){let{instances:t,allKanonaks:r,repository:o,options:a}=e;if(t.length===0){console.error("No Agent instances to deploy.");return}let{agentsDir:s,format:c,fileExtension:i}=await Oe(a,o),l=await zs(o,this.objectParser);if(!l){console.error(`Cannot deploy: ${Ot}/${Lt}@1.0.0 is not installed in the workspace or cache.`);return}let u=c==="toml"?"toml":"markdown-with-frontmatter",d=await this.runner.run({transformation:l,instances:t,allKanonaks:r,repository:o,parser:this.parser,objectParser:this.objectParser,outputFormat:u});if(d.length===0){console.error("No agents could be transformed from the package.");return}Ls(s,{recursive:!0});let m=Le(s),y=t[0].namespace,{publisher:g,package_:k,version:b}=Gs(y);for(let h of d){let $=`${h.fileName}${i}`,S=Ne(s,$),A=ln(S);Ms(S,h.content,"utf-8"),m.agents[h.fileName]={publisher:g,package_:k,version:b,resolved:g?`kanonak://${g}/${k}@${b}`:"",integrity:N(h.content),fileName:$},console.log(` ${A?"Updated":"Installed"} agent "${h.fileName}" \u2192 ${S}`)}cn(s,m)}async undeploy(e,t){let{repository:r,options:o}=t,{agentsDir:a}=await Oe(o,r),s=Le(a),c=s.agents[e];c||(console.error(`Agent "${e}" is not installed at ${a}`),process.exit(1));let i=Ne(a,c.fileName);ln(i)&&Ns(i,{force:!0}),delete s.agents[e],cn(a,s),console.log(`Removed agent "${e}" from ${i}`)}async list(e){let{repository:t,options:r}=e,{agentsDir:o}=await Oe(r,t),a=Le(o),s=[];for(let[c,i]of Object.entries(a.agents))s.push({name:c,publisher:i.publisher,package_:i.package_,version:i.version,path:Ne(o,i.fileName)});if(ln(o))try{let c=Fs(o,{withFileTypes:!0});for(let i of c){if(!i.isFile()||i.name==="agents.lock")continue;let l=Ne(o,i.name),u=qs(i.name);if(!a.agents[u]){try{if(!Bs(l).isFile())continue}catch{continue}s.push({name:u,publisher:"",package_:"",version:"",path:l})}}}catch{}return s}};async function zs(n,e){let t=await n.getDocumentsByNamespaceAsync(Ot,Lt);if(t.length===0)return;let r=new D(t[0],n),o=await e.parseKanonaks(r);return K(o,f.Transformation)[0]}function qs(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function Gs(n){if(!n)return{publisher:"",package_:"",version:""};let e=n.indexOf("@");if(e===-1)return{publisher:"",package_:"",version:""};let t=n.substring(0,e),r=n.substring(e+1),o=t.indexOf("/");return o===-1?{publisher:"",package_:"",version:""}:{publisher:t.substring(0,o),package_:t.substring(o+1),version:r}}var ri=Ys(Js(import.meta.url)),oi=JSON.parse(Xs(Zs(ri,"..","package.json"),"utf-8")),O=new Ws;O.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(oi.version);O.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await fn(n)});O.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await yn(n)});O.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await wn(n)});O.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await An(n)});O.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await Kn(n)});O.addCommand(Nn());O.addCommand(ct());O.addCommand(ft());async function ai(){try{let n=new T,e=new Qs,t=new ni,r=ti(t),o=new ei({fetchFn:r}),a=await j(process.cwd(),e),s=new Re;s.register("kanonak.org/capabilities/agent-skill-deployment",new Ue),s.register("kanonak.org/agent-capabilities/agent-instance-deployment",new Fe);let c=await On(n,e,a),i=new _e(n,e,o,r,s,a);ht(O,c,i)}catch{}}await ai();O.parse();
162
+ ${m}`)}let i=Array.from(c.values())[0];if(i.length===1)return{transformation:i[0].tx,transformationKanonaks:i[0].kanonaks};let l=new Map(i.map(m=>[m.doc,m])),u=nn(i.map(m=>m.doc));if(!u.chosen)throw new Error(`Could not select a Transformation version for "${a}".`);let d=l.get(u.chosen);if(u.multipleVersionsPresent){let m=f=>{let h=f.metadata.namespace_?.version;return h?it(h):""},k=d.tx.namespace??"",b=k.includes("@")?k.substring(0,k.indexOf("@")):k;console.warn(`Warning: Transformation "${a}" has ${i.length} versions present (${i.map(f=>m(f.doc)).filter(Boolean).join(", ")}); using @${m(u.chosen)}. Pin with ${b}@<version>/${a} to suppress this warning.`)}return{transformation:d.tx,transformationKanonaks:d.kanonaks}}async function Oa(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||rt(n)&&Da(n).isFile()){if(!rt(n))throw new Error(`Scope file not found: ${n}`);let b=$a(n,"utf-8"),f=t.parse(b),h=new A(f,e);return o.parseKanonaks(h)}let a=n.indexOf("@"),s=a===-1?n:n.substring(0,a),c=a===-1?void 0:n.substring(a+1),i=s.indexOf("/");if(i===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=s.substring(0,i),u=s.substring(i+1),d=await e.getDocumentsByNamespaceAsync(l,u);if(d.length===0)throw new Error(`Scope package ${l}/${u} not found in the local workspace or cache.`);let m=ut(d,c,`${l}/${u}`),k=new A(m,e);return o.parseKanonaks(k)}function La(n){let e=n.indexOf("@");if(e===-1)return;let t=n.substring(e+1),o=t.indexOf("/");return o===-1?t:t.substring(0,o)}function ut(n,e,t){let o=a=>{let s=a.metadata.namespace_?.version;return s?it(s):""},r=nn(n,{requestedVersion:e});if(r.exactRequestedVersionMissing){let a=n.map(o).filter(Boolean).sort().join(", ");throw new Error(`${t}@${e} not found in the local workspace or cache. Available versions: ${a||"(none with parseable namespace)"}`)}if(!r.chosen)throw new Error(`${t} not found in the local workspace or cache.`);return!e&&r.multipleVersionsPresent&&console.warn(`Warning: ${t} has ${n.length} versions present (${n.map(o).filter(Boolean).join(", ")}); using @${o(r.chosen)}. Pin with ${t}@<version> to suppress this warning.`),r.chosen}function at(n,e){try{let t=ee(n,e);return{uri:Ee(n),matchesClass:Pe(t.inputPattern.matchesClass),outputs:Array.from(t.outputs).sort()}}catch(t){return{uri:Ee(n),matchesClass:`(compile error: ${t.message})`,outputs:[]}}}function Ee(n){let e=n.namespace||"",t=e.indexOf("@");return`${t===-1?e:e.substring(0,t)}/${n.name}`}function Pe(n){return`${n.publisher}/${n.package_}/${n.name}`}function Fa(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Ma(n,e,t){let o=new Map;for(let s of n){if(!(s instanceof Ca))continue;let c=tn(s);c&&o.set(c,s)}let r=[];try{r=(await new Pa({vocabulary:new Ea}).reason(t)).getInstancesOfClass(st(e.publisher,e.package_,e.name))}catch{}let a=[];for(let s of r){let c=o.get(s);c&&a.push(c)}return a.length>0?a:C(n,e)}function tn(n){let e=n.namespace??"",t=e.indexOf("@"),o=t===-1?e:e.substring(0,t),r=o.indexOf("/");return r===-1||!n.name?null:st(o.substring(0,r),o.substring(r+1),n.name)}import{Command as Ba}from"commander";import{KanonakParser as Va,PublisherIndex as dt,CredentialStore as mt,createAuthenticatedFetch as pt,FileSystemKanonakDocumentRepository as Ha,Reasoner as za,KanonakVocabulary as qa,getGlobalCachePath as Ga,makeUriKey as Wa}from"@kanonak-protocol/sdk";function Xa(n){let e=n.split("/");if(e.length!==3)return null;let[t,o,r]=e;return!t||!o||!r?null:{publisher:t,package_:o,name:r}}function ft(){return new Ba("search").description("Browse a publisher's catalogue or find instances of a class via the SDK reasoner").argument("<publisher>","Publisher domain (e.g. kanonak.org)").option("--type <uri>","Class URI to search for, in publisher/package/Name form").action(async(n,e)=>{e.type?await Ya(n,e.type):await Ja(n)})}async function Ja(n){let e=new mt,t=pt(e),o=new dt({fetchFn:t}),r;try{r=await o.listLatestPackages(n)}catch(s){console.error(`Failed to fetch publisher index for ${n}: ${s.message}`),process.exit(1)}if(r.length===0){console.log(`No packages found at ${n}.`);return}console.log(`Packages published by ${n}:
163
+ `);let a=r.reduce((s,c)=>Math.max(s,c.packageName.length),0);for(let{packageName:s,version:c}of r)console.log(` ${s.padEnd(a)} @${c}`)}async function Ya(n,e){let t=Xa(e);t||(console.error(`Invalid --type value: ${e}`),console.error("Expected: publisher/package/Name (e.g. kanonak.org/capabilities/Capability)"),process.exit(1));let o=new Va,r=new mt,a=pt(r),s=new dt({fetchFn:a}),c=new T,i=new Set,l=[];try{l=await s.listLatestPackages(n)}catch(h){console.error(`Failed to fetch publisher index for ${n}: ${h.message}`),process.exit(1)}for(let{packageName:h,version:g}of l)i.add(`${n}|${h}|${g}`);await on(s,c,a,"kanonak.org","core-rdf",i),await on(s,c,a,"kanonak.org","core-owl",i),await on(s,c,a,t.publisher,t.package_,i);for(let h of i){let[g,w,$]=h.split("|");if(!c.has(g,w,$))try{let v=await s.getPackageUrl(g,w,$),D=await a(v,g);if(!D.ok){console.error(`Warning: failed to fetch ${g}/${w}@${$}: ${D.status} ${D.statusText}`);continue}let q=await D.text();c.put(g,w,$,q)}catch(v){console.error(`Warning: failed to fetch ${g}/${w}@${$}: ${v.message}`)}}let u=new Ha(Ga(),!0,o),m=await new za({vocabulary:new qa}).reason(u),k=Wa(t.publisher,t.package_,t.name),f=m.getInstancesOfClass(k).filter(h=>h!==k);if(f.length===0){console.log(`No instances of ${k} found in ${n}'s catalogue.`);return}console.log(`Instances of ${k} in ${n}'s catalogue:
164
+ `),f.sort();for(let h of f)console.log(` ${h}`)}async function on(n,e,t,o,r,a){try{let s=await n.getHighestVersion(o,r);if(!s)return;a.add(`${o}|${r}|${s}`)}catch{}}import{Command as gt}from"commander";function oe(n){return`${E}/${_}/${n}`}var rn={[oe("fetch-and-deploy")]:(n,e,t,o)=>n.add(e,t[0],o),[oe("remove-deployed")]:(n,e,t,o)=>n.remove(e,t[0],o),[oe("list-deployed")]:(n,e,t,o)=>n.list(e,o),[oe("update-deployed")]:(n,e,t,o)=>n.update(e,t[0],o),[oe("search-available")]:(n,e,t,o)=>n.search(e,o),[oe("show-info")]:(n,e,t,o)=>n.info(e,t[0],o)};function ht(n,e,t){for(let o of e){let r=new gt(o.commandName).description(o.description.trim());for(let a of o.commands){let s=r.command(Za(a));s.description(a.description);for(let c of a.arguments)if(c.isOption){let i=c.defaultValue!=null?`--${c.argumentName} [value]`:`--${c.argumentName} <value>`;s.option(i,"",c.defaultValue)}s.action(async(...c)=>{let i=Qa(c);await es(t,o,a,c,i)})}n.addCommand(r)}}function Za(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function Qa(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof gt))return n[e];return{}}async function es(n,e,t,o,r){let a=[];for(let c of o)if(typeof c=="string")a.push(c);else break;t.actionKey||(console.error(`Capability subcommand '${t.subcommandName}' has no resolved \`performs:\` Action. Every CapabilityCommand must declare a performs value pointing at a named Action instance from the capabilities ontology. Known actions: ${Object.keys(rn).join(", ")}.`),process.exit(1));let s=rn[t.actionKey];s||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(rn).join(", ")}.`),process.exit(1)),await s(n,e,a,r)}import{KanonakObjectParser as ns,PublisherIndex as an,PublisherConfigResolver as ts}from"@kanonak-protocol/sdk";var _e=class{constructor(e,t,o,r,a,s){this.fileCache=e;this.parser=t;this.publisherIndex=o;this.fetchFn=r;this.handlerRegistry=a;this.repository=s}fileCache;parser;publisherIndex;fetchFn;handlerRegistry;repository;objectParser=new ns;async add(e,t,o){let r=G(t);r||(console.error(`Invalid package reference: "${t}"`),console.error(""),console.error("Accepted forms:"),console.error(" publisher/package (install all instances, latest version)"),console.error(" publisher/package@version (install all instances, pinned)"),console.error(" publisher/package/instance (install one instance, latest version)"),console.error(" publisher/package@version/instance (install one instance, pinned)"),console.error(""),console.error("Tip: copy a URI directly from `kanonak "+e.commandName+" search`."),process.exit(1));let{publisher:a,packageName:s,version:c,instanceName:i}=r,l=c??await this.publisherIndex.getHighestVersion(a,s);l||(console.error(`Could not resolve version for "${a}/${s}".`),await this.printPackageSuggestions(a,s,e.commandName),process.exit(1));let u=this.fileCache.get(a,s,l);if(!u){let $=await this.publisherIndex.getPackageUrl(a,s,l),v=await this.fetchFn($,a);v.ok||(v.status===404?(console.error(`Package ${a}/${s}@${l} not found at ${$}.`),console.error(`The publisher index lists this version but the file is missing \u2014 it may have been unpublished. Try \`kanonak ${e.commandName} search\` to see the current catalogue.`)):console.error(`Failed to fetch ${$} (${v.status} ${v.statusText}).`),process.exit(1)),u=await v.text(),this.fileCache.put(a,s,l,u)}let d=this.parser.parse(u),m=new A(d,this.repository),k=await this.objectParser.parseKanonaks(m),b=kt(e.managesTypeKey);b||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let f=C(k,b);f.length===0&&(console.error(`Package ${a}/${s}@${l} does not contain any ${N(b)} instances.`),process.exit(1));let h=f;if(i&&(h=f.filter($=>$.name===i),h.length===0)){console.error(`Instance "${i}" not found in ${a}/${s}@${l}.`),console.error(""),console.error(`This package contains ${f.length} ${N(b)} instance(s):`);for(let $ of f)console.error(` - ${$.name}`);console.error(""),console.error("To install all of them, drop the instance suffix:"),console.error(` kanonak ${e.commandName} add ${a}/${s}`),process.exit(1)}let g=i?`${i} from ${a}/${s}@${l}`:`${h.length} ${N(b)} instance(s) from ${a}/${s}@${l}`;console.log(`Installing ${g}...`);let w=this.handlerRegistry.get(e.deploymentTargetKey);w?await w.deploy({instances:h,allKanonaks:k,repository:this.repository,options:o}):console.log(`Cached ${a}/${s}@${l} (no deployment handler for "${e.deploymentTargetKey}")`)}async printPackageSuggestions(e,t,o){let r;try{r=await this.publisherIndex.listLatestPackages(e)}catch{return}let a=r.map(s=>({name:s.packageName,version:s.version,score:os(t,s.packageName)})).filter(s=>s.score>0).sort((s,c)=>c.score-s.score).slice(0,5);if(a.length!==0){console.error(""),console.error("Did you mean one of:");for(let s of a)console.error(` kanonak ${o} add ${e}/${s.name}`)}}async remove(e,t,o){await this.requireHandler(e).undeploy(t,{repository:this.repository,options:o})}async list(e,t){let r=await this.requireHandler(e).list({repository:this.repository,options:t}),a=e.managesTypeKey||"managed";if(r.length===0){console.log(`No ${a} instances installed.`);return}console.log(`Installed ${a} instances:
165
+ `);for(let s of r){let c=s.publisher?`${s.publisher}/${s.package_}@${s.version}`:"unmanaged";console.log(` ${s.name} (${c}) ${s.path}`)}}async update(e,t,o){let a=await this.requireHandler(e).list({repository:this.repository,options:o}),s=t?a.filter(i=>i.name===t):a.filter(i=>i.publisher);if(s.length===0){console.log(t?`"${t}" not found.`:"No managed instances to update.");return}let c=0;for(let i of s){let l=await this.publisherIndex.getHighestVersion(i.publisher,i.package_);!l||l===i.version||(console.log(`Updating ${i.name}: ${i.version} \u2192 ${l}`),await this.add(e,`${i.publisher}/${i.package_}@${l}`,o),c++)}console.log(c===0?"All instances are up to date.":`
166
+ Updated ${c} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=kt(e.managesTypeKey);if(!r){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${o} for ${N(r)} instances...
167
+ `);let a=new ts,s=await a.getConfig(o),c=a.resolveIndexUrl(o,s),i=await this.fetchFn(c,o);if(!i.ok){console.error(`Failed to fetch package index from ${o}.`);return}let l=await i.text(),u=an.parseIndex(l);if(u.size===0){console.error(`No packages found for publisher "${o}".`);return}let d=new Map;for(let[f,h]of u){let g=[...h].sort((w,$)=>{let v=an.parseVersion(w),D=an.parseVersion($);return!v||!D?0:v.major!==D.major?D.major-v.major:v.minor!==D.minor?D.minor-v.minor:D.patch-v.patch});d.set(f,g[0])}let m=[],k=0;for(let[f,h]of d){let g=this.fileCache.get(o,f,h);if(!g)try{let w=await this.publisherIndex.getPackageUrl(o,f,h),$=await this.fetchFn(w,o);if(!$.ok)continue;g=await $.text(),this.fileCache.put(o,f,h,g)}catch{continue}try{let w=this.parser.parse(g),$=new A(w,this.repository),v=await this.objectParser.parseKanonaks($),D=C(v,r);for(let q of D)m.push({publisher:o,package_:f,version:h,subject:q});k++}catch{continue}}if(m.length===0){console.log(`No ${N(r)} instances found across ${k} package(s).`);return}console.log(`Found ${m.length} ${N(r)} instance(s) in ${k} package(s):
168
+ `);let b=new Map;for(let f of m){let h=`${f.publisher}/${f.package_}@${f.version}`,g=b.get(h);g?g.push(f):b.set(h,[f])}for(let[f,h]of b){let g=h[0],w=`${g.publisher}/${g.package_}`,$=h.length===1;console.log(` ${f}`),console.log(` ${h.length} skill${$?"":"s"}:`);for(let v of h)console.log(` - ${v.subject.name}`);if(console.log(""),$)console.log(" install:"),console.log(` kanonak ${e.commandName} add ${w}/${g.subject.name}`);else{console.log(" install one of them:");for(let v of h)console.log(` kanonak ${e.commandName} add ${w}/${v.subject.name}`);console.log(" install all of them:"),console.log(` kanonak ${e.commandName} add ${w}`)}console.log("")}}async info(e,t,o){let s=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(c=>c.name===t);s||(console.error(`"${t}" is not installed.`),process.exit(1)),console.log(`Name: ${s.name}`),console.log(`Type: ${e.managesTypeKey||"n/a"}`),console.log(`Publisher: ${s.publisher||"unmanaged"}`),console.log(`Package: ${s.package_||"n/a"}`),console.log(`Version: ${s.version||"n/a"}`),console.log(`Path: ${s.path}`)}requireHandler(e){let t=this.handlerRegistry.get(e.deploymentTargetKey);return t||(console.error(`No deployment handler registered for "${e.deploymentTargetKey}". Ensure the capability's deploymentTarget resolves to a DeploymentTarget instance whose URI is registered in the CLI at startup.`),process.exit(1)),t}};function kt(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function os(n,e){let t=n.toLowerCase(),o=e.toLowerCase();if(t===o)return 100;if(o.includes(t)||t.includes(o))return 50;let r=new Set(t.split("-").filter(Boolean)),a=new Set(o.split("-").filter(Boolean)),s=0;for(let i of r)a.has(i)&&s++;if(s>0)return s*10;let c=rs(t,o);return c===0?100:c<=2?Math.max(1,20-c*5):0}function rs(n,e){if(n===e)return 0;if(n.length===0)return e.length;if(e.length===0)return n.length;let t=new Array(e.length+1),o=new Array(e.length+1);for(let r=0;r<=e.length;r++)t[r]=r;for(let r=0;r<n.length;r++){o[0]=r+1;for(let a=0;a<e.length;a++){let s=n[r]===e[a]?0:1;o[a+1]=Math.min(o[a]+1,t[a+1]+1,t[a]+s)}for(let a=0;a<=e.length;a++)t[a]=o[a]}return t[e.length]}var Ie=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as ks,rmSync as ys,existsSync as xe,readdirSync as bs,writeFileSync as ws}from"fs";import{join as je}from"path";import{KanonakObjectParser as $s,KanonakParser as Ss,computeIntegrity as vs}from"@kanonak-protocol/sdk";import{join as sn}from"path";import{homedir as yt}from"os";import{KanonakObjectParser as as}from"@kanonak-protocol/sdk";var re="kanonak.org",ae="agent-skills",wt={publisher:re,package_:ae,name:"Client"},$t={publisher:re,package_:ae,name:"clientId"},ss={publisher:re,package_:ae,name:"projectSkillDir"},is={publisher:re,package_:ae,name:"userSkillDir"},cs="agents";async function me(n,e){let t=(n.client??ls()??cs).toLowerCase(),o=n.scope??"project",r=await us(t,e);if(!r){let c=await ds(e);throw new Error(`Unknown client "${t}". Known clients: ${c.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=P(r,o==="user"?is:ss);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return ms(s)}async function Re(n,e,t){let o=await me(e,t);return sn(o,n)}function ls(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var bt=new WeakMap;async function St(n){let e=bt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(re,ae);if(t.length===0)throw new Error(`Could not find ${re}/${ae} in the repository. Install a skill capability (which transitively imports agent-skills) or fetch agent-skills directly to populate the cache.`);let r=[...t].sort((i,l)=>{let u=i.metadata.namespace_?.version,d=l.metadata.namespace_?.version;return!u||!d?0:u.major!==d.major?d.major-u.major:u.minor!==d.minor?d.minor-u.minor:d.patch-u.patch})[0],a=new as,s=new A(r,n),c=await a.parseKanonaks(s);return bt.set(n,c),c}async function us(n,e){let t=await St(e),o=C(t,wt);for(let r of o)if(P(r,$t)===n)return r}async function ds(n){let e=await St(n),t=C(e,wt),o=[];for(let r of t){let a=P(r,$t);a&&o.push(a)}return o}function ms(n){return n.startsWith("~/")?sn(yt(),n.slice(2)):n==="~"?yt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:sn(process.cwd(),n)}import{readFileSync as ps,writeFileSync as fs,existsSync as gs}from"fs";import{join as vt}from"path";import Dt from"js-yaml";var Kt="skills.lock",hs=`# This file is generated by Kanonak CLI. Do not edit manually.
169
+ `;function Te(n){let e=vt(n,Kt);if(!gs(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=ps(e,"utf-8"),o=Dt.load(t);return!o||typeof o!="object"||o.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),skills:{}}:{version:"1",lastUpdated:o.lastUpdated??new Date().toISOString(),skills:o.skills??{}}}function cn(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.skills).sort())t[a]=e.skills[a];e.skills=t;let o=vt(n,Kt),r=Dt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});fs(o,hs+r,"utf-8")}var At="kanonak.org",Ct="skill-to-skill-md",Ue=class{parser=new Ss;objectParser=new $s;runner=new B;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:a}=e;if(t.length===0){console.error("No Skill instances to deploy.");return}let s=await Ds(r,this.objectParser);if(!s){console.error(`Cannot deploy: ${At}/${Ct}@1.0.0 is not installed in the workspace or cache.`);return}let c=await this.runner.run({transformation:s,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:"markdown-with-frontmatter"});if(c.length===0){console.error("No skills could be transformed from the package.");return}let i=await me(a,r),l=Te(i),u=t[0].namespace,{publisher:d,package_:m,version:k}=Ks(u);for(let b of c){let f=await Re(b.fileName,a,r),h=xe(je(f,"SKILL.md"));ks(f,{recursive:!0}),ws(je(f,"SKILL.md"),b.content,"utf-8"),l.skills[b.fileName]={publisher:d,package_:m,version:k,resolved:d?`kanonak://${d}/${m}@${k}`:"",integrity:vs(b.content)},console.log(` ${h?"Updated":"Installed"} skill "${b.fileName}" \u2192 ${f}`)}cn(i,l)}async undeploy(e,t){let{repository:o,options:r}=t,a=await Re(e,r,o);xe(a)||(console.error(`Skill "${e}" is not installed at ${a}`),process.exit(1)),ys(a,{recursive:!0,force:!0});let s=await me(r,o),c=Te(s);delete c.skills[e],cn(s,c),console.log(`Removed skill "${e}" from ${a}`)}async list(e){let{repository:t,options:o}=e,r=await me(o,t),a=Te(r),s=[];for(let[c,i]of Object.entries(a.skills))s.push({name:c,publisher:i.publisher,package_:i.package_,version:i.version,path:await Re(c,o,t)});if(xe(r))try{let c=bs(r,{withFileTypes:!0});for(let i of c){if(!i.isDirectory()||a.skills[i.name])continue;let l=je(r,i.name,"SKILL.md");xe(l)&&s.push({name:i.name,publisher:"",package_:"",version:"",path:je(r,i.name)})}}catch{}return s}};async function Ds(n,e){let t=await n.getDocumentsByNamespaceAsync(At,Ct);if(t.length===0)return;let o=new A(t[0],n),r=await e.parseKanonaks(o);return C(r,y.Transformation)[0]}function Ks(n){if(!n)return{publisher:"",package_:"",version:""};let e=n.indexOf("@");if(e===-1)return{publisher:"",package_:"",version:""};let t=n.substring(0,e),o=n.substring(e+1),r=t.indexOf("/");return r===-1?{publisher:"",package_:"",version:""}:{publisher:t.substring(0,r),package_:t.substring(r+1),version:o}}import{mkdirSync as Ls,rmSync as Fs,existsSync as un,readdirSync as Ms,writeFileSync as Bs,statSync as Vs}from"fs";import{join as Le}from"path";import{KanonakObjectParser as Hs,KanonakParser as zs,computeIntegrity as qs}from"@kanonak-protocol/sdk";import{join as Pt}from"path";import{homedir as Et}from"os";import{KanonakObjectParser as As}from"@kanonak-protocol/sdk";var H="kanonak.org",z="agent-skills",It={publisher:H,package_:z,name:"Client"},Rt={publisher:H,package_:z,name:"clientId"},Cs={publisher:H,package_:z,name:"projectAgentDir"},Ps={publisher:H,package_:z,name:"userAgentDir"},Es={publisher:H,package_:z,name:"agentFileFormat"},_s="agents";function Is(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Ne(n,e){let t=(n.client??Is()??_s).toLowerCase(),o=n.scope??"project",r=await Rs(t,e);if(!r){let u=await Ts(e);throw new Error(`Unknown client "${t}". Known clients: ${u.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=P(r,o==="user"?Ps:Cs);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let i=M(r,Es)?.name==="toml"?"toml":"markdown-frontmatter",l=i==="toml"?".toml":".md";return{agentsDir:xs(s),format:i,fileExtension:l}}var _t=new WeakMap;async function Tt(n){let e=_t.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(H,z);if(t.length===0)throw new Error(`Could not find ${H}/${z} in the repository. Install a capability that imports agent-skills to populate the cache.`);let r=[...t].sort((i,l)=>{let u=i.metadata.namespace_?.version,d=l.metadata.namespace_?.version;return!u||!d?0:u.major!==d.major?d.major-u.major:u.minor!==d.minor?d.minor-u.minor:d.patch-u.patch})[0],a=new As,s=new A(r,n),c=await a.parseKanonaks(s);return _t.set(n,c),c}async function Rs(n,e){let t=await Tt(e),o=C(t,It);for(let r of o)if(P(r,Rt)===n)return r}async function Ts(n){let e=await Tt(n),t=C(e,It),o=[];for(let r of t){let a=P(r,Rt);a&&o.push(a)}return o}function xs(n){return n.startsWith("~/")?Pt(Et(),n.slice(2)):n==="~"?Et():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Pt(process.cwd(),n)}import{readFileSync as js,writeFileSync as Us,existsSync as Ns}from"fs";import{join as xt}from"path";import jt from"js-yaml";var Ut="agents.lock",Os=`# This file is generated by Kanonak CLI. Do not edit manually.
170
+ `;function Oe(n){let e=xt(n,Ut);if(!Ns(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=js(e,"utf-8"),o=jt.load(t);return!o||typeof o!="object"||o.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),agents:{}}:{version:"1",lastUpdated:o.lastUpdated??new Date().toISOString(),agents:o.agents??{}}}function ln(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.agents).sort())t[a]=e.agents[a];e.agents=t;let o=xt(n,Ut),r=jt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Us(o,Os+r,"utf-8")}var Nt="kanonak.org",Ot="agent-to-agent-file",Fe=class{parser=new zs;objectParser=new Hs;runner=new B;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:a}=e;if(t.length===0){console.error("No Agent instances to deploy.");return}let{agentsDir:s,format:c,fileExtension:i}=await Ne(a,r),l=await Gs(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Nt}/${Ot}@1.0.0 is not installed in the workspace or cache.`);return}let u=c==="toml"?"toml":"markdown-with-frontmatter",d=await this.runner.run({transformation:l,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:u});if(d.length===0){console.error("No agents could be transformed from the package.");return}Ls(s,{recursive:!0});let m=Oe(s),k=t[0].namespace,{publisher:b,package_:f,version:h}=Xs(k);for(let g of d){let w=`${g.fileName}${i}`,$=Le(s,w),v=un($);Bs($,g.content,"utf-8"),m.agents[g.fileName]={publisher:b,package_:f,version:h,resolved:b?`kanonak://${b}/${f}@${h}`:"",integrity:qs(g.content),fileName:w},console.log(` ${v?"Updated":"Installed"} agent "${g.fileName}" \u2192 ${$}`)}ln(s,m)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:a}=await Ne(r,o),s=Oe(a),c=s.agents[e];c||(console.error(`Agent "${e}" is not installed at ${a}`),process.exit(1));let i=Le(a,c.fileName);un(i)&&Fs(i,{force:!0}),delete s.agents[e],ln(a,s),console.log(`Removed agent "${e}" from ${i}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await Ne(o,t),a=Oe(r),s=[];for(let[c,i]of Object.entries(a.agents))s.push({name:c,publisher:i.publisher,package_:i.package_,version:i.version,path:Le(r,i.fileName)});if(un(r))try{let c=Ms(r,{withFileTypes:!0});for(let i of c){if(!i.isFile()||i.name==="agents.lock")continue;let l=Le(r,i.name),u=Ws(i.name);if(!a.agents[u]){try{if(!Vs(l).isFile())continue}catch{continue}s.push({name:u,publisher:"",package_:"",version:"",path:l})}}}catch{}return s}};async function Gs(n,e){let t=await n.getDocumentsByNamespaceAsync(Nt,Ot);if(t.length===0)return;let o=new A(t[0],n),r=await e.parseKanonaks(o);return C(r,y.Transformation)[0]}function Ws(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function Xs(n){if(!n)return{publisher:"",package_:"",version:""};let e=n.indexOf("@");if(e===-1)return{publisher:"",package_:"",version:""};let t=n.substring(0,e),o=n.substring(e+1),r=t.indexOf("/");return r===-1?{publisher:"",package_:"",version:""}:{publisher:t.substring(0,r),package_:t.substring(r+1),version:o}}var ai=Qs(Zs(import.meta.url)),si=JSON.parse(Ys(ei(ai,"..","package.json"),"utf-8")),O=new Js;O.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(si.version);O.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await gn(n)});O.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await hn(n)});O.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await yn(n)});O.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await vn(n)});O.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await Dn(n)});O.addCommand(Nn());O.addCommand(ct());O.addCommand(ft());async function ii(){try{let n=new T,e=new ni,t=new oi,o=ri(t),r=new ti({fetchFn:o}),a=await x(process.cwd(),e),s=new Ie;s.register("kanonak.org/capabilities/agent-skill-deployment",new Ue),s.register("kanonak.org/agent-capabilities/agent-instance-deployment",new Fe);let c=await jn(n,e,a),i=new _e(n,e,r,o,s,a);ht(O,c,i)}catch{}}await ii();O.parse();
@@ -1,18 +1,52 @@
1
1
  /**
2
2
  * Parsed Kanonak package reference.
3
+ *
4
+ * Captures every form the CLI accepts on the command line:
5
+ *
6
+ * publisher/package
7
+ * publisher/package@version
8
+ * publisher/package/instance
9
+ * publisher/package@version/instance
10
+ *
11
+ * The optional `instanceName` selects a specific named entity inside
12
+ * the package (e.g. one Skill out of several). When omitted, callers
13
+ * that act on instances (like `kanonak skill add`) operate on every
14
+ * instance of the relevant type.
3
15
  */
4
16
  export interface PackageRef {
5
17
  publisher: string;
6
18
  packageName: string;
7
19
  version: string | null;
20
+ instanceName: string | null;
8
21
  }
9
22
  /**
10
- * Parse a package reference string.
23
+ * Parse a package reference string. Returns `null` if the input does
24
+ * not match any of the four accepted forms.
11
25
  *
12
- * Accepts formats:
13
- * publisher/package@version (e.g., "kanonak.org/core-rdf@1.0.1")
14
- * publisher/package (e.g., "kanonak.org/core-rdf")
26
+ * Accepted forms:
27
+ * - `publisher/package` (e.g. `kanonak.org/core-rdf`)
28
+ * - `publisher/package@version` (e.g. `kanonak.org/core-rdf@1.1.0`)
29
+ * - `publisher/package/instance` (e.g. `kanonak.org/kanonak-skills/kanonak-protocol-skill`)
30
+ * - `publisher/package@version/instance` (e.g. `kanonak.org/kanonak-skills@1.0.0/kanonak-protocol-skill`)
15
31
  *
16
- * @returns Parsed reference or null if invalid
32
+ * Parsing strategy:
33
+ * 1. Split on the FIRST `/` — that's the publisher boundary.
34
+ * 2. In the remainder, look for the FIRST `@` — that opens the
35
+ * version segment and ends at the next `/` (if any).
36
+ * 3. Anything after the version (or after the package, when there
37
+ * is no `@`) is the instance name.
38
+ *
39
+ * The previous implementation parsed the `@` first, which silently
40
+ * folded an instance segment INTO the version string when both were
41
+ * present (e.g. `pub/pkg@1.0.0/foo` → version=`1.0.0/foo`). That
42
+ * produced 404s downstream because the URL template substitution
43
+ * baked the instance into the file path. This parser distinguishes
44
+ * the two segments cleanly.
17
45
  */
18
46
  export declare function parsePackageRef(ref: string): PackageRef | null;
47
+ /**
48
+ * Render a `PackageRef` back to its canonical string form. The
49
+ * inverse of `parsePackageRef`. Useful for echoing the parsed
50
+ * shape back to the user in error messages.
51
+ */
52
+ export declare function formatPackageRef(ref: PackageRef): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanonak-protocol/cli",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,8 +24,7 @@
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "git+https://github.com/kanonak-protocol/typescript.git",
28
- "directory": "cli"
27
+ "url": "https://github.com/kanonak-protocol"
29
28
  },
30
29
  "keywords": [
31
30
  "kanonak",
@@ -35,8 +34,8 @@
35
34
  "semantic-web"
36
35
  ],
37
36
  "dependencies": {
38
- "@kanonak-protocol/sdk": "^2.0.0",
39
- "@kanonak-protocol/types": "^2.0.0",
37
+ "@kanonak-protocol/sdk": "^2.2.0",
38
+ "@kanonak-protocol/types": "^2.2.0",
40
39
  "commander": "^13.0.0",
41
40
  "js-yaml": "^4.1.1"
42
41
  },
@@ -1,14 +0,0 @@
1
- export interface LockEntry {
2
- version: string;
3
- resolved: string;
4
- integrity: string;
5
- dependencies: Record<string, string>;
6
- }
7
- export interface LockFile {
8
- version: string;
9
- lastUpdated: string;
10
- packages: Record<string, LockEntry>;
11
- }
12
- export declare function loadLockFile(): LockFile | null;
13
- export declare function saveLockFile(lock: LockFile): void;
14
- export declare function computeIntegrity(content: string): string;