@kanonak-protocol/cli 3.47.0 → 3.48.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.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `kanonak serve` — a live origin server on the SDK's routing/rendering core.
3
+ *
4
+ * Thin wrapper: an HTTP listener + optional workspace watcher. All routing and
5
+ * rendering lives in `@kanonak-protocol/sdk/server` (`loadServerModel` + `route`),
6
+ * which makes the SAME `LookRenderer` calls `kanonak publish` does — so a live
7
+ * response is byte-equivalent to the static page `publish` would write, plus the
8
+ * machine-facing endpoints publish omits (`/.well-known/kanonak.json`,
9
+ * `/index.txt`, raw `{package}/{version}.kan.yml`).
10
+ *
11
+ * - Local dev: `kanonak serve --watch` → edit a `.kan.yml`, refresh, see the
12
+ * exact page publish would emit. No publish step.
13
+ * - Production: run the same process behind a load balancer + domain + TLS and
14
+ * it IS the publisher origin, serving human- and machine-facing content from
15
+ * one source of truth (the workspace).
16
+ */
17
+ import { Command } from 'commander';
18
+ export declare function serveCommand(): Command;
package/dist/index.js CHANGED
@@ -1,63 +1,63 @@
1
1
  #!/usr/bin/env node
2
- import{Command as vi}from"commander";import{readFileSync as $i}from"fs";import{fileURLToPath as Si}from"url";import{dirname as Pi,join as _i}from"path";import{KanonakParser as Ci,PublisherIndex as Ri,CredentialStore as Ki,createAuthenticatedFetch as Di}from"@kanonak-protocol/sdk";import{readFileSync as oo,statSync as ro}from"fs";import{resolve as so,dirname as ao}from"path";import{KanonakParser as io,KanonakObjectValidator as co,ValidationSeverity as an}from"@kanonak-protocol/sdk";import{readFileSync as Jt,readdirSync as Yt}from"fs";import{join as Xt,dirname as Zt,basename as sn}from"path";import{InMemoryKanonakDocumentRepository as Qt,FileSystemKanonakDocumentRepository as eo,HttpKanonakDocumentRepository as no,getGlobalCachePath as to}from"@kanonak-protocol/sdk";import{mkdirSync as Ht,readFileSync as on,writeFileSync as rn,existsSync as Re,appendFileSync as Bt}from"fs";import{join as zt,dirname as Wt,isAbsolute as qt}from"path";import{getGlobalCachePath as Gt}from"@kanonak-protocol/sdk";var x=class{constructor(e=Gt()){this.cacheDir=e;this.isProjectLocal=!qt(e)}cacheDir;gitignoreChecked=!1;isProjectLocal;get(e,t,o){let r=this.getPath(e,t,o);return Re(r)?on(r,"utf-8"):null}put(e,t,o,r){let a=this.getPath(e,t,o);Ht(Wt(a),{recursive:!0}),rn(a,r,"utf-8"),this.isProjectLocal&&this.ensureGitignore()}has(e,t,o){return Re(this.getPath(e,t,o))}ensureGitignore(){if(this.gitignoreChecked)return;this.gitignoreChecked=!0;let e=".gitignore",t=this.cacheDir;if(Re(e)){if(on(e,"utf-8").split(`
2
+ import{Command as Si}from"commander";import{readFileSync as Pi}from"fs";import{fileURLToPath as Ci}from"url";import{dirname as _i,join as Ri}from"path";import{KanonakParser as Ii,PublisherIndex as Ki,CredentialStore as xi,createAuthenticatedFetch as Ti}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 an}from"@kanonak-protocol/sdk";import{readdirSync as Jt}from"fs";import{join as Yt,dirname as Xt,basename as rn}from"path";import{LocalFirstRepository as Hi,buildLocalFirstRepository as Zt}from"@kanonak-protocol/sdk";import{mkdirSync as Ht,readFileSync as tn,writeFileSync as on,existsSync as Re,appendFileSync as Bt}from"fs";import{join as zt,dirname as Wt,isAbsolute as qt}from"path";import{getGlobalCachePath as Gt}from"@kanonak-protocol/sdk";var T=class{constructor(e=Gt()){this.cacheDir=e;this.isProjectLocal=!qt(e)}cacheDir;gitignoreChecked=!1;isProjectLocal;get(e,t,o){let r=this.getPath(e,t,o);return Re(r)?tn(r,"utf-8"):null}put(e,t,o,r){let a=this.getPath(e,t,o);Ht(Wt(a),{recursive:!0}),on(a,r,"utf-8"),this.isProjectLocal&&this.ensureGitignore()}has(e,t,o){return Re(this.getPath(e,t,o))}ensureGitignore(){if(this.gitignoreChecked)return;this.gitignoreChecked=!0;let e=".gitignore",t=this.cacheDir;if(Re(e)){if(tn(e,"utf-8").split(`
3
3
  `).some(r=>r.trim()===t||r.trim()===t+"/"))return;Bt(e,`
4
4
  ${t}/
5
- `)}else rn(e,`${t}/
6
- `)}getPath(e,t,o){return zt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function M(n){let e=n;for(;;){let t=Zt(e);if(t===e)break;if(sn(e).includes(".")||sn(t).includes(".")){e=t;continue}break}return e}function G(n,e){for(let t of Yt(n,{withFileTypes:!0})){let o=Xt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?G(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}var Ke=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 S(n,e){let t=[];G(n,t);let o=new Qt(e);for(let i of t)try{let c=Jt(i,"utf-8"),l=e.parse(c),p=l.metadata.namespace_;if(p){let u=`${p.publisher}/${p.package_}@${p.version}`;await o.saveDocumentAsync(l,u)}}catch{}let r=new eo(to(),!0,e),a=new x,s=new no({getFromCache:(i,c,l)=>a.get(i,c,l),onFetch:(i,c,l,p)=>a.put(i,c,l,p)});return new Ke(o,r,s)}async function cn(n){let e=so(n),t=ro(e),o=t.isDirectory()?M(e):M(ao(e)),r=new io,a=new co(r),s=await S(o,r),i=[];if(t.isDirectory()?G(e,i):i.push(e),i.length===0){console.log("No .kan.yml files found.");return}let c=0,l=0;for(let p of i){let u=oo(p,"utf-8"),m=r.parseWithErrors(u);if(m.errors&&m.errors.length>0){console.log(`
5
+ `)}else on(e,`${t}/
6
+ `)}getPath(e,t,o){return zt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function V(n){let e=n;for(;;){let t=Xt(e);if(t===e)break;if(rn(e).includes(".")||rn(t).includes(".")){e=t;continue}break}return e}function ee(n,e){for(let t of Jt(n,{withFileTypes:!0})){let o=Yt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?ee(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}async function S(n,e){let t=new T;return Zt(n,e,{httpCache:{getFromCache:(o,r,a)=>t.get(o,r,a),onFetch:(o,r,a,s)=>t.put(o,r,a,s)}})}async function sn(n){let e=no(n),t=eo(e),o=t.isDirectory()?V(e):V(to(e)),r=new oo,a=new ro(r),s=await S(o,r),i=[];if(t.isDirectory()?ee(e,i):i.push(e),i.length===0){console.log("No .kan.yml files found.");return}let c=0,l=0;for(let p of i){let u=Qt(p,"utf-8"),m=r.parseWithErrors(u);if(m.errors&&m.errors.length>0){console.log(`
7
7
  ${p}:`);for(let g of m.errors)console.log(` ERROR (parse): ${g.message} [line ${g.line}:${g.column}]`),c++;continue}let h=m.document;if(!h){console.log(`
8
8
  ${p}:`),console.log(" ERROR: Failed to parse document"),c++;continue}let k=await a.validateAsync(h,s),d=k.errors.filter(g=>g.severity===an.Error),f=k.warnings.filter(g=>g.severity===an.Warning);if(d.length>0||f.length>0){let g=h.metadata.namespace_,y=g?`${g.publisher}/${g.package_}@${g.version}`:p;console.log(`
9
9
  ${y}:`);for(let b of d)console.log(` ERROR: ${b.message}`),b.suggestion&&console.log(` -> ${b.suggestion}`);for(let b of f)console.log(` WARN: ${b.message}`)}c+=d.length,l+=f.length}console.log(`
10
- ${i.length} file(s) validated. ${c} error(s), ${l} warning(s).`),c>0&&process.exit(1)}import{KanonakParser as lo,PublisherIndex as uo,CredentialStore as po,createAuthenticatedFetch as mo}from"@kanonak-protocol/sdk";import{loadLockFile as fo,saveLockFile as go,computeIntegrity as ho}from"@kanonak-protocol/sdk";function E(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,i=o.indexOf("@");if(i!==-1){r=o.substring(0,i);let c=o.substring(i+1),l=c.indexOf("/");l===-1?a=c||null:(a=c.substring(0,l)||null,s=c.substring(l+1)||null)}else{let c=o.indexOf("/");c===-1?r=o:(r=o.substring(0,c),s=o.substring(c+1)||null)}return!r||s&&s.includes("/")||a&&a.includes("@")?null:{publisher:t,packageName:r,version:a,instanceName:s}}async function ln(n){let e=new x,t=new lo,o=new po,r=mo(o),a=new uo({fetchFn:r}),s=fo()??{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[k,d]of Object.entries(s.packages)){let f=k.indexOf("/"),g=k.substring(0,f),y=k.substring(f+1),b=e.get(g,y,d.version);if(b)console.log(` ${k}@${d.version} (cached)`);else{let w=d.resolved,v=await r(w,g);if(!v.ok)throw new Error(`Failed to fetch ${w} (${v.status} ${v.statusText})`);b=await v.text(),e.put(g,y,d.version,b),console.log(` ${k}@${d.version}`)}}console.log(`
11
- Installed ${Object.keys(s.packages).length} package(s) from lock file.`);return}let i=E(n);i||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:c,packageName:l,version:p,instanceName:u}=i;u&&(console.error(`\`kanonak install\` works on whole packages \u2014 got an instance suffix "/${u}".`),console.error(`Try: kanonak install ${c}/${l}${p?"@"+p:""}`),console.error("(Use `kanonak <capability> add` if you want to install one named instance.)"),process.exit(1));let m=p??await a.getHighestVersion(c,l);m||(console.error(`Could not resolve version for "${c}/${l}".`),console.error("Check the spelling, or run a search to see what the publisher offers."),process.exit(1)),console.log(`Installing ${c}/${l}@${m}...`);let h=new Set;await un(c,l,m,e,t,a,r,h,s),go(s),console.log(`
12
- Installed ${h.size} package(s).`)}async function un(n,e,t,o,r,a,s,i,c){let l=`${n}/${e}@${t}`;if(i.has(l))return;i.add(l);let p=`${n}/${e}`,u=o.get(n,e,t),m;if(u)console.log(` ${l} (cached)`),m=await a.getPackageUrl(n,e,t);else{m=await a.getPackageUrl(n,e,t);let d=await s(m,n);if(!d.ok)throw new Error(`Failed to fetch ${m} (${d.status} ${d.statusText})`);u=await d.text(),o.put(n,e,t,u),console.log(` ${l}`)}let h={},k=r.parse(u);if(k.metadata.imports)for(let[d,f]of Object.entries(k.metadata.imports))for(let g of f){let y=await a.resolveVersion(d,g);y?(h[`${d}/${g.packageName}`]=y,await un(d,g.packageName,y,o,r,a,s,i,c)):console.error(` WARNING: Could not resolve ${d}/${g.packageName} ${g.package_}`)}c.packages[p]={version:t,resolved:m,integrity:ho(u),dependencies:h}}import{readFileSync as ko}from"fs";import{resolve as yo,dirname as bo}from"path";import{KanonakParser as wo}from"@kanonak-protocol/sdk";async function pn(n){let e=yo(n),t=ko(e,"utf-8"),o=new wo,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 i=M(bo(e)),c=await S(i,o),l=new Set;for(let[p,u]of Object.entries(r.metadata.imports))for(let m of u)await mn(p,m,c,l," ")}async function mn(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 i=s.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${i}`),s.metadata.imports)for(let[c,l]of Object.entries(s.metadata.imports))for(let p of l)await mn(c,p,t,o,r+" ")}import{createHash as $o,randomBytes as gn}from"crypto";import{createServer as So}from"http";import{execFile as De}from"child_process";import{CredentialStore as Po,generateDPoPKeyPair as _o,createDPoPProof as dn,serverSupportsDPoP as Co}from"@kanonak-protocol/sdk";import{normalizeHost as vo}from"@kanonak-protocol/sdk";var F=class{cache=new Map;async discover(e){let t=vo(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:ne(o.issuer),authorizationEndpoint:ne(o.authorization_endpoint),tokenEndpoint:ne(o.token_endpoint),registrationEndpoint:ne(o.registration_endpoint),revocationEndpoint:ne(o.revocation_endpoint),scopesSupported:J(o.scopes_supported),responseTypesSupported:J(o.response_types_supported),grantTypesSupported:J(o.grant_types_supported),codeChallengeMethodsSupported:J(o.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:J(o.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:J(o.dpop_signing_alg_values_supported)}}};function ne(n){return typeof n=="string"?n:null}function J(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):null}var X=class{discovery;credentialStore;constructor(e,t){this.discovery=e??new F,this.credentialStore=t??new Po}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}'.
10
+ ${i.length} file(s) validated. ${c} error(s), ${l} warning(s).`),c>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 po}from"@kanonak-protocol/sdk";function A(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,i=o.indexOf("@");if(i!==-1){r=o.substring(0,i);let c=o.substring(i+1),l=c.indexOf("/");l===-1?a=c||null:(a=c.substring(0,l)||null,s=c.substring(l+1)||null)}else{let c=o.indexOf("/");c===-1?r=o:(r=o.substring(0,c),s=o.substring(c+1)||null)}return!r||s&&s.includes("/")||a&&a.includes("@")?null:{publisher:t,packageName:r,version:a,instanceName:s}}async function cn(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[k,d]of Object.entries(s.packages)){let f=k.indexOf("/"),g=k.substring(0,f),y=k.substring(f+1),b=e.get(g,y,d.version);if(b)console.log(` ${k}@${d.version} (cached)`);else{let w=d.resolved,$=await r(w,g);if(!$.ok)throw new Error(`Failed to fetch ${w} (${$.status} ${$.statusText})`);b=await $.text(),e.put(g,y,d.version,b),console.log(` ${k}@${d.version}`)}}console.log(`
11
+ Installed ${Object.keys(s.packages).length} package(s) from lock file.`);return}let i=A(n);i||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:c,packageName:l,version:p,instanceName:u}=i;u&&(console.error(`\`kanonak install\` works on whole packages \u2014 got an instance suffix "/${u}".`),console.error(`Try: kanonak install ${c}/${l}${p?"@"+p:""}`),console.error("(Use `kanonak <capability> add` if you want to install one named instance.)"),process.exit(1));let m=p??await a.getHighestVersion(c,l);m||(console.error(`Could not resolve version for "${c}/${l}".`),console.error("Check the spelling, or run a search to see what the publisher offers."),process.exit(1)),console.log(`Installing ${c}/${l}@${m}...`);let h=new Set;await ln(c,l,m,e,t,a,r,h,s),uo(s),console.log(`
12
+ Installed ${h.size} package(s).`)}async function ln(n,e,t,o,r,a,s,i,c){let l=`${n}/${e}@${t}`;if(i.has(l))return;i.add(l);let p=`${n}/${e}`,u=o.get(n,e,t),m;if(u)console.log(` ${l} (cached)`),m=await a.getPackageUrl(n,e,t);else{m=await a.getPackageUrl(n,e,t);let d=await s(m,n);if(!d.ok)throw new Error(`Failed to fetch ${m} (${d.status} ${d.statusText})`);u=await d.text(),o.put(n,e,t,u),console.log(` ${l}`)}let h={},k=r.parse(u);if(k.metadata.imports)for(let[d,f]of Object.entries(k.metadata.imports))for(let g of f){let y=await a.resolveVersion(d,g);y?(h[`${d}/${g.packageName}`]=y,await ln(d,g.packageName,y,o,r,a,s,i,c)):console.error(` WARNING: Could not resolve ${d}/${g.packageName} ${g.package_}`)}c.packages[p]={version:t,resolved:m,integrity:po(u),dependencies:h}}import{readFileSync as mo}from"fs";import{resolve as fo,dirname as go}from"path";import{KanonakParser as ho}from"@kanonak-protocol/sdk";async function un(n){let e=fo(n),t=mo(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 i=V(go(e)),c=await S(i,o),l=new Set;for(let[p,u]of Object.entries(r.metadata.imports))for(let m of u)await pn(p,m,c,l," ")}async function pn(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 i=s.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${i}`),s.metadata.imports)for(let[c,l]of Object.entries(s.metadata.imports))for(let p of l)await pn(c,p,t,o,r+" ")}import{createHash as yo,randomBytes as fn}from"crypto";import{createServer as bo}from"http";import{execFile as Ie}from"child_process";import{CredentialStore as wo,generateDPoPKeyPair as $o,createDPoPProof as mn,serverSupportsDPoP as vo}from"@kanonak-protocol/sdk";import{normalizeHost as ko}from"@kanonak-protocol/sdk";var F=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:ne(o.issuer),authorizationEndpoint:ne(o.authorization_endpoint),tokenEndpoint:ne(o.token_endpoint),registrationEndpoint:ne(o.registration_endpoint),revocationEndpoint:ne(o.revocation_endpoint),scopesSupported:G(o.scopes_supported),responseTypesSupported:G(o.response_types_supported),grantTypesSupported:G(o.grant_types_supported),codeChallengeMethodsSupported:G(o.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:G(o.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:G(o.dpop_signing_alg_values_supported)}}};function ne(n){return typeof n=="string"?n:null}function G(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 wo}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let o=await this.discovery.discover(e);if(!o)return I(`No OAuth discovery endpoint found for '${e}'.
13
13
  The server must expose one of:
14
14
  - https://${e}/.well-known/oauth-authorization-server (RFC 8414)
15
15
  - https://${e}/.well-known/openid-configuration (OpenID Connect)
16
16
  Verify the hostname is correct and HTTPS is configured.
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=Co(o.dpopSigningAlgValuesSupported),s=null;if(a){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{s=_o()}catch(v){return R(`Failed to generate DPoP key pair: ${Y(v)}
19
- Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:i,port:c,waitForCallback:l,close:p}=await Ao(),u=await this.credentialStore.getCredential(e),m=u?.clientId??null,h=u?.clientSecret??null;if(!m&&o.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let v=await this.registerClient(o.registrationEndpoint,i);if(!v.success)return p(),R(v.error);m=v.clientId,h=v.clientSecret??null}if(!m)return p(),R(`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 I(`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=vo(o.dpopSigningAlgValuesSupported),s=null;if(a){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{s=$o()}catch($){return I(`Failed to generate DPoP key pair: ${J($)}
19
+ Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:i,port:c,waitForCallback:l,close:p}=await Ko(),u=await this.credentialStore.getCredential(e),m=u?.clientId??null,h=u?.clientSecret??null;if(!m&&o.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let $=await this.registerClient(o.registrationEndpoint,i);if(!$.success)return p(),I($.error);m=$.clientId,h=$.clientSecret??null}if(!m)return p(),I(`No OAuth client credentials for '${e}' and the server does not support dynamic client registration (no registration_endpoint in metadata).
20
20
  You must pre-register a client with your IDP and configure the client_id.
21
21
  Ask your IDP administrator to enable dynamic client registration (RFC 7591),
22
- or add a registration_endpoint to the OAuth metadata.`);let k=Ko(),d=Do(k),f=Io(),g=xo(o.authorizationEndpoint,m,i,t,f,d);console.log(` Opening browser for authorization on port ${c}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${g}`),jo(g);let y=await l();if(p(),!y)return R(`Authorization timed out after 5 minutes.
22
+ or add a registration_endpoint to the OAuth metadata.`);let k=Po(),d=Co(k),f=_o(),g=Ro(o.authorizationEndpoint,m,i,t,f,d);console.log(` Opening browser for authorization on port ${c}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${g}`),To(g);let y=await l();if(p(),!y)return I(`Authorization timed out after 5 minutes.
23
23
  The browser authorization was not completed in time.
24
- Re-run 'kanonak login ${e}' and complete the browser authorization promptly.`);if(!y.code){let v=y.error?`: ${y.error}`:"";return R(`No authorization code received${v}.
24
+ Re-run 'kanonak login ${e}' and complete the browser authorization promptly.`);if(!y.code){let $=y.error?`: ${y.error}`:"";return I(`No authorization code received${$}.
25
25
  The IDP may have rejected the authorization request.
26
- Check the IDP admin console for error details.`)}if(y.state!==f)return R(`Authorization state mismatch \u2014 possible CSRF attack.
26
+ Check the IDP admin console for error details.`)}if(y.state!==f)return I(`Authorization state mismatch \u2014 possible CSRF attack.
27
27
  The response did not match the expected session.
28
- Re-run 'kanonak login ${e}' to start a fresh authorization flow.`);console.log(" Exchanging authorization code for tokens...");let b=await this.exchangeCode(o.tokenEndpoint,m,h,y.code,i,k,s);if(!b.success)return R(b.error);let w={clientId:m,clientSecret:h,accessToken:b.tokens.accessToken,refreshToken:b.tokens.refreshToken,expiresAt:b.tokens.expiresIn?new Date(Date.now()+b.tokens.expiresIn*1e3).toISOString():null,tokenEndpoint:o.tokenEndpoint,dpopKeyPair:s};return await this.credentialStore.store(e,w),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}'.
28
+ Re-run 'kanonak login ${e}' to start a fresh authorization flow.`);console.log(" Exchanging authorization code for tokens...");let b=await this.exchangeCode(o.tokenEndpoint,m,h,y.code,i,k,s);if(!b.success)return I(b.error);let w={clientId:m,clientSecret:h,accessToken:b.tokens.accessToken,refreshToken:b.tokens.refreshToken,expiresAt:b.tokens.expiresIn?new Date(Date.now()+b.tokens.expiresIn*1e3).toISOString():null,tokenEndpoint:o.tokenEndpoint,dpopKeyPair:s};return await this.credentialStore.store(e,w),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}'.
29
29
  The authorization server may not issue refresh tokens for this client.
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}'.
30
+ Run 'kanonak login ${e}' to re-authenticate.`);if(!t.clientId)return I(`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 I(`Cannot find token endpoint for '${e}'.
32
32
  The OAuth discovery endpoint may be unreachable.
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: ${Y(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}):I(`${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 I(`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: ${J(s)}
36
36
  Ensure the IDP is reachable and HTTPS is properly configured.
37
- If using a corporate proxy or custom CA, set NODE_EXTRA_CA_CERTS.`}}if(!o.ok){let s=await Ie(o);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 Ke(o);return{success:!1,error:`Dynamic client registration (RFC 7591) failed.
38
38
  Endpoint: ${e}
39
39
  HTTP ${o.status}: ${s}
40
40
  The IDP may not support dynamic registration for public clients.
41
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,i){let c=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:a,code_verifier:s});o&&c.set("client_secret",o);let l={"Content-Type":"application/x-www-form-urlencoded"};if(i)try{l.DPoP=dn(i.privateKey,i.publicKey,"POST",e)}catch(u){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${Y(u)}
43
- The stored key pair may be corrupted. Run 'kanonak login' to re-authenticate.`}}let p;try{p=await fetch(e,{method:"POST",headers:l,body:c.toString()})}catch(u){return{success:!1,error:`Token exchange request to ${e} failed: ${Y(u)}
44
- Ensure the token endpoint is reachable.`}}if(!p.ok){let u=await Ie(p),m=Ro(u);return{success:!1,error:`Token exchange failed.
42
+ The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,o,r,a,s,i){let c=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:a,code_verifier:s});o&&c.set("client_secret",o);let l={"Content-Type":"application/x-www-form-urlencoded"};if(i)try{l.DPoP=mn(i.privateKey,i.publicKey,"POST",e)}catch(u){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${J(u)}
43
+ The stored key pair may be corrupted. Run 'kanonak login' to re-authenticate.`}}let p;try{p=await fetch(e,{method:"POST",headers:l,body:c.toString()})}catch(u){return{success:!1,error:`Token exchange request to ${e} failed: ${J(u)}
44
+ Ensure the token endpoint is reachable.`}}if(!p.ok){let u=await Ke(p),m=So(u);return{success:!1,error:`Token exchange failed.
45
45
  Endpoint: ${e}
46
46
  HTTP ${p.status}: ${u}`+(m?`
47
- ${m}`:"")}}return{success:!0,tokens:fn(await p.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 i={"Content-Type":"application/x-www-form-urlencoded"};if(a)try{i.DPoP=dn(a.privateKey,a.publicKey,"POST",e)}catch(l){return{success:!1,error:`Failed to create DPoP proof for token refresh: ${Y(l)}`}}let c;try{c=await fetch(e,{method:"POST",headers:i,body:s.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${Y(l)}`}}if(!c.ok){let l=await Ie(c);return{success:!1,error:`Token refresh failed \u2014 HTTP ${c.status}: ${l}`}}return{success:!0,tokens:fn(await c.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 fn(n){return{accessToken:n.access_token,refreshToken:n.refresh_token,expiresIn:typeof n.expires_in=="number"?n.expires_in:void 0}}function Y(n){return n instanceof Error?n.message:String(n)}async function Ie(n){try{return await n.text()}catch{return"(could not read response body)"}}function Ro(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 Ko(){return gn(32).toString("base64url")}function Do(n){return $o("sha256").update(n).digest("base64url")}function Io(){return gn(16).toString("base64url")}function xo(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 To=300*1e3;async function Ao(){return new Promise(n=>{let e=So((r,a)=>{let s=new URL(r.url,"http://localhost"),i=s.searchParams.get("code")??void 0,c=s.searchParams.get("state")??void 0,l=s.searchParams.get("error")??s.searchParams.get("error_description")??void 0,p=l?Eo(l):null,u=p?`<html><body><h1>Authorization failed</h1><p>${p}</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(u),t({code:i,state:c,error:l})}),t,o=new Promise(r=>{t=r,setTimeout(()=>{r(null),e.close()},To)});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 Eo(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function jo(n){try{process.platform==="win32"?De("cmd",["/c","start","",n]):process.platform==="darwin"?De("open",[n]):De("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as No}from"@kanonak-protocol/sdk";async function hn(n){try{let e=new F,t=new No,r=await new X(e,t).authorize(n);r.success?console.log(`
47
+ ${m}`:"")}}return{success:!0,tokens:dn(await p.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 i={"Content-Type":"application/x-www-form-urlencoded"};if(a)try{i.DPoP=mn(a.privateKey,a.publicKey,"POST",e)}catch(l){return{success:!1,error:`Failed to create DPoP proof for token refresh: ${J(l)}`}}let c;try{c=await fetch(e,{method:"POST",headers:i,body:s.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${J(l)}`}}if(!c.ok){let l=await Ke(c);return{success:!1,error:`Token refresh failed \u2014 HTTP ${c.status}: ${l}`}}return{success:!0,tokens:dn(await c.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 I(n){return{success:!1,error:n}}function dn(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 Ke(n){try{return await n.text()}catch{return"(could not read response body)"}}function So(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 Po(){return fn(32).toString("base64url")}function Co(n){return yo("sha256").update(n).digest("base64url")}function _o(){return fn(16).toString("base64url")}function Ro(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 Io=300*1e3;async function Ko(){return new Promise(n=>{let e=bo((r,a)=>{let s=new URL(r.url,"http://localhost"),i=s.searchParams.get("code")??void 0,c=s.searchParams.get("state")??void 0,l=s.searchParams.get("error")??s.searchParams.get("error_description")??void 0,p=l?xo(l):null,u=p?`<html><body><h1>Authorization failed</h1><p>${p}</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(u),t({code:i,state:c,error:l})}),t,o=new Promise(r=>{t=r,setTimeout(()=>{r(null),e.close()},Io)});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 xo(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function To(n){try{process.platform==="win32"?Ie("cmd",["/c","start","",n]):process.platform==="darwin"?Ie("open",[n]):Ie("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as Do}from"@kanonak-protocol/sdk";async function gn(n){try{let e=new F,t=new Do,r=await new Y(e,t).authorize(n);r.success?console.log(`
48
48
  Authenticated with ${n}.`):(console.error(`
49
49
  Authentication failed:
50
50
  ${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
51
51
  Authentication failed unexpectedly:
52
52
  ${t}`),console.error(`
53
- If this persists, see https://github.com/kanonak-protocol for support channels.`),process.exit(1)}}import{CredentialStore as Oo}from"@kanonak-protocol/sdk";async function kn(n){try{let e=new F,t=new Oo,r=await new X(e,t).logout(n);r.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 Eo}from"@kanonak-protocol/sdk";async function hn(n){try{let e=new F,t=new Eo,r=await new Y(e,t).logout(n);r.success?console.log(`Logged out from ${n}.`):(console.error(`
54
54
  Logout failed:
55
55
  ${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
56
56
  Logout failed unexpectedly:
57
- ${t}`),process.exit(1)}}import{Command as cr}from"commander";import{KanonakParser as lr,KanonakObjectParser as ur,PublisherIndex as pr,CredentialStore as mr,createAuthenticatedFetch as dr,computeIntegrity as fr}from"@kanonak-protocol/sdk";import{readFileSync as Lo,writeFileSync as Uo,existsSync as Fo}from"fs";import{join as Vo}from"path";import yn from"js-yaml";import{getGlobalCachePath as Mo}from"@kanonak-protocol/sdk";var Ho=`# This file is generated by Kanonak CLI. Do not edit manually.
58
- `;function bn(){let n=Mo();return Vo(n,"..","capabilities.lock")}function Z(){let n=bn();if(!Fo(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=Lo(n,"utf-8"),t=yn.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 te(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=yn.dump(n,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Uo(bn(),Ho+t,"utf-8")}import{SingleDocumentRepository as gr}from"@kanonak-protocol/sdk/uri-helpers";import{existsSync as Bo,readdirSync as zo,readFileSync as Wo}from"fs";import{join as wn}from"path";import{KanonakObjectParser as qo,EmbeddedKanonak as Pn,ReferenceKanonak as _n,getGlobalCachePath as Go}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Cn}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as xe,findSubjectsByType as Jo,getStringValue as V,getReferenceUri as Te,getListValues as Rn}from"@kanonak-protocol/sdk/uri-helpers";var _="kanonak.org",C="capabilities",Ae={publisher:_,package_:C,name:"Capability"},Yo={publisher:_,package_:C,name:"commandName"},Kn={publisher:_,package_:C,name:"description"},Xo={publisher:_,package_:C,name:"managesType"},Zo={publisher:_,package_:C,name:"deploymentTarget"},Qo={publisher:_,package_:C,name:"hasCommand"},er={publisher:_,package_:C,name:"subcommandName"},nr={publisher:_,package_:C,name:"performs"},tr={publisher:_,package_:C,name:"hasArgument"},or={publisher:_,package_:C,name:"argumentName"},vn={publisher:_,package_:C,name:"isRequired"},$n={publisher:_,package_:C,name:"isOption"},rr={publisher:_,package_:C,name:"defaultValue"};async function Dn(n,e,t){let o=Z(),r=new qo,a=[],s=!1;for(let[i,c]of Object.entries(o.capabilities)){let l=c,p=n.get(l.publisher,l.package_,l.version);if(!p){let u=await sr(i,l,e,r,t);if(u)console.error(` Healed capability "${i}": ${l.publisher}/${l.package_}@${l.version} \u2192 ${u.entry.publisher}/${u.entry.package_}@${u.entry.version} (package was renamed)`),o.capabilities[i]=u.entry,l=u.entry,p=u.content,s=!0;else{console.error(` WARNING: Cached content missing for capability "${i}" (${l.publisher}/${l.package_}@${l.version}). Reinstall it with: kanonak capability remove ${i} && kanonak capability add ${l.publisher}/${l.package_}`);continue}}try{let u=e.parse(p),m=new Cn(u,t),h=await r.parseKanonaks(m),k=In(h,l.publisher,l.package_,l.version);k?a.push(k):console.error(` WARNING: No Capability instance found in "${i}" (${l.publisher}/${l.package_}@${l.version})`)}catch(u){console.error(` WARNING: Failed to parse capability "${i}": ${u}`)}}return s&&te(o),a}async function sr(n,e,t,o,r){let a=wn(Go(),e.publisher);if(!Bo(a))return;let s=[];for(let i of zo(a)){if(!i.endsWith(".kan.yml"))continue;let c=i.slice(0,-8),l=c.lastIndexOf("@");if(l===-1)continue;let p=c.substring(0,l),u=c.substring(l+1);if(p===e.package_&&u===e.version)continue;let m;try{m=Wo(wn(a,i),"utf-8")}catch{continue}let h;try{let k=t.parse(m),d=new Cn(k,r),f=await o.parseKanonaks(d);h=In(f,e.publisher,p,u)?.commandName}catch{continue}h===n&&s.push({entry:{publisher:e.publisher,package_:p,version:u,resolved:`kanonak://${e.publisher}/${p}@${u}`,integrity:""},content:m})}if(s.length===1)return s[0]}function In(n,e,t,o){let r=Jo(n,Ae);if(r.length===0)return;let a=r[0],s=V(a,Yo)??"",i=V(a,Kn)??"",c=Te(a,Xo),l=Te(a,Zo),p=[];for(let u of Rn(a,Qo)){let m=ar(u,n);m&&p.push(m)}return{commandName:s,description:i,managesTypeKey:c?xe(c):"",deploymentTargetKey:l?xe(l):"",commands:p,publisher:e,package_:t,version:o}}function ar(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof _n){let c=xn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=V(t,er)??"",r=V(t,Kn)??"",a=Te(t,nr),s=Rn(t,tr),i=[];for(let c of s){let l=ir(c,e);l&&i.push(l)}return{subcommandName:o,description:r,arguments:i,actionKey:a?xe(a):""}}function ir(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof _n){let c=xn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=V(t,or)??"",r=V(t,vn)==="true"||Sn(t,vn)===!0,a=V(t,$n)==="true"||Sn(t,$n)===!0,s=V(t,rr),i={argumentName:o,required:r,isOption:a};return s!==void 0&&(i.defaultValue=s),i}function Sn(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 xn(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}}import{findSubjectsByType as hr,getStringValue as kr}from"@kanonak-protocol/sdk/uri-helpers";var yr={publisher:_,package_:C,name:"commandName"};function Tn(){let n=new cr("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 br(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await wr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await vr()}),n}async function br(n){let e=E(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 x,i=new lr,c=new ur,l=new mr,p=dr(l),u=new pr({fetchFn:p}),m=r??await u.getHighestVersion(t,o);m||(console.error(`Could not resolve version for "${t}/${o}".`),process.exit(1)),console.log(`Installing capability ${t}/${o}@${m}...`);let h=s.get(t,o,m);if(!h){let $=await u.getPackageUrl(t,o,m),I=await p($,t);if(!I.ok)throw new Error(`Failed to fetch ${$} (${I.status} ${I.statusText})`);h=await I.text(),s.put(t,o,m,h)}let k=i.parse(h),d=await S(process.cwd(),i),f=new gr(k,d),g=await c.parseKanonaks(f),y=hr(g,Ae);y.length===0&&(console.error(`Package ${t}/${o}@${m} does not contain a ${_}/${C}/Capability instance.`),process.exit(1));let b=y[0],w=kr(b,yr);w||(console.error(`Capability instance in ${t}/${o}@${m} has no commandName property.`),process.exit(1));let v=Z();v.capabilities[w]={publisher:t,package_:o,version:m,resolved:await u.getPackageUrl(t,o,m),integrity:fr(h)},te(v),console.log(`
59
- Installed capability "${w}".`),console.log(`Run "kanonak ${w} --help" to get started.`)}async function wr(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],te(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function vr(){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:
60
- `);for(let[t,o]of e)console.log(` ${t} ${o.publisher}/${o.package_}@${o.version}`)}import{Command as re}from"commander";import{readFileSync as $r,writeFileSync as Sr,mkdirSync as Pr,existsSync as An,statSync as _r}from"fs";import{join as Cr,resolve as Rr}from"path";import{KanonakParser as Ne,KanonakObjectParser as Oe,SubjectKanonak as Kr,Reasoner as Dr,KanonakVocabulary as Ir,makeUriKey as Nn,pickHighestDocument as Le,formatVersion as On}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as oe}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Ee,findSubjectByUri as xr}from"@kanonak-protocol/sdk/uri-helpers";import{TX_V3 as En}from"@kanonak-protocol/sdk/transformations";import{TransformationRunnerV3 as Tr,SUPPORTED_FORMATS_V3 as Ln}from"@kanonak-protocol/sdk/transformations";import{compileTransformationV3 as Ue}from"@kanonak-protocol/sdk/transformations";function je(n){return[...Ee(n,En.InstanceTransformation),...Ee(n,En.SetTransformation)]}function Un(){let n=new re("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",`
57
+ ${t}`),process.exit(1)}}import{Command as rr}from"commander";import{KanonakParser as ar,KanonakObjectParser as sr,PublisherIndex as ir,CredentialStore as cr,createAuthenticatedFetch as lr,computeIntegrity as ur}from"@kanonak-protocol/sdk";import{readFileSync as Ao,writeFileSync as jo,existsSync as No}from"fs";import{join as Oo}from"path";import kn from"js-yaml";import{getGlobalCachePath as Lo}from"@kanonak-protocol/sdk";var Uo=`# This file is generated by Kanonak CLI. Do not edit manually.
58
+ `;function yn(){let n=Lo();return Oo(n,"..","capabilities.lock")}function X(){let n=yn();if(!No(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=Ao(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 te(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(yn(),Uo+t,"utf-8")}import{SingleDocumentRepository as pr}from"@kanonak-protocol/sdk/uri-helpers";import{existsSync as Fo,readdirSync as Mo,readFileSync as Vo}from"fs";import{join as bn}from"path";import{KanonakObjectParser as Ho,EmbeddedKanonak as Sn,ReferenceKanonak as Pn,getGlobalCachePath as Bo}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Cn}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as xe,findSubjectsByType as zo,getStringValue as M,getReferenceUri as Te,getListValues as _n}from"@kanonak-protocol/sdk/uri-helpers";var C="kanonak.org",_="capabilities",De={publisher:C,package_:_,name:"Capability"},Wo={publisher:C,package_:_,name:"commandName"},Rn={publisher:C,package_:_,name:"description"},qo={publisher:C,package_:_,name:"managesType"},Go={publisher:C,package_:_,name:"deploymentTarget"},Jo={publisher:C,package_:_,name:"hasCommand"},Yo={publisher:C,package_:_,name:"subcommandName"},Xo={publisher:C,package_:_,name:"performs"},Zo={publisher:C,package_:_,name:"hasArgument"},Qo={publisher:C,package_:_,name:"argumentName"},wn={publisher:C,package_:_,name:"isRequired"},$n={publisher:C,package_:_,name:"isOption"},er={publisher:C,package_:_,name:"defaultValue"};async function In(n,e,t){let o=X(),r=new Ho,a=[],s=!1;for(let[i,c]of Object.entries(o.capabilities)){let l=c,p=n.get(l.publisher,l.package_,l.version);if(!p){let u=await nr(i,l,e,r,t);if(u)console.error(` Healed capability "${i}": ${l.publisher}/${l.package_}@${l.version} \u2192 ${u.entry.publisher}/${u.entry.package_}@${u.entry.version} (package was renamed)`),o.capabilities[i]=u.entry,l=u.entry,p=u.content,s=!0;else{console.error(` WARNING: Cached content missing for capability "${i}" (${l.publisher}/${l.package_}@${l.version}). Reinstall it with: kanonak capability remove ${i} && kanonak capability add ${l.publisher}/${l.package_}`);continue}}try{let u=e.parse(p),m=new Cn(u,t),h=await r.parseKanonaks(m),k=Kn(h,l.publisher,l.package_,l.version);k?a.push(k):console.error(` WARNING: No Capability instance found in "${i}" (${l.publisher}/${l.package_}@${l.version})`)}catch(u){console.error(` WARNING: Failed to parse capability "${i}": ${u}`)}}return s&&te(o),a}async function nr(n,e,t,o,r){let a=bn(Bo(),e.publisher);if(!Fo(a))return;let s=[];for(let i of Mo(a)){if(!i.endsWith(".kan.yml"))continue;let c=i.slice(0,-8),l=c.lastIndexOf("@");if(l===-1)continue;let p=c.substring(0,l),u=c.substring(l+1);if(p===e.package_&&u===e.version)continue;let m;try{m=Vo(bn(a,i),"utf-8")}catch{continue}let h;try{let k=t.parse(m),d=new Cn(k,r),f=await o.parseKanonaks(d);h=Kn(f,e.publisher,p,u)?.commandName}catch{continue}h===n&&s.push({entry:{publisher:e.publisher,package_:p,version:u,resolved:`kanonak://${e.publisher}/${p}@${u}`,integrity:""},content:m})}if(s.length===1)return s[0]}function Kn(n,e,t,o){let r=zo(n,De);if(r.length===0)return;let a=r[0],s=M(a,Wo)??"",i=M(a,Rn)??"",c=Te(a,qo),l=Te(a,Go),p=[];for(let u of _n(a,Jo)){let m=tr(u,n);m&&p.push(m)}return{commandName:s,description:i,managesTypeKey:c?xe(c):"",deploymentTargetKey:l?xe(l):"",commands:p,publisher:e,package_:t,version:o}}function tr(n,e){let t;if(n instanceof Sn)t=n;else if(n instanceof Pn){let c=xn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,Yo)??"",r=M(t,Rn)??"",a=Te(t,Xo),s=_n(t,Zo),i=[];for(let c of s){let l=or(c,e);l&&i.push(l)}return{subcommandName:o,description:r,arguments:i,actionKey:a?xe(a):""}}function or(n,e){let t;if(n instanceof Sn)t=n;else if(n instanceof Pn){let c=xn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,Qo)??"",r=M(t,wn)==="true"||vn(t,wn)===!0,a=M(t,$n)==="true"||vn(t,$n)===!0,s=M(t,er),i={argumentName:o,required:r,isOption:a};return s!==void 0&&(i.defaultValue=s),i}function vn(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 xn(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}}import{findSubjectsByType as mr,getStringValue as dr}from"@kanonak-protocol/sdk/uri-helpers";var fr={publisher:C,package_:_,name:"commandName"};function Tn(){let n=new rr("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 gr(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await hr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await kr()}),n}async function gr(n){let e=A(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,i=new ar,c=new sr,l=new cr,p=lr(l),u=new ir({fetchFn:p}),m=r??await u.getHighestVersion(t,o);m||(console.error(`Could not resolve version for "${t}/${o}".`),process.exit(1)),console.log(`Installing capability ${t}/${o}@${m}...`);let h=s.get(t,o,m);if(!h){let v=await u.getPackageUrl(t,o,m),x=await p(v,t);if(!x.ok)throw new Error(`Failed to fetch ${v} (${x.status} ${x.statusText})`);h=await x.text(),s.put(t,o,m,h)}let k=i.parse(h),d=await S(process.cwd(),i),f=new pr(k,d),g=await c.parseKanonaks(f),y=mr(g,De);y.length===0&&(console.error(`Package ${t}/${o}@${m} does not contain a ${C}/${_}/Capability instance.`),process.exit(1));let b=y[0],w=dr(b,fr);w||(console.error(`Capability instance in ${t}/${o}@${m} has no commandName property.`),process.exit(1));let $=X();$.capabilities[w]={publisher:t,package_:o,version:m,resolved:await u.getPackageUrl(t,o,m),integrity:ur(h)},te($),console.log(`
59
+ Installed capability "${w}".`),console.log(`Run "kanonak ${w} --help" to get started.`)}async function hr(n){let e=X();e.capabilities[n]||(console.error(`Capability "${n}" is not installed.`),process.exit(1));let t=e.capabilities[n];delete e.capabilities[n],te(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function kr(){let n=X(),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 re}from"commander";import{readFileSync as yr,writeFileSync as br,mkdirSync as wr,existsSync as Dn,statSync as $r}from"fs";import{join as vr,resolve as Sr}from"path";import{KanonakParser as je,KanonakObjectParser as Ne,SubjectKanonak as Pr,Reasoner as Cr,KanonakVocabulary as _r,makeUriKey as jn,pickHighestDocument as Oe,formatVersion as Nn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as oe}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Ee,findSubjectByUri as Rr}from"@kanonak-protocol/sdk/uri-helpers";import{TX_V3 as En}from"@kanonak-protocol/sdk/transformations";import{TransformationRunnerV3 as Ir,SUPPORTED_FORMATS_V3 as On}from"@kanonak-protocol/sdk/transformations";import{compileTransformationV3 as Le}from"@kanonak-protocol/sdk/transformations";function Ae(n){return[...Ee(n,En.InstanceTransformation),...Ee(n,En.SetTransformation)]}function Ln(){let n=new re("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",`
61
61
  Examples:
62
62
 
63
63
  # List every Transformation available in the local workspace
@@ -95,9 +95,9 @@ Examples:
95
95
 
96
96
  # List the registered format backends
97
97
  $ kanonak transform formats
98
- `);return n.addCommand(Ar()),n.addCommand(Or()),n.addCommand(Ur()),n.addCommand(Vr()),n}function Ar(){return new re("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. Repeatable: pass `--scope X --scope Y` to aggregate matching instances across multiple packages, useful for index pages and other cross-package SetTransformations.",Er,[]).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 jr(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}function Er(n,e){return[...e,n]}async function jr(n,e){let t=new Ne,o=new Oe,r=await S(process.cwd(),t),a=await Fn(n,r,o),{transformation:s,transformationKanonaks:i}=a;console.log(`Transformation: ${pe(s)}`);let c=Ue(s,i);e.scope.length===0&&(console.error("At least one --scope is required."),process.exit(1));let l=[],p=new Map;for(let y of e.scope){let b=await Mr(y,r,t,o);l.push(...b);let w=await zr(b,c.inputPattern.matchesClass,r);for(let v of w){let $=Wr(v);$&&!p.has($)&&p.set($,v)}console.log(`Scope: ${y} \u2014 found ${w.length} instance(s) of ${c.inputPattern.matchesClass.publisher}/${c.inputPattern.matchesClass.package_}/${c.inputPattern.matchesClass.name}`)}let u=[...p.values()],m=l;e.scope.length>1&&console.log(`Total across ${e.scope.length} scope(s): ${u.length} unique instance(s)`),u.length===0&&c.kind==="instance"&&(console.error("No matching input instances across the supplied scope(s). Check the transformation's inputPattern.matchesClass vs. the scope package(s)."),process.exit(1));let h=Nr(c.outputs,e.format);console.log(`Output format: ${h}`);let k=Ln[h];if(!k)throw new Error(`Unknown format "${h}". Run \`kanonak transform formats\` to see what the runner supports.`);let f=await new Tr().run({transformation:s,instances:u,allKanonaks:m,transformationKanonaks:i,repository:r,parser:t,objectParser:o,outputFormat:h}),g=Rr(e.out);Pr(g,{recursive:!0});for(let y of f){let b=Br(y.fileName),w=Cr(g,`${b}${k.extension}`);Sr(w,y.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${f.length} artifact(s) written to ${g}`)}function Nr(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 Or(){return new re("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await Lr()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function Lr(){let n=new Ne,e=new Oe,t=await S(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let s of o)try{let i=new oe(s,t),c=await e.parseKanonaks(i),l=je(c);for(let p of l){let u=Fe(p);if(!u)continue;let m=r.get(u)??[];m.push({tx:p,kanonaks:c,doc:s}),r.set(u,m)}}catch{}let a=[];for(let s of r.values()){if(s.length===1){a.push(jn(s[0].tx,s[0].kanonaks));continue}let i=Le(s.map(l=>l.doc));if(!i.chosen)continue;let c=s.find(l=>l.doc===i.chosen);c&&a.push(jn(c.tx,c.kanonaks))}if(a.length===0){console.log("No Transformation instances found in the current workspace.");return}a.sort((s,i)=>s.uri.localeCompare(i.uri));for(let s of a)console.log(`${s.uri}`),console.log(` matches: ${s.matchesClass}`),console.log(` outputs: ${s.outputs.join(", ")}`)}function Ur(){return new re("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 Fr(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Fr(n){let e=new Ne,t=new Oe,o=await S(process.cwd(),e),{transformation:r,transformationKanonaks:a}=await Fn(n,o,t),s=Ue(r,a);if(console.log(`Transformation: ${pe(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${ue(s.inputPattern.matchesClass)}`),s.inputPattern.requires.length>0){console.log(" Required properties:");for(let i of s.inputPattern.requires)console.log(` - ${ue(i)}`)}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[i,c]of s.overrides){if(console.log(` ${i}:`),c.metadataKeys&&console.log(` metadata keys: ${c.metadataKeys.join(", ")}`),c.metadataRenames.size>0){let l=[];for(let[p,u]of c.metadataRenames)l.push(`${p} \u2192 ${u}`);console.log(` metadata renames: ${l.join(", ")}`)}c.trailingNewline!==void 0&&console.log(` trailing newline: ${c.trailingNewline}`)}console.log()}console.log(`Rule root kind: ${s.rule.kind}`),s.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${ue(s.rule.astClass)}`),console.log(`Rule root bindings: ${s.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${s.artifactName.kind}`)}function Vr(){return new re("formats").description("List the OutputFormat names the runner can serialize to.").action(()=>{console.log("Registered format backends:");let n=Object.entries(Ln).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 Fn(n,e,t){let o,r,a;if(n.includes("/")){let m=n.indexOf("@"),h=n;if(m!==-1){let d=n.indexOf("/",m);if(d===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);h=n.substring(0,m)+n.substring(d)}let k=h.split("/");if(k.length<3)throw new Error(`Invalid transformation URI "${n}" \u2014 expected publisher/package/name or publisher/package@version/name`);o=k[0],r=k[1],a=k.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 h=Hr(n),k=Vn(m,h,`${o}/${r}`),d=new oe(k,e),f=await t.parseKanonaks(d),g=xr(f,{publisher:o,package_:r,name:a,version:""});if(!g){let y=je(f),b=y.find(w=>w.name===a);if(!b)throw new Error(`Transformation "${a}" not found in package ${o}/${r}. Package contains ${y.length} Transformation(s): ${y.map(w=>w.name).join(", ")||"(none)"}`);return{transformation:b,transformationKanonaks:f}}return{transformation:g,transformationKanonaks:f}}let s=await e.getAllDocumentsAsync(),i=new Map;for(let m of s)try{let h=new oe(m,e),k=await t.parseKanonaks(h),d=je(k);for(let f of d){if(f.name!==a)continue;let g=Fe(f);if(!g)continue;let y=i.get(g)??[];y.push({tx:f,kanonaks:k,doc:m}),i.set(g,y)}}catch{}if(i.size===0)throw new Error(`No Transformation named "${a}" found in the workspace. Try \`kanonak transform list\` to see available transformations.`);if(i.size>1){let m=Array.from(i.keys()).sort().join(`
98
+ `);return n.addCommand(Kr()),n.addCommand(Er()),n.addCommand(jr()),n.addCommand(Or()),n}function Kr(){return new re("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. Repeatable: pass `--scope X --scope Y` to aggregate matching instances across multiple packages, useful for index pages and other cross-package SetTransformations.",xr,[]).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 Tr(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}function xr(n,e){return[...e,n]}async function Tr(n,e){let t=new je,o=new Ne,r=await S(process.cwd(),t),a=await Un(n,r,o),{transformation:s,transformationKanonaks:i}=a;console.log(`Transformation: ${pe(s)}`);let c=Le(s,i);e.scope.length===0&&(console.error("At least one --scope is required."),process.exit(1));let l=[],p=new Map;for(let y of e.scope){let b=await Lr(y,r,t,o);l.push(...b);let w=await Mr(b,c.inputPattern.matchesClass,r);for(let $ of w){let v=Vr($);v&&!p.has(v)&&p.set(v,$)}console.log(`Scope: ${y} \u2014 found ${w.length} instance(s) of ${c.inputPattern.matchesClass.publisher}/${c.inputPattern.matchesClass.package_}/${c.inputPattern.matchesClass.name}`)}let u=[...p.values()],m=l;e.scope.length>1&&console.log(`Total across ${e.scope.length} scope(s): ${u.length} unique instance(s)`),u.length===0&&c.kind==="instance"&&(console.error("No matching input instances across the supplied scope(s). Check the transformation's inputPattern.matchesClass vs. the scope package(s)."),process.exit(1));let h=Dr(c.outputs,e.format);console.log(`Output format: ${h}`);let k=On[h];if(!k)throw new Error(`Unknown format "${h}". Run \`kanonak transform formats\` to see what the runner supports.`);let f=await new Ir().run({transformation:s,instances:u,allKanonaks:m,transformationKanonaks:i,repository:r,parser:t,objectParser:o,outputFormat:h}),g=Sr(e.out);wr(g,{recursive:!0});for(let y of f){let b=Fr(y.fileName),w=vr(g,`${b}${k.extension}`);br(w,y.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${f.length} artifact(s) written to ${g}`)}function Dr(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 Er(){return new re("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await Ar()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function Ar(){let n=new je,e=new Ne,t=await S(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let s of o)try{let i=new oe(s,t),c=await e.parseKanonaks(i),l=Ae(c);for(let p of l){let u=Ue(p);if(!u)continue;let m=r.get(u)??[];m.push({tx:p,kanonaks:c,doc:s}),r.set(u,m)}}catch{}let a=[];for(let s of r.values()){if(s.length===1){a.push(An(s[0].tx,s[0].kanonaks));continue}let i=Oe(s.map(l=>l.doc));if(!i.chosen)continue;let c=s.find(l=>l.doc===i.chosen);c&&a.push(An(c.tx,c.kanonaks))}if(a.length===0){console.log("No Transformation instances found in the current workspace.");return}a.sort((s,i)=>s.uri.localeCompare(i.uri));for(let s of a)console.log(`${s.uri}`),console.log(` matches: ${s.matchesClass}`),console.log(` outputs: ${s.outputs.join(", ")}`)}function jr(){return new re("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 Nr(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Nr(n){let e=new je,t=new Ne,o=await S(process.cwd(),e),{transformation:r,transformationKanonaks:a}=await Un(n,o,t),s=Le(r,a);if(console.log(`Transformation: ${pe(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${ue(s.inputPattern.matchesClass)}`),s.inputPattern.requires.length>0){console.log(" Required properties:");for(let i of s.inputPattern.requires)console.log(` - ${ue(i)}`)}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[i,c]of s.overrides){if(console.log(` ${i}:`),c.metadataKeys&&console.log(` metadata keys: ${c.metadataKeys.join(", ")}`),c.metadataRenames.size>0){let l=[];for(let[p,u]of c.metadataRenames)l.push(`${p} \u2192 ${u}`);console.log(` metadata renames: ${l.join(", ")}`)}c.trailingNewline!==void 0&&console.log(` trailing newline: ${c.trailingNewline}`)}console.log()}console.log(`Rule root kind: ${s.rule.kind}`),s.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${ue(s.rule.astClass)}`),console.log(`Rule root bindings: ${s.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${s.artifactName.kind}`)}function Or(){return new re("formats").description("List the OutputFormat names the runner can serialize to.").action(()=>{console.log("Registered format backends:");let n=Object.entries(On).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 Un(n,e,t){let o,r,a;if(n.includes("/")){let m=n.indexOf("@"),h=n;if(m!==-1){let d=n.indexOf("/",m);if(d===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);h=n.substring(0,m)+n.substring(d)}let k=h.split("/");if(k.length<3)throw new Error(`Invalid transformation URI "${n}" \u2014 expected publisher/package/name or publisher/package@version/name`);o=k[0],r=k[1],a=k.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 h=Ur(n),k=Fn(m,h,`${o}/${r}`),d=new oe(k,e),f=await t.parseKanonaks(d),g=Rr(f,{publisher:o,package_:r,name:a,version:""});if(!g){let y=Ae(f),b=y.find(w=>w.name===a);if(!b)throw new Error(`Transformation "${a}" not found in package ${o}/${r}. Package contains ${y.length} Transformation(s): ${y.map(w=>w.name).join(", ")||"(none)"}`);return{transformation:b,transformationKanonaks:f}}return{transformation:g,transformationKanonaks:f}}let s=await e.getAllDocumentsAsync(),i=new Map;for(let m of s)try{let h=new oe(m,e),k=await t.parseKanonaks(h),d=Ae(k);for(let f of d){if(f.name!==a)continue;let g=Ue(f);if(!g)continue;let y=i.get(g)??[];y.push({tx:f,kanonaks:k,doc:m}),i.set(g,y)}}catch{}if(i.size===0)throw new Error(`No Transformation named "${a}" found in the workspace. Try \`kanonak transform list\` to see available transformations.`);if(i.size>1){let m=Array.from(i.keys()).sort().join(`
99
99
  `);throw new Error(`Multiple Transformations named "${a}" in the workspace \u2014 disambiguate with a full publisher/package/name URI:
100
- ${m}`)}let c=Array.from(i.values())[0];if(c.length===1)return{transformation:c[0].tx,transformationKanonaks:c[0].kanonaks};let l=new Map(c.map(m=>[m.doc,m])),p=Le(c.map(m=>m.doc));if(!p.chosen)throw new Error(`Could not select a Transformation version for "${a}".`);let u=l.get(p.chosen);if(p.multipleVersionsPresent){let m=d=>{let f=d.metadata.namespace_?.version;return f?On(f):""},h=u.tx.namespace??"",k=h.includes("@")?h.substring(0,h.indexOf("@")):h;console.warn(`Warning: Transformation "${a}" has ${c.length} versions present (${c.map(d=>m(d.doc)).filter(Boolean).join(", ")}); using @${m(p.chosen)}. Pin with ${k}@<version>/${a} to suppress this warning.`)}return{transformation:u.tx,transformationKanonaks:u.kanonaks}}async function Mr(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||An(n)&&_r(n).isFile()){if(!An(n))throw new Error(`Scope file not found: ${n}`);let k=$r(n,"utf-8"),d=t.parse(k),f=new oe(d,e);return o.parseKanonaks(f)}let a=n.indexOf("@"),s=a===-1?n:n.substring(0,a),i=a===-1?void 0:n.substring(a+1),c=s.indexOf("/");if(c===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=s.substring(0,c),p=s.substring(c+1),u=await e.getDocumentsByNamespaceAsync(l,p);if(u.length===0)throw new Error(`Scope package ${l}/${p} not found in the local workspace or cache.`);let m=Vn(u,i,`${l}/${p}`),h=new oe(m,e);return o.parseKanonaks(h)}function Hr(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 Vn(n,e,t){let o=a=>{let s=a.metadata.namespace_?.version;return s?On(s):""},r=Le(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 jn(n,e){try{let t=Ue(n,e);return{uri:pe(n),matchesClass:ue(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 ue(n){return`${n.publisher}/${n.package_}/${n.name}`}function Br(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function zr(n,e,t){let o=new Map;for(let s of n){if(!(s instanceof Kr))continue;let i=Fe(s);i&&o.set(i,s)}let r=[];try{r=(await new Dr({vocabulary:new Ir}).reason(t)).getInstancesOfClass(Nn(e.publisher,e.package_,e.name))}catch{}let a=[];for(let s of r){let i=o.get(s);i&&a.push(i)}return a.length>0?a:Ee(n,e)}function Fe(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:Nn(o.substring(0,r),o.substring(r+1),n.name)}function Wr(n){let e=n.namespace??"";return!e||!n.name?null:`${e}/${n.name}`}import{Command as qr}from"commander";import{writeFileSync as Gr,mkdirSync as Jr}from"fs";import{join as Yr,resolve as Xr}from"path";import{KanonakParser as Zr,KanonakObjectParser as Qr,SubjectKanonak as Bn,findDerivation as es}from"@kanonak-protocol/sdk";import{TransformationRunnerV3 as ns}from"@kanonak-protocol/sdk/transformations";var ts={publisher:"kanonak.org",package_:"formats",name:"html"},os={publisher:"kanonak.org",package_:"derivation",name:"default"},rs={html:".html",markdown:".md",json:".json",yaml:".yaml",xml:".xml",svg:".svg",typescript:".ts","c-sharp":".cs",rust:".rs",python:".py"};function ss(n){return n==="markdown"?"markdown-with-frontmatter":n}function zn(){return new qr("derive").description("Materialize a derived artifact from a Kanonak resource by walking the polymorphic derivation discovery: instance overrides \u2192 class hierarchy \u2192 universal defaults. The result is written to disk.").argument("<resource>","Resource URI in the form publisher/package[@version]/name. Identifies the specific instance to derive.").option("--format <name>","Format instance name (e.g. html, markdown, json). Defaults to html.","html").option("--variant <name>","Variant instance name (e.g. default, compact, summary). Defaults to default.","default").option("--out <dir>","Directory to write the artifact into.",".").addHelpText("after",`
100
+ ${m}`)}let c=Array.from(i.values())[0];if(c.length===1)return{transformation:c[0].tx,transformationKanonaks:c[0].kanonaks};let l=new Map(c.map(m=>[m.doc,m])),p=Oe(c.map(m=>m.doc));if(!p.chosen)throw new Error(`Could not select a Transformation version for "${a}".`);let u=l.get(p.chosen);if(p.multipleVersionsPresent){let m=d=>{let f=d.metadata.namespace_?.version;return f?Nn(f):""},h=u.tx.namespace??"",k=h.includes("@")?h.substring(0,h.indexOf("@")):h;console.warn(`Warning: Transformation "${a}" has ${c.length} versions present (${c.map(d=>m(d.doc)).filter(Boolean).join(", ")}); using @${m(p.chosen)}. Pin with ${k}@<version>/${a} to suppress this warning.`)}return{transformation:u.tx,transformationKanonaks:u.kanonaks}}async function Lr(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||Dn(n)&&$r(n).isFile()){if(!Dn(n))throw new Error(`Scope file not found: ${n}`);let k=yr(n,"utf-8"),d=t.parse(k),f=new oe(d,e);return o.parseKanonaks(f)}let a=n.indexOf("@"),s=a===-1?n:n.substring(0,a),i=a===-1?void 0:n.substring(a+1),c=s.indexOf("/");if(c===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=s.substring(0,c),p=s.substring(c+1),u=await e.getDocumentsByNamespaceAsync(l,p);if(u.length===0)throw new Error(`Scope package ${l}/${p} not found in the local workspace or cache.`);let m=Fn(u,i,`${l}/${p}`),h=new oe(m,e);return o.parseKanonaks(h)}function Ur(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 Fn(n,e,t){let o=a=>{let s=a.metadata.namespace_?.version;return s?Nn(s):""},r=Oe(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 An(n,e){try{let t=Le(n,e);return{uri:pe(n),matchesClass:ue(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 ue(n){return`${n.publisher}/${n.package_}/${n.name}`}function Fr(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Mr(n,e,t){let o=new Map;for(let s of n){if(!(s instanceof Pr))continue;let i=Ue(s);i&&o.set(i,s)}let r=[];try{r=(await new Cr({vocabulary:new _r}).reason(t)).getInstancesOfClass(jn(e.publisher,e.package_,e.name))}catch{}let a=[];for(let s of r){let i=o.get(s);i&&a.push(i)}return a.length>0?a:Ee(n,e)}function Ue(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:jn(o.substring(0,r),o.substring(r+1),n.name)}function Vr(n){let e=n.namespace??"";return!e||!n.name?null:`${e}/${n.name}`}import{Command as Hr}from"commander";import{writeFileSync as Br,mkdirSync as zr}from"fs";import{join as Wr,resolve as qr}from"path";import{KanonakParser as Gr,KanonakObjectParser as Jr,SubjectKanonak as Hn,findDerivation as Yr}from"@kanonak-protocol/sdk";import{TransformationRunnerV3 as Xr}from"@kanonak-protocol/sdk/transformations";var Zr={publisher:"kanonak.org",package_:"formats",name:"html"},Qr={publisher:"kanonak.org",package_:"derivation",name:"default"},ea={html:".html",markdown:".md",json:".json",yaml:".yaml",xml:".xml",svg:".svg",typescript:".ts","c-sharp":".cs",rust:".rs",python:".py"};function na(n){return n==="markdown"?"markdown-with-frontmatter":n}function Bn(){return new Hr("derive").description("Materialize a derived artifact from a Kanonak resource by walking the polymorphic derivation discovery: instance overrides \u2192 class hierarchy \u2192 universal defaults. The result is written to disk.").argument("<resource>","Resource URI in the form publisher/package[@version]/name. Identifies the specific instance to derive.").option("--format <name>","Format instance name (e.g. html, markdown, json). Defaults to html.","html").option("--variant <name>","Variant instance name (e.g. default, compact, summary). Defaults to default.","default").option("--out <dir>","Directory to write the artifact into.",".").addHelpText("after",`
101
101
  Examples:
102
102
 
103
103
  # Render a resource as HTML using whatever derivation the discovery
@@ -108,20 +108,20 @@ Examples:
108
108
 
109
109
  # Materialize the JSON view (universal default unless overridden).
110
110
  $ kanonak derive my-publisher.com/my-package/my-resource --format json
111
- `).action(async(n,e)=>{try{await as(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function as(n,e){let t=E(n);if(!t||!t.instanceName)throw new Error(`Invalid resource URI "${n}". Expected publisher/package[@version]/instance.`);let o=new Zr,r=new Qr,a=await S(process.cwd(),o),s=await r.parseKanonaks(a),i=is(s,t);if(!i)throw new Error(`Resource ${t.publisher}/${t.packageName}${t.version?`@${t.version}`:""}/${t.instanceName} not found in the workspace or cache.`);console.log(`Resource: ${Mn(i)}`);let c=ls(e.format),l=us(e.variant),p=es(i,c,l,s);if(!p)throw new Error(`No derivation found for resource ${Mn(i)} at (format=${e.format}, variant=${e.variant}). The class hierarchy declares no binding and no universal default applies.`);console.log(`Derivation: ${ps(p)} \u2192 ${Hn(p.transformation)}`);let u=cs(s,p.transformation);if(!u)throw new Error(`Transformation ${Hn(p.transformation)} not found in the workspace or cache. The binding pointed at a transformation the resolver cannot locate.`);let m=ss(e.format),k=await new ns().run({transformation:u,instances:[i],allKanonaks:s,repository:a,parser:o,objectParser:r,outputFormat:m}),d=Xr(e.out);Jr(d,{recursive:!0});let f=rs[e.format]??"";for(let g of k){let y=ms(g.fileName),b=Yr(d,`${y}${f}`);Gr(b,g.content,"utf-8"),console.log(` wrote ${b}`)}console.log(`Done. ${k.length} artifact(s) written to ${d}`)}function is(n,e){for(let t of n){if(!(t instanceof Bn)||t.name!==e.instanceName)continue;let o=t.namespace||"",r=`${e.publisher}/${e.packageName}@`;if(o.startsWith(r))if(e.version){if(o===`${e.publisher}/${e.packageName}@${e.version}`)return t}else return t}}function cs(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Bn&&o.name===e.name&&o.namespace===t)return o}function ls(n){if(n.includes("/")){let e=E(n);if(!e||!e.instanceName)throw new Error(`Invalid --format URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...ts,name:n}}function us(n){if(n.includes("/")){let e=E(n);if(!e||!e.instanceName)throw new Error(`Invalid --variant URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...os,name:n}}function Mn(n){return`${n.namespace}/${n.name}`}function Hn(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}function ps(n){return n.source==="instance"?"instance override":`class ${n.source.publisher}/${n.source.package_}/${n.source.name}`}function ms(n){return n.replace(/[^a-zA-Z0-9._@-]+/g,"_")}import{Command as ds}from"commander";import{writeFileSync as K,mkdirSync as se}from"fs";import{join as P,resolve as Wn}from"path";import{KanonakParser as fs,KanonakObjectParser as gs,SubjectKanonak as hs,LookRenderer as ks}from"@kanonak-protocol/sdk";import{TransformationEngine as ys}from"@kanonak-protocol/sdk/transformations";import{readFileSync as bs}from"fs";var ws=[{format:{publisher:"kanonak.org",package_:"formats",name:"html"},fileExtension:".html"},{format:{publisher:"kanonak.org",package_:"formats",name:"stylesheet"},fileExtension:".css"},{format:{publisher:"kanonak.org",package_:"formats",name:"svg"},fileExtension:".svg"}];function qn(){return new ds("publish").description("Generate a static Kanonak site from the local workspace. Walks every resource and renders HTML + stylesheet via the engine. Writes to --out in the canonical Kanonak URL hierarchy.").option("--workspace <dir>","Workspace directory containing .kan.yml package files. Defaults to current directory.",process.cwd()).option("--out <dir>","Output directory for the generated site. Defaults to _site.","_site").action(async n=>{await vs(n)})}async function vs(n){let e=Wn(n.workspace),t=Wn(n.out),o=new fs,r=new gs,a=[];G(e,a),a.length===0&&(console.error(`No .kan.yml files found under ${e}`),process.exit(1)),console.log(`Found ${a.length} local package file(s) under ${e}`);let s=new Set;for(let f of a)try{let g=bs(f,"utf-8"),b=o.parse(g).metadata?.namespace_;if(!b)continue;let w=b.version;s.add(`${b.publisher}/${b.package_}@${w.major}.${w.minor}.${w.patch}`)}catch(g){console.warn(` warning: failed to parse ${f}: ${g.message}`)}console.log(`Local namespaces: ${[...s].join(", ")}`);let i=await S(e,o),c=await r.parseKanonaks(i),l=c.filter(f=>!(!(f instanceof hs)||!s.has(f.namespace||"")));console.log(`Publishing ${l.length} resource(s) to ${t}`);let p=new ys(i,o,r),u=new ks(c),m=0,h=0;for(let f of l){let g=f.namespace||"",[y,b]=g.split("/");if(!y||!b)continue;let[w,v]=b.split("@");if(!w||!v)continue;let $=P(t,w,v);se($,{recursive:!0});let ie=!!u.findCascadedLook(f),O=v.split(".").map(Number),q=O.length===3&&O.every(T=>!Number.isNaN(T))?{major:O[0],minor:O[1],patch:O[2]}:void 0,ce=u.renderRawMarkdown(f);ce!==void 0&&(K(P($,`${f.name}.md`),ce,"utf-8"),m+=1);for(let T of ws){let L=T.format.name;try{let A,U;if(ie&&(L==="html"||L==="stylesheet"))A=L==="html"?u.renderDocument(f):u.renderStylesheet(f),U=`${f.name}${T.fileExtension}`;else if(L==="svg")A=u.renderSvg(f),U=`${f.name}${T.fileExtension}`;else{let Mt={publisher:y,package_:w,name:f.name,...q?{version:q}:{}},le=await p.render({resource:Mt,format:T.format});A=le.content,L==="html"?U=`${f.name}${T.fileExtension}`:U=le.filename.includes(".")?le.filename:`${le.filename}${T.fileExtension}`}let Vt=P($,U);K(Vt,A,"utf-8"),m+=1}catch(A){console.warn(` ${y}/${w}@${v}/${f.name} [${L}]: ${A.message}`),h+=1}}}console.log(`Done. ${m} artifact(s) written, ${h} skipped.`),h>0&&console.log("Skipped artifacts are typically resources with no derivation binding for the requested format (e.g. an instance class without an html transformation). This is expected for vocabulary-only packages \u2014 they have no instances to render.");let k=$s(t,l,u);console.log(`Wrote ${k} package overview page(s).`),Ss(t,l,u);let d=Ps(t,l);console.log(`Wrote ${d} version-form redirect stub(s).`)}function $s(n,e,t){let o=new Map,r=new Map;for(let i of e){let c=i.namespace||"",[,l]=c.split("/");if(!l)continue;let[p,u]=l.split("@");if(!p||!u||i.name!==p)continue;let m=u.split(".").map(Number);if(m.length!==3||m.some(d=>Number.isNaN(d)))continue;let h={verStr:u,major:m[0],minor:m[1],patch:m[2]};o.has(p)||o.set(p,[]),o.get(p).push({resource:i,ver:h});let k=r.get(p);(!k||h.major>k.ver.major||h.major===k.ver.major&&h.minor>k.ver.minor||h.major===k.ver.major&&h.minor===k.ver.minor&&h.patch>k.ver.patch)&&r.set(p,{resource:i,ver:h})}let a=(i,c)=>{try{return se(i,{recursive:!0}),K(P(i,"index.html"),t.renderDocument(c),"utf-8"),K(P(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},s=0;for(let[i,c]of o)for(let{resource:l,ver:p}of c)a(P(n,i,p.verStr),l)&&(s+=1);for(let[i,{resource:c}]of r){let l=P(n,i);try{if(se(l,{recursive:!0}),t.hasDeclaredView(c))K(P(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8");else{let p=(o.get(i)??[]).slice().sort((u,m)=>m.ver.major-u.ver.major||m.ver.minor-u.ver.minor||m.ver.patch-u.ver.patch).map(u=>u.ver.verStr);K(P(l,"index.html"),t.renderPackageVersionList(i,p,c),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}s+=1}catch{}}return s}function Ss(n,e,t){let o="",r=new Map;for(let p of e){let m=(p.namespace||"").split("/"),[h]=(m[1]??"").split("@");if(!m[0]||!h||(o||(o=m[0]),p.name!==h))continue;let k=(m[1]??"").split("@")[1]??"",d=k.split(".").map(Number);if(d.length!==3||d.some(y=>Number.isNaN(y)))continue;let f={verStr:k,major:d[0],minor:d[1],patch:d[2]},g=r.get(h);(!g||f.major>g.ver.major||f.major===g.ver.major&&f.minor>g.ver.minor||f.major===g.ver.major&&f.minor===g.ver.minor&&f.patch>g.ver.patch)&&r.set(h,{resource:p,ver:f})}if(!o||r.size===0)return;let a=t.findPublisherRootView(o);if(a){K(P(n,"index.html"),t.renderDocument(a,{rootIndex:!0}),"utf-8"),K(P(n,"index.css"),t.renderStylesheet(a),"utf-8");return}let s=[...r.entries()].sort((p,u)=>p[0].localeCompare(u[0])).map(([p,{resource:u}])=>({label:p,href:`/${p}`,comment:void 0})),i=[...r.values()][0]?.resource,c=t.renderPublisherIndex(o,s,i),l=t.renderPublisherIndexStylesheet(i);K(P(n,"index.html"),c,"utf-8"),K(P(n,"index.css"),l,"utf-8")}function Ps(n,e){let t=new Map;for(let r of e){let a=r.namespace||"",[,s]=a.split("/");if(!s)continue;let[i,c]=s.split("@");if(!i||!c)continue;let l=c.split(".").map(Number);if(l.length!==3||l.some(u=>Number.isNaN(u)))continue;let p=`${i}/${r.name}`;t.has(p)||t.set(p,[]),t.get(p).push({verStr:c,major:l[0],minor:l[1],patch:l[2]})}let o=0;for(let[r,a]of t){let[s,i]=r.split("/");a.sort((u,m)=>m.major-u.major||m.minor-u.minor||m.patch-u.patch);let c=a[0];K(P(n,s,`${i}.html`),Ve(`/${s}/${c.verStr}/${i}`),"utf-8"),o+=1;let l=new Set;for(let u of a){if(l.has(u.major))continue;l.add(u.major);let m=P(n,s,String(u.major));se(m,{recursive:!0}),K(P(m,`${i}.html`),Ve(`/${s}/${u.verStr}/${i}`),"utf-8"),o+=1}let p=new Set;for(let u of a){let m=`${u.major}.${u.minor}`;if(p.has(m))continue;p.add(m);let h=P(n,s,m);se(h,{recursive:!0}),K(P(h,`${i}.html`),Ve(`/${s}/${u.verStr}/${i}`),"utf-8"),o+=1}}return o}function Ve(n){let e=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");return`<!doctype html>
111
+ `).action(async(n,e)=>{try{await ta(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function ta(n,e){let t=A(n);if(!t||!t.instanceName)throw new Error(`Invalid resource URI "${n}". Expected publisher/package[@version]/instance.`);let o=new Gr,r=new Jr,a=await S(process.cwd(),o),s=await r.parseKanonaks(a),i=oa(s,t);if(!i)throw new Error(`Resource ${t.publisher}/${t.packageName}${t.version?`@${t.version}`:""}/${t.instanceName} not found in the workspace or cache.`);console.log(`Resource: ${Mn(i)}`);let c=aa(e.format),l=sa(e.variant),p=Yr(i,c,l,s);if(!p)throw new Error(`No derivation found for resource ${Mn(i)} at (format=${e.format}, variant=${e.variant}). The class hierarchy declares no binding and no universal default applies.`);console.log(`Derivation: ${ia(p)} \u2192 ${Vn(p.transformation)}`);let u=ra(s,p.transformation);if(!u)throw new Error(`Transformation ${Vn(p.transformation)} not found in the workspace or cache. The binding pointed at a transformation the resolver cannot locate.`);let m=na(e.format),k=await new Xr().run({transformation:u,instances:[i],allKanonaks:s,repository:a,parser:o,objectParser:r,outputFormat:m}),d=qr(e.out);zr(d,{recursive:!0});let f=ea[e.format]??"";for(let g of k){let y=ca(g.fileName),b=Wr(d,`${y}${f}`);Br(b,g.content,"utf-8"),console.log(` wrote ${b}`)}console.log(`Done. ${k.length} artifact(s) written to ${d}`)}function oa(n,e){for(let t of n){if(!(t instanceof Hn)||t.name!==e.instanceName)continue;let o=t.namespace||"",r=`${e.publisher}/${e.packageName}@`;if(o.startsWith(r))if(e.version){if(o===`${e.publisher}/${e.packageName}@${e.version}`)return t}else return t}}function ra(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Hn&&o.name===e.name&&o.namespace===t)return o}function aa(n){if(n.includes("/")){let e=A(n);if(!e||!e.instanceName)throw new Error(`Invalid --format URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...Zr,name:n}}function sa(n){if(n.includes("/")){let e=A(n);if(!e||!e.instanceName)throw new Error(`Invalid --variant URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...Qr,name:n}}function Mn(n){return`${n.namespace}/${n.name}`}function Vn(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}function ia(n){return n.source==="instance"?"instance override":`class ${n.source.publisher}/${n.source.package_}/${n.source.name}`}function ca(n){return n.replace(/[^a-zA-Z0-9._@-]+/g,"_")}import{Command as la}from"commander";import{writeFileSync as K,mkdirSync as ae}from"fs";import{join as P,resolve as zn}from"path";import{KanonakParser as ua,KanonakObjectParser as pa,SubjectKanonak as ma,LookRenderer as da}from"@kanonak-protocol/sdk";import{TransformationEngine as fa}from"@kanonak-protocol/sdk/transformations";import{readFileSync as ga}from"fs";var ha=[{format:{publisher:"kanonak.org",package_:"formats",name:"html"},fileExtension:".html"},{format:{publisher:"kanonak.org",package_:"formats",name:"stylesheet"},fileExtension:".css"},{format:{publisher:"kanonak.org",package_:"formats",name:"svg"},fileExtension:".svg"}];function Wn(){return new la("publish").description("Generate a static Kanonak site from the local workspace. Walks every resource and renders HTML + stylesheet via the engine. Writes to --out in the canonical Kanonak URL hierarchy.").option("--workspace <dir>","Workspace directory containing .kan.yml package files. Defaults to current directory.",process.cwd()).option("--out <dir>","Output directory for the generated site. Defaults to _site.","_site").action(async n=>{await ka(n)})}async function ka(n){let e=zn(n.workspace),t=zn(n.out),o=new ua,r=new pa,a=[];ee(e,a),a.length===0&&(console.error(`No .kan.yml files found under ${e}`),process.exit(1)),console.log(`Found ${a.length} local package file(s) under ${e}`);let s=new Set;for(let f of a)try{let g=ga(f,"utf-8"),b=o.parse(g).metadata?.namespace_;if(!b)continue;let w=b.version;s.add(`${b.publisher}/${b.package_}@${w.major}.${w.minor}.${w.patch}`)}catch(g){console.warn(` warning: failed to parse ${f}: ${g.message}`)}console.log(`Local namespaces: ${[...s].join(", ")}`);let i=await S(e,o),c=await r.parseKanonaks(i),l=c.filter(f=>!(!(f instanceof ma)||!s.has(f.namespace||"")));console.log(`Publishing ${l.length} resource(s) to ${t}`);let p=new fa(i,o,r),u=new da(c),m=0,h=0;for(let f of l){let g=f.namespace||"",[y,b]=g.split("/");if(!y||!b)continue;let[w,$]=b.split("@");if(!w||!$)continue;let v=P(t,w,$);ae(v,{recursive:!0});let ie=!!u.findCascadedLook(f),O=$.split(".").map(Number),q=O.length===3&&O.every(D=>!Number.isNaN(D))?{major:O[0],minor:O[1],patch:O[2]}:void 0,ce=u.renderRawMarkdown(f);ce!==void 0&&(K(P(v,`${f.name}.md`),ce,"utf-8"),m+=1);for(let D of ha){let L=D.format.name;try{let E,U;if(ie&&(L==="html"||L==="stylesheet"))E=L==="html"?u.renderDocument(f):u.renderStylesheet(f),U=`${f.name}${D.fileExtension}`;else if(L==="svg")E=u.renderSvg(f),U=`${f.name}${D.fileExtension}`;else{let Vt={publisher:y,package_:w,name:f.name,...q?{version:q}:{}},le=await p.render({resource:Vt,format:D.format});E=le.content,L==="html"?U=`${f.name}${D.fileExtension}`:U=le.filename.includes(".")?le.filename:`${le.filename}${D.fileExtension}`}let Mt=P(v,U);K(Mt,E,"utf-8"),m+=1}catch(E){console.warn(` ${y}/${w}@${$}/${f.name} [${L}]: ${E.message}`),h+=1}}}console.log(`Done. ${m} artifact(s) written, ${h} skipped.`),h>0&&console.log("Skipped artifacts are typically resources with no derivation binding for the requested format (e.g. an instance class without an html transformation). This is expected for vocabulary-only packages \u2014 they have no instances to render.");let k=ya(t,l,u);console.log(`Wrote ${k} package overview page(s).`),ba(t,l,u);let d=wa(t,l);console.log(`Wrote ${d} version-form redirect stub(s).`)}function ya(n,e,t){let o=new Map,r=new Map;for(let i of e){let c=i.namespace||"",[,l]=c.split("/");if(!l)continue;let[p,u]=l.split("@");if(!p||!u||i.name!==p)continue;let m=u.split(".").map(Number);if(m.length!==3||m.some(d=>Number.isNaN(d)))continue;let h={verStr:u,major:m[0],minor:m[1],patch:m[2]};o.has(p)||o.set(p,[]),o.get(p).push({resource:i,ver:h});let k=r.get(p);(!k||h.major>k.ver.major||h.major===k.ver.major&&h.minor>k.ver.minor||h.major===k.ver.major&&h.minor===k.ver.minor&&h.patch>k.ver.patch)&&r.set(p,{resource:i,ver:h})}let a=(i,c)=>{try{return ae(i,{recursive:!0}),K(P(i,"index.html"),t.renderDocument(c),"utf-8"),K(P(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},s=0;for(let[i,c]of o)for(let{resource:l,ver:p}of c)a(P(n,i,p.verStr),l)&&(s+=1);for(let[i,{resource:c}]of r){let l=P(n,i);try{if(ae(l,{recursive:!0}),t.hasDeclaredView(c))K(P(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8");else{let p=(o.get(i)??[]).slice().sort((u,m)=>m.ver.major-u.ver.major||m.ver.minor-u.ver.minor||m.ver.patch-u.ver.patch).map(u=>u.ver.verStr);K(P(l,"index.html"),t.renderPackageVersionList(i,p,c),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}s+=1}catch{}}return s}function ba(n,e,t){let o="",r=new Map;for(let p of e){let m=(p.namespace||"").split("/"),[h]=(m[1]??"").split("@");if(!m[0]||!h||(o||(o=m[0]),p.name!==h))continue;let k=(m[1]??"").split("@")[1]??"",d=k.split(".").map(Number);if(d.length!==3||d.some(y=>Number.isNaN(y)))continue;let f={verStr:k,major:d[0],minor:d[1],patch:d[2]},g=r.get(h);(!g||f.major>g.ver.major||f.major===g.ver.major&&f.minor>g.ver.minor||f.major===g.ver.major&&f.minor===g.ver.minor&&f.patch>g.ver.patch)&&r.set(h,{resource:p,ver:f})}if(!o||r.size===0)return;let a=t.findPublisherRootView(o);if(a){K(P(n,"index.html"),t.renderDocument(a,{rootIndex:!0}),"utf-8"),K(P(n,"index.css"),t.renderStylesheet(a),"utf-8");return}let s=[...r.entries()].sort((p,u)=>p[0].localeCompare(u[0])).map(([p,{resource:u}])=>({label:p,href:`/${p}`,comment:void 0})),i=[...r.values()][0]?.resource,c=t.renderPublisherIndex(o,s,i),l=t.renderPublisherIndexStylesheet(i);K(P(n,"index.html"),c,"utf-8"),K(P(n,"index.css"),l,"utf-8")}function wa(n,e){let t=new Map;for(let r of e){let a=r.namespace||"",[,s]=a.split("/");if(!s)continue;let[i,c]=s.split("@");if(!i||!c)continue;let l=c.split(".").map(Number);if(l.length!==3||l.some(u=>Number.isNaN(u)))continue;let p=`${i}/${r.name}`;t.has(p)||t.set(p,[]),t.get(p).push({verStr:c,major:l[0],minor:l[1],patch:l[2]})}let o=0;for(let[r,a]of t){let[s,i]=r.split("/");a.sort((u,m)=>m.major-u.major||m.minor-u.minor||m.patch-u.patch);let c=a[0];K(P(n,s,`${i}.html`),Fe(`/${s}/${c.verStr}/${i}`),"utf-8"),o+=1;let l=new Set;for(let u of a){if(l.has(u.major))continue;l.add(u.major);let m=P(n,s,String(u.major));ae(m,{recursive:!0}),K(P(m,`${i}.html`),Fe(`/${s}/${u.verStr}/${i}`),"utf-8"),o+=1}let p=new Set;for(let u of a){let m=`${u.major}.${u.minor}`;if(p.has(m))continue;p.add(m);let h=P(n,s,m);ae(h,{recursive:!0}),K(P(h,`${i}.html`),Fe(`/${s}/${u.verStr}/${i}`),"utf-8"),o+=1}}return o}function Fe(n){let e=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");return`<!doctype html>
112
112
  <meta charset="utf-8">
113
113
  <title>Redirecting\u2026</title>
114
114
  <meta http-equiv="refresh" content="0; url=${e}">
115
115
  <link rel="canonical" href="${e}">
116
116
  <p>If you are not redirected automatically, follow this <a href="${e}">link</a>.</p>
117
- `}import{Command as Zn}from"commander";import{writeFileSync as Me,mkdirSync as me}from"fs";import{join as He,resolve as _s,dirname as Be}from"path";import{KanonakParser as Cs,KanonakObjectParser as Rs,SubjectKanonak as Qn,ReferenceStatement as Ks,ReferenceKanonak as Ds,ListStatement as Is,StringStatement as et,EmbeddedStatement as xs,findDerivation as Gn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ts}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as As}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as de}from"@kanonak-protocol/sdk/uri-helpers";var j="kanonak.org",N="site",Jn={publisher:"kanonak.org",package_:"formats",name:"html"},Yn={publisher:"kanonak.org",package_:"derivation",name:"default"};function nt(){let n=new Zn("site").description("Materialize a publisher's site \u2014 every StaticPage and AggregateView in the workspace gets rendered to its declared output path under the --out directory.");return n.addCommand(Es()),n}function Es(){return new Zn("build").description("Walk the workspace, find every StaticPage and AggregateView, and write each materialized artifact to its declared output path under the --out directory.").option("--out <dir>","Output base directory.","./_site").action(async n=>{try{await js(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function js(n){let e=new Cs,t=new Rs,o=await S(process.cwd(),e),r=await t.parseKanonaks(o),a=_s(n.out);me(a,{recursive:!0});let s=await o.getAllDocumentsAsync(),i=new Set;for(let d of s){let f=d.metadata.namespace_?.toString();f&&i.add(f)}let c={publisher:j,package_:N,name:"StaticPage"},l={publisher:j,package_:N,name:"ResourcePage"},p={publisher:j,package_:N,name:"AggregateView"},u=de(r,c).filter(d=>i.has(d.namespace||"")),m=de(r,l).filter(d=>i.has(d.namespace||"")),h=de(r,p).filter(d=>i.has(d.namespace||""));console.log(`Found ${u.length} StaticPage(s), ${m.length} ResourcePage(s), and ${h.length} AggregateView(s) in the workspace.`);let k=new As;for(let d of u){let f=ze(d,j,N,"outputPath")??`${d.name}.html`,g=Gn(d,Jn,Yn,r);if(!g){console.warn(` [skip] ${d.name}: no HTML/default derivation found (check class hierarchy or universal-derivations is loaded)`);continue}let y=We(r,g.transformation);if(!y){console.warn(` [skip] ${d.name}: transformation ${qe(g.transformation)} not found`);continue}let b=await k.run({transformation:y,instances:[d],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(b.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let w=He(a,f);me(Be(w),{recursive:!0}),Me(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${d.name})`)}for(let d of m){let f=ze(d,j,N,"outputPath")??`${d.name}.html`,g=Xn(d,j,N,"pageOf");if(!g){console.warn(` [skip] ${d.name}: no pageOf declared`);continue}let y=r.find(I=>I instanceof Qn&&I.name===g.name&&(I.namespace||"").startsWith(`${g.publisher}/${g.package_}@`));if(!y){console.warn(` [skip] ${d.name}: pageOf target ${g.publisher}/${g.package_}/${g.name} not found`);continue}let b=Gn(y,Jn,Yn,r);if(!b){console.warn(` [skip] ${d.name}: no derivation for target ${y.name}`);continue}let w=We(r,b.transformation);if(!w){console.warn(` [skip] ${d.name}: transformation ${qe(b.transformation)} not found`);continue}let v=await k.run({transformation:w,instances:[y],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(v.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let $=He(a,f);me(Be($),{recursive:!0}),Me($,v[0].content,"utf-8"),console.log(` wrote ${$} (ResourcePage ${d.name} \u2192 ${y.name})`)}for(let d of h){let f=ze(d,j,N,"outputPath");if(!f){console.warn(` [skip] ${d.name}: no outputPath declared`);continue}let g=Xn(d,j,N,"scopeClass");if(!g){console.warn(` [skip] ${d.name}: no scopeClass declared`);continue}let y={publisher:g.publisher,package_:g.package_,name:g.name},b=Ns(d,j,N,"scopeSources"),w=Os(d);if(!w){console.warn(` [skip] ${d.name}: no transformation declared`);continue}let v=We(r,w);if(!v){console.warn(` [skip] ${d.name}: transformation ${qe(w)} not found`);continue}let $=await Us(b,o),I=[],ie=new Set;for(let ce of $){let T=await Fs(ce,o,e,t),L=de(T,y);for(let A of L){let U=`${A.namespace}/${A.name}`;ie.has(U)||(ie.add(U),I.push(A))}}console.log(` ${d.name}: ${I.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${$.length} scope(s)`);let O=await k.run({transformation:v,instances:I,allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(O.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let q=He(a,f);me(Be(q),{recursive:!0}),Me(q,O[0].content,"utf-8"),console.log(` wrote ${q} (AggregateView ${d.name})`)}console.log("Site build complete.")}function ze(n,e,t,o){for(let r of n.statement)if(r instanceof et&&fe(r,e,t,o))return r.object}function Ns(n,e,t,o){for(let r of n.statement){if(!(r instanceof Is)||!fe(r,e,t,o))continue;let a=[];for(let s of r.object??[]){let i=s.value;typeof i=="string"&&a.push(i)}return a}return[]}function Xn(n,e,t,o){for(let r of n.statement)if(r instanceof Ks&&fe(r,e,t,o)&&r.object instanceof Ds)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Os(n){for(let e of n.statement)if(e instanceof xs&&fe(e,j,N,"transformation"))return Ls(e.object)}function Ls(n){let e,t,o,r;for(let a of n.statement){if(!(a instanceof et))continue;let s=a.predicate?.subject?.name;s==="publisher"?e=a.object:s==="package"?t=a.object:s==="version"?o=a.object:s==="name"&&(r=a.object)}if(!(!e||!t||!o||!r))return{publisher:e,package_:t,version:o,name:r}}function fe(n,e,t,o){let r=n.predicate?.subject;return r?r.publisher===e&&r.package_===t&&r.name===o:!1}function We(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Qn&&o.name===e.name&&o.namespace===t)return o}function qe(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function Us(n,e){let t=[];for(let o of n){let r=o.indexOf("@*");if(r===-1){t.push(o);continue}let a=o.substring(0,r),s=a.indexOf("/");if(s===-1){t.push(o);continue}let i=a.substring(0,s),c=a.substring(s+1),l=await e.getDocumentsByNamespaceAsync(i,c);for(let p of l){let u=p.metadata.namespace_;if(!u)continue;let m=u.version;t.push(`${u.publisher}/${u.package_}@${m.major}.${m.minor}.${m.patch}`)}}return t}async function Fs(n,e,t,o){let r=n.indexOf("/"),a=n.indexOf("@");if(r===-1||a===-1)return[];let s=n.substring(0,r),i=n.substring(r+1,a),c=n.substring(a+1),l=await e.getDocumentsByNamespaceAsync(s,i);for(let p of l){let u=p.metadata.namespace_?.version;if(u&&`${u.major}.${u.minor}.${u.patch}`===c){let m=new Ts(p,e);return o.parseKanonaks(m)}}return[]}import{Command as Vs}from"commander";import{KanonakParser as Ms,PublisherIndex as tt,CredentialStore as ot,createAuthenticatedFetch as rt,FileSystemKanonakDocumentRepository as Hs,Reasoner as Bs,KanonakVocabulary as zs,getGlobalCachePath as Ws,makeUriKey as qs}from"@kanonak-protocol/sdk";function Gs(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 st(){return new Vs("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 Ys(n,e.type):await Js(n)})}async function Js(n){let e=new ot,t=rt(e),o=new tt({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}:
118
- `);let a=r.reduce((s,i)=>Math.max(s,i.packageName.length),0);for(let{packageName:s,version:i}of r)console.log(` ${s.padEnd(a)} @${i}`)}async function Ys(n,e){let t=Gs(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 Ms,r=new ot,a=rt(r),s=new tt({fetchFn:a}),i=new x,c=new Set,l=[];try{l=await s.listLatestPackages(n)}catch(f){console.error(`Failed to fetch publisher index for ${n}: ${f.message}`),process.exit(1)}for(let{packageName:f,version:g}of l)c.add(`${n}|${f}|${g}`);await Ge(s,i,a,"kanonak.org","core-rdf",c),await Ge(s,i,a,"kanonak.org","core-owl",c),await Ge(s,i,a,t.publisher,t.package_,c);for(let f of c){let[g,y,b]=f.split("|");if(!i.has(g,y,b))try{let w=await s.getPackageUrl(g,y,b),v=await a(w,g);if(!v.ok){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${v.status} ${v.statusText}`);continue}let $=await v.text();i.put(g,y,b,$)}catch(w){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${w.message}`)}}let p=new Hs(Ws(),!0,o),m=await new Bs({vocabulary:new zs}).reason(p),h=qs(t.publisher,t.package_,t.name),d=m.getInstancesOfClass(h).filter(f=>f!==h);if(d.length===0){console.log(`No instances of ${h} found in ${n}'s catalogue.`);return}console.log(`Instances of ${h} in ${n}'s catalogue:
119
- `),d.sort();for(let f of d)console.log(` ${f}`)}async function Ge(n,e,t,o,r,a){try{let s=await n.getHighestVersion(o,r);if(!s)return;a.add(`${o}|${r}|${s}`)}catch{}}import{existsSync as Xs,readFileSync as Zs}from"fs";import{dirname as Qs,resolve as ea}from"path";import{KanonakObjectParser as na,KanonakParser as ta,canonicalForm as oa,canonicalHash as ra,parseKanonakAddress as sa,pickHighestDocument as aa}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as ia}from"@kanonak-protocol/sdk/uri-helpers";async function at(n,e={}){let t=new ta,o=new na,{document:r,source:a}=await ca(n,t),s=await S(la(a),t),i=new ia(r,s),c=await o.parseKanonaks(i),l=ra(c);if(console.log(l),e.verbose){let p=oa(c);process.stderr.write(`# canonical form for ${a}
117
+ `}import{Command as Xn}from"commander";import{writeFileSync as Me,mkdirSync as me}from"fs";import{join as Ve,resolve as $a,dirname as He}from"path";import{KanonakParser as va,KanonakObjectParser as Sa,SubjectKanonak as Zn,ReferenceStatement as Pa,ReferenceKanonak as Ca,ListStatement as _a,StringStatement as Qn,EmbeddedStatement as Ra,findDerivation as qn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ia}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Ka}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as de}from"@kanonak-protocol/sdk/uri-helpers";var j="kanonak.org",N="site",Gn={publisher:"kanonak.org",package_:"formats",name:"html"},Jn={publisher:"kanonak.org",package_:"derivation",name:"default"};function et(){let n=new Xn("site").description("Materialize a publisher's site \u2014 every StaticPage and AggregateView in the workspace gets rendered to its declared output path under the --out directory.");return n.addCommand(xa()),n}function xa(){return new Xn("build").description("Walk the workspace, find every StaticPage and AggregateView, and write each materialized artifact to its declared output path under the --out directory.").option("--out <dir>","Output base directory.","./_site").action(async n=>{try{await Ta(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ta(n){let e=new va,t=new Sa,o=await S(process.cwd(),e),r=await t.parseKanonaks(o),a=$a(n.out);me(a,{recursive:!0});let s=await o.getAllDocumentsAsync(),i=new Set;for(let d of s){let f=d.metadata.namespace_?.toString();f&&i.add(f)}let c={publisher:j,package_:N,name:"StaticPage"},l={publisher:j,package_:N,name:"ResourcePage"},p={publisher:j,package_:N,name:"AggregateView"},u=de(r,c).filter(d=>i.has(d.namespace||"")),m=de(r,l).filter(d=>i.has(d.namespace||"")),h=de(r,p).filter(d=>i.has(d.namespace||""));console.log(`Found ${u.length} StaticPage(s), ${m.length} ResourcePage(s), and ${h.length} AggregateView(s) in the workspace.`);let k=new Ka;for(let d of u){let f=Be(d,j,N,"outputPath")??`${d.name}.html`,g=qn(d,Gn,Jn,r);if(!g){console.warn(` [skip] ${d.name}: no HTML/default derivation found (check class hierarchy or universal-derivations is loaded)`);continue}let y=ze(r,g.transformation);if(!y){console.warn(` [skip] ${d.name}: transformation ${We(g.transformation)} not found`);continue}let b=await k.run({transformation:y,instances:[d],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(b.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let w=Ve(a,f);me(He(w),{recursive:!0}),Me(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${d.name})`)}for(let d of m){let f=Be(d,j,N,"outputPath")??`${d.name}.html`,g=Yn(d,j,N,"pageOf");if(!g){console.warn(` [skip] ${d.name}: no pageOf declared`);continue}let y=r.find(x=>x instanceof Zn&&x.name===g.name&&(x.namespace||"").startsWith(`${g.publisher}/${g.package_}@`));if(!y){console.warn(` [skip] ${d.name}: pageOf target ${g.publisher}/${g.package_}/${g.name} not found`);continue}let b=qn(y,Gn,Jn,r);if(!b){console.warn(` [skip] ${d.name}: no derivation for target ${y.name}`);continue}let w=ze(r,b.transformation);if(!w){console.warn(` [skip] ${d.name}: transformation ${We(b.transformation)} not found`);continue}let $=await k.run({transformation:w,instances:[y],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if($.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let v=Ve(a,f);me(He(v),{recursive:!0}),Me(v,$[0].content,"utf-8"),console.log(` wrote ${v} (ResourcePage ${d.name} \u2192 ${y.name})`)}for(let d of h){let f=Be(d,j,N,"outputPath");if(!f){console.warn(` [skip] ${d.name}: no outputPath declared`);continue}let g=Yn(d,j,N,"scopeClass");if(!g){console.warn(` [skip] ${d.name}: no scopeClass declared`);continue}let y={publisher:g.publisher,package_:g.package_,name:g.name},b=Da(d,j,N,"scopeSources"),w=Ea(d);if(!w){console.warn(` [skip] ${d.name}: no transformation declared`);continue}let $=ze(r,w);if(!$){console.warn(` [skip] ${d.name}: transformation ${We(w)} not found`);continue}let v=await ja(b,o),x=[],ie=new Set;for(let ce of v){let D=await Na(ce,o,e,t),L=de(D,y);for(let E of L){let U=`${E.namespace}/${E.name}`;ie.has(U)||(ie.add(U),x.push(E))}}console.log(` ${d.name}: ${x.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${v.length} scope(s)`);let O=await k.run({transformation:$,instances:x,allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(O.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let q=Ve(a,f);me(He(q),{recursive:!0}),Me(q,O[0].content,"utf-8"),console.log(` wrote ${q} (AggregateView ${d.name})`)}console.log("Site build complete.")}function Be(n,e,t,o){for(let r of n.statement)if(r instanceof Qn&&fe(r,e,t,o))return r.object}function Da(n,e,t,o){for(let r of n.statement){if(!(r instanceof _a)||!fe(r,e,t,o))continue;let a=[];for(let s of r.object??[]){let i=s.value;typeof i=="string"&&a.push(i)}return a}return[]}function Yn(n,e,t,o){for(let r of n.statement)if(r instanceof Pa&&fe(r,e,t,o)&&r.object instanceof Ca)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Ea(n){for(let e of n.statement)if(e instanceof Ra&&fe(e,j,N,"transformation"))return Aa(e.object)}function Aa(n){let e,t,o,r;for(let a of n.statement){if(!(a instanceof Qn))continue;let s=a.predicate?.subject?.name;s==="publisher"?e=a.object:s==="package"?t=a.object:s==="version"?o=a.object:s==="name"&&(r=a.object)}if(!(!e||!t||!o||!r))return{publisher:e,package_:t,version:o,name:r}}function fe(n,e,t,o){let r=n.predicate?.subject;return r?r.publisher===e&&r.package_===t&&r.name===o:!1}function ze(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Zn&&o.name===e.name&&o.namespace===t)return o}function We(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function ja(n,e){let t=[];for(let o of n){let r=o.indexOf("@*");if(r===-1){t.push(o);continue}let a=o.substring(0,r),s=a.indexOf("/");if(s===-1){t.push(o);continue}let i=a.substring(0,s),c=a.substring(s+1),l=await e.getDocumentsByNamespaceAsync(i,c);for(let p of l){let u=p.metadata.namespace_;if(!u)continue;let m=u.version;t.push(`${u.publisher}/${u.package_}@${m.major}.${m.minor}.${m.patch}`)}}return t}async function Na(n,e,t,o){let r=n.indexOf("/"),a=n.indexOf("@");if(r===-1||a===-1)return[];let s=n.substring(0,r),i=n.substring(r+1,a),c=n.substring(a+1),l=await e.getDocumentsByNamespaceAsync(s,i);for(let p of l){let u=p.metadata.namespace_?.version;if(u&&`${u.major}.${u.minor}.${u.patch}`===c){let m=new Ia(p,e);return o.parseKanonaks(m)}}return[]}import{Command as Oa}from"commander";import{createServer as La}from"http";import{watch as Ua}from"fs";import{resolve as Fa}from"path";import{loadServerModel as Ma,route as Va}from"@kanonak-protocol/sdk/server";function nt(){return new Oa("serve").description("Serve a publisher's workspace as a live origin \u2014 the same rendering `kanonak publish` produces, plus the machine-facing publisher endpoints, from one process. Use --watch for a dev preview.").option("--root <dir>","Workspace root to serve.",".").option("--port <number>","Port to listen on.","8080").option("--publisher <domain>","Publisher to serve (required only if the workspace has more than one).").option("--watch","Re-load the workspace on .kan.yml changes.",!1).action(async n=>{let e=Fa(n.root),t=Number(n.port);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error(`Invalid --port "${n.port}".`);let o,r=async a=>{let s=Date.now(),i=await Ma(e,n.publisher?{publisher:n.publisher}:{});o=i;let c=i.availablePublishers.filter(l=>l!==i.publisher);console.log(`[model] serving ${i.publisher} \u2014 ${i.pkgVersions.size} package(s)${a?` (${a})`:""} in ${Date.now()-s}ms`+(c.length?` [also in workspace: ${c.join(", ")} \u2014 switch with --publisher]`:""))};try{await r()}catch(a){console.error(`[error] ${a.message}`),process.exitCode=1;return}if(n.watch){let a;Ua(e,{recursive:!0},(s,i)=>{!i||!String(i).endsWith(".kan.yml")||(clearTimeout(a),a=setTimeout(()=>{r(`changed: ${i}`).catch(c=>console.error("[reload error]",c.message))},150))}),console.log("[watch] re-loading on .kan.yml changes")}La((a,s)=>{let i="/";try{let c=new URL(a.url??"/","http://localhost");i=decodeURIComponent(c.pathname);let l=Va(o,i,a.headers.accept??"");s.writeHead(l.status,l.headers),s.end(l.body),console.log(`${l.status} ${a.method} ${i}${l.headers.Location?` -> ${l.headers.Location}`:""}`)}catch(c){s.writeHead(500,{"Content-Type":"text/plain; charset=utf-8"}),s.end(String(c?.stack??c)),console.error(`500 ${i}: ${c?.message??c}`)}}).listen(t,()=>{console.log(`kanonak origin server \u2192 http://localhost:${t}/ (root=${e})`)})})}import{Command as Ha}from"commander";import{KanonakParser as Ba,PublisherIndex as tt,CredentialStore as ot,createAuthenticatedFetch as rt,FileSystemKanonakDocumentRepository as za,Reasoner as Wa,KanonakVocabulary as qa,getGlobalCachePath as Ga,makeUriKey as Ja}from"@kanonak-protocol/sdk";function Ya(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 at(){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 Za(n,e.type):await Xa(n)})}async function Xa(n){let e=new ot,t=rt(e),o=new tt({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}:
118
+ `);let a=r.reduce((s,i)=>Math.max(s,i.packageName.length),0);for(let{packageName:s,version:i}of r)console.log(` ${s.padEnd(a)} @${i}`)}async function Za(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 o=new Ba,r=new ot,a=rt(r),s=new tt({fetchFn:a}),i=new T,c=new Set,l=[];try{l=await s.listLatestPackages(n)}catch(f){console.error(`Failed to fetch publisher index for ${n}: ${f.message}`),process.exit(1)}for(let{packageName:f,version:g}of l)c.add(`${n}|${f}|${g}`);await qe(s,i,a,"kanonak.org","core-rdf",c),await qe(s,i,a,"kanonak.org","core-owl",c),await qe(s,i,a,t.publisher,t.package_,c);for(let f of c){let[g,y,b]=f.split("|");if(!i.has(g,y,b))try{let w=await s.getPackageUrl(g,y,b),$=await a(w,g);if(!$.ok){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${$.status} ${$.statusText}`);continue}let v=await $.text();i.put(g,y,b,v)}catch(w){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${w.message}`)}}let p=new za(Ga(),!0,o),m=await new Wa({vocabulary:new qa}).reason(p),h=Ja(t.publisher,t.package_,t.name),d=m.getInstancesOfClass(h).filter(f=>f!==h);if(d.length===0){console.log(`No instances of ${h} found in ${n}'s catalogue.`);return}console.log(`Instances of ${h} in ${n}'s catalogue:
119
+ `),d.sort();for(let f of d)console.log(` ${f}`)}async function qe(n,e,t,o,r,a){try{let s=await n.getHighestVersion(o,r);if(!s)return;a.add(`${o}|${r}|${s}`)}catch{}}import{existsSync as Qa,readFileSync as es}from"fs";import{dirname as ns,resolve as ts}from"path";import{KanonakObjectParser as os,KanonakParser as rs,canonicalForm as as,canonicalHash as ss,parseKanonakAddress as is,pickHighestDocument as cs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as ls}from"@kanonak-protocol/sdk/uri-helpers";async function st(n,e={}){let t=new rs,o=new os,{document:r,source:a}=await us(n,t),s=await S(ps(a),t),i=new ls(r,s),c=await o.parseKanonaks(i),l=ss(c);if(console.log(l),e.verbose){let p=as(c);process.stderr.write(`# canonical form for ${a}
120
120
  `),process.stderr.write(p),process.stderr.write(`
121
- `)}}async function ca(n,e){if(n.endsWith(".kan.yml")){let i=ea(n);if(!Xs(i))throw new Error(`kanonak hash: file not found: ${i}`);let c=Zs(i,"utf-8");return{document:e.parse(c),source:i}}let t=sa(n);if(t.kind!=="package")throw new Error(`kanonak hash: expected a package address (publisher/package[@version]) or a path ending in .kan.yml; got ${t.kind} address "${n}"`);let r=await(await S(process.cwd(),e)).getDocumentsByNamespaceAsync(t.publisher,t.package_);if(r.length===0)throw new Error(`kanonak hash: could not find ${n} in local workspace, global cache, or publisher HTTP`);let a=t.version?`${t.version.major}.${t.version.minor}.${t.version.patch}`:void 0,s=aa(r,a?{requestedVersion:a}:{});if(!s.chosen){let i=a?`@${a}`:"";throw new Error(`kanonak hash: no version of ${t.publisher}/${t.package_}${i} available across local/cache/HTTP`)}return{document:s.chosen,source:n}}function la(n){return n.endsWith(".kan.yml")?M(Qs(n)):process.cwd()}import{Command as it}from"commander";function Q(n){return`${_}/${C}/${n}`}var Je={[Q("fetch-and-deploy")]:(n,e,t,o)=>n.add(e,t[0],o),[Q("remove-deployed")]:(n,e,t,o)=>n.remove(e,t[0],o),[Q("list-deployed")]:(n,e,t,o)=>n.list(e,o),[Q("update-deployed")]:(n,e,t,o)=>n.update(e,t[0],o),[Q("search-available")]:(n,e,t,o)=>n.search(e,o),[Q("show-info")]:(n,e,t,o)=>n.info(e,t[0],o)};function ct(n,e,t){for(let o of e){let r=new it(o.commandName).description(o.description.trim());for(let a of o.commands){let s=r.command(ua(a));s.description(a.description);for(let i of a.arguments)if(i.isOption){let c=i.defaultValue!=null?`--${i.argumentName} [value]`:`--${i.argumentName} <value>`;s.option(c,"",i.defaultValue)}s.action(async(...i)=>{let c=pa(i);await ma(t,o,a,i,c)})}n.addCommand(r)}}function ua(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function pa(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof it))return n[e];return{}}async function ma(n,e,t,o,r){let a=[];for(let i of o)if(typeof i=="string")a.push(i);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(Je).join(", ")}.`),process.exit(1));let s=Je[t.actionKey];s||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(Je).join(", ")}.`),process.exit(1)),await s(n,e,a,r)}import{existsSync as lt,readFileSync as da,statSync as ut}from"fs";import{resolve as fa}from"path";import{KanonakObjectParser as ga,PublisherIndex as Ye,PublisherConfigResolver as ha,formatVersion as pt,pickHighestDocument as ka}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as mt}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as ee,findSubjectsByType as dt}from"@kanonak-protocol/sdk/uri-helpers";var ge=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 ga;async add(e,t,o){let r=this.tryLoadFromLocalFile(t);if(r){this.fileCache.put(r.publisher,r.packageName,r.version,r.content),await this.deployFromDoc(e,r.doc,r.publisher,r.packageName,r.version,void 0,`local file ${t}`,o);return}let a=E(t);a||(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(" ./path/to/file.kan.yml (install all instances from a local document)"),console.error(""),console.error("Tip: copy a URI directly from `kanonak "+e.commandName+" search`."),process.exit(1));let{publisher:s,packageName:i,version:c,instanceName:l}=a,p=await this.repository.getDocumentsByNamespaceAsync(s,i);if(p.length>0){let h=ka(p,{requestedVersion:c??void 0});if(h.chosen){let k=h.chosen.metadata.namespace_;(!k||!k.version)&&(console.error(`Document for ${s}/${i} is missing namespace metadata.`),process.exit(1));let d=pt(k.version);this.fileCache.put(s,i,d,this.parser.save(h.chosen)),await this.deployFromDoc(e,h.chosen,s,i,d,l??void 0,`${s}/${i}@${d}`,o);return}}let u=c??await this.publisherIndex.getHighestVersion(s,i);u||(console.error(`Could not resolve version for "${s}/${i}".`),await this.printPackageSuggestions(s,i,e.commandName),process.exit(1));let m=this.fileCache.get(s,i,u);if(!m){let h=await this.publisherIndex.getPackageUrl(s,i,u),k=await this.fetchFn(h,s);k.ok||(k.status===404?(console.error(`Package ${s}/${i}@${u} not found at ${h}.`),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 ${h} (${k.status} ${k.statusText}).`),process.exit(1)),m=await k.text(),this.fileCache.put(s,i,u,m)}await this.deployFromDoc(e,this.parser.parse(m),s,i,u,l??void 0,`${s}/${i}@${u}`,o)}tryLoadFromLocalFile(e){if(!(/^[.\/\\]/.test(e)||/^[A-Za-z]:[\\/]/.test(e)||e.endsWith(".kan.yml")||lt(e)&&ut(e).isFile()))return;let o=fa(e);(!lt(o)||!ut(o).isFile())&&(console.error(`Local file not found: ${e}`),process.exit(1));let r=da(o,"utf-8"),a=this.parser.parse(r),s=a.metadata.namespace_;return(!s||!s.version)&&(console.error(`${e} has no namespace metadata; cannot determine publisher/package/version. A Kanonak document must declare \`type: Package\` with publisher and version.`),process.exit(1)),{doc:a,content:r,publisher:s.publisher,packageName:s.package_,version:pt(s.version)}}async deployFromDoc(e,t,o,r,a,s,i,c){let l=new mt(t,this.repository),p=await this.objectParser.parseKanonaks(l),u=ft(e.managesTypeKey);u||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let m=dt(p,u);m.length===0&&(console.error(`${i} does not contain any ${ee(u)} instances.`),process.exit(1));let h=m;if(s&&(h=m.filter(f=>f.name===s),h.length===0)){console.error(`Instance "${s}" not found in ${i}.`),console.error(""),console.error(`Available ${ee(u)} instance(s):`);for(let f of m)console.error(` - ${f.name}`);console.error(""),console.error("To install all of them, drop the instance suffix:"),console.error(` kanonak ${e.commandName} add ${o}/${r}`),process.exit(1)}let k=s?`${s} from ${i}`:`${h.length} ${ee(u)} instance(s) from ${i}`;console.log(`Installing ${k}...`);let d=this.handlerRegistry.get(e.deploymentTargetKey);d?await d.deploy({instances:h,allKanonaks:p,repository:this.repository,options:c}):console.log(`Cached ${o}/${r}@${a} (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:ya(t,s.packageName)})).filter(s=>s.score>0).sort((s,i)=>i.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:
121
+ `)}}async function us(n,e){if(n.endsWith(".kan.yml")){let i=ts(n);if(!Qa(i))throw new Error(`kanonak hash: file not found: ${i}`);let c=es(i,"utf-8");return{document:e.parse(c),source:i}}let t=is(n);if(t.kind!=="package")throw new Error(`kanonak hash: expected a package address (publisher/package[@version]) or a path ending in .kan.yml; got ${t.kind} address "${n}"`);let r=await(await S(process.cwd(),e)).getDocumentsByNamespaceAsync(t.publisher,t.package_);if(r.length===0)throw new Error(`kanonak hash: could not find ${n} in local workspace, global cache, or publisher HTTP`);let a=t.version?`${t.version.major}.${t.version.minor}.${t.version.patch}`:void 0,s=cs(r,a?{requestedVersion:a}:{});if(!s.chosen){let i=a?`@${a}`:"";throw new Error(`kanonak hash: no version of ${t.publisher}/${t.package_}${i} available across local/cache/HTTP`)}return{document:s.chosen,source:n}}function ps(n){return n.endsWith(".kan.yml")?V(ns(n)):process.cwd()}import{Command as it}from"commander";function Z(n){return`${C}/${_}/${n}`}var Ge={[Z("fetch-and-deploy")]:(n,e,t,o)=>n.add(e,t[0],o),[Z("remove-deployed")]:(n,e,t,o)=>n.remove(e,t[0],o),[Z("list-deployed")]:(n,e,t,o)=>n.list(e,o),[Z("update-deployed")]:(n,e,t,o)=>n.update(e,t[0],o),[Z("search-available")]:(n,e,t,o)=>n.search(e,o),[Z("show-info")]:(n,e,t,o)=>n.info(e,t[0],o)};function ct(n,e,t){for(let o of e){let r=new it(o.commandName).description(o.description.trim());for(let a of o.commands){let s=r.command(ms(a));s.description(a.description);for(let i of a.arguments)if(i.isOption){let c=i.defaultValue!=null?`--${i.argumentName} [value]`:`--${i.argumentName} <value>`;s.option(c,"",i.defaultValue)}s.action(async(...i)=>{let c=ds(i);await fs(t,o,a,i,c)})}n.addCommand(r)}}function ms(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function ds(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof it))return n[e];return{}}async function fs(n,e,t,o,r){let a=[];for(let i of o)if(typeof i=="string")a.push(i);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(Ge).join(", ")}.`),process.exit(1));let s=Ge[t.actionKey];s||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(Ge).join(", ")}.`),process.exit(1)),await s(n,e,a,r)}import{existsSync as lt,readFileSync as gs,statSync as ut}from"fs";import{resolve as hs}from"path";import{KanonakObjectParser as ks,PublisherIndex as Je,PublisherConfigResolver as ys,formatVersion as pt,pickHighestDocument as bs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as mt}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as Q,findSubjectsByType as dt}from"@kanonak-protocol/sdk/uri-helpers";var ge=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 ks;async add(e,t,o){let r=this.tryLoadFromLocalFile(t);if(r){this.fileCache.put(r.publisher,r.packageName,r.version,r.content),await this.deployFromDoc(e,r.doc,r.publisher,r.packageName,r.version,void 0,`local file ${t}`,o);return}let a=A(t);a||(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(" ./path/to/file.kan.yml (install all instances from a local document)"),console.error(""),console.error("Tip: copy a URI directly from `kanonak "+e.commandName+" search`."),process.exit(1));let{publisher:s,packageName:i,version:c,instanceName:l}=a,p=await this.repository.getDocumentsByNamespaceAsync(s,i);if(p.length>0){let h=bs(p,{requestedVersion:c??void 0});if(h.chosen){let k=h.chosen.metadata.namespace_;(!k||!k.version)&&(console.error(`Document for ${s}/${i} is missing namespace metadata.`),process.exit(1));let d=pt(k.version);this.fileCache.put(s,i,d,this.parser.save(h.chosen)),await this.deployFromDoc(e,h.chosen,s,i,d,l??void 0,`${s}/${i}@${d}`,o);return}}let u=c??await this.publisherIndex.getHighestVersion(s,i);u||(console.error(`Could not resolve version for "${s}/${i}".`),await this.printPackageSuggestions(s,i,e.commandName),process.exit(1));let m=this.fileCache.get(s,i,u);if(!m){let h=await this.publisherIndex.getPackageUrl(s,i,u),k=await this.fetchFn(h,s);k.ok||(k.status===404?(console.error(`Package ${s}/${i}@${u} not found at ${h}.`),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 ${h} (${k.status} ${k.statusText}).`),process.exit(1)),m=await k.text(),this.fileCache.put(s,i,u,m)}await this.deployFromDoc(e,this.parser.parse(m),s,i,u,l??void 0,`${s}/${i}@${u}`,o)}tryLoadFromLocalFile(e){if(!(/^[.\/\\]/.test(e)||/^[A-Za-z]:[\\/]/.test(e)||e.endsWith(".kan.yml")||lt(e)&&ut(e).isFile()))return;let o=hs(e);(!lt(o)||!ut(o).isFile())&&(console.error(`Local file not found: ${e}`),process.exit(1));let r=gs(o,"utf-8"),a=this.parser.parse(r),s=a.metadata.namespace_;return(!s||!s.version)&&(console.error(`${e} has no namespace metadata; cannot determine publisher/package/version. A Kanonak document must declare \`type: Package\` with publisher and version.`),process.exit(1)),{doc:a,content:r,publisher:s.publisher,packageName:s.package_,version:pt(s.version)}}async deployFromDoc(e,t,o,r,a,s,i,c){let l=new mt(t,this.repository),p=await this.objectParser.parseKanonaks(l),u=ft(e.managesTypeKey);u||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let m=dt(p,u);m.length===0&&(console.error(`${i} does not contain any ${Q(u)} instances.`),process.exit(1));let h=m;if(s&&(h=m.filter(f=>f.name===s),h.length===0)){console.error(`Instance "${s}" not found in ${i}.`),console.error(""),console.error(`Available ${Q(u)} instance(s):`);for(let f of m)console.error(` - ${f.name}`);console.error(""),console.error("To install all of them, drop the instance suffix:"),console.error(` kanonak ${e.commandName} add ${o}/${r}`),process.exit(1)}let k=s?`${s} from ${i}`:`${h.length} ${Q(u)} instance(s) from ${i}`;console.log(`Installing ${k}...`);let d=this.handlerRegistry.get(e.deploymentTargetKey);d?await d.deploy({instances:h,allKanonaks:p,repository:this.repository,options:c}):console.log(`Cached ${o}/${r}@${a} (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:ws(t,s.packageName)})).filter(s=>s.score>0).sort((s,i)=>i.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:
122
122
  `);for(let s of r){let i=s.publisher?`${s.publisher}/${s.package_}@${s.version}`:"unmanaged";console.log(` ${s.name} (${i}) ${s.path}`)}}async update(e,t,o){let a=await this.requireHandler(e).list({repository:this.repository,options:o}),s=t?a.filter(c=>c.name===t):a.filter(c=>c.publisher);if(s.length===0){console.log(t?`"${t}" not found.`:"No managed instances to update.");return}let i=0;for(let c of s){let l=await this.publisherIndex.getHighestVersion(c.publisher,c.package_);!l||l===c.version||(console.log(`Updating ${c.name}: ${c.version} \u2192 ${l}`),await this.add(e,`${c.publisher}/${c.package_}@${l}`,o),i++)}console.log(i===0?"All instances are up to date.":`
123
- Updated ${i} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=ft(e.managesTypeKey);if(!r){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${o} for ${ee(r)} instances...
124
- `);let a=new ha,s=await a.getConfig(o),i=a.resolveIndexUrl(o,s),c=await this.fetchFn(i,o);if(!c.ok){console.error(`Failed to fetch package index from ${o}.`);return}let l=await c.text(),p=Ye.parseIndex(l);if(p.size===0){console.error(`No packages found for publisher "${o}".`);return}let u=new Map;for(let[d,f]of p){let g=[...f].sort((y,b)=>{let w=Ye.parseVersion(y),v=Ye.parseVersion(b);return!w||!v?0:w.major!==v.major?v.major-w.major:w.minor!==v.minor?v.minor-w.minor:v.patch-w.patch});u.set(d,g[0])}let m=[],h=0;for(let[d,f]of u){let g=this.fileCache.get(o,d,f);if(!g)try{let y=await this.publisherIndex.getPackageUrl(o,d,f),b=await this.fetchFn(y,o);if(!b.ok)continue;g=await b.text(),this.fileCache.put(o,d,f,g)}catch{continue}try{let y=this.parser.parse(g),b=new mt(y,this.repository),w=await this.objectParser.parseKanonaks(b),v=dt(w,r);for(let $ of v)m.push({publisher:o,package_:d,version:f,subject:$});h++}catch{continue}}if(m.length===0){console.log(`No ${ee(r)} instances found across ${h} package(s).`);return}console.log(`Found ${m.length} ${ee(r)} instance(s) in ${h} package(s):
125
- `);let k=new Map;for(let d of m){let f=`${d.publisher}/${d.package_}@${d.version}`,g=k.get(f);g?g.push(d):k.set(f,[d])}for(let[d,f]of k){let g=f[0],y=`${g.publisher}/${g.package_}`,b=f.length===1;console.log(` ${d}`),console.log(` ${f.length} skill${b?"":"s"}:`);for(let w of f)console.log(` - ${w.subject.name}`);if(console.log(""),b)console.log(" install:"),console.log(` kanonak ${e.commandName} add ${y}/${g.subject.name}`);else{console.log(" install one of them:");for(let w of f)console.log(` kanonak ${e.commandName} add ${y}/${w.subject.name}`);console.log(" install all of them:"),console.log(` kanonak ${e.commandName} add ${y}`)}console.log("")}}async info(e,t,o){let s=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(i=>i.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 ft(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function ya(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 c of r)a.has(c)&&s++;if(s>0)return s*10;let i=ba(t,o);return i===0?100:i<=2?Math.max(1,20-i*5):0}function ba(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 he=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as xa,rmSync as Ta,existsSync as we,readdirSync as Aa,writeFileSync as Ea}from"fs";import{join as ve}from"path";import{KanonakObjectParser as ja,KanonakParser as Na,computeIntegrity as Oa,compareVersions as La}from"@kanonak-protocol/sdk";import{findSubjectsByType as Ua}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as Fa}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Va}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as Ma}from"@kanonak-protocol/sdk/transformations";import{join as Xe}from"path";import{homedir as gt}from"os";import{KanonakObjectParser as wa}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as va}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as kt,getStringValue as ke}from"@kanonak-protocol/sdk/uri-helpers";var H="kanonak.org",B="agent-skills",yt={publisher:H,package_:B,name:"Client"},bt={publisher:H,package_:B,name:"clientId"},$a={publisher:H,package_:B,name:"projectSkillDir"},Sa={publisher:H,package_:B,name:"userSkillDir"},Pa={publisher:H,package_:B,name:"skillFileName"},wt="agents";async function ae(n,e){let t=(n.client??vt()??wt).toLowerCase(),o=n.scope??"project",r=await St(t,e);if(!r){let i=await _a(e);throw new Error(`Unknown client "${t}". Known clients: ${i.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=ke(r,o==="user"?Sa:$a);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return Ca(s)}async function ye(n,e,t){let o=await ae(e,t);return Xe(o,n)}async function Ze(n,e){let t=(n.client??vt()??wt).toLowerCase(),o=await St(t,e);return o?ke(o,Pa)??"SKILL.md":"SKILL.md"}function vt(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var ht=new WeakMap;async function $t(n){let e=ht.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(H,B);if(t.length===0)throw new Error(`Could not find ${H}/${B} 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((c,l)=>{let p=c.metadata.namespace_?.version,u=l.metadata.namespace_?.version;return!p||!u?0:p.major!==u.major?u.major-p.major:p.minor!==u.minor?u.minor-p.minor:u.patch-p.patch})[0],a=new wa,s=new va(r,n),i=await a.parseKanonaks(s);return ht.set(n,i),i}async function St(n,e){let t=await $t(e),o=kt(t,yt);for(let r of o)if(ke(r,bt)===n)return r}async function _a(n){let e=await $t(n),t=kt(e,yt),o=[];for(let r of t){let a=ke(r,bt);a&&o.push(a)}return o}function Ca(n){return n.startsWith("~/")?Xe(gt(),n.slice(2)):n==="~"?gt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Xe(process.cwd(),n)}import{readFileSync as Ra,writeFileSync as Ka,existsSync as Da}from"fs";import{join as Pt}from"path";import _t from"js-yaml";var Ct="skills.lock",Ia=`# This file is generated by Kanonak CLI. Do not edit manually.
126
- `;function be(n){let e=Pt(n,Ct);if(!Da(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=Ra(e,"utf-8"),o=_t.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 Qe(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=Pt(n,Ct),r=_t.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ka(o,Ia+r,"utf-8")}var Rt="kanonak.org",Kt="skill-to-skill-md",$e=class{parser=new Na;objectParser=new ja;runner=new Va;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 Ha(r,this.objectParser);if(!s){console.error(`Cannot deploy: ${Rt}/${Kt}@3.0.0 is not installed in the workspace or cache.`);return}let i=await this.runner.run({transformation:s,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:"markdown-with-frontmatter"});if(i.length===0){console.error("No skills could be transformed from the package.");return}let c=await ae(a,r),l=await Ze(a,r),p=be(c),u=t[0].namespace,{publisher:m,package_:h,version:k}=Ba(u);for(let d of i){let f=await ye(d.fileName,a,r),g=we(ve(f,l));xa(f,{recursive:!0}),Ea(ve(f,l),d.content,"utf-8"),p.skills[d.fileName]={publisher:m,package_:h,version:k,resolved:m?`kanonak://${m}/${h}@${k}`:"",integrity:Oa(d.content)},console.log(` ${g?"Updated":"Installed"} skill "${d.fileName}" \u2192 ${f}`)}Qe(c,p)}async undeploy(e,t){let{repository:o,options:r}=t,a=await ye(e,r,o);we(a)||(console.error(`Skill "${e}" is not installed at ${a}`),process.exit(1)),Ta(a,{recursive:!0,force:!0});let s=await ae(r,o),i=be(s);delete i.skills[e],Qe(s,i),console.log(`Removed skill "${e}" from ${a}`)}async list(e){let{repository:t,options:o}=e,r=await ae(o,t),a=be(r),s=[];for(let[c,l]of Object.entries(a.skills))s.push({name:c,publisher:l.publisher,package_:l.package_,version:l.version,path:await ye(c,o,t)});let i=await Ze(o,t);if(we(r))try{let c=Aa(r,{withFileTypes:!0});for(let l of c){if(!l.isDirectory()||a.skills[l.name])continue;let p=ve(r,l.name,i);we(p)&&s.push({name:l.name,publisher:"",package_:"",version:"",path:ve(r,l.name)})}}catch{}return s}};async function Ha(n,e){let t=await n.getDocumentsByNamespaceAsync(Rt,Kt);if(t.length===0)return;let o=[...t].sort((r,a)=>{let s=r.metadata.namespace_?.version,i=a.metadata.namespace_?.version;return!s||!i?0:La(i,s)});for(let r of o){let a=new Fa(r,n),s=await e.parseKanonaks(a),i=Ua(s,Ma.InstanceTransformation);if(i[0])return i[0]}}function Ba(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 ai,rmSync as ii,existsSync as tn,readdirSync as ci,writeFileSync as li,statSync as ui}from"fs";import{join as _e}from"path";import{KanonakObjectParser as pi,KanonakParser as mi,computeIntegrity as di}from"@kanonak-protocol/sdk";import{findSubjectsByType as fi}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as gi}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as hi}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as ki}from"@kanonak-protocol/sdk/transformations";import{join as Dt}from"path";import{homedir as It}from"os";import{KanonakObjectParser as za}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Wa}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Tt,getStringValue as en,getReferenceUri as qa}from"@kanonak-protocol/sdk/uri-helpers";var z="kanonak.org",W="agent-skills",At={publisher:z,package_:W,name:"Client"},Et={publisher:z,package_:W,name:"clientId"},Ga={publisher:z,package_:W,name:"projectAgentDir"},Ja={publisher:z,package_:W,name:"userAgentDir"},Ya={publisher:z,package_:W,name:"agentFileFormat"},Xa="agents";function Za(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Se(n,e){let t=(n.client??Za()??Xa).toLowerCase(),o=n.scope??"project",r=await Qa(t,e);if(!r){let p=await ei(e);throw new Error(`Unknown client "${t}". Known clients: ${p.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=en(r,o==="user"?Ja:Ga);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let c=qa(r,Ya)?.name==="toml"?"toml":"markdown-frontmatter",l=c==="toml"?".toml":".md";return{agentsDir:ni(s),format:c,fileExtension:l}}var xt=new WeakMap;async function jt(n){let e=xt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(z,W);if(t.length===0)throw new Error(`Could not find ${z}/${W} in the repository. Install a capability that imports agent-skills to populate the cache.`);let r=[...t].sort((c,l)=>{let p=c.metadata.namespace_?.version,u=l.metadata.namespace_?.version;return!p||!u?0:p.major!==u.major?u.major-p.major:p.minor!==u.minor?u.minor-p.minor:u.patch-p.patch})[0],a=new za,s=new Wa(r,n),i=await a.parseKanonaks(s);return xt.set(n,i),i}async function Qa(n,e){let t=await jt(e),o=Tt(t,At);for(let r of o)if(en(r,Et)===n)return r}async function ei(n){let e=await jt(n),t=Tt(e,At),o=[];for(let r of t){let a=en(r,Et);a&&o.push(a)}return o}function ni(n){return n.startsWith("~/")?Dt(It(),n.slice(2)):n==="~"?It():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Dt(process.cwd(),n)}import{readFileSync as ti,writeFileSync as oi,existsSync as ri}from"fs";import{join as Nt}from"path";import Ot from"js-yaml";var Lt="agents.lock",si=`# This file is generated by Kanonak CLI. Do not edit manually.
127
- `;function Pe(n){let e=Nt(n,Lt);if(!ri(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=ti(e,"utf-8"),o=Ot.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 nn(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=Nt(n,Lt),r=Ot.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});oi(o,si+r,"utf-8")}var Ut="kanonak.org",Ft="agent-to-agent-file",Ce=class{parser=new mi;objectParser=new pi;runner=new hi;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:i,fileExtension:c}=await Se(a,r),l=await yi(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Ut}/${Ft}@3.0.0 is not installed in the workspace or cache.`);return}let p=i==="toml"?"toml":"markdown-with-frontmatter",u=await this.runner.run({transformation:l,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:p});if(u.length===0){console.error("No agents could be transformed from the package.");return}ai(s,{recursive:!0});let m=Pe(s),h=t[0].namespace,{publisher:k,package_:d,version:f}=wi(h);for(let g of u){let y=`${g.fileName}${c}`,b=_e(s,y),w=tn(b);li(b,g.content,"utf-8"),m.agents[g.fileName]={publisher:k,package_:d,version:f,resolved:k?`kanonak://${k}/${d}@${f}`:"",integrity:di(g.content),fileName:y},console.log(` ${w?"Updated":"Installed"} agent "${g.fileName}" \u2192 ${b}`)}nn(s,m)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:a}=await Se(r,o),s=Pe(a),i=s.agents[e];i||(console.error(`Agent "${e}" is not installed at ${a}`),process.exit(1));let c=_e(a,i.fileName);tn(c)&&ii(c,{force:!0}),delete s.agents[e],nn(a,s),console.log(`Removed agent "${e}" from ${c}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await Se(o,t),a=Pe(r),s=[];for(let[i,c]of Object.entries(a.agents))s.push({name:i,publisher:c.publisher,package_:c.package_,version:c.version,path:_e(r,c.fileName)});if(tn(r))try{let i=ci(r,{withFileTypes:!0});for(let c of i){if(!c.isFile()||c.name==="agents.lock")continue;let l=_e(r,c.name),p=bi(c.name);if(!a.agents[p]){try{if(!ui(l).isFile())continue}catch{continue}s.push({name:p,publisher:"",package_:"",version:"",path:l})}}}catch{}return s}};async function yi(n,e){let t=await n.getDocumentsByNamespaceAsync(Ut,Ft);if(t.length===0)return;let o=new gi(t[0],n),r=await e.parseKanonaks(o);return fi(r,ki.InstanceTransformation)[0]}function bi(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function wi(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 Ii=Pi(Si(import.meta.url)),xi=JSON.parse($i(_i(Ii,"..","package.json"),"utf-8")),D=new vi;D.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(xi.version);D.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await cn(n)});D.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await ln(n)});D.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await pn(n)});D.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await hn(n)});D.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await kn(n)});D.command("hash <target>").description("Print the canonical structural hash (sha256:\u2026) of a Kanonak package.").option("-v, --verbose","Also print the canonical form on stderr.").action(async(n,e)=>{await at(n,e)});D.addCommand(Tn());D.addCommand(Un());D.addCommand(zn());D.addCommand(qn());D.addCommand(nt());D.addCommand(st());async function Ti(){try{let n=new x,e=new Ci,t=new Ki,o=Di(t),r=new Ri({fetchFn:o}),a=await S(process.cwd(),e),s=new he;s.register("kanonak.org/capabilities/agent-skill-deployment",new $e),s.register("kanonak.org/agent-capabilities/agent-instance-deployment",new Ce);let i=await Dn(n,e,a),c=new ge(n,e,r,o,s,a);ct(D,i,c)}catch{}}await Ti();D.parse();
123
+ Updated ${i} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=ft(e.managesTypeKey);if(!r){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${o} for ${Q(r)} instances...
124
+ `);let a=new ys,s=await a.getConfig(o),i=a.resolveIndexUrl(o,s),c=await this.fetchFn(i,o);if(!c.ok){console.error(`Failed to fetch package index from ${o}.`);return}let l=await c.text(),p=Je.parseIndex(l);if(p.size===0){console.error(`No packages found for publisher "${o}".`);return}let u=new Map;for(let[d,f]of p){let g=[...f].sort((y,b)=>{let w=Je.parseVersion(y),$=Je.parseVersion(b);return!w||!$?0:w.major!==$.major?$.major-w.major:w.minor!==$.minor?$.minor-w.minor:$.patch-w.patch});u.set(d,g[0])}let m=[],h=0;for(let[d,f]of u){let g=this.fileCache.get(o,d,f);if(!g)try{let y=await this.publisherIndex.getPackageUrl(o,d,f),b=await this.fetchFn(y,o);if(!b.ok)continue;g=await b.text(),this.fileCache.put(o,d,f,g)}catch{continue}try{let y=this.parser.parse(g),b=new mt(y,this.repository),w=await this.objectParser.parseKanonaks(b),$=dt(w,r);for(let v of $)m.push({publisher:o,package_:d,version:f,subject:v});h++}catch{continue}}if(m.length===0){console.log(`No ${Q(r)} instances found across ${h} package(s).`);return}console.log(`Found ${m.length} ${Q(r)} instance(s) in ${h} package(s):
125
+ `);let k=new Map;for(let d of m){let f=`${d.publisher}/${d.package_}@${d.version}`,g=k.get(f);g?g.push(d):k.set(f,[d])}for(let[d,f]of k){let g=f[0],y=`${g.publisher}/${g.package_}`,b=f.length===1;console.log(` ${d}`),console.log(` ${f.length} skill${b?"":"s"}:`);for(let w of f)console.log(` - ${w.subject.name}`);if(console.log(""),b)console.log(" install:"),console.log(` kanonak ${e.commandName} add ${y}/${g.subject.name}`);else{console.log(" install one of them:");for(let w of f)console.log(` kanonak ${e.commandName} add ${y}/${w.subject.name}`);console.log(" install all of them:"),console.log(` kanonak ${e.commandName} add ${y}`)}console.log("")}}async info(e,t,o){let s=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(i=>i.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 ft(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function ws(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 c of r)a.has(c)&&s++;if(s>0)return s*10;let i=$s(t,o);return i===0?100:i<=2?Math.max(1,20-i*5):0}function $s(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 he=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as Es,rmSync as As,existsSync as we,readdirSync as js,writeFileSync as Ns}from"fs";import{join as $e}from"path";import{KanonakObjectParser as Os,KanonakParser as Ls,computeIntegrity as Us,compareVersions as Fs}from"@kanonak-protocol/sdk";import{findSubjectsByType as Ms}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as Vs}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Hs}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as Bs}from"@kanonak-protocol/sdk/transformations";import{join as Ye}from"path";import{homedir as gt}from"os";import{KanonakObjectParser as vs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ss}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as kt,getStringValue as ke}from"@kanonak-protocol/sdk/uri-helpers";var H="kanonak.org",B="agent-skills",yt={publisher:H,package_:B,name:"Client"},bt={publisher:H,package_:B,name:"clientId"},Ps={publisher:H,package_:B,name:"projectSkillDir"},Cs={publisher:H,package_:B,name:"userSkillDir"},_s={publisher:H,package_:B,name:"skillFileName"},wt="agents";async function se(n,e){let t=(n.client??$t()??wt).toLowerCase(),o=n.scope??"project",r=await St(t,e);if(!r){let i=await Rs(e);throw new Error(`Unknown client "${t}". Known clients: ${i.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=ke(r,o==="user"?Cs:Ps);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return Is(s)}async function ye(n,e,t){let o=await se(e,t);return Ye(o,n)}async function Xe(n,e){let t=(n.client??$t()??wt).toLowerCase(),o=await St(t,e);return o?ke(o,_s)??"SKILL.md":"SKILL.md"}function $t(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var ht=new WeakMap;async function vt(n){let e=ht.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(H,B);if(t.length===0)throw new Error(`Could not find ${H}/${B} 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((c,l)=>{let p=c.metadata.namespace_?.version,u=l.metadata.namespace_?.version;return!p||!u?0:p.major!==u.major?u.major-p.major:p.minor!==u.minor?u.minor-p.minor:u.patch-p.patch})[0],a=new vs,s=new Ss(r,n),i=await a.parseKanonaks(s);return ht.set(n,i),i}async function St(n,e){let t=await vt(e),o=kt(t,yt);for(let r of o)if(ke(r,bt)===n)return r}async function Rs(n){let e=await vt(n),t=kt(e,yt),o=[];for(let r of t){let a=ke(r,bt);a&&o.push(a)}return o}function Is(n){return n.startsWith("~/")?Ye(gt(),n.slice(2)):n==="~"?gt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Ye(process.cwd(),n)}import{readFileSync as Ks,writeFileSync as xs,existsSync as Ts}from"fs";import{join as Pt}from"path";import Ct from"js-yaml";var _t="skills.lock",Ds=`# This file is generated by Kanonak CLI. Do not edit manually.
126
+ `;function be(n){let e=Pt(n,_t);if(!Ts(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=Ks(e,"utf-8"),o=Ct.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 Ze(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=Pt(n,_t),r=Ct.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});xs(o,Ds+r,"utf-8")}var Rt="kanonak.org",It="skill-to-skill-md",ve=class{parser=new Ls;objectParser=new Os;runner=new Hs;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 zs(r,this.objectParser);if(!s){console.error(`Cannot deploy: ${Rt}/${It}@3.0.0 is not installed in the workspace or cache.`);return}let i=await this.runner.run({transformation:s,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:"markdown-with-frontmatter"});if(i.length===0){console.error("No skills could be transformed from the package.");return}let c=await se(a,r),l=await Xe(a,r),p=be(c),u=t[0].namespace,{publisher:m,package_:h,version:k}=Ws(u);for(let d of i){let f=await ye(d.fileName,a,r),g=we($e(f,l));Es(f,{recursive:!0}),Ns($e(f,l),d.content,"utf-8"),p.skills[d.fileName]={publisher:m,package_:h,version:k,resolved:m?`kanonak://${m}/${h}@${k}`:"",integrity:Us(d.content)},console.log(` ${g?"Updated":"Installed"} skill "${d.fileName}" \u2192 ${f}`)}Ze(c,p)}async undeploy(e,t){let{repository:o,options:r}=t,a=await ye(e,r,o);we(a)||(console.error(`Skill "${e}" is not installed at ${a}`),process.exit(1)),As(a,{recursive:!0,force:!0});let s=await se(r,o),i=be(s);delete i.skills[e],Ze(s,i),console.log(`Removed skill "${e}" from ${a}`)}async list(e){let{repository:t,options:o}=e,r=await se(o,t),a=be(r),s=[];for(let[c,l]of Object.entries(a.skills))s.push({name:c,publisher:l.publisher,package_:l.package_,version:l.version,path:await ye(c,o,t)});let i=await Xe(o,t);if(we(r))try{let c=js(r,{withFileTypes:!0});for(let l of c){if(!l.isDirectory()||a.skills[l.name])continue;let p=$e(r,l.name,i);we(p)&&s.push({name:l.name,publisher:"",package_:"",version:"",path:$e(r,l.name)})}}catch{}return s}};async function zs(n,e){let t=await n.getDocumentsByNamespaceAsync(Rt,It);if(t.length===0)return;let o=[...t].sort((r,a)=>{let s=r.metadata.namespace_?.version,i=a.metadata.namespace_?.version;return!s||!i?0:Fs(i,s)});for(let r of o){let a=new Vs(r,n),s=await e.parseKanonaks(a),i=Ms(s,Bs.InstanceTransformation);if(i[0])return i[0]}}function Ws(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 ci,rmSync as li,existsSync as nn,readdirSync as ui,writeFileSync as pi,statSync as mi}from"fs";import{join as Ce}from"path";import{KanonakObjectParser as di,KanonakParser as fi,computeIntegrity as gi}from"@kanonak-protocol/sdk";import{findSubjectsByType as hi}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as ki}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as yi}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as bi}from"@kanonak-protocol/sdk/transformations";import{join as Kt}from"path";import{homedir as xt}from"os";import{KanonakObjectParser as qs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Gs}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Dt,getStringValue as Qe,getReferenceUri as Js}from"@kanonak-protocol/sdk/uri-helpers";var z="kanonak.org",W="agent-skills",Et={publisher:z,package_:W,name:"Client"},At={publisher:z,package_:W,name:"clientId"},Ys={publisher:z,package_:W,name:"projectAgentDir"},Xs={publisher:z,package_:W,name:"userAgentDir"},Zs={publisher:z,package_:W,name:"agentFileFormat"},Qs="agents";function ei(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Se(n,e){let t=(n.client??ei()??Qs).toLowerCase(),o=n.scope??"project",r=await ni(t,e);if(!r){let p=await ti(e);throw new Error(`Unknown client "${t}". Known clients: ${p.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=Qe(r,o==="user"?Xs:Ys);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let c=Js(r,Zs)?.name==="toml"?"toml":"markdown-frontmatter",l=c==="toml"?".toml":".md";return{agentsDir:oi(s),format:c,fileExtension:l}}var Tt=new WeakMap;async function jt(n){let e=Tt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(z,W);if(t.length===0)throw new Error(`Could not find ${z}/${W} in the repository. Install a capability that imports agent-skills to populate the cache.`);let r=[...t].sort((c,l)=>{let p=c.metadata.namespace_?.version,u=l.metadata.namespace_?.version;return!p||!u?0:p.major!==u.major?u.major-p.major:p.minor!==u.minor?u.minor-p.minor:u.patch-p.patch})[0],a=new qs,s=new Gs(r,n),i=await a.parseKanonaks(s);return Tt.set(n,i),i}async function ni(n,e){let t=await jt(e),o=Dt(t,Et);for(let r of o)if(Qe(r,At)===n)return r}async function ti(n){let e=await jt(n),t=Dt(e,Et),o=[];for(let r of t){let a=Qe(r,At);a&&o.push(a)}return o}function oi(n){return n.startsWith("~/")?Kt(xt(),n.slice(2)):n==="~"?xt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Kt(process.cwd(),n)}import{readFileSync as ri,writeFileSync as ai,existsSync as si}from"fs";import{join as Nt}from"path";import Ot from"js-yaml";var Lt="agents.lock",ii=`# This file is generated by Kanonak CLI. Do not edit manually.
127
+ `;function Pe(n){let e=Nt(n,Lt);if(!si(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=ri(e,"utf-8"),o=Ot.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 en(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=Nt(n,Lt),r=Ot.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});ai(o,ii+r,"utf-8")}var Ut="kanonak.org",Ft="agent-to-agent-file",_e=class{parser=new fi;objectParser=new di;runner=new yi;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:i,fileExtension:c}=await Se(a,r),l=await wi(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Ut}/${Ft}@3.0.0 is not installed in the workspace or cache.`);return}let p=i==="toml"?"toml":"markdown-with-frontmatter",u=await this.runner.run({transformation:l,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:p});if(u.length===0){console.error("No agents could be transformed from the package.");return}ci(s,{recursive:!0});let m=Pe(s),h=t[0].namespace,{publisher:k,package_:d,version:f}=vi(h);for(let g of u){let y=`${g.fileName}${c}`,b=Ce(s,y),w=nn(b);pi(b,g.content,"utf-8"),m.agents[g.fileName]={publisher:k,package_:d,version:f,resolved:k?`kanonak://${k}/${d}@${f}`:"",integrity:gi(g.content),fileName:y},console.log(` ${w?"Updated":"Installed"} agent "${g.fileName}" \u2192 ${b}`)}en(s,m)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:a}=await Se(r,o),s=Pe(a),i=s.agents[e];i||(console.error(`Agent "${e}" is not installed at ${a}`),process.exit(1));let c=Ce(a,i.fileName);nn(c)&&li(c,{force:!0}),delete s.agents[e],en(a,s),console.log(`Removed agent "${e}" from ${c}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await Se(o,t),a=Pe(r),s=[];for(let[i,c]of Object.entries(a.agents))s.push({name:i,publisher:c.publisher,package_:c.package_,version:c.version,path:Ce(r,c.fileName)});if(nn(r))try{let i=ui(r,{withFileTypes:!0});for(let c of i){if(!c.isFile()||c.name==="agents.lock")continue;let l=Ce(r,c.name),p=$i(c.name);if(!a.agents[p]){try{if(!mi(l).isFile())continue}catch{continue}s.push({name:p,publisher:"",package_:"",version:"",path:l})}}}catch{}return s}};async function wi(n,e){let t=await n.getDocumentsByNamespaceAsync(Ut,Ft);if(t.length===0)return;let o=new ki(t[0],n),r=await e.parseKanonaks(o);return hi(r,bi.InstanceTransformation)[0]}function $i(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function vi(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 Di=_i(Ci(import.meta.url)),Ei=JSON.parse(Pi(Ri(Di,"..","package.json"),"utf-8")),R=new Si;R.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(Ei.version);R.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await sn(n)});R.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await cn(n)});R.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await un(n)});R.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await gn(n)});R.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await hn(n)});R.command("hash <target>").description("Print the canonical structural hash (sha256:\u2026) of a Kanonak package.").option("-v, --verbose","Also print the canonical form on stderr.").action(async(n,e)=>{await st(n,e)});R.addCommand(Tn());R.addCommand(Ln());R.addCommand(Bn());R.addCommand(Wn());R.addCommand(et());R.addCommand(nt());R.addCommand(at());async function Ai(){try{let n=new T,e=new Ii,t=new xi,o=Ti(t),r=new Ki({fetchFn:o}),a=await S(process.cwd(),e),s=new he;s.register("kanonak.org/capabilities/agent-skill-deployment",new ve),s.register("kanonak.org/agent-capabilities/agent-instance-deployment",new _e);let i=await In(n,e,a),c=new ge(n,e,r,o,s,a);ct(R,i,c)}catch{}}await Ai();R.parse();
@@ -1,6 +1,6 @@
1
- import { KanonakParser } from '@kanonak-protocol/sdk';
1
+ import { KanonakParser, LocalFirstRepository } from '@kanonak-protocol/sdk';
2
2
  import type { IKanonakDocumentRepository } from '@kanonak-protocol/sdk';
3
- import type { KanonakDocument, Import, DocumentReference } from '@kanonak-protocol/types/document/models/types';
3
+ export { LocalFirstRepository };
4
4
  /**
5
5
  * Find the workspace root by walking up from the given path.
6
6
  * Walks up through publisher domain directories (names containing a dot)
@@ -12,28 +12,8 @@ import type { KanonakDocument, Import, DocumentReference } from '@kanonak-protoc
12
12
  export declare function findWorkspaceRoot(dir: string): string;
13
13
  export declare function collectKanonakFiles(dir: string, files: string[]): void;
14
14
  /**
15
- * Repository that tries multiple backends in order.
16
- * First match wins for all read operations.
17
- * Write operations go to the first repository.
18
- */
19
- export declare class LocalFirstRepository implements IKanonakDocumentRepository {
20
- private readonly repos;
21
- constructor(...repos: IKanonakDocumentRepository[]);
22
- getHighestCompatibleVersionAsync(publisher: string, import_: Import): Promise<KanonakDocument | null>;
23
- getAllDocumentsAsync(): Promise<KanonakDocument[]>;
24
- getDocumentAsync(identifier: string): Promise<KanonakDocument | null>;
25
- getDocumentsByNamespaceAsync(publisher: string, package_: string): Promise<KanonakDocument[]>;
26
- saveDocumentAsync(document: KanonakDocument, identifier: string): Promise<void>;
27
- deleteDocumentAsync(identifier: string): Promise<void>;
28
- clearNamespaceAsync(publisher: string, package_: string): Promise<void>;
29
- getAllDocumentReferencesAsync(): Promise<DocumentReference[]>;
30
- getDocumentContentAsync(identifier: string): Promise<string | null>;
31
- getDocumentUriAsync(identifier: string): Promise<string | null>;
32
- }
33
- /**
34
- * Build a three-tier repository:
35
- * 1. Local workspace (InMemoryKanonakDocumentRepository from scanned .kan.yml files)
36
- * 2. Global cache (~/.kanonak/packages/ via FileSystemKanonakDocumentRepository)
37
- * 3. HTTP (HttpKanonakDocumentRepository with FileCache write-through)
15
+ * Build the three-tier workspace cache → HTTP repository (the SDK's
16
+ * `buildLocalFirstRepository`), wiring HTTP write-through to the CLI's
17
+ * persistent `FileCache` so fetched packages land in `~/.kanonak/packages/`.
38
18
  */
39
19
  export declare function buildRepository(workspaceRoot: string, parser: KanonakParser): Promise<IKanonakDocumentRepository>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanonak-protocol/cli",
3
- "version": "3.47.0",
3
+ "version": "3.48.0",
4
4
  "description": "Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,8 +34,8 @@
34
34
  "semantic-web"
35
35
  ],
36
36
  "dependencies": {
37
- "@kanonak-protocol/sdk": "^3.47.0",
38
- "@kanonak-protocol/types": "^3.47.0",
37
+ "@kanonak-protocol/sdk": "^3.48.0",
38
+ "@kanonak-protocol/types": "^3.48.0",
39
39
  "commander": "^13.0.0",
40
40
  "js-yaml": "^4.1.1"
41
41
  },