@kanonak-protocol/cli 3.52.0 → 3.53.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.
Files changed (2) hide show
  1. package/dist/index.js +34 -34
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -3,29 +3,29 @@ import{Command as Vi}from"commander";import{readFileSync as Bi}from"fs";import{f
3
3
  `).some(r=>r.trim()===t||r.trim()===t+"/"))return;qt(e,`
4
4
  ${t}/
5
5
  `)}else rn(e,`${t}/
6
- `)}getPath(e,t,o){return Wt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function H(n){let e=n;for(;;){let t=Qt(e);if(t===e)break;if(an(e).includes(".")||an(t).includes(".")){e=t;continue}break}return e}function ne(n,e){for(let t of Xt(n,{withFileTypes:!0})){let o=Zt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?ne(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}async function v(n,e){let t=new T;return eo(n,e,{httpCache:{getFromCache:(o,r,s)=>t.get(o,r,s),onFetch:(o,r,s,a)=>t.put(o,r,s,a)}})}async function cn(n){let e=oo(n),t=to(e),o=t.isDirectory()?H(e):H(ro(e)),r=new ao,s=new so(r),a=await v(o,r),i=[];if(t.isDirectory()?ne(e,i):i.push(e),i.length===0){console.log("No .kan.yml files found.");return}let c=0,l=0;for(let u of i){let p=no(u,"utf-8"),m=r.parseWithErrors(p);if(m.errors&&m.errors.length>0){console.log(`
7
- ${u}:`);for(let g of m.errors)console.log(` ERROR (parse): ${g.message} [line ${g.line}:${g.column}]`),c++;continue}let h=m.document;if(!h){console.log(`
8
- ${u}:`),console.log(" ERROR: Failed to parse document"),c++;continue}let k=await s.validateAsync(h,a),d=k.errors.filter(g=>g.severity===sn.Error),f=k.warnings.filter(g=>g.severity===sn.Warning);if(d.length>0||f.length>0){let g=h.metadata.namespace_,y=g?`${g.publisher}/${g.package_}@${g.version}`:u;console.log(`
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 io,PublisherIndex as co,CredentialStore as lo,createAuthenticatedFetch as uo}from"@kanonak-protocol/sdk";import{loadLockFile as po,saveLockFile as mo,computeIntegrity as fo}from"@kanonak-protocol/sdk";function j(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,s=null,a=null,i=o.indexOf("@");if(i!==-1){r=o.substring(0,i);let c=o.substring(i+1),l=c.indexOf("/");l===-1?s=c||null:(s=c.substring(0,l)||null,a=c.substring(l+1)||null)}else{let c=o.indexOf("/");c===-1?r=o:(r=o.substring(0,c),a=o.substring(c+1)||null)}return!r||a&&a.includes("/")||s&&s.includes("@")?null:{publisher:t,packageName:r,version:s,instanceName:a}}async function ln(n){let e=new T,t=new io,o=new lo,r=uo(o),s=new co({fetchFn:r}),a=po()??{version:"1",lastUpdated:new Date().toISOString(),packages:{}};if(!n){Object.keys(a.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(a.packages).length} package(s) from kanonak.lock...`);for(let[k,d]of Object.entries(a.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(a.packages).length} package(s) from lock file.`);return}let i=j(n);i||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:c,packageName:l,version:u,instanceName:p}=i;p&&(console.error(`\`kanonak install\` works on whole packages \u2014 got an instance suffix "/${p}".`),console.error(`Try: kanonak install ${c}/${l}${u?"@"+u:""}`),console.error("(Use `kanonak <capability> add` if you want to install one named instance.)"),process.exit(1));let m=u??await s.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,s,r,h,a),mo(a),console.log(`
12
- Installed ${h.size} package(s).`)}async function un(n,e,t,o,r,s,a,i,c){let l=`${n}/${e}@${t}`;if(i.has(l))return;i.add(l);let u=`${n}/${e}`,p=o.get(n,e,t),m;if(p)console.log(` ${l} (cached)`),m=await s.getPackageUrl(n,e,t);else{m=await s.getPackageUrl(n,e,t);let d=await a(m,n);if(!d.ok)throw new Error(`Failed to fetch ${m} (${d.status} ${d.statusText})`);p=await d.text(),o.put(n,e,t,p),console.log(` ${l}`)}let h={},k=r.parse(p);if(k.metadata.imports)for(let[d,f]of Object.entries(k.metadata.imports))for(let g of f){let y=await s.resolveVersion(d,g);y?(h[`${d}/${g.packageName}`]=y,await un(d,g.packageName,y,o,r,s,a,i,c)):console.error(` WARNING: Could not resolve ${d}/${g.packageName} ${g.package_}`)}c.packages[u]={version:t,resolved:m,integrity:fo(p),dependencies:h}}import{readFileSync as go}from"fs";import{resolve as ho,dirname as ko}from"path";import{KanonakParser as yo}from"@kanonak-protocol/sdk";async function pn(n){let e=ho(n),t=go(e,"utf-8"),o=new yo,r=o.parse(t),s=r.metadata.namespace_,a=s?`${s.publisher}/${s.package_}@${s.version}`:n;if(console.log(a),!r.metadata.imports){console.log(" (no imports)");return}let i=H(ko(e)),c=await v(i,o),l=new Set;for(let[u,p]of Object.entries(r.metadata.imports))for(let m of p)await mn(u,m,c,l," ")}async function mn(n,e,t,o,r){let s=`${n}/${e.packageName}`;if(o.has(s)){console.log(`${r}${s} (${e.package_}) [circular]`);return}o.add(s);let a;try{a=await t.getHighestCompatibleVersionAsync(n,e)}catch{console.log(`${r}${s} (${e.package_}) [fetch failed]`);return}if(!a){console.log(`${r}${s} (${e.package_}) [not found]`);return}let i=a.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${i}`),a.metadata.imports)for(let[c,l]of Object.entries(a.metadata.imports))for(let u of l)await mn(c,u,t,o,r+" ")}import{createHash as wo,randomBytes as gn}from"crypto";import{createServer as $o}from"http";import{execFile as Ie}from"child_process";import{CredentialStore as vo,generateDPoPKeyPair as So,createDPoPProof as dn,serverSupportsDPoP as Po}from"@kanonak-protocol/sdk";import{normalizeHost as bo}from"@kanonak-protocol/sdk";var F=class{cache=new Map;async discover(e){let t=bo(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 s=`https://${t}/.well-known/openid-configuration`;r=await this.tryEndpoint(s)}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 s=r instanceof Error?r.message:String(r);return s.includes("ENOTFOUND")||s.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${s})`),console.error(" If the server is behind a VPN, ensure you are connected.")):s.includes("CERT")||s.includes("SSL")||s.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${s})`),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: ${s}`),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:te(o.issuer),authorizationEndpoint:te(o.authorization_endpoint),tokenEndpoint:te(o.token_endpoint),registrationEndpoint:te(o.registration_endpoint),revocationEndpoint:te(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 te(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 vo}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let o=await this.discovery.discover(e);if(!o)return x(`No OAuth discovery endpoint found for '${e}'.
6
+ `)}getPath(e,t,o){return Wt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function H(n){let e=n;for(;;){let t=Qt(e);if(t===e)break;if(an(e).includes(".")||an(t).includes(".")){e=t;continue}break}return e}function ne(n,e){for(let t of Xt(n,{withFileTypes:!0})){let o=Zt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?ne(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}async function v(n,e){let t=new T;return eo(n,e,{httpCache:{getFromCache:(o,r,s)=>t.get(o,r,s),onFetch:(o,r,s,a)=>t.put(o,r,s,a)}})}async function cn(n){let e=oo(n),t=to(e),o=t.isDirectory()?H(e):H(ro(e)),r=new ao,s=new so(r),a=await v(o,r),i=[];if(t.isDirectory()?ne(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=no(p,"utf-8"),m=r.parseWithErrors(u);if(m.errors&&m.errors.length>0){console.log(`
7
+ ${p}:`);for(let h of m.errors)console.log(` ERROR (parse): ${h.message} [line ${h.line}:${h.column}]`),c++;continue}let f=m.document;if(!f){console.log(`
8
+ ${p}:`),console.log(" ERROR: Failed to parse document"),c++;continue}let k=await s.validateAsync(f,a),d=k.errors.filter(h=>h.severity===sn.Error),g=k.warnings.filter(h=>h.severity===sn.Warning);if(d.length>0||g.length>0){let h=f.metadata.namespace_,y=h?`${h.publisher}/${h.package_}@${h.version}`:p;console.log(`
9
+ ${y}:`);for(let b of d)console.log(` ERROR: ${b.message}`),b.suggestion&&console.log(` -> ${b.suggestion}`);for(let b of g)console.log(` WARN: ${b.message}`)}c+=d.length,l+=g.length}console.log(`
10
+ ${i.length} file(s) validated. ${c} error(s), ${l} warning(s).`),c>0&&process.exit(1)}import{KanonakParser as io,PublisherIndex as co,CredentialStore as lo,createAuthenticatedFetch as uo}from"@kanonak-protocol/sdk";import{loadLockFile as po,saveLockFile as mo,computeIntegrity as fo}from"@kanonak-protocol/sdk";function j(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,s=null,a=null,i=o.indexOf("@");if(i!==-1){r=o.substring(0,i);let c=o.substring(i+1),l=c.indexOf("/");l===-1?s=c||null:(s=c.substring(0,l)||null,a=c.substring(l+1)||null)}else{let c=o.indexOf("/");c===-1?r=o:(r=o.substring(0,c),a=o.substring(c+1)||null)}return!r||a&&a.includes("/")||s&&s.includes("@")?null:{publisher:t,packageName:r,version:s,instanceName:a}}async function ln(n){let e=new T,t=new io,o=new lo,r=uo(o),s=new co({fetchFn:r}),a=po()??{version:"1",lastUpdated:new Date().toISOString(),packages:{}};if(!n){Object.keys(a.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(a.packages).length} package(s) from kanonak.lock...`);for(let[k,d]of Object.entries(a.packages)){let g=k.indexOf("/"),h=k.substring(0,g),y=k.substring(g+1),b=e.get(h,y,d.version);if(b)console.log(` ${k}@${d.version} (cached)`);else{let w=d.resolved,$=await r(w,h);if(!$.ok)throw new Error(`Failed to fetch ${w} (${$.status} ${$.statusText})`);b=await $.text(),e.put(h,y,d.version,b),console.log(` ${k}@${d.version}`)}}console.log(`
11
+ Installed ${Object.keys(a.packages).length} package(s) from lock file.`);return}let i=j(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 s.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 f=new Set;await un(c,l,m,e,t,s,r,f,a),mo(a),console.log(`
12
+ Installed ${f.size} package(s).`)}async function un(n,e,t,o,r,s,a,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 s.getPackageUrl(n,e,t);else{m=await s.getPackageUrl(n,e,t);let d=await a(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 f={},k=r.parse(u);if(k.metadata.imports)for(let[d,g]of Object.entries(k.metadata.imports))for(let h of g){let y=await s.resolveVersion(d,h);y?(f[`${d}/${h.packageName}`]=y,await un(d,h.packageName,y,o,r,s,a,i,c)):console.error(` WARNING: Could not resolve ${d}/${h.packageName} ${h.package_}`)}c.packages[p]={version:t,resolved:m,integrity:fo(u),dependencies:f}}import{readFileSync as go}from"fs";import{resolve as ho,dirname as ko}from"path";import{KanonakParser as yo}from"@kanonak-protocol/sdk";async function pn(n){let e=ho(n),t=go(e,"utf-8"),o=new yo,r=o.parse(t),s=r.metadata.namespace_,a=s?`${s.publisher}/${s.package_}@${s.version}`:n;if(console.log(a),!r.metadata.imports){console.log(" (no imports)");return}let i=H(ko(e)),c=await v(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 s=`${n}/${e.packageName}`;if(o.has(s)){console.log(`${r}${s} (${e.package_}) [circular]`);return}o.add(s);let a;try{a=await t.getHighestCompatibleVersionAsync(n,e)}catch{console.log(`${r}${s} (${e.package_}) [fetch failed]`);return}if(!a){console.log(`${r}${s} (${e.package_}) [not found]`);return}let i=a.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${i}`),a.metadata.imports)for(let[c,l]of Object.entries(a.metadata.imports))for(let p of l)await mn(c,p,t,o,r+" ")}import{createHash as wo,randomBytes as gn}from"crypto";import{createServer as $o}from"http";import{execFile as Ke}from"child_process";import{CredentialStore as vo,generateDPoPKeyPair as So,createDPoPProof as dn,serverSupportsDPoP as Po}from"@kanonak-protocol/sdk";import{normalizeHost as bo}from"@kanonak-protocol/sdk";var F=class{cache=new Map;async discover(e){let t=bo(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 s=`https://${t}/.well-known/openid-configuration`;r=await this.tryEndpoint(s)}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 s=r instanceof Error?r.message:String(r);return s.includes("ENOTFOUND")||s.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${s})`),console.error(" If the server is behind a VPN, ensure you are connected.")):s.includes("CERT")||s.includes("SSL")||s.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${s})`),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: ${s}`),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:te(o.issuer),authorizationEndpoint:te(o.authorization_endpoint),tokenEndpoint:te(o.token_endpoint),registrationEndpoint:te(o.registration_endpoint),revocationEndpoint:te(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 te(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 vo}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let o=await this.discovery.discover(e);if(!o)return x(`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
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 x(`OAuth metadata for '${e}' is missing required fields: ${r.join(", ")}.
18
18
  Contact the IDP administrator to ensure these are included in the discovery document.`);let s=Po(o.dpopSigningAlgValuesSupported),a=null;if(s){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{a=So()}catch($){return x(`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:u}=await To(),p=await this.credentialStore.getCredential(e),m=p?.clientId??null,h=p?.clientSecret??null;if(!m&&o.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let $=await this.registerClient(o.registrationEndpoint,i);if(!$.success)return u(),x($.error);m=$.clientId,h=$.clientSecret??null}if(!m)return u(),x(`No OAuth client credentials for '${e}' and the server does not support dynamic client registration (no registration_endpoint in metadata).
19
+ Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:i,port:c,waitForCallback:l,close:p}=await To(),u=await this.credentialStore.getCredential(e),m=u?.clientId??null,f=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(),x($.error);m=$.clientId,f=$.clientSecret??null}if(!m)return p(),x(`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=_o(),d=Ro(k),f=xo(),g=Io(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}`),Eo(g);let y=await l();if(u(),!y)return x(`Authorization timed out after 5 minutes.
22
+ or add a registration_endpoint to the OAuth metadata.`);let k=_o(),d=Ro(k),g=xo(),h=Ko(o.authorizationEndpoint,m,i,t,g,d);console.log(` Opening browser for authorization on port ${c}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${h}`),Eo(h);let y=await l();if(p(),!y)return x(`Authorization timed out after 5 minutes.
23
23
  The browser authorization was not completed in time.
24
24
  Re-run 'kanonak login ${e}' and complete the browser authorization promptly.`);if(!y.code){let $=y.error?`: ${y.error}`:"";return x(`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 x(`Authorization state mismatch \u2014 possible CSRF attack.
26
+ Check the IDP admin console for error details.`)}if(y.state!==g)return x(`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,a);if(!b.success)return x(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:a};return await this.credentialStore.store(e,w),console.log(` Successfully authenticated with ${e}`),s&&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 x(`No stored credentials for '${e}'. Run 'kanonak login ${e}' to authenticate first.`);if(!t.refreshToken)return x(`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,f,y.code,i,k,a);if(!b.success)return x(b.error);let w={clientId:m,clientSecret:f,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:a};return await this.credentialStore.store(e,w),console.log(` Successfully authenticated with ${e}`),s&&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 x(`No stored credentials for '${e}'. Run 'kanonak login ${e}' to authenticate first.`);if(!t.refreshToken)return x(`No refresh token available for '${e}'.
29
29
  The authorization server may not issue refresh tokens for this client.
30
30
  Run 'kanonak login ${e}' to re-authenticate.`);if(!t.clientId)return x(`No client ID in stored credentials for '${e}'.
31
31
  The stored credential may be corrupted. Run 'kanonak logout ${e}' then 'kanonak login ${e}'.`);let o=t.tokenEndpoint;if(!o){let s=await this.discovery.discover(e);if(!s?.tokenEndpoint)return x(`Cannot find token endpoint for '${e}'.
@@ -34,17 +34,17 @@ Installed ${h.size} package(s).`)}async function un(n,e,t,o,r,s,a,i,c){let l=`${
34
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 x(`No stored credentials for '${e}'.
35
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(a){return{success:!1,error:`Dynamic client registration request to ${e} failed: ${J(a)}
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 a=await Ke(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 a=await Ie(o);return{success:!1,error:`Dynamic client registration (RFC 7591) failed.
38
38
  Endpoint: ${e}
39
39
  HTTP ${o.status}: ${a}
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(),s=r.client_id;return s?{success:!0,clientId:s,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,s,a,i){let c=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:s,code_verifier:a});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(p){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${J(p)}
43
- The stored key pair may be corrupted. Run 'kanonak login' to re-authenticate.`}}let u;try{u=await fetch(e,{method:"POST",headers:l,body:c.toString()})}catch(p){return{success:!1,error:`Token exchange request to ${e} failed: ${J(p)}
44
- Ensure the token endpoint is reachable.`}}if(!u.ok){let p=await Ke(u),m=Co(p);return{success:!1,error:`Token exchange failed.
42
+ The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,o,r,s,a,i){let c=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:s,code_verifier:a});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: ${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 Ie(p),m=Co(u);return{success:!1,error:`Token exchange failed.
45
45
  Endpoint: ${e}
46
- HTTP ${u.status}: ${p}`+(m?`
47
- ${m}`:"")}}return{success:!0,tokens:fn(await u.json())}}async refreshTokenRequest(e,t,o,r,s){let a=new URLSearchParams({grant_type:"refresh_token",client_id:t,refresh_token:r});o&&a.set("client_secret",o);let i={"Content-Type":"application/x-www-form-urlencoded"};if(s)try{i.DPoP=dn(s.privateKey,s.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:a.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: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 x(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 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 Co(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 _o(){return gn(32).toString("base64url")}function Ro(n){return wo("sha256").update(n).digest("base64url")}function xo(){return gn(16).toString("base64url")}function Io(n,e,t,o,r,s){let a=new URLSearchParams({client_id:e,response_type:"code",redirect_uri:t,scope:o.join(" "),state:r,code_challenge:s,code_challenge_method:"S256"});return`${n}?${a}`}var Ko=300*1e3;async function To(){return new Promise(n=>{let e=$o((r,s)=>{let a=new URL(r.url,"http://localhost"),i=a.searchParams.get("code")??void 0,c=a.searchParams.get("state")??void 0,l=a.searchParams.get("error")??a.searchParams.get("error_description")??void 0,u=l?Do(l):null,p=u?`<html><body><h1>Authorization failed</h1><p>${u}</p></body></html>`:"<html><body><h1>Authorization successful!</h1><p>You can close this window.</p></body></html>";s.writeHead(200,{"Content-Type":"text/html"}),s.end(p),t({code:i,state:c,error:l})}),t,o=new Promise(r=>{t=r,setTimeout(()=>{r(null),e.close()},Ko)});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 Do(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Eo(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 jo}from"@kanonak-protocol/sdk";async function hn(n){try{let e=new F,t=new jo,r=await new Y(e,t).authorize(n);r.success?console.log(`
46
+ HTTP ${p.status}: ${u}`+(m?`
47
+ ${m}`:"")}}return{success:!0,tokens:fn(await p.json())}}async refreshTokenRequest(e,t,o,r,s){let a=new URLSearchParams({grant_type:"refresh_token",client_id:t,refresh_token:r});o&&a.set("client_secret",o);let i={"Content-Type":"application/x-www-form-urlencoded"};if(s)try{i.DPoP=dn(s.privateKey,s.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:a.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${J(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 x(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 J(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 Co(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 _o(){return gn(32).toString("base64url")}function Ro(n){return wo("sha256").update(n).digest("base64url")}function xo(){return gn(16).toString("base64url")}function Ko(n,e,t,o,r,s){let a=new URLSearchParams({client_id:e,response_type:"code",redirect_uri:t,scope:o.join(" "),state:r,code_challenge:s,code_challenge_method:"S256"});return`${n}?${a}`}var Io=300*1e3;async function To(){return new Promise(n=>{let e=$o((r,s)=>{let a=new URL(r.url,"http://localhost"),i=a.searchParams.get("code")??void 0,c=a.searchParams.get("state")??void 0,l=a.searchParams.get("error")??a.searchParams.get("error_description")??void 0,p=l?Do(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>";s.writeHead(200,{"Content-Type":"text/html"}),s.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 Do(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Eo(n){try{process.platform==="win32"?Ke("cmd",["/c","start","",n]):process.platform==="darwin"?Ke("open",[n]):Ke("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as jo}from"@kanonak-protocol/sdk";async function hn(n){try{let e=new F,t=new jo,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(`
@@ -55,9 +55,9 @@ 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
57
  ${t}`),process.exit(1)}}import{Command as sr}from"commander";import{KanonakParser as ir,KanonakObjectParser as cr,PublisherIndex as lr,CredentialStore as ur,createAuthenticatedFetch as pr,computeIntegrity as mr}from"@kanonak-protocol/sdk";import{readFileSync as No,writeFileSync as Oo,existsSync as Lo}from"fs";import{join as Uo}from"path";import yn from"js-yaml";import{getGlobalCachePath as Fo}from"@kanonak-protocol/sdk";var Mo=`# This file is generated by Kanonak CLI. Do not edit manually.
58
- `;function bn(){let n=Fo();return Uo(n,"..","capabilities.lock")}function X(){let n=bn();if(!Lo(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=No(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 oe(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:'"'});Oo(bn(),Mo+t,"utf-8")}import{SingleDocumentRepository as dr}from"@kanonak-protocol/sdk/uri-helpers";import{existsSync as Ho,readdirSync as Vo,readFileSync as Bo}from"fs";import{join as wn}from"path";import{KanonakObjectParser as zo,EmbeddedKanonak as Pn,ReferenceKanonak as Cn,getGlobalCachePath as qo}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as _n}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as Te,findSubjectsByType as Wo,getStringValue as M,getReferenceUri as De,getListValues as Rn}from"@kanonak-protocol/sdk/uri-helpers";var C="kanonak.org",_="capabilities",Ee={publisher:C,package_:_,name:"Capability"},Go={publisher:C,package_:_,name:"commandName"},xn={publisher:C,package_:_,name:"description"},Jo={publisher:C,package_:_,name:"managesType"},Yo={publisher:C,package_:_,name:"deploymentTarget"},Xo={publisher:C,package_:_,name:"hasCommand"},Zo={publisher:C,package_:_,name:"subcommandName"},Qo={publisher:C,package_:_,name:"performs"},er={publisher:C,package_:_,name:"hasArgument"},nr={publisher:C,package_:_,name:"argumentName"},$n={publisher:C,package_:_,name:"isRequired"},vn={publisher:C,package_:_,name:"isOption"},tr={publisher:C,package_:_,name:"defaultValue"};async function In(n,e,t){let o=X(),r=new zo,s=[],a=!1;for(let[i,c]of Object.entries(o.capabilities)){let l=c,u=n.get(l.publisher,l.package_,l.version);if(!u){let p=await or(i,l,e,r,t);if(p)console.error(` Healed capability "${i}": ${l.publisher}/${l.package_}@${l.version} \u2192 ${p.entry.publisher}/${p.entry.package_}@${p.entry.version} (package was renamed)`),o.capabilities[i]=p.entry,l=p.entry,u=p.content,a=!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 p=e.parse(u),m=new _n(p,t),h=await r.parseKanonaks(m),k=Kn(h,l.publisher,l.package_,l.version);k?s.push(k):console.error(` WARNING: No Capability instance found in "${i}" (${l.publisher}/${l.package_}@${l.version})`)}catch(p){console.error(` WARNING: Failed to parse capability "${i}": ${p}`)}}return a&&oe(o),s}async function or(n,e,t,o,r){let s=wn(qo(),e.publisher);if(!Ho(s))return;let a=[];for(let i of Vo(s)){if(!i.endsWith(".kan.yml"))continue;let c=i.slice(0,-8),l=c.lastIndexOf("@");if(l===-1)continue;let u=c.substring(0,l),p=c.substring(l+1);if(u===e.package_&&p===e.version)continue;let m;try{m=Bo(wn(s,i),"utf-8")}catch{continue}let h;try{let k=t.parse(m),d=new _n(k,r),f=await o.parseKanonaks(d);h=Kn(f,e.publisher,u,p)?.commandName}catch{continue}h===n&&a.push({entry:{publisher:e.publisher,package_:u,version:p,resolved:`kanonak://${e.publisher}/${u}@${p}`,integrity:""},content:m})}if(a.length===1)return a[0]}function Kn(n,e,t,o){let r=Wo(n,Ee);if(r.length===0)return;let s=r[0],a=M(s,Go)??"",i=M(s,xn)??"",c=De(s,Jo),l=De(s,Yo),u=[];for(let p of Rn(s,Xo)){let m=rr(p,n);m&&u.push(m)}return{commandName:a,description:i,managesTypeKey:c?Te(c):"",deploymentTargetKey:l?Te(l):"",commands:u,publisher:e,package_:t,version:o}}function rr(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof Cn){let c=Tn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,Zo)??"",r=M(t,xn)??"",s=De(t,Qo),a=Rn(t,er),i=[];for(let c of a){let l=ar(c,e);l&&i.push(l)}return{subcommandName:o,description:r,arguments:i,actionKey:s?Te(s):""}}function ar(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof Cn){let c=Tn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,nr)??"",r=M(t,$n)==="true"||Sn(t,$n)===!0,s=M(t,vn)==="true"||Sn(t,vn)===!0,a=M(t,tr),i={argumentName:o,required:r,isOption:s};return a!==void 0&&(i.defaultValue=a),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 Tn(n,e,t,o){for(let r of n){if(!("name"in r)||!("namespace"in r))continue;let s=r;if(s.name===o&&!(!s.namespace||typeof s.namespace!="string")&&s.namespace.startsWith(`${e}/${t}@`))return r}}import{findSubjectsByType as fr,getStringValue as gr}from"@kanonak-protocol/sdk/uri-helpers";var hr={publisher:C,package_:_,name:"commandName"};function Dn(){let n=new sr("capability").description("Manage Kanonak CLI capabilities (pluggable command groups)");return n.command("add <package>").description("Install a capability from a Kanonak publisher").action(async e=>{await kr(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await yr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await br()}),n}async function kr(n){let e=j(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:s}=e;s&&(console.error(`\`kanonak capability add\` installs whole packages \u2014 got an instance suffix "/${s}".`),console.error(`Try: kanonak capability add ${t}/${o}${r?"@"+r:""}`),process.exit(1));let a=new T,i=new ir,c=new cr,l=new ur,u=pr(l),p=new lr({fetchFn:u}),m=r??await p.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=a.get(t,o,m);if(!h){let S=await p.getPackageUrl(t,o,m),K=await u(S,t);if(!K.ok)throw new Error(`Failed to fetch ${S} (${K.status} ${K.statusText})`);h=await K.text(),a.put(t,o,m,h)}let k=i.parse(h),d=await v(process.cwd(),i),f=new dr(k,d),g=await c.parseKanonaks(f),y=fr(g,Ee);y.length===0&&(console.error(`Package ${t}/${o}@${m} does not contain a ${C}/${_}/Capability instance.`),process.exit(1));let b=y[0],w=gr(b,hr);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 p.getPackageUrl(t,o,m),integrity:mr(h)},oe($),console.log(`
58
+ `;function bn(){let n=Fo();return Uo(n,"..","capabilities.lock")}function X(){let n=bn();if(!Lo(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=No(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 oe(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:'"'});Oo(bn(),Mo+t,"utf-8")}import{SingleDocumentRepository as dr}from"@kanonak-protocol/sdk/uri-helpers";import{existsSync as Ho,readdirSync as Vo,readFileSync as Bo}from"fs";import{join as wn}from"path";import{KanonakObjectParser as zo,EmbeddedKanonak as Pn,ReferenceKanonak as Cn,getGlobalCachePath as qo}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as _n}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as Te,findSubjectsByType as Wo,getStringValue as M,getReferenceUri as De,getListValues as Rn}from"@kanonak-protocol/sdk/uri-helpers";var P="kanonak.org",C="capabilities",Ee={publisher:P,package_:C,name:"Capability"},Go={publisher:P,package_:C,name:"commandName"},xn={publisher:P,package_:C,name:"description"},Jo={publisher:P,package_:C,name:"managesType"},Yo={publisher:P,package_:C,name:"deploymentTarget"},Xo={publisher:P,package_:C,name:"hasCommand"},Zo={publisher:P,package_:C,name:"subcommandName"},Qo={publisher:P,package_:C,name:"performs"},er={publisher:P,package_:C,name:"hasArgument"},nr={publisher:P,package_:C,name:"argumentName"},$n={publisher:P,package_:C,name:"isRequired"},vn={publisher:P,package_:C,name:"isOption"},tr={publisher:P,package_:C,name:"defaultValue"};async function Kn(n,e,t){let o=X(),r=new zo,s=[],a=!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 or(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,a=!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 _n(u,t),f=await r.parseKanonaks(m),k=In(f,l.publisher,l.package_,l.version);k?s.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 a&&oe(o),s}async function or(n,e,t,o,r){let s=wn(qo(),e.publisher);if(!Ho(s))return;let a=[];for(let i of Vo(s)){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=Bo(wn(s,i),"utf-8")}catch{continue}let f;try{let k=t.parse(m),d=new _n(k,r),g=await o.parseKanonaks(d);f=In(g,e.publisher,p,u)?.commandName}catch{continue}f===n&&a.push({entry:{publisher:e.publisher,package_:p,version:u,resolved:`kanonak://${e.publisher}/${p}@${u}`,integrity:""},content:m})}if(a.length===1)return a[0]}function In(n,e,t,o){let r=Wo(n,Ee);if(r.length===0)return;let s=r[0],a=M(s,Go)??"",i=M(s,xn)??"",c=De(s,Jo),l=De(s,Yo),p=[];for(let u of Rn(s,Xo)){let m=rr(u,n);m&&p.push(m)}return{commandName:a,description:i,managesTypeKey:c?Te(c):"",deploymentTargetKey:l?Te(l):"",commands:p,publisher:e,package_:t,version:o}}function rr(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof Cn){let c=Tn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,Zo)??"",r=M(t,xn)??"",s=De(t,Qo),a=Rn(t,er),i=[];for(let c of a){let l=ar(c,e);l&&i.push(l)}return{subcommandName:o,description:r,arguments:i,actionKey:s?Te(s):""}}function ar(n,e){let t;if(n instanceof Pn)t=n;else if(n instanceof Cn){let c=Tn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=M(t,nr)??"",r=M(t,$n)==="true"||Sn(t,$n)===!0,s=M(t,vn)==="true"||Sn(t,vn)===!0,a=M(t,tr),i={argumentName:o,required:r,isOption:s};return a!==void 0&&(i.defaultValue=a),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 Tn(n,e,t,o){for(let r of n){if(!("name"in r)||!("namespace"in r))continue;let s=r;if(s.name===o&&!(!s.namespace||typeof s.namespace!="string")&&s.namespace.startsWith(`${e}/${t}@`))return r}}import{findSubjectsByType as fr,getStringValue as gr}from"@kanonak-protocol/sdk/uri-helpers";var hr={publisher:P,package_:C,name:"commandName"};function Dn(){let n=new sr("capability").description("Manage Kanonak CLI capabilities (pluggable command groups)");return n.command("add <package>").description("Install a capability from a Kanonak publisher").action(async e=>{await kr(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await yr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await br()}),n}async function kr(n){let e=j(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:s}=e;s&&(console.error(`\`kanonak capability add\` installs whole packages \u2014 got an instance suffix "/${s}".`),console.error(`Try: kanonak capability add ${t}/${o}${r?"@"+r:""}`),process.exit(1));let a=new T,i=new ir,c=new cr,l=new ur,p=pr(l),u=new lr({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 f=a.get(t,o,m);if(!f){let S=await u.getPackageUrl(t,o,m),K=await p(S,t);if(!K.ok)throw new Error(`Failed to fetch ${S} (${K.status} ${K.statusText})`);f=await K.text(),a.put(t,o,m,f)}let k=i.parse(f),d=await v(process.cwd(),i),g=new dr(k,d),h=await c.parseKanonaks(g),y=fr(h,Ee);y.length===0&&(console.error(`Package ${t}/${o}@${m} does not contain a ${P}/${C}/Capability instance.`),process.exit(1));let b=y[0],w=gr(b,hr);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:mr(f)},oe($),console.log(`
59
59
  Installed capability "${w}".`),console.log(`Run "kanonak ${w} --help" to get started.`)}async function yr(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],oe(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function br(){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 ae}from"commander";import{readFileSync as wr,writeFileSync as $r,mkdirSync as vr,existsSync as En,statSync as Sr}from"fs";import{join as Pr,resolve as Cr}from"path";import{KanonakParser as Ne,KanonakObjectParser as Oe,SubjectKanonak as _r,Reasoner as Rr,KanonakVocabulary as xr,makeUriKey as Nn,pickHighestDocument as Le,formatVersion as On}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as re}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as je,findSubjectByUri as Ir}from"@kanonak-protocol/sdk/uri-helpers";import{TX_V3 as jn}from"@kanonak-protocol/sdk/transformations";import{TransformationRunnerV3 as Kr,SUPPORTED_FORMATS_V3 as Ln}from"@kanonak-protocol/sdk/transformations";import{compileTransformationV3 as Ue}from"@kanonak-protocol/sdk/transformations";function Ae(n){return[...je(n,jn.InstanceTransformation),...je(n,jn.SetTransformation)]}function Un(){let n=new ae("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",`
60
+ `);for(let[t,o]of e)console.log(` ${t} ${o.publisher}/${o.package_}@${o.version}`)}import{Command as ae}from"commander";import{readFileSync as wr,writeFileSync as $r,mkdirSync as vr,existsSync as En,statSync as Sr}from"fs";import{join as Pr,resolve as Cr}from"path";import{KanonakParser as Ne,KanonakObjectParser as Oe,SubjectKanonak as _r,Reasoner as Rr,KanonakVocabulary as xr,makeUriKey as Nn,pickHighestDocument as Le,formatVersion as On}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as re}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as je,findSubjectByUri as Kr}from"@kanonak-protocol/sdk/uri-helpers";import{TX_V3 as jn}from"@kanonak-protocol/sdk/transformations";import{TransformationRunnerV3 as Ir,SUPPORTED_FORMATS_V3 as Ln}from"@kanonak-protocol/sdk/transformations";import{compileTransformationV3 as Ue}from"@kanonak-protocol/sdk/transformations";function Ae(n){return[...je(n,jn.InstanceTransformation),...je(n,jn.SetTransformation)]}function Un(){let n=new ae("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(Tr()),n.addCommand(Ar()),n.addCommand(Or()),n.addCommand(Ur()),n}function Tr(){return new ae("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.",Dr,[]).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 Er(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}function Dr(n,e){return[...e,n]}async function Er(n,e){let t=new Ne,o=new Oe,r=await v(process.cwd(),t),s=await Fn(n,r,o),{transformation:a,transformationKanonaks:i}=s;console.log(`Transformation: ${me(a)}`);let c=Ue(a,i);e.scope.length===0&&(console.error("At least one --scope is required."),process.exit(1));let l=[],u=new Map;for(let y of e.scope){let b=await Fr(y,r,t,o);l.push(...b);let w=await Vr(b,c.inputPattern.matchesClass,r);for(let $ of w){let S=Br($);S&&!u.has(S)&&u.set(S,$)}console.log(`Scope: ${y} \u2014 found ${w.length} instance(s) of ${c.inputPattern.matchesClass.publisher}/${c.inputPattern.matchesClass.package_}/${c.inputPattern.matchesClass.name}`)}let p=[...u.values()],m=l;e.scope.length>1&&console.log(`Total across ${e.scope.length} scope(s): ${p.length} unique instance(s)`),p.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=jr(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 Kr().run({transformation:a,instances:p,allKanonaks:m,transformationKanonaks:i,repository:r,parser:t,objectParser:o,outputFormat:h}),g=Cr(e.out);vr(g,{recursive:!0});for(let y of f){let b=Hr(y.fileName),w=Pr(g,`${b}${k.extension}`);$r(w,y.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${f.length} artifact(s) written to ${g}`)}function jr(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 Ar(){return new ae("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await Nr()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function Nr(){let n=new Ne,e=new Oe,t=await v(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let a of o)try{let i=new re(a,t),c=await e.parseKanonaks(i),l=Ae(c);for(let u of l){let p=Fe(u);if(!p)continue;let m=r.get(p)??[];m.push({tx:u,kanonaks:c,doc:a}),r.set(p,m)}}catch{}let s=[];for(let a of r.values()){if(a.length===1){s.push(An(a[0].tx,a[0].kanonaks));continue}let i=Le(a.map(l=>l.doc));if(!i.chosen)continue;let c=a.find(l=>l.doc===i.chosen);c&&s.push(An(c.tx,c.kanonaks))}if(s.length===0){console.log("No Transformation instances found in the current workspace.");return}s.sort((a,i)=>a.uri.localeCompare(i.uri));for(let a of s)console.log(`${a.uri}`),console.log(` matches: ${a.matchesClass}`),console.log(` outputs: ${a.outputs.join(", ")}`)}function Or(){return new ae("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 Lr(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Lr(n){let e=new Ne,t=new Oe,o=await v(process.cwd(),e),{transformation:r,transformationKanonaks:s}=await Fn(n,o,t),a=Ue(r,s);if(console.log(`Transformation: ${me(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${pe(a.inputPattern.matchesClass)}`),a.inputPattern.requires.length>0){console.log(" Required properties:");for(let i of a.inputPattern.requires)console.log(` - ${pe(i)}`)}else console.log(" Required properties: (none)");if(console.log(),console.log(`Outputs: ${Array.from(a.outputs).sort().join(", ")}`),console.log(),a.overrides.size>0){console.log("Format overrides:");for(let[i,c]of a.overrides){if(console.log(` ${i}:`),c.metadataKeys&&console.log(` metadata keys: ${c.metadataKeys.join(", ")}`),c.metadataRenames.size>0){let l=[];for(let[u,p]of c.metadataRenames)l.push(`${u} \u2192 ${p}`);console.log(` metadata renames: ${l.join(", ")}`)}c.trailingNewline!==void 0&&console.log(` trailing newline: ${c.trailingNewline}`)}console.log()}console.log(`Rule root kind: ${a.rule.kind}`),a.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${pe(a.rule.astClass)}`),console.log(`Rule root bindings: ${a.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${a.artifactName.kind}`)}function Ur(){return new ae("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,s;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],s=k.slice(2).join("/")}else s=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=Mr(n),k=Mn(m,h,`${o}/${r}`),d=new re(k,e),f=await t.parseKanonaks(d),g=Ir(f,{publisher:o,package_:r,name:s,version:""});if(!g){let y=Ae(f),b=y.find(w=>w.name===s);if(!b)throw new Error(`Transformation "${s}" 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 a=await e.getAllDocumentsAsync(),i=new Map;for(let m of a)try{let h=new re(m,e),k=await t.parseKanonaks(h),d=Ae(k);for(let f of d){if(f.name!==s)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 "${s}" 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(Tr()),n.addCommand(Ar()),n.addCommand(Or()),n.addCommand(Ur()),n}function Tr(){return new ae("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.",Dr,[]).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 Er(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}function Dr(n,e){return[...e,n]}async function Er(n,e){let t=new Ne,o=new Oe,r=await v(process.cwd(),t),s=await Fn(n,r,o),{transformation:a,transformationKanonaks:i}=s;console.log(`Transformation: ${me(a)}`);let c=Ue(a,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 Fr(y,r,t,o);l.push(...b);let w=await Vr(b,c.inputPattern.matchesClass,r);for(let $ of w){let S=Br($);S&&!p.has(S)&&p.set(S,$)}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 f=jr(c.outputs,e.format);console.log(`Output format: ${f}`);let k=Ln[f];if(!k)throw new Error(`Unknown format "${f}". Run \`kanonak transform formats\` to see what the runner supports.`);let g=await new Ir().run({transformation:a,instances:u,allKanonaks:m,transformationKanonaks:i,repository:r,parser:t,objectParser:o,outputFormat:f}),h=Cr(e.out);vr(h,{recursive:!0});for(let y of g){let b=Hr(y.fileName),w=Pr(h,`${b}${k.extension}`);$r(w,y.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${g.length} artifact(s) written to ${h}`)}function jr(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 Ar(){return new ae("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await Nr()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function Nr(){let n=new Ne,e=new Oe,t=await v(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let a of o)try{let i=new re(a,t),c=await e.parseKanonaks(i),l=Ae(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:a}),r.set(u,m)}}catch{}let s=[];for(let a of r.values()){if(a.length===1){s.push(An(a[0].tx,a[0].kanonaks));continue}let i=Le(a.map(l=>l.doc));if(!i.chosen)continue;let c=a.find(l=>l.doc===i.chosen);c&&s.push(An(c.tx,c.kanonaks))}if(s.length===0){console.log("No Transformation instances found in the current workspace.");return}s.sort((a,i)=>a.uri.localeCompare(i.uri));for(let a of s)console.log(`${a.uri}`),console.log(` matches: ${a.matchesClass}`),console.log(` outputs: ${a.outputs.join(", ")}`)}function Or(){return new ae("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 Lr(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Lr(n){let e=new Ne,t=new Oe,o=await v(process.cwd(),e),{transformation:r,transformationKanonaks:s}=await Fn(n,o,t),a=Ue(r,s);if(console.log(`Transformation: ${me(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${pe(a.inputPattern.matchesClass)}`),a.inputPattern.requires.length>0){console.log(" Required properties:");for(let i of a.inputPattern.requires)console.log(` - ${pe(i)}`)}else console.log(" Required properties: (none)");if(console.log(),console.log(`Outputs: ${Array.from(a.outputs).sort().join(", ")}`),console.log(),a.overrides.size>0){console.log("Format overrides:");for(let[i,c]of a.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: ${a.rule.kind}`),a.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${pe(a.rule.astClass)}`),console.log(`Rule root bindings: ${a.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${a.artifactName.kind}`)}function Ur(){return new ae("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,s;if(n.includes("/")){let m=n.indexOf("@"),f=n;if(m!==-1){let d=n.indexOf("/",m);if(d===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);f=n.substring(0,m)+n.substring(d)}let k=f.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],s=k.slice(2).join("/")}else s=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 f=Mr(n),k=Mn(m,f,`${o}/${r}`),d=new re(k,e),g=await t.parseKanonaks(d),h=Kr(g,{publisher:o,package_:r,name:s,version:""});if(!h){let y=Ae(g),b=y.find(w=>w.name===s);if(!b)throw new Error(`Transformation "${s}" not found in package ${o}/${r}. Package contains ${y.length} Transformation(s): ${y.map(w=>w.name).join(", ")||"(none)"}`);return{transformation:b,transformationKanonaks:g}}return{transformation:h,transformationKanonaks:g}}let a=await e.getAllDocumentsAsync(),i=new Map;for(let m of a)try{let f=new re(m,e),k=await t.parseKanonaks(f),d=Ae(k);for(let g of d){if(g.name!==s)continue;let h=Fe(g);if(!h)continue;let y=i.get(h)??[];y.push({tx:g,kanonaks:k,doc:m}),i.set(h,y)}}catch{}if(i.size===0)throw new Error(`No Transformation named "${s}" 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 "${s}" 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])),u=Le(c.map(m=>m.doc));if(!u.chosen)throw new Error(`Could not select a Transformation version for "${s}".`);let p=l.get(u.chosen);if(u.multipleVersionsPresent){let m=d=>{let f=d.metadata.namespace_?.version;return f?On(f):""},h=p.tx.namespace??"",k=h.includes("@")?h.substring(0,h.indexOf("@")):h;console.warn(`Warning: Transformation "${s}" has ${c.length} versions present (${c.map(d=>m(d.doc)).filter(Boolean).join(", ")}); using @${m(u.chosen)}. Pin with ${k}@<version>/${s} to suppress this warning.`)}return{transformation:p.tx,transformationKanonaks:p.kanonaks}}async function Fr(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||En(n)&&Sr(n).isFile()){if(!En(n))throw new Error(`Scope file not found: ${n}`);let k=wr(n,"utf-8"),d=t.parse(k),f=new re(d,e);return o.parseKanonaks(f)}let s=n.indexOf("@"),a=s===-1?n:n.substring(0,s),i=s===-1?void 0:n.substring(s+1),c=a.indexOf("/");if(c===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=a.substring(0,c),u=a.substring(c+1),p=await e.getDocumentsByNamespaceAsync(l,u);if(p.length===0)throw new Error(`Scope package ${l}/${u} not found in the local workspace or cache.`);let m=Mn(p,i,`${l}/${u}`),h=new re(m,e);return o.parseKanonaks(h)}function Mr(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 Mn(n,e,t){let o=s=>{let a=s.metadata.namespace_?.version;return a?On(a):""},r=Le(n,{requestedVersion:e});if(r.exactRequestedVersionMissing){let s=n.map(o).filter(Boolean).sort().join(", ");throw new Error(`${t}@${e} not found in the local workspace or cache. Available versions: ${s||"(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=Ue(n,e);return{uri:me(n),matchesClass:pe(t.inputPattern.matchesClass),outputs:Array.from(t.outputs).sort()}}catch(t){return{uri:me(n),matchesClass:`(compile error: ${t.message})`,outputs:[]}}}function me(n){let e=n.namespace||"",t=e.indexOf("@");return`${t===-1?e:e.substring(0,t)}/${n.name}`}function pe(n){return`${n.publisher}/${n.package_}/${n.name}`}function Hr(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Vr(n,e,t){let o=new Map;for(let a of n){if(!(a instanceof _r))continue;let i=Fe(a);i&&o.set(i,a)}let r=[];try{r=(await new Rr({vocabulary:new xr}).reason(t)).getInstancesOfClass(Nn(e.publisher,e.package_,e.name))}catch{}let s=[];for(let a of r){let i=o.get(a);i&&s.push(i)}return s.length>0?s:je(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 Br(n){let e=n.namespace??"";return!e||!n.name?null:`${e}/${n.name}`}import{Command as zr}from"commander";import{writeFileSync as qr,mkdirSync as Wr}from"fs";import{join as Gr,resolve as Jr}from"path";import{KanonakParser as Yr,KanonakObjectParser as Xr,SubjectKanonak as Bn,findDerivation as Zr}from"@kanonak-protocol/sdk";import{TransformationRunnerV3 as Qr}from"@kanonak-protocol/sdk/transformations";var ea={publisher:"kanonak.org",package_:"formats",name:"html"},na={publisher:"kanonak.org",package_:"derivation",name:"default"},ta={html:".html",markdown:".md",json:".json",yaml:".yaml",xml:".xml",svg:".svg",typescript:".ts","c-sharp":".cs",rust:".rs",python:".py"};function oa(n){return n==="markdown"?"markdown-with-frontmatter":n}function zn(){return new zr("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=Le(c.map(m=>m.doc));if(!p.chosen)throw new Error(`Could not select a Transformation version for "${s}".`);let u=l.get(p.chosen);if(p.multipleVersionsPresent){let m=d=>{let g=d.metadata.namespace_?.version;return g?On(g):""},f=u.tx.namespace??"",k=f.includes("@")?f.substring(0,f.indexOf("@")):f;console.warn(`Warning: Transformation "${s}" has ${c.length} versions present (${c.map(d=>m(d.doc)).filter(Boolean).join(", ")}); using @${m(p.chosen)}. Pin with ${k}@<version>/${s} to suppress this warning.`)}return{transformation:u.tx,transformationKanonaks:u.kanonaks}}async function Fr(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||En(n)&&Sr(n).isFile()){if(!En(n))throw new Error(`Scope file not found: ${n}`);let k=wr(n,"utf-8"),d=t.parse(k),g=new re(d,e);return o.parseKanonaks(g)}let s=n.indexOf("@"),a=s===-1?n:n.substring(0,s),i=s===-1?void 0:n.substring(s+1),c=a.indexOf("/");if(c===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=a.substring(0,c),p=a.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=Mn(u,i,`${l}/${p}`),f=new re(m,e);return o.parseKanonaks(f)}function Mr(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 Mn(n,e,t){let o=s=>{let a=s.metadata.namespace_?.version;return a?On(a):""},r=Le(n,{requestedVersion:e});if(r.exactRequestedVersionMissing){let s=n.map(o).filter(Boolean).sort().join(", ");throw new Error(`${t}@${e} not found in the local workspace or cache. Available versions: ${s||"(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=Ue(n,e);return{uri:me(n),matchesClass:pe(t.inputPattern.matchesClass),outputs:Array.from(t.outputs).sort()}}catch(t){return{uri:me(n),matchesClass:`(compile error: ${t.message})`,outputs:[]}}}function me(n){let e=n.namespace||"",t=e.indexOf("@");return`${t===-1?e:e.substring(0,t)}/${n.name}`}function pe(n){return`${n.publisher}/${n.package_}/${n.name}`}function Hr(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Vr(n,e,t){let o=new Map;for(let a of n){if(!(a instanceof _r))continue;let i=Fe(a);i&&o.set(i,a)}let r=[];try{r=(await new Rr({vocabulary:new xr}).reason(t)).getInstancesOfClass(Nn(e.publisher,e.package_,e.name))}catch{}let s=[];for(let a of r){let i=o.get(a);i&&s.push(i)}return s.length>0?s:je(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 Br(n){let e=n.namespace??"";return!e||!n.name?null:`${e}/${n.name}`}import{Command as zr}from"commander";import{writeFileSync as qr,mkdirSync as Wr}from"fs";import{join as Gr,resolve as Jr}from"path";import{KanonakParser as Yr,KanonakObjectParser as Xr,SubjectKanonak as Bn,findDerivation as Zr}from"@kanonak-protocol/sdk";import{TransformationRunnerV3 as Qr}from"@kanonak-protocol/sdk/transformations";var ea={publisher:"kanonak.org",package_:"formats",name:"html"},na={publisher:"kanonak.org",package_:"derivation",name:"default"},ta={html:".html",markdown:".md",json:".json",yaml:".yaml",xml:".xml",svg:".svg",typescript:".ts","c-sharp":".cs",rust:".rs",python:".py"};function oa(n){return n==="markdown"?"markdown-with-frontmatter":n}function zn(){return new zr("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,25 +108,25 @@ 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 ra(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function ra(n,e){let t=j(n);if(!t||!t.instanceName)throw new Error(`Invalid resource URI "${n}". Expected publisher/package[@version]/instance.`);let o=new Yr,r=new Xr,s=await v(process.cwd(),o),a=await r.parseKanonaks(s),i=aa(a,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: ${Hn(i)}`);let c=ia(e.format),l=ca(e.variant),u=Zr(i,c,l,a);if(!u)throw new Error(`No derivation found for resource ${Hn(i)} at (format=${e.format}, variant=${e.variant}). The class hierarchy declares no binding and no universal default applies.`);console.log(`Derivation: ${la(u)} \u2192 ${Vn(u.transformation)}`);let p=sa(a,u.transformation);if(!p)throw new Error(`Transformation ${Vn(u.transformation)} not found in the workspace or cache. The binding pointed at a transformation the resolver cannot locate.`);let m=oa(e.format),k=await new Qr().run({transformation:p,instances:[i],allKanonaks:a,repository:s,parser:o,objectParser:r,outputFormat:m}),d=Jr(e.out);Wr(d,{recursive:!0});let f=ta[e.format]??"";for(let g of k){let y=ua(g.fileName),b=Gr(d,`${y}${f}`);qr(b,g.content,"utf-8"),console.log(` wrote ${b}`)}console.log(`Done. ${k.length} artifact(s) written to ${d}`)}function aa(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 sa(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 ia(n){if(n.includes("/")){let e=j(n);if(!e||!e.instanceName)throw new Error(`Invalid --format URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...ea,name:n}}function ca(n){if(n.includes("/")){let e=j(n);if(!e||!e.instanceName)throw new Error(`Invalid --variant URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...na,name:n}}function Hn(n){return`${n.namespace}/${n.name}`}function Vn(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}function la(n){return n.source==="instance"?"instance override":`class ${n.source.publisher}/${n.source.package_}/${n.source.name}`}function ua(n){return n.replace(/[^a-zA-Z0-9._@-]+/g,"_")}import{Command as pa}from"commander";import{writeFileSync as I,mkdirSync as se}from"fs";import{join as P,resolve as qn}from"path";import{KanonakParser as ma,KanonakObjectParser as da,SubjectKanonak as fa,LookRenderer as ga}from"@kanonak-protocol/sdk";import{TransformationEngine as ha}from"@kanonak-protocol/sdk/transformations";import{readFileSync as ka}from"fs";var ya=[{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 pa("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 ba(n)})}async function ba(n){let e=qn(n.workspace),t=qn(n.out),o=new ma,r=new da,s=[];ne(e,s),s.length===0&&(console.error(`No .kan.yml files found under ${e}`),process.exit(1)),console.log(`Found ${s.length} local package file(s) under ${e}`);let a=new Set;for(let f of s)try{let g=ka(f,"utf-8"),b=o.parse(g).metadata?.namespace_;if(!b)continue;let w=b.version;a.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: ${[...a].join(", ")}`);let i=await v(e,o),c=await r.parseKanonaks(i),l=c.filter(f=>!(!(f instanceof fa)||!a.has(f.namespace||"")));console.log(`Publishing ${l.length} resource(s) to ${t}`);let u=new ha(i,o,r),p=new ga(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 S=P(t,w,$);se(S,{recursive:!0});let ce=!!p.findCascadedLook(f),O=$.split(".").map(Number),W=O.length===3&&O.every(D=>!Number.isNaN(D))?{major:O[0],minor:O[1],patch:O[2]}:void 0,le=p.renderRawMarkdown(f);le!==void 0&&(I(P(S,`${f.name}.md`),le,"utf-8"),m+=1);for(let D of ya){let L=D.format.name;try{let E,U;if(ce&&(L==="html"||L==="stylesheet"))E=L==="html"?p.renderDocument(f):p.renderStylesheet(f),U=`${f.name}${D.fileExtension}`;else if(L==="svg")E=p.renderSvg(f),U=`${f.name}${D.fileExtension}`;else{let Bt={publisher:y,package_:w,name:f.name,...W?{version:W}:{}},ue=await u.render({resource:Bt,format:D.format});E=ue.content,L==="html"?U=`${f.name}${D.fileExtension}`:U=ue.filename.includes(".")?ue.filename:`${ue.filename}${D.fileExtension}`}let Vt=P(S,U);I(Vt,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=wa(t,l,p);console.log(`Wrote ${k} package overview page(s).`),$a(t,l,p);let d=va(t,l);console.log(`Wrote ${d} version-form redirect stub(s).`)}function wa(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[u,p]=l.split("@");if(!u||!p||i.name!==u)continue;let m=p.split(".").map(Number);if(m.length!==3||m.some(d=>Number.isNaN(d)))continue;let h={verStr:p,major:m[0],minor:m[1],patch:m[2]};o.has(u)||o.set(u,[]),o.get(u).push({resource:i,ver:h});let k=r.get(u);(!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(u,{resource:i,ver:h})}let s=(i,c)=>{try{return se(i,{recursive:!0}),I(P(i,"index.html"),t.renderDocument(c),"utf-8"),I(P(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},a=0;for(let[i,c]of o)for(let{resource:l,ver:u}of c)s(P(n,i,u.verStr),l)&&(a+=1);for(let[i,{resource:c}]of r){let l=P(n,i);try{if(se(l,{recursive:!0}),t.hasDeclaredView(c))I(P(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),I(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8");else{let u=(o.get(i)??[]).slice().sort((p,m)=>m.ver.major-p.ver.major||m.ver.minor-p.ver.minor||m.ver.patch-p.ver.patch).map(p=>p.ver.verStr);I(P(l,"index.html"),t.renderPackageVersionList(i,u,c),"utf-8"),I(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}a+=1}catch{}}return a}function $a(n,e,t){let o="",r=new Map;for(let u of e){let m=(u.namespace||"").split("/"),[h]=(m[1]??"").split("@");if(!m[0]||!h||(o||(o=m[0]),u.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:u,ver:f})}if(!o||r.size===0)return;let s=t.findPublisherRootView(o);if(s){I(P(n,"index.html"),t.renderDocument(s,{rootIndex:!0}),"utf-8"),I(P(n,"index.css"),t.renderStylesheet(s),"utf-8");return}let a=[...r.entries()].sort((u,p)=>u[0].localeCompare(p[0])).map(([u,{resource:p}])=>({label:u,href:`/${u}`,comment:void 0})),i=[...r.values()][0]?.resource,c=t.renderPublisherIndex(o,a,i),l=t.renderPublisherIndexStylesheet(i);I(P(n,"index.html"),c,"utf-8"),I(P(n,"index.css"),l,"utf-8")}function va(n,e){let t=new Map;for(let r of e){let s=r.namespace||"",[,a]=s.split("/");if(!a)continue;let[i,c]=a.split("@");if(!i||!c)continue;let l=c.split(".").map(Number);if(l.length!==3||l.some(p=>Number.isNaN(p)))continue;let u=`${i}/${r.name}`;t.has(u)||t.set(u,[]),t.get(u).push({verStr:c,major:l[0],minor:l[1],patch:l[2]})}let o=0;for(let[r,s]of t){let[a,i]=r.split("/");s.sort((p,m)=>m.major-p.major||m.minor-p.minor||m.patch-p.patch);let c=s[0];I(P(n,a,`${i}.html`),Me(`/${a}/${c.verStr}/${i}`),"utf-8"),o+=1;let l=new Set;for(let p of s){if(l.has(p.major))continue;l.add(p.major);let m=P(n,a,String(p.major));se(m,{recursive:!0}),I(P(m,`${i}.html`),Me(`/${a}/${p.verStr}/${i}`),"utf-8"),o+=1}let u=new Set;for(let p of s){let m=`${p.major}.${p.minor}`;if(u.has(m))continue;u.add(m);let h=P(n,a,m);se(h,{recursive:!0}),I(P(h,`${i}.html`),Me(`/${a}/${p.verStr}/${i}`),"utf-8"),o+=1}}return o}function Me(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 ra(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function ra(n,e){let t=j(n);if(!t||!t.instanceName)throw new Error(`Invalid resource URI "${n}". Expected publisher/package[@version]/instance.`);let o=new Yr,r=new Xr,s=await v(process.cwd(),o),a=await r.parseKanonaks(s),i=aa(a,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: ${Hn(i)}`);let c=ia(e.format),l=ca(e.variant),p=Zr(i,c,l,a);if(!p)throw new Error(`No derivation found for resource ${Hn(i)} at (format=${e.format}, variant=${e.variant}). The class hierarchy declares no binding and no universal default applies.`);console.log(`Derivation: ${la(p)} \u2192 ${Vn(p.transformation)}`);let u=sa(a,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=oa(e.format),k=await new Qr().run({transformation:u,instances:[i],allKanonaks:a,repository:s,parser:o,objectParser:r,outputFormat:m}),d=Jr(e.out);Wr(d,{recursive:!0});let g=ta[e.format]??"";for(let h of k){let y=ua(h.fileName),b=Gr(d,`${y}${g}`);qr(b,h.content,"utf-8"),console.log(` wrote ${b}`)}console.log(`Done. ${k.length} artifact(s) written to ${d}`)}function aa(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 sa(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 ia(n){if(n.includes("/")){let e=j(n);if(!e||!e.instanceName)throw new Error(`Invalid --format URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...ea,name:n}}function ca(n){if(n.includes("/")){let e=j(n);if(!e||!e.instanceName)throw new Error(`Invalid --variant URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...na,name:n}}function Hn(n){return`${n.namespace}/${n.name}`}function Vn(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}function la(n){return n.source==="instance"?"instance override":`class ${n.source.publisher}/${n.source.package_}/${n.source.name}`}function ua(n){return n.replace(/[^a-zA-Z0-9._@-]+/g,"_")}import{Command as pa}from"commander";import{writeFileSync as I,mkdirSync as se}from"fs";import{join as _,resolve as qn}from"path";import{KanonakParser as ma,KanonakObjectParser as da,SubjectKanonak as fa,LookRenderer as ga}from"@kanonak-protocol/sdk";import{TransformationEngine as ha}from"@kanonak-protocol/sdk/transformations";import{readFileSync as ka}from"fs";var ya=[{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 pa("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 ba(n)})}async function ba(n){let e=qn(n.workspace),t=qn(n.out),o=new ma,r=new da,s=[];ne(e,s),s.length===0&&(console.error(`No .kan.yml files found under ${e}`),process.exit(1)),console.log(`Found ${s.length} local package file(s) under ${e}`);let a=new Set;for(let g of s)try{let h=ka(g,"utf-8"),b=o.parse(h).metadata?.namespace_;if(!b)continue;let w=b.version;a.add(`${b.publisher}/${b.package_}@${w.major}.${w.minor}.${w.patch}`)}catch(h){console.warn(` warning: failed to parse ${g}: ${h.message}`)}console.log(`Local namespaces: ${[...a].join(", ")}`);let i=await v(e,o),c=await r.parseKanonaks(i),l=c.filter(g=>!(!(g instanceof fa)||!a.has(g.namespace||"")));console.log(`Publishing ${l.length} resource(s) to ${t}`);let p=new ha(i,o,r),u=new ga(c),m=0,f=0;for(let g of l){let h=g.namespace||"",[y,b]=h.split("/");if(!y||!b)continue;let[w,$]=b.split("@");if(!w||!$)continue;let S=_(t,w,$);se(S,{recursive:!0});let ce=!!u.findCascadedLook(g),O=$.split(".").map(Number),W=O.length===3&&O.every(D=>!Number.isNaN(D))?{major:O[0],minor:O[1],patch:O[2]}:void 0,le=u.renderRawMarkdown(g);le!==void 0&&(I(_(S,`${g.name}.md`),le,"utf-8"),m+=1);for(let D of ya){let L=D.format.name;try{let E,U;if(ce&&(L==="html"||L==="stylesheet"))E=L==="html"?u.renderDocument(g):u.renderStylesheet(g),U=`${g.name}${D.fileExtension}`;else if(L==="svg")E=u.renderSvg(g),U=`${g.name}${D.fileExtension}`;else{let Bt={publisher:y,package_:w,name:g.name,...W?{version:W}:{}},ue=await p.render({resource:Bt,format:D.format});E=ue.content,L==="html"?U=`${g.name}${D.fileExtension}`:U=ue.filename.includes(".")?ue.filename:`${ue.filename}${D.fileExtension}`}let Vt=_(S,U);I(Vt,E,"utf-8"),m+=1}catch(E){console.warn(` ${y}/${w}@${$}/${g.name} [${L}]: ${E.message}`),f+=1}}}console.log(`Done. ${m} artifact(s) written, ${f} skipped.`),f>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=wa(t,l,u);console.log(`Wrote ${k} package overview page(s).`),$a(t,l,u);let d=va(t,l);console.log(`Wrote ${d} version-form redirect stub(s).`)}function wa(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 f={verStr:u,major:m[0],minor:m[1],patch:m[2]};o.has(p)||o.set(p,[]),o.get(p).push({resource:i,ver:f});let k=r.get(p);(!k||f.major>k.ver.major||f.major===k.ver.major&&f.minor>k.ver.minor||f.major===k.ver.major&&f.minor===k.ver.minor&&f.patch>k.ver.patch)&&r.set(p,{resource:i,ver:f})}let s=(i,c)=>{try{return se(i,{recursive:!0}),I(_(i,"index.html"),t.renderDocument(c),"utf-8"),I(_(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},a=0;for(let[i,c]of o)for(let{resource:l,ver:p}of c)s(_(n,i,p.verStr),l)&&(a+=1);for(let[i,{resource:c}]of r){let l=_(n,i);try{if(se(l,{recursive:!0}),t.hasDeclaredView(c))I(_(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),I(_(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);I(_(l,"index.html"),t.renderPackageVersionList(i,p,c),"utf-8"),I(_(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}a+=1}catch{}}return a}function $a(n,e,t){let o="",r=new Map;for(let a of e){let c=(a.namespace||"").split("/"),[l]=(c[1]??"").split("@");if(!c[0]||!l||(o||(o=c[0]),a.name!==l))continue;let p=(c[1]??"").split("@")[1]??"",u=p.split(".").map(Number);if(u.length!==3||u.some(k=>Number.isNaN(k)))continue;let m={verStr:p,major:u[0],minor:u[1],patch:u[2]},f=r.get(l);(!f||m.major>f.ver.major||m.major===f.ver.major&&m.minor>f.ver.minor||m.major===f.ver.major&&m.minor===f.ver.minor&&m.patch>f.ver.patch)&&r.set(l,{resource:a,ver:m})}if(!o||r.size===0)return;let s=t.publisherSubject(o);I(_(n,"index.html"),t.renderDocument(s,{rootIndex:!0}),"utf-8"),I(_(n,"index.css"),t.renderStylesheet(s),"utf-8")}function va(n,e){let t=new Map;for(let r of e){let s=r.namespace||"",[,a]=s.split("/");if(!a)continue;let[i,c]=a.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,s]of t){let[a,i]=r.split("/");s.sort((u,m)=>m.major-u.major||m.minor-u.minor||m.patch-u.patch);let c=s[0];I(_(n,a,`${i}.html`),Me(`/${a}/${c.verStr}/${i}`),"utf-8"),o+=1;let l=new Set;for(let u of s){if(l.has(u.major))continue;l.add(u.major);let m=_(n,a,String(u.major));se(m,{recursive:!0}),I(_(m,`${i}.html`),Me(`/${a}/${u.verStr}/${i}`),"utf-8"),o+=1}let p=new Set;for(let u of s){let m=`${u.major}.${u.minor}`;if(p.has(m))continue;p.add(m);let f=_(n,a,m);se(f,{recursive:!0}),I(_(f,`${i}.html`),Me(`/${a}/${u.verStr}/${i}`),"utf-8"),o+=1}}return o}function Me(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 He,mkdirSync as de}from"fs";import{join as Ve,resolve as Sa,dirname as Be}from"path";import{KanonakParser as Pa,KanonakObjectParser as Ca,SubjectKanonak as Qn,ReferenceStatement as _a,ReferenceKanonak as Ra,ListStatement as xa,StringStatement as et,EmbeddedStatement as Ia,findDerivation as Gn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ka}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Ta}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as fe}from"@kanonak-protocol/sdk/uri-helpers";var A="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(Da()),n}function Da(){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 Ea(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ea(n){let e=new Pa,t=new Ca,o=await v(process.cwd(),e),r=await t.parseKanonaks(o),s=Sa(n.out);de(s,{recursive:!0});let a=await o.getAllDocumentsAsync(),i=new Set;for(let d of a){let f=d.metadata.namespace_?.toString();f&&i.add(f)}let c={publisher:A,package_:N,name:"StaticPage"},l={publisher:A,package_:N,name:"ResourcePage"},u={publisher:A,package_:N,name:"AggregateView"},p=fe(r,c).filter(d=>i.has(d.namespace||"")),m=fe(r,l).filter(d=>i.has(d.namespace||"")),h=fe(r,u).filter(d=>i.has(d.namespace||""));console.log(`Found ${p.length} StaticPage(s), ${m.length} ResourcePage(s), and ${h.length} AggregateView(s) in the workspace.`);let k=new Ta;for(let d of p){let f=ze(d,A,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=qe(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(s,f);de(Be(w),{recursive:!0}),He(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${d.name})`)}for(let d of m){let f=ze(d,A,N,"outputPath")??`${d.name}.html`,g=Xn(d,A,N,"pageOf");if(!g){console.warn(` [skip] ${d.name}: no pageOf declared`);continue}let y=r.find(K=>K instanceof Qn&&K.name===g.name&&(K.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=qe(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 S=Ve(s,f);de(Be(S),{recursive:!0}),He(S,$[0].content,"utf-8"),console.log(` wrote ${S} (ResourcePage ${d.name} \u2192 ${y.name})`)}for(let d of h){let f=ze(d,A,N,"outputPath");if(!f){console.warn(` [skip] ${d.name}: no outputPath declared`);continue}let g=Xn(d,A,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=ja(d,A,N,"scopeSources"),w=Aa(d);if(!w){console.warn(` [skip] ${d.name}: no transformation declared`);continue}let $=qe(r,w);if(!$){console.warn(` [skip] ${d.name}: transformation ${We(w)} not found`);continue}let S=await Oa(b,o),K=[],ce=new Set;for(let le of S){let D=await La(le,o,e,t),L=fe(D,y);for(let E of L){let U=`${E.namespace}/${E.name}`;ce.has(U)||(ce.add(U),K.push(E))}}console.log(` ${d.name}: ${K.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${S.length} scope(s)`);let O=await k.run({transformation:$,instances:K,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 W=Ve(s,f);de(Be(W),{recursive:!0}),He(W,O[0].content,"utf-8"),console.log(` wrote ${W} (AggregateView ${d.name})`)}console.log("Site build complete.")}function ze(n,e,t,o){for(let r of n.statement)if(r instanceof et&&ge(r,e,t,o))return r.object}function ja(n,e,t,o){for(let r of n.statement){if(!(r instanceof xa)||!ge(r,e,t,o))continue;let s=[];for(let a of r.object??[]){let i=a.value;typeof i=="string"&&s.push(i)}return s}return[]}function Xn(n,e,t,o){for(let r of n.statement)if(r instanceof _a&&ge(r,e,t,o)&&r.object instanceof Ra)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Aa(n){for(let e of n.statement)if(e instanceof Ia&&ge(e,A,N,"transformation"))return Na(e.object)}function Na(n){let e,t,o,r;for(let s of n.statement){if(!(s instanceof et))continue;let a=s.predicate?.subject?.name;a==="publisher"?e=s.object:a==="package"?t=s.object:a==="version"?o=s.object:a==="name"&&(r=s.object)}if(!(!e||!t||!o||!r))return{publisher:e,package_:t,version:o,name:r}}function ge(n,e,t,o){let r=n.predicate?.subject;return r?r.publisher===e&&r.package_===t&&r.name===o:!1}function qe(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 We(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function Oa(n,e){let t=[];for(let o of n){let r=o.indexOf("@*");if(r===-1){t.push(o);continue}let s=o.substring(0,r),a=s.indexOf("/");if(a===-1){t.push(o);continue}let i=s.substring(0,a),c=s.substring(a+1),l=await e.getDocumentsByNamespaceAsync(i,c);for(let u of l){let p=u.metadata.namespace_;if(!p)continue;let m=p.version;t.push(`${p.publisher}/${p.package_}@${m.major}.${m.minor}.${m.patch}`)}}return t}async function La(n,e,t,o){let r=n.indexOf("/"),s=n.indexOf("@");if(r===-1||s===-1)return[];let a=n.substring(0,r),i=n.substring(r+1,s),c=n.substring(s+1),l=await e.getDocumentsByNamespaceAsync(a,i);for(let u of l){let p=u.metadata.namespace_?.version;if(p&&`${p.major}.${p.minor}.${p.patch}`===c){let m=new Ka(u,e);return o.parseKanonaks(m)}}return[]}import{Command as Ua}from"commander";import{createServer as Fa}from"http";import{watch as Ma}from"fs";import{resolve as Ha,join as Va}from"path";import{homedir as Ba}from"os";import{loadServerModel as za,route as qa}from"@kanonak-protocol/sdk/server";import{SearchIndex as Wa}from"@kanonak-protocol/sdk/search";import{resolveDisplayValue as Ga,subjectUri as Ja}from"@kanonak-protocol/sdk";function tt(){return new Ua("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).option("--search","Enable opt-in semantic search at ?q= (builds an embedding index).",!1).action(async n=>{let e=Ha(n.root),t=Number(n.port);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error(`Invalid --port "${n.port}".`);let o,r,s=async a=>{let i=Date.now(),c=await za(e,n.publisher?{publisher:n.publisher}:{});if(o=c,n.search){let u=new Wa,p=await u.build(c.catalog,{cacheDir:Va(Ba(),".kanonak","search"),include:m=>c.localNamespaces.has(m.namespace??"")});r=u,console.log(`[search] indexed ${p.size} resource(s)${p.cached?" (from cache)":""}`)}let l=c.availablePublishers.filter(u=>u!==c.publisher);console.log(`[model] serving ${c.publisher} \u2014 ${c.pkgVersions.size} package(s)${a?` (${a})`:""} in ${Date.now()-i}ms`+(l.length?` [also in workspace: ${l.join(", ")} \u2014 switch with --publisher]`:""))};try{await s()}catch(a){console.error(`[error] ${a.message}`),process.exitCode=1;return}if(n.watch){let a;Ma(e,{recursive:!0},(i,c)=>{!c||!String(c).endsWith(".kan.yml")||(clearTimeout(a),a=setTimeout(()=>{s(`changed: ${c}`).catch(l=>console.error("[reload error]",l.message))},150))}),console.log("[watch] re-loading on .kan.yml changes")}Fa(async(a,i)=>{let c="/";try{let l=new URL(a.url??"/","http://localhost");c=decodeURIComponent(l.pathname);let u=l.searchParams.get("q");if(u&&r){let m=await r.query(u,{scope:Ya(o.publisher,c),limit:30}),h=Za(o,u,m);i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(h),console.log(`200 ${a.method} ${c}?q=${u} (${m.length} hit(s))`);return}let p=qa(o,c,a.headers.accept??"");i.writeHead(p.status,p.headers),i.end(p.body),console.log(`${p.status} ${a.method} ${c}${p.headers.Location?` -> ${p.headers.Location}`:""}`)}catch(l){i.writeHead(500,{"Content-Type":"text/plain; charset=utf-8"}),i.end(String(l?.stack??l)),console.error(`500 ${c}: ${l?.message??l}`)}}).listen(t,()=>{console.log(`kanonak origin server \u2192 http://localhost:${t}/ (root=${e})`),n.search&&console.log("[search] enabled \u2014 append ?q=<keywords> at any level")})})}function Ya(n,e){let t=e.split("/").filter(Boolean);if(t.length!==0)return`${n}/${t[0]}@`}function Xa(n,e){let t=Ja(e);if(!t)return"#";let o=t.version?`/${t.version.major}.${t.version.minor}.${t.version.patch}`:"";return t.publisher===n.publisher?`/${t.package_}${o}/${t.name}`:`https://${t.publisher}/${t.package_}${o}/${t.name}`}function Z(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Za(n,e,t){let o=t.map(r=>{let s=Ga(n.catalog,r.subject),a=Xa(n,r.subject),i=Math.max(0,Math.min(100,Math.round(r.score*100))),c=s.summary?`<span class="kan-pkg-card-comment">${Z(s.summary.slice(0,160))}</span>`:"";return`<a class="kan-pkg-card" href="${Z(a)}"><span class="kan-pkg-card-body"><span class="kan-pkg-card-title">${Z(s.label)}</span>${c}<span style="display:block;height:5px;border-radius:3px;margin-top:8px;background:var(--kan-accent,#888);width:${i}%"></span><span class="kan-pkg-card-comment">${i}% match</span></span></a>`}).join("");return`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Search: ${Z(e)}</title><link rel="stylesheet" href="/index.css"></head><body><main class="kan-page" style="max-width:960px;margin:0 auto;padding:2rem"><form method="get" style="margin-bottom:1.5rem"><input name="q" value="${Z(e)}" placeholder="Search\u2026" style="width:100%;padding:.6rem .8rem;font-size:1rem;box-sizing:border-box"></form><h1>Results for \u201C${Z(e)}\u201D</h1><section class="kan-pkg-grid">${o||"<p>No matches.</p>"}</section></main></body></html>`}import{Command as Qa}from"commander";import{resolve as es,join as ns}from"path";import{homedir as ts}from"os";import{readFileSync as os}from"fs";import{KanonakParser as ot,KanonakObjectParser as rs,PublisherIndex as rt,CredentialStore as at,createAuthenticatedFetch as st,FileSystemKanonakDocumentRepository as as,Reasoner as ss,KanonakVocabulary as is,getGlobalCachePath as cs,makeUriKey as ls,resolveDisplayValue as us,subjectUri as ps,contextTypesOf as ms,collectKanonakFiles as ds}from"@kanonak-protocol/sdk";import{SearchIndex as fs}from"@kanonak-protocol/sdk/search";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 it(){return new Qa("search").description("Semantic-search your workspace (-q), browse a publisher's catalogue, or find instances of a class").argument("[publisher]","Publisher domain (e.g. kanonak.org) \u2014 for the catalogue / --type modes").option("-q, --query <text>","Semantically search the LOCAL workspace for resources matching free-text keywords").option("--root <dir>","Workspace root for -q",".").option("--scope <prefix>","Limit -q to namespaces starting with this prefix (e.g. kanonak.org/look@)").option("--limit <n>","Max results for -q","20").option("--format <fmt>","Output for -q: text | json","text").option("--all","For -q: index imported packages too (default: only your workspace's own resources)",!1).option("--type <uri>","Class URI to search for, in publisher/package/Name form").action(async(n,e)=>{if(e.query){await hs(e);return}n||(console.error(`Nothing to search. Either:
117
+ `}import{Command as Zn}from"commander";import{writeFileSync as He,mkdirSync as de}from"fs";import{join as Ve,resolve as Sa,dirname as Be}from"path";import{KanonakParser as Pa,KanonakObjectParser as Ca,SubjectKanonak as Qn,ReferenceStatement as _a,ReferenceKanonak as Ra,ListStatement as xa,StringStatement as et,EmbeddedStatement as Ka,findDerivation as Gn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ia}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Ta}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as fe}from"@kanonak-protocol/sdk/uri-helpers";var A="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(Da()),n}function Da(){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 Ea(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ea(n){let e=new Pa,t=new Ca,o=await v(process.cwd(),e),r=await t.parseKanonaks(o),s=Sa(n.out);de(s,{recursive:!0});let a=await o.getAllDocumentsAsync(),i=new Set;for(let d of a){let g=d.metadata.namespace_?.toString();g&&i.add(g)}let c={publisher:A,package_:N,name:"StaticPage"},l={publisher:A,package_:N,name:"ResourcePage"},p={publisher:A,package_:N,name:"AggregateView"},u=fe(r,c).filter(d=>i.has(d.namespace||"")),m=fe(r,l).filter(d=>i.has(d.namespace||"")),f=fe(r,p).filter(d=>i.has(d.namespace||""));console.log(`Found ${u.length} StaticPage(s), ${m.length} ResourcePage(s), and ${f.length} AggregateView(s) in the workspace.`);let k=new Ta;for(let d of u){let g=ze(d,A,N,"outputPath")??`${d.name}.html`,h=Gn(d,Jn,Yn,r);if(!h){console.warn(` [skip] ${d.name}: no HTML/default derivation found (check class hierarchy or universal-derivations is loaded)`);continue}let y=qe(r,h.transformation);if(!y){console.warn(` [skip] ${d.name}: transformation ${We(h.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(s,g);de(Be(w),{recursive:!0}),He(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${d.name})`)}for(let d of m){let g=ze(d,A,N,"outputPath")??`${d.name}.html`,h=Xn(d,A,N,"pageOf");if(!h){console.warn(` [skip] ${d.name}: no pageOf declared`);continue}let y=r.find(K=>K instanceof Qn&&K.name===h.name&&(K.namespace||"").startsWith(`${h.publisher}/${h.package_}@`));if(!y){console.warn(` [skip] ${d.name}: pageOf target ${h.publisher}/${h.package_}/${h.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=qe(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 S=Ve(s,g);de(Be(S),{recursive:!0}),He(S,$[0].content,"utf-8"),console.log(` wrote ${S} (ResourcePage ${d.name} \u2192 ${y.name})`)}for(let d of f){let g=ze(d,A,N,"outputPath");if(!g){console.warn(` [skip] ${d.name}: no outputPath declared`);continue}let h=Xn(d,A,N,"scopeClass");if(!h){console.warn(` [skip] ${d.name}: no scopeClass declared`);continue}let y={publisher:h.publisher,package_:h.package_,name:h.name},b=ja(d,A,N,"scopeSources"),w=Aa(d);if(!w){console.warn(` [skip] ${d.name}: no transformation declared`);continue}let $=qe(r,w);if(!$){console.warn(` [skip] ${d.name}: transformation ${We(w)} not found`);continue}let S=await Oa(b,o),K=[],ce=new Set;for(let le of S){let D=await La(le,o,e,t),L=fe(D,y);for(let E of L){let U=`${E.namespace}/${E.name}`;ce.has(U)||(ce.add(U),K.push(E))}}console.log(` ${d.name}: ${K.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${S.length} scope(s)`);let O=await k.run({transformation:$,instances:K,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 W=Ve(s,g);de(Be(W),{recursive:!0}),He(W,O[0].content,"utf-8"),console.log(` wrote ${W} (AggregateView ${d.name})`)}console.log("Site build complete.")}function ze(n,e,t,o){for(let r of n.statement)if(r instanceof et&&ge(r,e,t,o))return r.object}function ja(n,e,t,o){for(let r of n.statement){if(!(r instanceof xa)||!ge(r,e,t,o))continue;let s=[];for(let a of r.object??[]){let i=a.value;typeof i=="string"&&s.push(i)}return s}return[]}function Xn(n,e,t,o){for(let r of n.statement)if(r instanceof _a&&ge(r,e,t,o)&&r.object instanceof Ra)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Aa(n){for(let e of n.statement)if(e instanceof Ka&&ge(e,A,N,"transformation"))return Na(e.object)}function Na(n){let e,t,o,r;for(let s of n.statement){if(!(s instanceof et))continue;let a=s.predicate?.subject?.name;a==="publisher"?e=s.object:a==="package"?t=s.object:a==="version"?o=s.object:a==="name"&&(r=s.object)}if(!(!e||!t||!o||!r))return{publisher:e,package_:t,version:o,name:r}}function ge(n,e,t,o){let r=n.predicate?.subject;return r?r.publisher===e&&r.package_===t&&r.name===o:!1}function qe(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 We(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function Oa(n,e){let t=[];for(let o of n){let r=o.indexOf("@*");if(r===-1){t.push(o);continue}let s=o.substring(0,r),a=s.indexOf("/");if(a===-1){t.push(o);continue}let i=s.substring(0,a),c=s.substring(a+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 La(n,e,t,o){let r=n.indexOf("/"),s=n.indexOf("@");if(r===-1||s===-1)return[];let a=n.substring(0,r),i=n.substring(r+1,s),c=n.substring(s+1),l=await e.getDocumentsByNamespaceAsync(a,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 Ua}from"commander";import{createServer as Fa}from"http";import{watch as Ma}from"fs";import{resolve as Ha,join as Va}from"path";import{homedir as Ba}from"os";import{loadServerModel as za,route as qa}from"@kanonak-protocol/sdk/server";import{SearchIndex as Wa}from"@kanonak-protocol/sdk/search";import{resolveDisplayValue as Ga,subjectUri as Ja}from"@kanonak-protocol/sdk";function tt(){return new Ua("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).option("--search","Enable opt-in semantic search at ?q= (builds an embedding index).",!1).action(async n=>{let e=Ha(n.root),t=Number(n.port);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error(`Invalid --port "${n.port}".`);let o,r,s=async a=>{let i=Date.now(),c=await za(e,n.publisher?{publisher:n.publisher}:{});if(o=c,n.search){let p=new Wa,u=await p.build(c.catalog,{cacheDir:Va(Ba(),".kanonak","search"),include:m=>c.localNamespaces.has(m.namespace??"")});r=p,console.log(`[search] indexed ${u.size} resource(s)${u.cached?" (from cache)":""}`)}let l=c.availablePublishers.filter(p=>p!==c.publisher);console.log(`[model] serving ${c.publisher} \u2014 ${c.pkgVersions.size} package(s)${a?` (${a})`:""} in ${Date.now()-i}ms`+(l.length?` [also in workspace: ${l.join(", ")} \u2014 switch with --publisher]`:""))};try{await s()}catch(a){console.error(`[error] ${a.message}`),process.exitCode=1;return}if(n.watch){let a;Ma(e,{recursive:!0},(i,c)=>{!c||!String(c).endsWith(".kan.yml")||(clearTimeout(a),a=setTimeout(()=>{s(`changed: ${c}`).catch(l=>console.error("[reload error]",l.message))},150))}),console.log("[watch] re-loading on .kan.yml changes")}Fa(async(a,i)=>{let c="/";try{let l=new URL(a.url??"/","http://localhost");c=decodeURIComponent(l.pathname);let p=l.searchParams.get("q");if(p&&r){let m=await r.query(p,{scope:Ya(o.publisher,c),limit:30}),f=Za(o,p,m);i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(f),console.log(`200 ${a.method} ${c}?q=${p} (${m.length} hit(s))`);return}let u=qa(o,c,a.headers.accept??"");i.writeHead(u.status,u.headers),i.end(u.body),console.log(`${u.status} ${a.method} ${c}${u.headers.Location?` -> ${u.headers.Location}`:""}`)}catch(l){i.writeHead(500,{"Content-Type":"text/plain; charset=utf-8"}),i.end(String(l?.stack??l)),console.error(`500 ${c}: ${l?.message??l}`)}}).listen(t,()=>{console.log(`kanonak origin server \u2192 http://localhost:${t}/ (root=${e})`),n.search&&console.log("[search] enabled \u2014 append ?q=<keywords> at any level")})})}function Ya(n,e){let t=e.split("/").filter(Boolean);if(t.length!==0)return`${n}/${t[0]}@`}function Xa(n,e){let t=Ja(e);if(!t)return"#";let o=t.version?`/${t.version.major}.${t.version.minor}.${t.version.patch}`:"";return t.publisher===n.publisher?`/${t.package_}${o}/${t.name}`:`https://${t.publisher}/${t.package_}${o}/${t.name}`}function Z(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Za(n,e,t){let o=t.map(r=>{let s=Ga(n.catalog,r.subject),a=Xa(n,r.subject),i=Math.max(0,Math.min(100,Math.round(r.score*100))),c=s.summary?`<span class="kan-pkg-card-comment">${Z(s.summary.slice(0,160))}</span>`:"";return`<a class="kan-pkg-card" href="${Z(a)}"><span class="kan-pkg-card-body"><span class="kan-pkg-card-title">${Z(s.label)}</span>${c}<span style="display:block;height:5px;border-radius:3px;margin-top:8px;background:var(--kan-accent,#888);width:${i}%"></span><span class="kan-pkg-card-comment">${i}% match</span></span></a>`}).join("");return`<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Search: ${Z(e)}</title><link rel="stylesheet" href="/index.css"></head><body><main class="kan-page" style="max-width:960px;margin:0 auto;padding:2rem"><form method="get" style="margin-bottom:1.5rem"><input name="q" value="${Z(e)}" placeholder="Search\u2026" style="width:100%;padding:.6rem .8rem;font-size:1rem;box-sizing:border-box"></form><h1>Results for \u201C${Z(e)}\u201D</h1><section class="kan-pkg-grid">${o||"<p>No matches.</p>"}</section></main></body></html>`}import{Command as Qa}from"commander";import{resolve as es,join as ns}from"path";import{homedir as ts}from"os";import{readFileSync as os}from"fs";import{KanonakParser as ot,KanonakObjectParser as rs,PublisherIndex as rt,CredentialStore as at,createAuthenticatedFetch as st,FileSystemKanonakDocumentRepository as as,Reasoner as ss,KanonakVocabulary as is,getGlobalCachePath as cs,makeUriKey as ls,resolveDisplayValue as us,subjectUri as ps,contextTypesOf as ms,collectKanonakFiles as ds}from"@kanonak-protocol/sdk";import{SearchIndex as fs}from"@kanonak-protocol/sdk/search";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 it(){return new Qa("search").description("Semantic-search your workspace (-q), browse a publisher's catalogue, or find instances of a class").argument("[publisher]","Publisher domain (e.g. kanonak.org) \u2014 for the catalogue / --type modes").option("-q, --query <text>","Semantically search the LOCAL workspace for resources matching free-text keywords").option("--root <dir>","Workspace root for -q",".").option("--scope <prefix>","Limit -q to namespaces starting with this prefix (e.g. kanonak.org/look@)").option("--limit <n>","Max results for -q","20").option("--format <fmt>","Output for -q: text | json","text").option("--all","For -q: index imported packages too (default: only your workspace's own resources)",!1).option("--type <uri>","Class URI to search for, in publisher/package/Name form").action(async(n,e)=>{if(e.query){await hs(e);return}n||(console.error(`Nothing to search. Either:
118
118
  \u2022 semantic-search your workspace: kanonak search -q "<keywords>"
119
119
  \u2022 browse a publisher's catalogue: kanonak search <publisher>
120
- \u2022 find instances of a class: kanonak search <publisher> --type <pub>/<pkg>/<Name>`),process.exit(1)),e.type?await ys(n,e.type):await ks(n)})}async function hs(n){let e=es(n.root??"."),t=new ot,o;try{let u=await v(e,t);o=await new rs().parseKanonaks(u)}catch(u){console.error(`Failed to load workspace at ${e}: ${u.message}`),process.exit(1)}let r={cacheDir:ns(ts(),".kanonak","search"),onProgress:(u,p)=>process.stderr.write(`\r embedding ${u}/${p}\u2026 `)};if(!n.all){let u=new Set;for(let p of ds(e))try{let m=t.parse(os(p,"utf-8")).metadata?.namespace_;m?.version&&u.add(`${m.publisher}/${m.package_}@${m.version.major}.${m.version.minor}.${m.version.patch}`)}catch{}r.include=p=>u.has(p.namespace??"")}let s=new fs,a;try{a=await s.build(o,r),a.size>0&&!a.cached&&process.stderr.write(`
121
- `)}catch(u){console.error(u.message),process.exit(1)}a.size===0&&(console.error(n.all?`No resources found in the workspace at ${e}.`:`No resources defined in the workspace at ${e}. (It imports packages but defines none of its own \u2014 use --all to also search imported packages.)`),process.exit(1));let i=Number(n.limit)||20,l=(await s.query(n.query,{scope:n.scope,limit:i})).map(u=>{let p=us(o,u.subject),m=ps(u.subject),h=ms(u.subject)[0]?.name;return{uri:m?`${m.publisher}/${m.package_}/${m.name}`:u.subject.name,label:p.label,type:h??null,score:Number(u.score.toFixed(4))}});if(n.format==="json"){console.log(JSON.stringify(l,null,2));return}if(l.length===0){console.log(`No matches for "${n.query}".`);return}console.log(`Results for "${n.query}":
122
- `);for(let u of l)console.log(` ${u.score.toFixed(3)} ${u.label}${u.type?` (${u.type})`:""}`),console.log(` ${u.uri}`)}async function ks(n){let e=new at,t=st(e),o=new rt({fetchFn:t}),r;try{r=await o.listLatestPackages(n)}catch(a){console.error(`Failed to fetch publisher index for ${n}: ${a.message}`),process.exit(1)}if(r.length===0){console.log(`No packages found at ${n}.`);return}console.log(`Packages published by ${n}:
123
- `);let s=r.reduce((a,i)=>Math.max(a,i.packageName.length),0);for(let{packageName:a,version:i}of r)console.log(` ${a.padEnd(s)} @${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 ot,r=new at,s=st(r),a=new rt({fetchFn:s}),i=new T,c=new Set,l=[];try{l=await a.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(a,i,s,"kanonak.org","core-rdf",c),await Ge(a,i,s,"kanonak.org","core-owl",c),await Ge(a,i,s,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 a.getPackageUrl(g,y,b),$=await s(w,g);if(!$.ok){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${$.status} ${$.statusText}`);continue}let S=await $.text();i.put(g,y,b,S)}catch(w){console.error(`Warning: failed to fetch ${g}/${y}@${b}: ${w.message}`)}}let u=new as(cs(),!0,o),m=await new ss({vocabulary:new is}).reason(u),h=ls(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:
124
- `),d.sort();for(let f of d)console.log(` ${f}`)}async function Ge(n,e,t,o,r,s){try{let a=await n.getHighestVersion(o,r);if(!a)return;s.add(`${o}|${r}|${a}`)}catch{}}import{existsSync as bs,readFileSync as ws}from"fs";import{dirname as $s,resolve as vs}from"path";import{KanonakObjectParser as Ss,KanonakParser as Ps,canonicalForm as Cs,canonicalHash as _s,parseKanonakAddress as Rs,pickHighestDocument as xs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Is}from"@kanonak-protocol/sdk/uri-helpers";async function ct(n,e={}){let t=new Ps,o=new Ss,{document:r,source:s}=await Ks(n,t),a=await v(Ts(s),t),i=new Is(r,a),c=await o.parseKanonaks(i),l=_s(c);if(console.log(l),e.verbose){let u=Cs(c);process.stderr.write(`# canonical form for ${s}
125
- `),process.stderr.write(u),process.stderr.write(`
126
- `)}}async function Ks(n,e){if(n.endsWith(".kan.yml")){let i=vs(n);if(!bs(i))throw new Error(`kanonak hash: file not found: ${i}`);let c=ws(i,"utf-8");return{document:e.parse(c),source:i}}let t=Rs(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 v(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 s=t.version?`${t.version.major}.${t.version.minor}.${t.version.patch}`:void 0,a=xs(r,s?{requestedVersion:s}:{});if(!a.chosen){let i=s?`@${s}`:"";throw new Error(`kanonak hash: no version of ${t.publisher}/${t.package_}${i} available across local/cache/HTTP`)}return{document:a.chosen,source:n}}function Ts(n){return n.endsWith(".kan.yml")?H($s(n)):process.cwd()}import{Command as lt}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 ut(n,e,t){for(let o of e){let r=new lt(o.commandName).description(o.description.trim());for(let s of o.commands){let a=r.command(Ds(s));a.description(s.description);for(let i of s.arguments)if(i.isOption){let c=i.defaultValue!=null?`--${i.argumentName} [value]`:`--${i.argumentName} <value>`;a.option(c,"",i.defaultValue)}a.action(async(...i)=>{let c=Es(i);await js(t,o,s,i,c)})}n.addCommand(r)}}function Ds(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function Es(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof lt))return n[e];return{}}async function js(n,e,t,o,r){let s=[];for(let i of o)if(typeof i=="string")s.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 a=Je[t.actionKey];a||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(Je).join(", ")}.`),process.exit(1)),await a(n,e,s,r)}import{existsSync as pt,readFileSync as As,statSync as mt}from"fs";import{resolve as Ns}from"path";import{KanonakObjectParser as Os,PublisherIndex as Ye,PublisherConfigResolver as Ls,formatVersion as dt,pickHighestDocument as Us}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as ft}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as ee,findSubjectsByType as gt}from"@kanonak-protocol/sdk/uri-helpers";var he=class{constructor(e,t,o,r,s,a){this.fileCache=e;this.parser=t;this.publisherIndex=o;this.fetchFn=r;this.handlerRegistry=s;this.repository=a}fileCache;parser;publisherIndex;fetchFn;handlerRegistry;repository;objectParser=new Os;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 s=j(t);s||(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:a,packageName:i,version:c,instanceName:l}=s,u=await this.repository.getDocumentsByNamespaceAsync(a,i);if(u.length>0){let h=Us(u,{requestedVersion:c??void 0});if(h.chosen){let k=h.chosen.metadata.namespace_;(!k||!k.version)&&(console.error(`Document for ${a}/${i} is missing namespace metadata.`),process.exit(1));let d=dt(k.version);this.fileCache.put(a,i,d,this.parser.save(h.chosen)),await this.deployFromDoc(e,h.chosen,a,i,d,l??void 0,`${a}/${i}@${d}`,o);return}}let p=c??await this.publisherIndex.getHighestVersion(a,i);p||(console.error(`Could not resolve version for "${a}/${i}".`),await this.printPackageSuggestions(a,i,e.commandName),process.exit(1));let m=this.fileCache.get(a,i,p);if(!m){let h=await this.publisherIndex.getPackageUrl(a,i,p),k=await this.fetchFn(h,a);k.ok||(k.status===404?(console.error(`Package ${a}/${i}@${p} 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(a,i,p,m)}await this.deployFromDoc(e,this.parser.parse(m),a,i,p,l??void 0,`${a}/${i}@${p}`,o)}tryLoadFromLocalFile(e){if(!(/^[.\/\\]/.test(e)||/^[A-Za-z]:[\\/]/.test(e)||e.endsWith(".kan.yml")||pt(e)&&mt(e).isFile()))return;let o=Ns(e);(!pt(o)||!mt(o).isFile())&&(console.error(`Local file not found: ${e}`),process.exit(1));let r=As(o,"utf-8"),s=this.parser.parse(r),a=s.metadata.namespace_;return(!a||!a.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:s,content:r,publisher:a.publisher,packageName:a.package_,version:dt(a.version)}}async deployFromDoc(e,t,o,r,s,a,i,c){let l=new ft(t,this.repository),u=await this.objectParser.parseKanonaks(l),p=ht(e.managesTypeKey);p||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let m=gt(u,p);m.length===0&&(console.error(`${i} does not contain any ${ee(p)} instances.`),process.exit(1));let h=m;if(a&&(h=m.filter(f=>f.name===a),h.length===0)){console.error(`Instance "${a}" not found in ${i}.`),console.error(""),console.error(`Available ${ee(p)} 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=a?`${a} from ${i}`:`${h.length} ${ee(p)} instance(s) from ${i}`;console.log(`Installing ${k}...`);let d=this.handlerRegistry.get(e.deploymentTargetKey);d?await d.deploy({instances:h,allKanonaks:u,repository:this.repository,options:c}):console.log(`Cached ${o}/${r}@${s} (no deployment handler for "${e.deploymentTargetKey}")`)}async printPackageSuggestions(e,t,o){let r;try{r=await this.publisherIndex.listLatestPackages(e)}catch{return}let s=r.map(a=>({name:a.packageName,version:a.version,score:Fs(t,a.packageName)})).filter(a=>a.score>0).sort((a,i)=>i.score-a.score).slice(0,5);if(s.length!==0){console.error(""),console.error("Did you mean one of:");for(let a of s)console.error(` kanonak ${o} add ${e}/${a.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}),s=e.managesTypeKey||"managed";if(r.length===0){console.log(`No ${s} instances installed.`);return}console.log(`Installed ${s} instances:
120
+ \u2022 find instances of a class: kanonak search <publisher> --type <pub>/<pkg>/<Name>`),process.exit(1)),e.type?await ys(n,e.type):await ks(n)})}async function hs(n){let e=es(n.root??"."),t=new ot,o;try{let p=await v(e,t);o=await new rs().parseKanonaks(p)}catch(p){console.error(`Failed to load workspace at ${e}: ${p.message}`),process.exit(1)}let r={cacheDir:ns(ts(),".kanonak","search"),onProgress:(p,u)=>process.stderr.write(`\r embedding ${p}/${u}\u2026 `)};if(!n.all){let p=new Set;for(let u of ds(e))try{let m=t.parse(os(u,"utf-8")).metadata?.namespace_;m?.version&&p.add(`${m.publisher}/${m.package_}@${m.version.major}.${m.version.minor}.${m.version.patch}`)}catch{}r.include=u=>p.has(u.namespace??"")}let s=new fs,a;try{a=await s.build(o,r),a.size>0&&!a.cached&&process.stderr.write(`
121
+ `)}catch(p){console.error(p.message),process.exit(1)}a.size===0&&(console.error(n.all?`No resources found in the workspace at ${e}.`:`No resources defined in the workspace at ${e}. (It imports packages but defines none of its own \u2014 use --all to also search imported packages.)`),process.exit(1));let i=Number(n.limit)||20,l=(await s.query(n.query,{scope:n.scope,limit:i})).map(p=>{let u=us(o,p.subject),m=ps(p.subject),f=ms(p.subject)[0]?.name;return{uri:m?`${m.publisher}/${m.package_}/${m.name}`:p.subject.name,label:u.label,type:f??null,score:Number(p.score.toFixed(4))}});if(n.format==="json"){console.log(JSON.stringify(l,null,2));return}if(l.length===0){console.log(`No matches for "${n.query}".`);return}console.log(`Results for "${n.query}":
122
+ `);for(let p of l)console.log(` ${p.score.toFixed(3)} ${p.label}${p.type?` (${p.type})`:""}`),console.log(` ${p.uri}`)}async function ks(n){let e=new at,t=st(e),o=new rt({fetchFn:t}),r;try{r=await o.listLatestPackages(n)}catch(a){console.error(`Failed to fetch publisher index for ${n}: ${a.message}`),process.exit(1)}if(r.length===0){console.log(`No packages found at ${n}.`);return}console.log(`Packages published by ${n}:
123
+ `);let s=r.reduce((a,i)=>Math.max(a,i.packageName.length),0);for(let{packageName:a,version:i}of r)console.log(` ${a.padEnd(s)} @${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 ot,r=new at,s=st(r),a=new rt({fetchFn:s}),i=new T,c=new Set,l=[];try{l=await a.listLatestPackages(n)}catch(g){console.error(`Failed to fetch publisher index for ${n}: ${g.message}`),process.exit(1)}for(let{packageName:g,version:h}of l)c.add(`${n}|${g}|${h}`);await Ge(a,i,s,"kanonak.org","core-rdf",c),await Ge(a,i,s,"kanonak.org","core-owl",c),await Ge(a,i,s,t.publisher,t.package_,c);for(let g of c){let[h,y,b]=g.split("|");if(!i.has(h,y,b))try{let w=await a.getPackageUrl(h,y,b),$=await s(w,h);if(!$.ok){console.error(`Warning: failed to fetch ${h}/${y}@${b}: ${$.status} ${$.statusText}`);continue}let S=await $.text();i.put(h,y,b,S)}catch(w){console.error(`Warning: failed to fetch ${h}/${y}@${b}: ${w.message}`)}}let p=new as(cs(),!0,o),m=await new ss({vocabulary:new is}).reason(p),f=ls(t.publisher,t.package_,t.name),d=m.getInstancesOfClass(f).filter(g=>g!==f);if(d.length===0){console.log(`No instances of ${f} found in ${n}'s catalogue.`);return}console.log(`Instances of ${f} in ${n}'s catalogue:
124
+ `),d.sort();for(let g of d)console.log(` ${g}`)}async function Ge(n,e,t,o,r,s){try{let a=await n.getHighestVersion(o,r);if(!a)return;s.add(`${o}|${r}|${a}`)}catch{}}import{existsSync as bs,readFileSync as ws}from"fs";import{dirname as $s,resolve as vs}from"path";import{KanonakObjectParser as Ss,KanonakParser as Ps,canonicalForm as Cs,canonicalHash as _s,parseKanonakAddress as Rs,pickHighestDocument as xs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Ks}from"@kanonak-protocol/sdk/uri-helpers";async function ct(n,e={}){let t=new Ps,o=new Ss,{document:r,source:s}=await Is(n,t),a=await v(Ts(s),t),i=new Ks(r,a),c=await o.parseKanonaks(i),l=_s(c);if(console.log(l),e.verbose){let p=Cs(c);process.stderr.write(`# canonical form for ${s}
125
+ `),process.stderr.write(p),process.stderr.write(`
126
+ `)}}async function Is(n,e){if(n.endsWith(".kan.yml")){let i=vs(n);if(!bs(i))throw new Error(`kanonak hash: file not found: ${i}`);let c=ws(i,"utf-8");return{document:e.parse(c),source:i}}let t=Rs(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 v(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 s=t.version?`${t.version.major}.${t.version.minor}.${t.version.patch}`:void 0,a=xs(r,s?{requestedVersion:s}:{});if(!a.chosen){let i=s?`@${s}`:"";throw new Error(`kanonak hash: no version of ${t.publisher}/${t.package_}${i} available across local/cache/HTTP`)}return{document:a.chosen,source:n}}function Ts(n){return n.endsWith(".kan.yml")?H($s(n)):process.cwd()}import{Command as lt}from"commander";function Q(n){return`${P}/${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 ut(n,e,t){for(let o of e){let r=new lt(o.commandName).description(o.description.trim());for(let s of o.commands){let a=r.command(Ds(s));a.description(s.description);for(let i of s.arguments)if(i.isOption){let c=i.defaultValue!=null?`--${i.argumentName} [value]`:`--${i.argumentName} <value>`;a.option(c,"",i.defaultValue)}a.action(async(...i)=>{let c=Es(i);await js(t,o,s,i,c)})}n.addCommand(r)}}function Ds(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function Es(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof lt))return n[e];return{}}async function js(n,e,t,o,r){let s=[];for(let i of o)if(typeof i=="string")s.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 a=Je[t.actionKey];a||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(Je).join(", ")}.`),process.exit(1)),await a(n,e,s,r)}import{existsSync as pt,readFileSync as As,statSync as mt}from"fs";import{resolve as Ns}from"path";import{KanonakObjectParser as Os,PublisherIndex as Ye,PublisherConfigResolver as Ls,formatVersion as dt,pickHighestDocument as Us}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as ft}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as ee,findSubjectsByType as gt}from"@kanonak-protocol/sdk/uri-helpers";var he=class{constructor(e,t,o,r,s,a){this.fileCache=e;this.parser=t;this.publisherIndex=o;this.fetchFn=r;this.handlerRegistry=s;this.repository=a}fileCache;parser;publisherIndex;fetchFn;handlerRegistry;repository;objectParser=new Os;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 s=j(t);s||(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:a,packageName:i,version:c,instanceName:l}=s,p=await this.repository.getDocumentsByNamespaceAsync(a,i);if(p.length>0){let f=Us(p,{requestedVersion:c??void 0});if(f.chosen){let k=f.chosen.metadata.namespace_;(!k||!k.version)&&(console.error(`Document for ${a}/${i} is missing namespace metadata.`),process.exit(1));let d=dt(k.version);this.fileCache.put(a,i,d,this.parser.save(f.chosen)),await this.deployFromDoc(e,f.chosen,a,i,d,l??void 0,`${a}/${i}@${d}`,o);return}}let u=c??await this.publisherIndex.getHighestVersion(a,i);u||(console.error(`Could not resolve version for "${a}/${i}".`),await this.printPackageSuggestions(a,i,e.commandName),process.exit(1));let m=this.fileCache.get(a,i,u);if(!m){let f=await this.publisherIndex.getPackageUrl(a,i,u),k=await this.fetchFn(f,a);k.ok||(k.status===404?(console.error(`Package ${a}/${i}@${u} not found at ${f}.`),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 ${f} (${k.status} ${k.statusText}).`),process.exit(1)),m=await k.text(),this.fileCache.put(a,i,u,m)}await this.deployFromDoc(e,this.parser.parse(m),a,i,u,l??void 0,`${a}/${i}@${u}`,o)}tryLoadFromLocalFile(e){if(!(/^[.\/\\]/.test(e)||/^[A-Za-z]:[\\/]/.test(e)||e.endsWith(".kan.yml")||pt(e)&&mt(e).isFile()))return;let o=Ns(e);(!pt(o)||!mt(o).isFile())&&(console.error(`Local file not found: ${e}`),process.exit(1));let r=As(o,"utf-8"),s=this.parser.parse(r),a=s.metadata.namespace_;return(!a||!a.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:s,content:r,publisher:a.publisher,packageName:a.package_,version:dt(a.version)}}async deployFromDoc(e,t,o,r,s,a,i,c){let l=new ft(t,this.repository),p=await this.objectParser.parseKanonaks(l),u=ht(e.managesTypeKey);u||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let m=gt(p,u);m.length===0&&(console.error(`${i} does not contain any ${ee(u)} instances.`),process.exit(1));let f=m;if(a&&(f=m.filter(g=>g.name===a),f.length===0)){console.error(`Instance "${a}" not found in ${i}.`),console.error(""),console.error(`Available ${ee(u)} instance(s):`);for(let g of m)console.error(` - ${g.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=a?`${a} from ${i}`:`${f.length} ${ee(u)} instance(s) from ${i}`;console.log(`Installing ${k}...`);let d=this.handlerRegistry.get(e.deploymentTargetKey);d?await d.deploy({instances:f,allKanonaks:p,repository:this.repository,options:c}):console.log(`Cached ${o}/${r}@${s} (no deployment handler for "${e.deploymentTargetKey}")`)}async printPackageSuggestions(e,t,o){let r;try{r=await this.publisherIndex.listLatestPackages(e)}catch{return}let s=r.map(a=>({name:a.packageName,version:a.version,score:Fs(t,a.packageName)})).filter(a=>a.score>0).sort((a,i)=>i.score-a.score).slice(0,5);if(s.length!==0){console.error(""),console.error("Did you mean one of:");for(let a of s)console.error(` kanonak ${o} add ${e}/${a.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}),s=e.managesTypeKey||"managed";if(r.length===0){console.log(`No ${s} instances installed.`);return}console.log(`Installed ${s} instances:
127
127
  `);for(let a of r){let i=a.publisher?`${a.publisher}/${a.package_}@${a.version}`:"unmanaged";console.log(` ${a.name} (${i}) ${a.path}`)}}async update(e,t,o){let s=await this.requireHandler(e).list({repository:this.repository,options:o}),a=t?s.filter(c=>c.name===t):s.filter(c=>c.publisher);if(a.length===0){console.log(t?`"${t}" not found.`:"No managed instances to update.");return}let i=0;for(let c of a){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.":`
128
128
  Updated ${i} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=ht(e.managesTypeKey);if(!r){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${o} for ${ee(r)} instances...
129
- `);let s=new Ls,a=await s.getConfig(o),i=s.resolveIndexUrl(o,a),c=await this.fetchFn(i,o);if(!c.ok){console.error(`Failed to fetch package index from ${o}.`);return}let l=await c.text(),u=Ye.parseIndex(l);if(u.size===0){console.error(`No packages found for publisher "${o}".`);return}let p=new Map;for(let[d,f]of u){let g=[...f].sort((y,b)=>{let w=Ye.parseVersion(y),$=Ye.parseVersion(b);return!w||!$?0:w.major!==$.major?$.major-w.major:w.minor!==$.minor?$.minor-w.minor:$.patch-w.patch});p.set(d,g[0])}let m=[],h=0;for(let[d,f]of p){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 ft(y,this.repository),w=await this.objectParser.parseKanonaks(b),$=gt(w,r);for(let S of $)m.push({publisher:o,package_:d,version:f,subject:S});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):
130
- `);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 a=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(i=>i.name===t);a||(console.error(`"${t}" is not installed.`),process.exit(1)),console.log(`Name: ${a.name}`),console.log(`Type: ${e.managesTypeKey||"n/a"}`),console.log(`Publisher: ${a.publisher||"unmanaged"}`),console.log(`Package: ${a.package_||"n/a"}`),console.log(`Version: ${a.version||"n/a"}`),console.log(`Path: ${a.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 ht(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function Fs(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)),s=new Set(o.split("-").filter(Boolean)),a=0;for(let c of r)s.has(c)&&a++;if(a>0)return a*10;let i=Ms(t,o);return i===0?100:i<=2?Math.max(1,20-i*5):0}function Ms(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 s=0;s<e.length;s++){let a=n[r]===e[s]?0:1;o[s+1]=Math.min(o[s]+1,t[s+1]+1,t[s]+a)}for(let s=0;s<=e.length;s++)t[s]=o[s]}return t[e.length]}var ke=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as Qs,rmSync as ei,existsSync as $e,readdirSync as ni,writeFileSync as ti}from"fs";import{join as ve}from"path";import{KanonakObjectParser as oi,KanonakParser as ri,computeIntegrity as ai,compareVersions as si}from"@kanonak-protocol/sdk";import{findSubjectsByType as ii}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as ci}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as li}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as ui}from"@kanonak-protocol/sdk/transformations";import{join as Xe}from"path";import{homedir as kt}from"os";import{KanonakObjectParser as Hs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Vs}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as bt,getStringValue as ye}from"@kanonak-protocol/sdk/uri-helpers";var V="kanonak.org",B="agent-skills",wt={publisher:V,package_:B,name:"Client"},$t={publisher:V,package_:B,name:"clientId"},Bs={publisher:V,package_:B,name:"projectSkillDir"},zs={publisher:V,package_:B,name:"userSkillDir"},qs={publisher:V,package_:B,name:"skillFileName"},vt="agents";async function ie(n,e){let t=(n.client??St()??vt).toLowerCase(),o=n.scope??"project",r=await Ct(t,e);if(!r){let i=await Ws(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 a=ye(r,o==="user"?zs:Bs);if(!a)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return Gs(a)}async function be(n,e,t){let o=await ie(e,t);return Xe(o,n)}async function Ze(n,e){let t=(n.client??St()??vt).toLowerCase(),o=await Ct(t,e);return o?ye(o,qs)??"SKILL.md":"SKILL.md"}function St(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var yt=new WeakMap;async function Pt(n){let e=yt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(V,B);if(t.length===0)throw new Error(`Could not find ${V}/${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 u=c.metadata.namespace_?.version,p=l.metadata.namespace_?.version;return!u||!p?0:u.major!==p.major?p.major-u.major:u.minor!==p.minor?p.minor-u.minor:p.patch-u.patch})[0],s=new Hs,a=new Vs(r,n),i=await s.parseKanonaks(a);return yt.set(n,i),i}async function Ct(n,e){let t=await Pt(e),o=bt(t,wt);for(let r of o)if(ye(r,$t)===n)return r}async function Ws(n){let e=await Pt(n),t=bt(e,wt),o=[];for(let r of t){let s=ye(r,$t);s&&o.push(s)}return o}function Gs(n){return n.startsWith("~/")?Xe(kt(),n.slice(2)):n==="~"?kt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Xe(process.cwd(),n)}import{readFileSync as Js,writeFileSync as Ys,existsSync as Xs}from"fs";import{join as _t}from"path";import Rt from"js-yaml";var xt="skills.lock",Zs=`# This file is generated by Kanonak CLI. Do not edit manually.
131
- `;function we(n){let e=_t(n,xt);if(!Xs(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=Js(e,"utf-8"),o=Rt.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 s of Object.keys(e.skills).sort())t[s]=e.skills[s];e.skills=t;let o=_t(n,xt),r=Rt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ys(o,Zs+r,"utf-8")}var It="kanonak.org",Kt="skill-to-skill-md",Se=class{parser=new ri;objectParser=new oi;runner=new li;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:s}=e;if(t.length===0){console.error("No Skill instances to deploy.");return}let a=await pi(r,this.objectParser);if(!a){console.error(`Cannot deploy: ${It}/${Kt}@3.0.0 is not installed in the workspace or cache.`);return}let i=await this.runner.run({transformation:a,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 ie(s,r),l=await Ze(s,r),u=we(c),p=t[0].namespace,{publisher:m,package_:h,version:k}=mi(p);for(let d of i){let f=await be(d.fileName,s,r),g=$e(ve(f,l));Qs(f,{recursive:!0}),ti(ve(f,l),d.content,"utf-8"),u.skills[d.fileName]={publisher:m,package_:h,version:k,resolved:m?`kanonak://${m}/${h}@${k}`:"",integrity:ai(d.content)},console.log(` ${g?"Updated":"Installed"} skill "${d.fileName}" \u2192 ${f}`)}Qe(c,u)}async undeploy(e,t){let{repository:o,options:r}=t,s=await be(e,r,o);$e(s)||(console.error(`Skill "${e}" is not installed at ${s}`),process.exit(1)),ei(s,{recursive:!0,force:!0});let a=await ie(r,o),i=we(a);delete i.skills[e],Qe(a,i),console.log(`Removed skill "${e}" from ${s}`)}async list(e){let{repository:t,options:o}=e,r=await ie(o,t),s=we(r),a=[];for(let[c,l]of Object.entries(s.skills))a.push({name:c,publisher:l.publisher,package_:l.package_,version:l.version,path:await be(c,o,t)});let i=await Ze(o,t);if($e(r))try{let c=ni(r,{withFileTypes:!0});for(let l of c){if(!l.isDirectory()||s.skills[l.name])continue;let u=ve(r,l.name,i);$e(u)&&a.push({name:l.name,publisher:"",package_:"",version:"",path:ve(r,l.name)})}}catch{}return a}};async function pi(n,e){let t=await n.getDocumentsByNamespaceAsync(It,Kt);if(t.length===0)return;let o=[...t].sort((r,s)=>{let a=r.metadata.namespace_?.version,i=s.metadata.namespace_?.version;return!a||!i?0:si(i,a)});for(let r of o){let s=new ci(r,n),a=await e.parseKanonaks(s),i=ii(a,ui.InstanceTransformation);if(i[0])return i[0]}}function mi(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 xi,rmSync as Ii,existsSync as tn,readdirSync as Ki,writeFileSync as Ti,statSync as Di}from"fs";import{join as _e}from"path";import{KanonakObjectParser as Ei,KanonakParser as ji,computeIntegrity as Ai}from"@kanonak-protocol/sdk";import{findSubjectsByType as Ni}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as Oi}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Li}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as Ui}from"@kanonak-protocol/sdk/transformations";import{join as Tt}from"path";import{homedir as Dt}from"os";import{KanonakObjectParser as di}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as fi}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as jt,getStringValue as en,getReferenceUri as gi}from"@kanonak-protocol/sdk/uri-helpers";var z="kanonak.org",q="agent-skills",At={publisher:z,package_:q,name:"Client"},Nt={publisher:z,package_:q,name:"clientId"},hi={publisher:z,package_:q,name:"projectAgentDir"},ki={publisher:z,package_:q,name:"userAgentDir"},yi={publisher:z,package_:q,name:"agentFileFormat"},bi="agents";function wi(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Pe(n,e){let t=(n.client??wi()??bi).toLowerCase(),o=n.scope??"project",r=await $i(t,e);if(!r){let u=await vi(e);throw new Error(`Unknown client "${t}". Known clients: ${u.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let a=en(r,o==="user"?ki:hi);if(!a)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let c=gi(r,yi)?.name==="toml"?"toml":"markdown-frontmatter",l=c==="toml"?".toml":".md";return{agentsDir:Si(a),format:c,fileExtension:l}}var Et=new WeakMap;async function Ot(n){let e=Et.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(z,q);if(t.length===0)throw new Error(`Could not find ${z}/${q} in the repository. Install a capability that imports agent-skills to populate the cache.`);let r=[...t].sort((c,l)=>{let u=c.metadata.namespace_?.version,p=l.metadata.namespace_?.version;return!u||!p?0:u.major!==p.major?p.major-u.major:u.minor!==p.minor?p.minor-u.minor:p.patch-u.patch})[0],s=new di,a=new fi(r,n),i=await s.parseKanonaks(a);return Et.set(n,i),i}async function $i(n,e){let t=await Ot(e),o=jt(t,At);for(let r of o)if(en(r,Nt)===n)return r}async function vi(n){let e=await Ot(n),t=jt(e,At),o=[];for(let r of t){let s=en(r,Nt);s&&o.push(s)}return o}function Si(n){return n.startsWith("~/")?Tt(Dt(),n.slice(2)):n==="~"?Dt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Tt(process.cwd(),n)}import{readFileSync as Pi,writeFileSync as Ci,existsSync as _i}from"fs";import{join as Lt}from"path";import Ut from"js-yaml";var Ft="agents.lock",Ri=`# This file is generated by Kanonak CLI. Do not edit manually.
132
- `;function Ce(n){let e=Lt(n,Ft);if(!_i(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=Pi(e,"utf-8"),o=Ut.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 s of Object.keys(e.agents).sort())t[s]=e.agents[s];e.agents=t;let o=Lt(n,Ft),r=Ut.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ci(o,Ri+r,"utf-8")}var Mt="kanonak.org",Ht="agent-to-agent-file",Re=class{parser=new ji;objectParser=new Ei;runner=new Li;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:s}=e;if(t.length===0){console.error("No Agent instances to deploy.");return}let{agentsDir:a,format:i,fileExtension:c}=await Pe(s,r),l=await Fi(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Mt}/${Ht}@3.0.0 is not installed in the workspace or cache.`);return}let u=i==="toml"?"toml":"markdown-with-frontmatter",p=await this.runner.run({transformation:l,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:u});if(p.length===0){console.error("No agents could be transformed from the package.");return}xi(a,{recursive:!0});let m=Ce(a),h=t[0].namespace,{publisher:k,package_:d,version:f}=Hi(h);for(let g of p){let y=`${g.fileName}${c}`,b=_e(a,y),w=tn(b);Ti(b,g.content,"utf-8"),m.agents[g.fileName]={publisher:k,package_:d,version:f,resolved:k?`kanonak://${k}/${d}@${f}`:"",integrity:Ai(g.content),fileName:y},console.log(` ${w?"Updated":"Installed"} agent "${g.fileName}" \u2192 ${b}`)}nn(a,m)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:s}=await Pe(r,o),a=Ce(s),i=a.agents[e];i||(console.error(`Agent "${e}" is not installed at ${s}`),process.exit(1));let c=_e(s,i.fileName);tn(c)&&Ii(c,{force:!0}),delete a.agents[e],nn(s,a),console.log(`Removed agent "${e}" from ${c}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await Pe(o,t),s=Ce(r),a=[];for(let[i,c]of Object.entries(s.agents))a.push({name:i,publisher:c.publisher,package_:c.package_,version:c.version,path:_e(r,c.fileName)});if(tn(r))try{let i=Ki(r,{withFileTypes:!0});for(let c of i){if(!c.isFile()||c.name==="agents.lock")continue;let l=_e(r,c.name),u=Mi(c.name);if(!s.agents[u]){try{if(!Di(l).isFile())continue}catch{continue}a.push({name:u,publisher:"",package_:"",version:"",path:l})}}}catch{}return a}};async function Fi(n,e){let t=await n.getDocumentsByNamespaceAsync(Mt,Ht);if(t.length===0)return;let o=new Oi(t[0],n),r=await e.parseKanonaks(o);return Ni(r,Ui.InstanceTransformation)[0]}function Mi(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function Hi(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 Zi=qi(zi(import.meta.url)),Qi=JSON.parse(Bi(Wi(Zi,"..","package.json"),"utf-8")),R=new Vi;R.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(Qi.version);R.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await cn(n)});R.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await ln(n)});R.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await pn(n)});R.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await hn(n)});R.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await kn(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 ct(n,e)});R.addCommand(Dn());R.addCommand(Un());R.addCommand(zn());R.addCommand(Wn());R.addCommand(nt());R.addCommand(tt());R.addCommand(it());async function ec(){try{let n=new T,e=new Gi,t=new Yi,o=Xi(t),r=new Ji({fetchFn:o}),s=await v(process.cwd(),e),a=new ke;a.register("kanonak.org/capabilities/agent-skill-deployment",new Se),a.register("kanonak.org/agent-capabilities/agent-instance-deployment",new Re);let i=await In(n,e,s),c=new he(n,e,r,o,a,s);ut(R,i,c)}catch{}}await ec();R.parse();
129
+ `);let s=new Ls,a=await s.getConfig(o),i=s.resolveIndexUrl(o,a),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,g]of p){let h=[...g].sort((y,b)=>{let w=Ye.parseVersion(y),$=Ye.parseVersion(b);return!w||!$?0:w.major!==$.major?$.major-w.major:w.minor!==$.minor?$.minor-w.minor:$.patch-w.patch});u.set(d,h[0])}let m=[],f=0;for(let[d,g]of u){let h=this.fileCache.get(o,d,g);if(!h)try{let y=await this.publisherIndex.getPackageUrl(o,d,g),b=await this.fetchFn(y,o);if(!b.ok)continue;h=await b.text(),this.fileCache.put(o,d,g,h)}catch{continue}try{let y=this.parser.parse(h),b=new ft(y,this.repository),w=await this.objectParser.parseKanonaks(b),$=gt(w,r);for(let S of $)m.push({publisher:o,package_:d,version:g,subject:S});f++}catch{continue}}if(m.length===0){console.log(`No ${ee(r)} instances found across ${f} package(s).`);return}console.log(`Found ${m.length} ${ee(r)} instance(s) in ${f} package(s):
130
+ `);let k=new Map;for(let d of m){let g=`${d.publisher}/${d.package_}@${d.version}`,h=k.get(g);h?h.push(d):k.set(g,[d])}for(let[d,g]of k){let h=g[0],y=`${h.publisher}/${h.package_}`,b=g.length===1;console.log(` ${d}`),console.log(` ${g.length} skill${b?"":"s"}:`);for(let w of g)console.log(` - ${w.subject.name}`);if(console.log(""),b)console.log(" install:"),console.log(` kanonak ${e.commandName} add ${y}/${h.subject.name}`);else{console.log(" install one of them:");for(let w of g)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 a=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(i=>i.name===t);a||(console.error(`"${t}" is not installed.`),process.exit(1)),console.log(`Name: ${a.name}`),console.log(`Type: ${e.managesTypeKey||"n/a"}`),console.log(`Publisher: ${a.publisher||"unmanaged"}`),console.log(`Package: ${a.package_||"n/a"}`),console.log(`Version: ${a.version||"n/a"}`),console.log(`Path: ${a.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 ht(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function Fs(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)),s=new Set(o.split("-").filter(Boolean)),a=0;for(let c of r)s.has(c)&&a++;if(a>0)return a*10;let i=Ms(t,o);return i===0?100:i<=2?Math.max(1,20-i*5):0}function Ms(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 s=0;s<e.length;s++){let a=n[r]===e[s]?0:1;o[s+1]=Math.min(o[s]+1,t[s+1]+1,t[s]+a)}for(let s=0;s<=e.length;s++)t[s]=o[s]}return t[e.length]}var ke=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as Qs,rmSync as ei,existsSync as $e,readdirSync as ni,writeFileSync as ti}from"fs";import{join as ve}from"path";import{KanonakObjectParser as oi,KanonakParser as ri,computeIntegrity as ai,compareVersions as si}from"@kanonak-protocol/sdk";import{findSubjectsByType as ii}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as ci}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as li}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as ui}from"@kanonak-protocol/sdk/transformations";import{join as Xe}from"path";import{homedir as kt}from"os";import{KanonakObjectParser as Hs}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Vs}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as bt,getStringValue as ye}from"@kanonak-protocol/sdk/uri-helpers";var V="kanonak.org",B="agent-skills",wt={publisher:V,package_:B,name:"Client"},$t={publisher:V,package_:B,name:"clientId"},Bs={publisher:V,package_:B,name:"projectSkillDir"},zs={publisher:V,package_:B,name:"userSkillDir"},qs={publisher:V,package_:B,name:"skillFileName"},vt="agents";async function ie(n,e){let t=(n.client??St()??vt).toLowerCase(),o=n.scope??"project",r=await Ct(t,e);if(!r){let i=await Ws(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 a=ye(r,o==="user"?zs:Bs);if(!a)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return Gs(a)}async function be(n,e,t){let o=await ie(e,t);return Xe(o,n)}async function Ze(n,e){let t=(n.client??St()??vt).toLowerCase(),o=await Ct(t,e);return o?ye(o,qs)??"SKILL.md":"SKILL.md"}function St(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var yt=new WeakMap;async function Pt(n){let e=yt.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(V,B);if(t.length===0)throw new Error(`Could not find ${V}/${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],s=new Hs,a=new Vs(r,n),i=await s.parseKanonaks(a);return yt.set(n,i),i}async function Ct(n,e){let t=await Pt(e),o=bt(t,wt);for(let r of o)if(ye(r,$t)===n)return r}async function Ws(n){let e=await Pt(n),t=bt(e,wt),o=[];for(let r of t){let s=ye(r,$t);s&&o.push(s)}return o}function Gs(n){return n.startsWith("~/")?Xe(kt(),n.slice(2)):n==="~"?kt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Xe(process.cwd(),n)}import{readFileSync as Js,writeFileSync as Ys,existsSync as Xs}from"fs";import{join as _t}from"path";import Rt from"js-yaml";var xt="skills.lock",Zs=`# This file is generated by Kanonak CLI. Do not edit manually.
131
+ `;function we(n){let e=_t(n,xt);if(!Xs(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=Js(e,"utf-8"),o=Rt.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 s of Object.keys(e.skills).sort())t[s]=e.skills[s];e.skills=t;let o=_t(n,xt),r=Rt.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ys(o,Zs+r,"utf-8")}var Kt="kanonak.org",It="skill-to-skill-md",Se=class{parser=new ri;objectParser=new oi;runner=new li;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:s}=e;if(t.length===0){console.error("No Skill instances to deploy.");return}let a=await pi(r,this.objectParser);if(!a){console.error(`Cannot deploy: ${Kt}/${It}@3.0.0 is not installed in the workspace or cache.`);return}let i=await this.runner.run({transformation:a,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 ie(s,r),l=await Ze(s,r),p=we(c),u=t[0].namespace,{publisher:m,package_:f,version:k}=mi(u);for(let d of i){let g=await be(d.fileName,s,r),h=$e(ve(g,l));Qs(g,{recursive:!0}),ti(ve(g,l),d.content,"utf-8"),p.skills[d.fileName]={publisher:m,package_:f,version:k,resolved:m?`kanonak://${m}/${f}@${k}`:"",integrity:ai(d.content)},console.log(` ${h?"Updated":"Installed"} skill "${d.fileName}" \u2192 ${g}`)}Qe(c,p)}async undeploy(e,t){let{repository:o,options:r}=t,s=await be(e,r,o);$e(s)||(console.error(`Skill "${e}" is not installed at ${s}`),process.exit(1)),ei(s,{recursive:!0,force:!0});let a=await ie(r,o),i=we(a);delete i.skills[e],Qe(a,i),console.log(`Removed skill "${e}" from ${s}`)}async list(e){let{repository:t,options:o}=e,r=await ie(o,t),s=we(r),a=[];for(let[c,l]of Object.entries(s.skills))a.push({name:c,publisher:l.publisher,package_:l.package_,version:l.version,path:await be(c,o,t)});let i=await Ze(o,t);if($e(r))try{let c=ni(r,{withFileTypes:!0});for(let l of c){if(!l.isDirectory()||s.skills[l.name])continue;let p=ve(r,l.name,i);$e(p)&&a.push({name:l.name,publisher:"",package_:"",version:"",path:ve(r,l.name)})}}catch{}return a}};async function pi(n,e){let t=await n.getDocumentsByNamespaceAsync(Kt,It);if(t.length===0)return;let o=[...t].sort((r,s)=>{let a=r.metadata.namespace_?.version,i=s.metadata.namespace_?.version;return!a||!i?0:si(i,a)});for(let r of o){let s=new ci(r,n),a=await e.parseKanonaks(s),i=ii(a,ui.InstanceTransformation);if(i[0])return i[0]}}function mi(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 xi,rmSync as Ki,existsSync as tn,readdirSync as Ii,writeFileSync as Ti,statSync as Di}from"fs";import{join as _e}from"path";import{KanonakObjectParser as Ei,KanonakParser as ji,computeIntegrity as Ai}from"@kanonak-protocol/sdk";import{findSubjectsByType as Ni}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as Oi}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Li}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as Ui}from"@kanonak-protocol/sdk/transformations";import{join as Tt}from"path";import{homedir as Dt}from"os";import{KanonakObjectParser as di}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as fi}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as jt,getStringValue as en,getReferenceUri as gi}from"@kanonak-protocol/sdk/uri-helpers";var z="kanonak.org",q="agent-skills",At={publisher:z,package_:q,name:"Client"},Nt={publisher:z,package_:q,name:"clientId"},hi={publisher:z,package_:q,name:"projectAgentDir"},ki={publisher:z,package_:q,name:"userAgentDir"},yi={publisher:z,package_:q,name:"agentFileFormat"},bi="agents";function wi(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function Pe(n,e){let t=(n.client??wi()??bi).toLowerCase(),o=n.scope??"project",r=await $i(t,e);if(!r){let p=await vi(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 a=en(r,o==="user"?ki:hi);if(!a)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let c=gi(r,yi)?.name==="toml"?"toml":"markdown-frontmatter",l=c==="toml"?".toml":".md";return{agentsDir:Si(a),format:c,fileExtension:l}}var Et=new WeakMap;async function Ot(n){let e=Et.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(z,q);if(t.length===0)throw new Error(`Could not find ${z}/${q} in the repository. Install a capability that imports agent-skills to populate the cache.`);let 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],s=new di,a=new fi(r,n),i=await s.parseKanonaks(a);return Et.set(n,i),i}async function $i(n,e){let t=await Ot(e),o=jt(t,At);for(let r of o)if(en(r,Nt)===n)return r}async function vi(n){let e=await Ot(n),t=jt(e,At),o=[];for(let r of t){let s=en(r,Nt);s&&o.push(s)}return o}function Si(n){return n.startsWith("~/")?Tt(Dt(),n.slice(2)):n==="~"?Dt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Tt(process.cwd(),n)}import{readFileSync as Pi,writeFileSync as Ci,existsSync as _i}from"fs";import{join as Lt}from"path";import Ut from"js-yaml";var Ft="agents.lock",Ri=`# This file is generated by Kanonak CLI. Do not edit manually.
132
+ `;function Ce(n){let e=Lt(n,Ft);if(!_i(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=Pi(e,"utf-8"),o=Ut.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 s of Object.keys(e.agents).sort())t[s]=e.agents[s];e.agents=t;let o=Lt(n,Ft),r=Ut.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ci(o,Ri+r,"utf-8")}var Mt="kanonak.org",Ht="agent-to-agent-file",Re=class{parser=new ji;objectParser=new Ei;runner=new Li;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:s}=e;if(t.length===0){console.error("No Agent instances to deploy.");return}let{agentsDir:a,format:i,fileExtension:c}=await Pe(s,r),l=await Fi(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Mt}/${Ht}@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}xi(a,{recursive:!0});let m=Ce(a),f=t[0].namespace,{publisher:k,package_:d,version:g}=Hi(f);for(let h of u){let y=`${h.fileName}${c}`,b=_e(a,y),w=tn(b);Ti(b,h.content,"utf-8"),m.agents[h.fileName]={publisher:k,package_:d,version:g,resolved:k?`kanonak://${k}/${d}@${g}`:"",integrity:Ai(h.content),fileName:y},console.log(` ${w?"Updated":"Installed"} agent "${h.fileName}" \u2192 ${b}`)}nn(a,m)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:s}=await Pe(r,o),a=Ce(s),i=a.agents[e];i||(console.error(`Agent "${e}" is not installed at ${s}`),process.exit(1));let c=_e(s,i.fileName);tn(c)&&Ki(c,{force:!0}),delete a.agents[e],nn(s,a),console.log(`Removed agent "${e}" from ${c}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await Pe(o,t),s=Ce(r),a=[];for(let[i,c]of Object.entries(s.agents))a.push({name:i,publisher:c.publisher,package_:c.package_,version:c.version,path:_e(r,c.fileName)});if(tn(r))try{let i=Ii(r,{withFileTypes:!0});for(let c of i){if(!c.isFile()||c.name==="agents.lock")continue;let l=_e(r,c.name),p=Mi(c.name);if(!s.agents[p]){try{if(!Di(l).isFile())continue}catch{continue}a.push({name:p,publisher:"",package_:"",version:"",path:l})}}}catch{}return a}};async function Fi(n,e){let t=await n.getDocumentsByNamespaceAsync(Mt,Ht);if(t.length===0)return;let o=new Oi(t[0],n),r=await e.parseKanonaks(o);return Ni(r,Ui.InstanceTransformation)[0]}function Mi(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function Hi(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 Zi=qi(zi(import.meta.url)),Qi=JSON.parse(Bi(Wi(Zi,"..","package.json"),"utf-8")),R=new Vi;R.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(Qi.version);R.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await cn(n)});R.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await ln(n)});R.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await pn(n)});R.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await hn(n)});R.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await kn(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 ct(n,e)});R.addCommand(Dn());R.addCommand(Un());R.addCommand(zn());R.addCommand(Wn());R.addCommand(nt());R.addCommand(tt());R.addCommand(it());async function ec(){try{let n=new T,e=new Gi,t=new Yi,o=Xi(t),r=new Ji({fetchFn:o}),s=await v(process.cwd(),e),a=new ke;a.register("kanonak.org/capabilities/agent-skill-deployment",new Se),a.register("kanonak.org/agent-capabilities/agent-instance-deployment",new Re);let i=await Kn(n,e,s),c=new he(n,e,r,o,a,s);ut(R,i,c)}catch{}}await ec();R.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanonak-protocol/cli",
3
- "version": "3.52.0",
3
+ "version": "3.53.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.52.0",
38
- "@kanonak-protocol/types": "^3.52.0",
37
+ "@kanonak-protocol/sdk": "^3.53.0",
38
+ "@kanonak-protocol/types": "^3.53.0",
39
39
  "commander": "^13.0.0",
40
40
  "js-yaml": "^4.1.1"
41
41
  },