@kanonak-protocol/cli 3.55.1 → 3.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +48 -51
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
3
|
-
`).some(r=>r.trim()===t||r.trim()===t+"/"))return;
|
|
2
|
+
import{Command as Li}from"commander";import{readFileSync as Ui}from"fs";import{fileURLToPath as Fi}from"url";import{dirname as Mi,join as Hi}from"path";import{KanonakParser as Vi,PublisherIndex as zi,CredentialStore as Bi,createAuthenticatedFetch as qi}from"@kanonak-protocol/sdk";import{readFileSync as Zt,statSync as Qt}from"fs";import{resolve as eo,dirname as no}from"path";import{KanonakParser as to,KanonakObjectValidator as oo,ValidationSeverity as tn}from"@kanonak-protocol/sdk";import{readdirSync as Gt}from"fs";import{join as Jt,dirname as Yt,basename as nn}from"path";import{LocalFirstRepository as rc,buildLocalFirstRepository as Xt}from"@kanonak-protocol/sdk";import{mkdirSync as Ht,readFileSync as Qe,writeFileSync as en,existsSync as we,appendFileSync as Vt}from"fs";import{join as zt,dirname as Bt,isAbsolute as qt}from"path";import{getGlobalCachePath as Wt}from"@kanonak-protocol/sdk";var D=class{constructor(e=Wt()){this.cacheDir=e;this.isProjectLocal=!qt(e)}cacheDir;gitignoreChecked=!1;isProjectLocal;get(e,t,o){let r=this.getPath(e,t,o);return we(r)?Qe(r,"utf-8"):null}put(e,t,o,r){let a=this.getPath(e,t,o);Ht(Bt(a),{recursive:!0}),en(a,r,"utf-8"),this.isProjectLocal&&this.ensureGitignore()}has(e,t,o){return we(this.getPath(e,t,o))}ensureGitignore(){if(this.gitignoreChecked)return;this.gitignoreChecked=!0;let e=".gitignore",t=this.cacheDir;if(we(e)){if(Qe(e,"utf-8").split(`
|
|
3
|
+
`).some(r=>r.trim()===t||r.trim()===t+"/"))return;Vt(e,`
|
|
4
4
|
${t}/
|
|
5
|
-
`)}else
|
|
6
|
-
`)}getPath(e,t,o){return
|
|
7
|
-
${u}:`);for(let
|
|
8
|
-
${u}:`),console.log(" ERROR: Failed to parse document"),c++;continue}let
|
|
9
|
-
${y}:`);for(let b of
|
|
10
|
-
${i.length} file(s) validated. ${c} error(s), ${l} warning(s).`),c>0&&process.exit(1)}import{KanonakParser as
|
|
11
|
-
Installed ${Object.keys(
|
|
12
|
-
Installed ${
|
|
5
|
+
`)}else en(e,`${t}/
|
|
6
|
+
`)}getPath(e,t,o){return zt(this.cacheDir,e,`${t}@${o}.kan.yml`)}};function O(n){let e=n;for(;;){let t=Yt(e);if(t===e)break;if(nn(e).includes(".")||nn(t).includes(".")){e=t;continue}break}return e}function $e(n,e){for(let t of Gt(n,{withFileTypes:!0})){let o=Jt(n,t.name);t.isDirectory()&&t.name!=="node_modules"&&t.name!==".kanonak"?$e(o,e):t.name.endsWith(".kan.yml")&&e.push(o)}}async function v(n,e){let t=new D;return Xt(n,e,{httpCache:{getFromCache:(o,r,a)=>t.get(o,r,a),onFetch:(o,r,a,s)=>t.put(o,r,a,s)}})}async function on(n){let e=eo(n),t=Qt(e),o=t.isDirectory()?O(e):O(no(e)),r=new to,a=new oo(r),s=await v(o,r),i=[];if(t.isDirectory()?$e(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=Zt(u,"utf-8"),d=r.parseWithErrors(p);if(d.errors&&d.errors.length>0){console.log(`
|
|
7
|
+
${u}:`);for(let h of d.errors)console.log(` ERROR (parse): ${h.message} [line ${h.line}:${h.column}]`),c++;continue}let f=d.document;if(!f){console.log(`
|
|
8
|
+
${u}:`),console.log(" ERROR: Failed to parse document"),c++;continue}let g=await a.validateAsync(f,s),m=g.errors.filter(h=>h.severity===tn.Error),k=g.warnings.filter(h=>h.severity===tn.Warning);if(m.length>0||k.length>0){let h=f.metadata.namespace_,y=h?`${h.publisher}/${h.package_}@${h.version}`:u;console.log(`
|
|
9
|
+
${y}:`);for(let b of m)console.log(` ERROR: ${b.message}`),b.suggestion&&console.log(` -> ${b.suggestion}`);for(let b of k)console.log(` WARN: ${b.message}`)}c+=m.length,l+=k.length}console.log(`
|
|
10
|
+
${i.length} file(s) validated. ${c} error(s), ${l} warning(s).`),c>0&&process.exit(1)}import{KanonakParser as ro,PublisherIndex as so,CredentialStore as ao,createAuthenticatedFetch as io}from"@kanonak-protocol/sdk";import{loadLockFile as co,saveLockFile as lo,computeIntegrity as uo}from"@kanonak-protocol/sdk";function T(n){if(!n)return null;let e=n.indexOf("/");if(e===-1)return null;let t=n.substring(0,e),o=n.substring(e+1);if(!t||!o)return null;let r,a=null,s=null,i=o.indexOf("@");if(i!==-1){r=o.substring(0,i);let c=o.substring(i+1),l=c.indexOf("/");l===-1?a=c||null:(a=c.substring(0,l)||null,s=c.substring(l+1)||null)}else{let c=o.indexOf("/");c===-1?r=o:(r=o.substring(0,c),s=o.substring(c+1)||null)}return!r||s&&s.includes("/")||a&&a.includes("@")?null:{publisher:t,packageName:r,version:a,instanceName:s}}async function rn(n){let e=new D,t=new ro,o=new ao,r=io(o),a=new so({fetchFn:r}),s=co()??{version:"1",lastUpdated:new Date().toISOString(),packages:{}};if(!n){Object.keys(s.packages).length===0&&(console.error("No kanonak.lock file found or lock file is empty."),console.error("Usage: kanonak install {publisher}/{package}[@{version}]"),process.exit(1)),console.log(`Installing ${Object.keys(s.packages).length} package(s) from kanonak.lock...`);for(let[g,m]of Object.entries(s.packages)){let k=g.indexOf("/"),h=g.substring(0,k),y=g.substring(k+1),b=e.get(h,y,m.version);if(b)console.log(` ${g}@${m.version} (cached)`);else{let w=m.resolved,$=await r(w,h);if(!$.ok)throw new Error(`Failed to fetch ${w} (${$.status} ${$.statusText})`);b=await $.text(),e.put(h,y,m.version,b),console.log(` ${g}@${m.version}`)}}console.log(`
|
|
11
|
+
Installed ${Object.keys(s.packages).length} package(s) from lock file.`);return}let i=T(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 d=u??await a.getHighestVersion(c,l);d||(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}@${d}...`);let f=new Set;await sn(c,l,d,e,t,a,r,f,s),lo(s),console.log(`
|
|
12
|
+
Installed ${f.size} package(s).`)}async function sn(n,e,t,o,r,a,s,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),d;if(p)console.log(` ${l} (cached)`),d=await a.getPackageUrl(n,e,t);else{d=await a.getPackageUrl(n,e,t);let m=await s(d,n);if(!m.ok)throw new Error(`Failed to fetch ${d} (${m.status} ${m.statusText})`);p=await m.text(),o.put(n,e,t,p),console.log(` ${l}`)}let f={},g=r.parse(p);if(g.metadata.imports)for(let[m,k]of Object.entries(g.metadata.imports))for(let h of k){let y=await a.resolveVersion(m,h);y?(f[`${m}/${h.packageName}`]=y,await sn(m,h.packageName,y,o,r,a,s,i,c)):console.error(` WARNING: Could not resolve ${m}/${h.packageName} ${h.package_}`)}c.packages[u]={version:t,resolved:d,integrity:uo(p),dependencies:f}}import{readFileSync as po}from"fs";import{resolve as mo,dirname as fo}from"path";import{KanonakParser as go}from"@kanonak-protocol/sdk";async function an(n){let e=mo(n),t=po(e,"utf-8"),o=new go,r=o.parse(t),a=r.metadata.namespace_,s=a?`${a.publisher}/${a.package_}@${a.version}`:n;if(console.log(s),!r.metadata.imports){console.log(" (no imports)");return}let i=O(fo(e)),c=await v(i,o),l=new Set;for(let[u,p]of Object.entries(r.metadata.imports))for(let d of p)await cn(u,d,c,l," ")}async function cn(n,e,t,o,r){let a=`${n}/${e.packageName}`;if(o.has(a)){console.log(`${r}${a} (${e.package_}) [circular]`);return}o.add(a);let s;try{s=await t.getHighestCompatibleVersionAsync(n,e)}catch{console.log(`${r}${a} (${e.package_}) [fetch failed]`);return}if(!s){console.log(`${r}${a} (${e.package_}) [not found]`);return}let i=s.metadata.namespace_?.version?.toString()??"?";if(console.log(`${r}${n}/${e.packageName}@${i}`),s.metadata.imports)for(let[c,l]of Object.entries(s.metadata.imports))for(let u of l)await cn(c,u,t,o,r+" ")}import{createHash as ko,randomBytes as pn}from"crypto";import{createServer as yo}from"http";import{execFile as ve}from"child_process";import{CredentialStore as bo,generateDPoPKeyPair as wo,createDPoPProof as ln,serverSupportsDPoP as $o}from"@kanonak-protocol/sdk";import{normalizeHost as ho}from"@kanonak-protocol/sdk";var A=class{cache=new Map;async discover(e){let t=ho(e);if(this.cache.has(t))return this.cache.get(t);let o=`https://${t}/.well-known/oauth-authorization-server`,r=await this.tryEndpoint(o);if(!r){let a=`https://${t}/.well-known/openid-configuration`;r=await this.tryEndpoint(a)}return this.cache.set(t,r),r}async supportsOAuth(e){return await this.discover(e)!==null}static supportsPkceS256(e){return e.codeChallengeMethodsSupported?.some(t=>t.toUpperCase()==="S256")??!1}static supportsDynamicRegistration(e){return!!e.registrationEndpoint}static supportsAuthorizationCode(e){return e.responseTypesSupported?.some(t=>t.toLowerCase()==="code")??!1}async tryEndpoint(e){let t;try{t=await fetch(e)}catch(r){let a=r instanceof Error?r.message:String(r);return a.includes("ENOTFOUND")||a.includes("ECONNREFUSED")?(console.error(` OAuth discovery: ${e} \u2014 host unreachable (${a})`),console.error(" If the server is behind a VPN, ensure you are connected.")):a.includes("CERT")||a.includes("SSL")||a.includes("TLS")?(console.error(` OAuth discovery: ${e} \u2014 TLS error (${a})`),console.error(" If using a custom CA certificate, set NODE_EXTRA_CA_CERTS=/path/to/ca.pem")):console.error(` OAuth discovery: ${e} \u2014 network error: ${a}`),null}if(!t.ok)return t.status===404||(t.status===403?(console.error(` OAuth discovery: ${e} \u2014 HTTP 403 Forbidden`),console.error(" Access may be blocked by a firewall, proxy, or WAF.")):t.status>=500&&(console.error(` OAuth discovery: ${e} \u2014 HTTP ${t.status} server error`),console.error(" The authorization server returned an internal error. Contact your IDP administrator."))),null;let o;try{o=await t.json()}catch{return console.error(` OAuth discovery: ${e} \u2014 response is not valid JSON`),console.error(" The endpoint may be returning HTML instead of JSON. Check IDP configuration."),null}return{issuer:Y(o.issuer),authorizationEndpoint:Y(o.authorization_endpoint),tokenEndpoint:Y(o.token_endpoint),registrationEndpoint:Y(o.registration_endpoint),revocationEndpoint:Y(o.revocation_endpoint),scopesSupported:V(o.scopes_supported),responseTypesSupported:V(o.response_types_supported),grantTypesSupported:V(o.grant_types_supported),codeChallengeMethodsSupported:V(o.code_challenge_methods_supported),tokenEndpointAuthMethodsSupported:V(o.token_endpoint_auth_methods_supported),dpopSigningAlgValuesSupported:V(o.dpop_signing_alg_values_supported)}}};function Y(n){return typeof n=="string"?n:null}function V(n){return Array.isArray(n)?n.filter(e=>typeof e=="string"):null}var B=class{discovery;credentialStore;constructor(e,t){this.discovery=e??new A,this.credentialStore=t??new bo}async authorize(e,t=[]){console.log(`Starting OAuth flow for ${e}...`);let o=await this.discovery.discover(e);if(!o)return I(`No OAuth discovery endpoint found for '${e}'.
|
|
13
13
|
The server must expose one of:
|
|
14
14
|
- https://${e}/.well-known/oauth-authorization-server (RFC 8414)
|
|
15
15
|
- https://${e}/.well-known/openid-configuration (OpenID Connect)
|
|
16
16
|
Verify the hostname is correct and HTTPS is configured.
|
|
17
17
|
If using a corporate proxy, ensure it is not blocking the discovery request.`);let r=[];if(o.authorizationEndpoint||r.push("authorization_endpoint"),o.tokenEndpoint||r.push("token_endpoint"),r.length>0)return I(`OAuth metadata for '${e}' is missing required fields: ${r.join(", ")}.
|
|
18
|
-
Contact the IDP administrator to ensure these are included in the discovery document.`);let
|
|
19
|
-
Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:i,port:c,waitForCallback:l,close:u}=await
|
|
18
|
+
Contact the IDP administrator to ensure these are included in the discovery document.`);let a=$o(o.dpopSigningAlgValuesSupported),s=null;if(a){console.log(" Server supports DPoP (RFC 9449) \u2014 generating key pair...");try{s=wo()}catch($){return I(`Failed to generate DPoP key pair: ${z($)}
|
|
19
|
+
Ensure your Node.js installation supports EC P-256 curves.`)}}let{redirectUri:i,port:c,waitForCallback:l,close:u}=await xo(),p=await this.credentialStore.getCredential(e),d=p?.clientId??null,f=p?.clientSecret??null;if(!d&&o.registrationEndpoint){console.log(" Registering dynamic OAuth client (RFC 7591)...");let $=await this.registerClient(o.registrationEndpoint,i);if(!$.success)return u(),I($.error);d=$.clientId,f=$.clientSecret??null}if(!d)return u(),I(`No OAuth client credentials for '${e}' and the server does not support dynamic client registration (no registration_endpoint in metadata).
|
|
20
20
|
You must pre-register a client with your IDP and configure the client_id.
|
|
21
21
|
Ask your IDP administrator to enable dynamic client registration (RFC 7591),
|
|
22
|
-
or add a registration_endpoint to the OAuth metadata.`);let
|
|
22
|
+
or add a registration_endpoint to the OAuth metadata.`);let g=So(),m=Po(g),k=Co(),h=_o(o.authorizationEndpoint,d,i,t,k,m);console.log(` Opening browser for authorization on port ${c}...`),console.log(" If the browser doesn't open, navigate to:"),console.log(` ${h}`),Ko(h);let y=await l();if(u(),!y)return I(`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 I(`No authorization code received${$}.
|
|
25
25
|
The IDP may have rejected the authorization request.
|
|
26
|
-
Check the IDP admin console for error details.`)}if(y.state!==
|
|
26
|
+
Check the IDP admin console for error details.`)}if(y.state!==k)return I(`Authorization state mismatch \u2014 possible CSRF attack.
|
|
27
27
|
The response did not match the expected session.
|
|
28
|
-
Re-run 'kanonak login ${e}' to start a fresh authorization flow.`);console.log(" Exchanging authorization code for tokens...");let b=await this.exchangeCode(o.tokenEndpoint,
|
|
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,d,f,y.code,i,g,s);if(!b.success)return I(b.error);let w={clientId:d,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:s};return await this.credentialStore.store(e,w),console.log(` Successfully authenticated with ${e}`),a&&console.log(" DPoP proof-of-possession is active"),{success:!0,host:e}}async refresh(e){let t=await this.credentialStore.getCredential(e);if(!t)return I(`No stored credentials for '${e}'. Run 'kanonak login ${e}' to authenticate first.`);if(!t.refreshToken)return I(`No refresh token available for '${e}'.
|
|
29
29
|
The authorization server may not issue refresh tokens for this client.
|
|
30
30
|
Run 'kanonak login ${e}' to re-authenticate.`);if(!t.clientId)return I(`No client ID in stored credentials for '${e}'.
|
|
31
|
-
The stored credential may be corrupted. Run 'kanonak logout ${e}' then 'kanonak login ${e}'.`);let o=t.tokenEndpoint;if(!o){let
|
|
31
|
+
The stored credential may be corrupted. Run 'kanonak logout ${e}' then 'kanonak login ${e}'.`);let o=t.tokenEndpoint;if(!o){let a=await this.discovery.discover(e);if(!a?.tokenEndpoint)return I(`Cannot find token endpoint for '${e}'.
|
|
32
32
|
The OAuth discovery endpoint may be unreachable.
|
|
33
|
-
Check network connectivity and run 'kanonak login ${e}' to re-authenticate.`);o=
|
|
33
|
+
Check network connectivity and run 'kanonak login ${e}' to re-authenticate.`);o=a.tokenEndpoint}let r=await this.refreshTokenRequest(o,t.clientId,t.clientSecret,t.refreshToken,t.dpopKeyPair);return r.success?(t.accessToken=r.tokens.accessToken,r.tokens.refreshToken&&(t.refreshToken=r.tokens.refreshToken),t.expiresAt=r.tokens.expiresIn?new Date(Date.now()+r.tokens.expiresIn*1e3).toISOString():null,t.tokenEndpoint=o,await this.credentialStore.store(e,t),{success:!0,host:e}):I(`${r.error}
|
|
34
34
|
The refresh token may have expired. Run 'kanonak login ${e}' to re-authenticate.`)}async logout(e){let t=await this.credentialStore.getCredential(e);if(!t)return I(`No stored credentials for '${e}'.
|
|
35
|
-
You may not be logged in, or credentials may be stored in a different backend.`);let o=await this.discovery.discover(e);if(o?.revocationEndpoint&&t.accessToken&&t.clientId)try{await this.revokeToken(o.revocationEndpoint,t.accessToken,t.clientId)}catch{console.warn(` Warning: Token revocation failed for '${e}'. The token has been removed locally but may still be valid on the server until it expires.`)}return await this.credentialStore.remove(e),{success:!0,host:e}}async registerClient(e,t){let o;try{o=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak CLI",redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})})}catch(
|
|
35
|
+
You may not be logged in, or credentials may be stored in a different backend.`);let o=await this.discovery.discover(e);if(o?.revocationEndpoint&&t.accessToken&&t.clientId)try{await this.revokeToken(o.revocationEndpoint,t.accessToken,t.clientId)}catch{console.warn(` Warning: Token revocation failed for '${e}'. The token has been removed locally but may still be valid on the server until it expires.`)}return await this.credentialStore.remove(e),{success:!0,host:e}}async registerClient(e,t){let o;try{o=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_name:"Kanonak CLI",redirect_uris:[t],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"})})}catch(s){return{success:!1,error:`Dynamic client registration request to ${e} failed: ${z(s)}
|
|
36
36
|
Ensure the IDP is reachable and HTTPS is properly configured.
|
|
37
|
-
If using a corporate proxy or custom CA, set NODE_EXTRA_CA_CERTS.`}}if(!o.ok){let
|
|
37
|
+
If using a corporate proxy or custom CA, set NODE_EXTRA_CA_CERTS.`}}if(!o.ok){let s=await Se(o);return{success:!1,error:`Dynamic client registration (RFC 7591) failed.
|
|
38
38
|
Endpoint: ${e}
|
|
39
|
-
HTTP ${o.status}: ${
|
|
39
|
+
HTTP ${o.status}: ${s}
|
|
40
40
|
The IDP may not support dynamic registration for public clients.
|
|
41
|
-
Ask your IDP administrator to enable RFC 7591 support, or pre-register a client manually.`}}let r=await o.json(),
|
|
42
|
-
The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,o,r,s,
|
|
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: ${
|
|
44
|
-
Ensure the token endpoint is reachable.`}}if(!u.ok){let p=await
|
|
41
|
+
Ask your IDP administrator to enable RFC 7591 support, or pre-register a client manually.`}}let r=await o.json(),a=r.client_id;return a?{success:!0,clientId:a,clientSecret:r.client_secret}:{success:!1,error:`Dynamic client registration response from ${e} did not contain a client_id.
|
|
42
|
+
The IDP response may be malformed. Contact your IDP administrator.`}}async exchangeCode(e,t,o,r,a,s,i){let c=new URLSearchParams({grant_type:"authorization_code",client_id:t,code:r,redirect_uri:a,code_verifier:s});o&&c.set("client_secret",o);let l={"Content-Type":"application/x-www-form-urlencoded"};if(i)try{l.DPoP=ln(i.privateKey,i.publicKey,"POST",e)}catch(p){return{success:!1,error:`Failed to create DPoP proof for token exchange: ${z(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: ${z(p)}
|
|
44
|
+
Ensure the token endpoint is reachable.`}}if(!u.ok){let p=await Se(u),d=vo(p);return{success:!1,error:`Token exchange failed.
|
|
45
45
|
Endpoint: ${e}
|
|
46
|
-
HTTP ${u.status}: ${p}`+(
|
|
47
|
-
${
|
|
46
|
+
HTTP ${u.status}: ${p}`+(d?`
|
|
47
|
+
${d}`:"")}}return{success:!0,tokens:un(await u.json())}}async refreshTokenRequest(e,t,o,r,a){let s=new URLSearchParams({grant_type:"refresh_token",client_id:t,refresh_token:r});o&&s.set("client_secret",o);let i={"Content-Type":"application/x-www-form-urlencoded"};if(a)try{i.DPoP=ln(a.privateKey,a.publicKey,"POST",e)}catch(l){return{success:!1,error:`Failed to create DPoP proof for token refresh: ${z(l)}`}}let c;try{c=await fetch(e,{method:"POST",headers:i,body:s.toString()})}catch(l){return{success:!1,error:`Token refresh request to ${e} failed: ${z(l)}`}}if(!c.ok){let l=await Se(c);return{success:!1,error:`Token refresh failed \u2014 HTTP ${c.status}: ${l}`}}return{success:!0,tokens:un(await c.json())}}async revokeToken(e,t,o){await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({token:t,client_id:o}).toString()})}};function I(n){return{success:!1,error:n}}function un(n){return{accessToken:n.access_token,refreshToken:n.refresh_token,expiresIn:typeof n.expires_in=="number"?n.expires_in:void 0}}function z(n){return n instanceof Error?n.message:String(n)}async function Se(n){try{return await n.text()}catch{return"(could not read response body)"}}function vo(n){try{let e=JSON.parse(n);switch(e.error){case"invalid_grant":return"Hint: The authorization code may have expired or already been used. Re-run the login flow.";case"invalid_client":return"Hint: The client credentials were rejected. The client_id may be invalid or the client_secret may be wrong.";case"redirect_uri_mismatch":return"Hint: The redirect_uri does not match what was registered with the IDP.";case"unsupported_grant_type":return"Hint: The IDP does not support authorization_code grants. Contact your IDP administrator.";case"invalid_scope":return"Hint: One or more requested scopes are not allowed. Check the scopes configured on the IDP.";case"use_dpop_nonce":return"Hint: The server requires a DPoP nonce. This should be handled automatically \u2014 please report this as a bug.";default:return e.error_description?`IDP says: ${e.error_description}`:null}}catch{return null}}function So(){return pn(32).toString("base64url")}function Po(n){return ko("sha256").update(n).digest("base64url")}function Co(){return pn(16).toString("base64url")}function _o(n,e,t,o,r,a){let s=new URLSearchParams({client_id:e,response_type:"code",redirect_uri:t,scope:o.join(" "),state:r,code_challenge:a,code_challenge_method:"S256"});return`${n}?${s}`}var Ro=300*1e3;async function xo(){return new Promise(n=>{let e=yo((r,a)=>{let s=new URL(r.url,"http://localhost"),i=s.searchParams.get("code")??void 0,c=s.searchParams.get("state")??void 0,l=s.searchParams.get("error")??s.searchParams.get("error_description")??void 0,u=l?Io(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>";a.writeHead(200,{"Content-Type":"text/html"}),a.end(p),t({code:i,state:c,error:l})}),t,o=new Promise(r=>{t=r,setTimeout(()=>{r(null),e.close()},Ro)});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 Io(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function Ko(n){try{process.platform==="win32"?ve("cmd",["/c","start","",n]):process.platform==="darwin"?ve("open",[n]):ve("xdg-open",[n])}catch{console.log(" Could not open browser automatically. Please navigate to the URL above manually.")}}import{CredentialStore as Do}from"@kanonak-protocol/sdk";async function dn(n){try{let e=new A,t=new Do,r=await new B(e,t).authorize(n);r.success?console.log(`
|
|
48
48
|
Authenticated with ${n}.`):(console.error(`
|
|
49
49
|
Authentication failed:
|
|
50
50
|
${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
|
|
51
51
|
Authentication failed unexpectedly:
|
|
52
52
|
${t}`),console.error(`
|
|
53
|
-
If this persists, see https://github.com/kanonak-protocol for support channels.`),process.exit(1)}}import{CredentialStore as
|
|
53
|
+
If this persists, see https://github.com/kanonak-protocol for support channels.`),process.exit(1)}}import{CredentialStore as To}from"@kanonak-protocol/sdk";async function mn(n){try{let e=new A,t=new To,r=await new B(e,t).logout(n);r.success?console.log(`Logged out from ${n}.`):(console.error(`
|
|
54
54
|
Logout failed:
|
|
55
55
|
${r.error}`),process.exit(1))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`
|
|
56
56
|
Logout failed unexpectedly:
|
|
57
|
-
${t}`),process.exit(1)}}import{Command as
|
|
58
|
-
`;function
|
|
59
|
-
Installed capability "${w}".`),console.log(`Run "kanonak ${w} --help" to get started.`)}async function
|
|
60
|
-
`);for(let[t,o]of e)console.log(` ${t} ${o.publisher}/${o.package_}@${o.version}`)}import{Command as
|
|
57
|
+
${t}`),process.exit(1)}}import{Command as or}from"commander";import{KanonakParser as rr,KanonakObjectParser as sr,PublisherIndex as ar,CredentialStore as ir,createAuthenticatedFetch as cr,computeIntegrity as lr}from"@kanonak-protocol/sdk";import{readFileSync as Eo,writeFileSync as jo,existsSync as Ao}from"fs";import{join as No}from"path";import fn from"js-yaml";import{getGlobalCachePath as Oo}from"@kanonak-protocol/sdk";var Lo=`# This file is generated by Kanonak CLI. Do not edit manually.
|
|
58
|
+
`;function gn(){let n=Oo();return No(n,"..","capabilities.lock")}function q(){let n=gn();if(!Ao(n))return{version:"1",lastUpdated:new Date().toISOString(),capabilities:{}};let e=Eo(n,"utf-8"),t=fn.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 X(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=fn.dump(n,{lineWidth:-1,sortKeys:!1,quotingType:'"'});jo(gn(),Lo+t,"utf-8")}import{SingleDocumentRepository as ur}from"@kanonak-protocol/sdk/uri-helpers";import{existsSync as Uo,readdirSync as Fo,readFileSync as Mo}from"fs";import{join as hn}from"path";import{KanonakObjectParser as Ho,EmbeddedKanonak as wn,ReferenceKanonak as $n,getGlobalCachePath as Vo}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as vn}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as Pe,findSubjectsByType as zo,getStringValue as N,getReferenceUri as Ce,getListValues as Sn}from"@kanonak-protocol/sdk/uri-helpers";var P="kanonak.org",C="capabilities",_e={publisher:P,package_:C,name:"Capability"},Bo={publisher:P,package_:C,name:"commandName"},Pn={publisher:P,package_:C,name:"description"},qo={publisher:P,package_:C,name:"managesType"},Wo={publisher:P,package_:C,name:"deploymentTarget"},Go={publisher:P,package_:C,name:"hasCommand"},Jo={publisher:P,package_:C,name:"subcommandName"},Yo={publisher:P,package_:C,name:"performs"},Xo={publisher:P,package_:C,name:"hasArgument"},Zo={publisher:P,package_:C,name:"argumentName"},kn={publisher:P,package_:C,name:"isRequired"},yn={publisher:P,package_:C,name:"isOption"},Qo={publisher:P,package_:C,name:"defaultValue"};async function Cn(n,e,t){let o=q(),r=new Ho,a=[],s=!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 er(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,s=!0;else{console.error(` WARNING: Cached content missing for capability "${i}" (${l.publisher}/${l.package_}@${l.version}). Reinstall it with: kanonak capability remove ${i} && kanonak capability add ${l.publisher}/${l.package_}`);continue}}try{let p=e.parse(u),d=new vn(p,t),f=await r.parseKanonaks(d),g=_n(f,l.publisher,l.package_,l.version);g?a.push(g):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 s&&X(o),a}async function er(n,e,t,o,r){let a=hn(Vo(),e.publisher);if(!Uo(a))return;let s=[];for(let i of Fo(a)){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 d;try{d=Mo(hn(a,i),"utf-8")}catch{continue}let f;try{let g=t.parse(d),m=new vn(g,r),k=await o.parseKanonaks(m);f=_n(k,e.publisher,u,p)?.commandName}catch{continue}f===n&&s.push({entry:{publisher:e.publisher,package_:u,version:p,resolved:`kanonak://${e.publisher}/${u}@${p}`,integrity:""},content:d})}if(s.length===1)return s[0]}function _n(n,e,t,o){let r=zo(n,_e);if(r.length===0)return;let a=r[0],s=N(a,Bo)??"",i=N(a,Pn)??"",c=Ce(a,qo),l=Ce(a,Wo),u=[];for(let p of Sn(a,Go)){let d=nr(p,n);d&&u.push(d)}return{commandName:s,description:i,managesTypeKey:c?Pe(c):"",deploymentTargetKey:l?Pe(l):"",commands:u,publisher:e,package_:t,version:o}}function nr(n,e){let t;if(n instanceof wn)t=n;else if(n instanceof $n){let c=Rn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=N(t,Jo)??"",r=N(t,Pn)??"",a=Ce(t,Yo),s=Sn(t,Xo),i=[];for(let c of s){let l=tr(c,e);l&&i.push(l)}return{subcommandName:o,description:r,arguments:i,actionKey:a?Pe(a):""}}function tr(n,e){let t;if(n instanceof wn)t=n;else if(n instanceof $n){let c=Rn(e,n.subject.publisher,n.subject.package_,n.subject.name);c&&(t=c)}if(!t)return;let o=N(t,Zo)??"",r=N(t,kn)==="true"||bn(t,kn)===!0,a=N(t,yn)==="true"||bn(t,yn)===!0,s=N(t,Qo),i={argumentName:o,required:r,isOption:a};return s!==void 0&&(i.defaultValue=s),i}function bn(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 Rn(n,e,t,o){for(let r of n){if(!("name"in r)||!("namespace"in r))continue;let a=r;if(a.name===o&&!(!a.namespace||typeof a.namespace!="string")&&a.namespace.startsWith(`${e}/${t}@`))return r}}import{findSubjectsByType as pr,getStringValue as dr}from"@kanonak-protocol/sdk/uri-helpers";var mr={publisher:P,package_:C,name:"commandName"};function xn(){let n=new or("capability").description("Manage Kanonak CLI capabilities (pluggable command groups)");return n.command("add <package>").description("Install a capability from a Kanonak publisher").action(async e=>{await fr(e)}),n.command("remove <name>").description("Remove an installed capability").action(async e=>{await gr(e)}),n.command("list").description("List installed capabilities").action(async()=>{await hr()}),n}async function fr(n){let e=T(n);e||(console.error(`Invalid package reference: "${n}"`),console.error("Expected format: {publisher}/{package}[@{version}]"),process.exit(1));let{publisher:t,packageName:o,version:r,instanceName:a}=e;a&&(console.error(`\`kanonak capability add\` installs whole packages \u2014 got an instance suffix "/${a}".`),console.error(`Try: kanonak capability add ${t}/${o}${r?"@"+r:""}`),process.exit(1));let s=new D,i=new rr,c=new sr,l=new ir,u=cr(l),p=new ar({fetchFn:u}),d=r??await p.getHighestVersion(t,o);d||(console.error(`Could not resolve version for "${t}/${o}".`),process.exit(1)),console.log(`Installing capability ${t}/${o}@${d}...`);let f=s.get(t,o,d);if(!f){let _=await p.getPackageUrl(t,o,d),K=await u(_,t);if(!K.ok)throw new Error(`Failed to fetch ${_} (${K.status} ${K.statusText})`);f=await K.text(),s.put(t,o,d,f)}let g=i.parse(f),m=await v(process.cwd(),i),k=new ur(g,m),h=await c.parseKanonaks(k),y=pr(h,_e);y.length===0&&(console.error(`Package ${t}/${o}@${d} does not contain a ${P}/${C}/Capability instance.`),process.exit(1));let b=y[0],w=dr(b,mr);w||(console.error(`Capability instance in ${t}/${o}@${d} has no commandName property.`),process.exit(1));let $=q();$.capabilities[w]={publisher:t,package_:o,version:d,resolved:await p.getPackageUrl(t,o,d),integrity:lr(f)},X($),console.log(`
|
|
59
|
+
Installed capability "${w}".`),console.log(`Run "kanonak ${w} --help" to get started.`)}async function gr(n){let e=q();e.capabilities[n]||(console.error(`Capability "${n}" is not installed.`),process.exit(1));let t=e.capabilities[n];delete e.capabilities[n],X(e),console.log(`Removed capability "${n}" (${t.publisher}/${t.package_}@${t.version}).`)}async function hr(){let n=q(),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 Q}from"commander";import{readFileSync as kr,writeFileSync as yr,mkdirSync as br,existsSync as In,statSync as wr}from"fs";import{join as $r,resolve as vr}from"path";import{KanonakParser as Ie,KanonakObjectParser as Ke,SubjectKanonak as Sr,Reasoner as Pr,KanonakVocabulary as Cr,makeUriKey as Tn,pickHighestDocument as De,formatVersion as En}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Z}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Re,findSubjectByUri as _r}from"@kanonak-protocol/sdk/uri-helpers";import{TX_V3 as Kn}from"@kanonak-protocol/sdk/transformations";import{TransformationRunnerV3 as Rr,SUPPORTED_FORMATS_V3 as jn}from"@kanonak-protocol/sdk/transformations";import{compileTransformationV3 as Te}from"@kanonak-protocol/sdk/transformations";function xe(n){return[...Re(n,Kn.InstanceTransformation),...Re(n,Kn.SetTransformation)]}function An(){let n=new Q("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(
|
|
99
|
-
`);throw new Error(`Multiple Transformations named "${
|
|
100
|
-
${
|
|
98
|
+
`);return n.addCommand(xr()),n.addCommand(Tr()),n.addCommand(jr()),n.addCommand(Nr()),n}function xr(){return new Q("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.",Ir,[]).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 Kr(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}function Ir(n,e){return[...e,n]}async function Kr(n,e){let t=new Ie,o=new Ke,r=await v(process.cwd(),t),a=await Nn(n,r,o),{transformation:s,transformationKanonaks:i}=a;console.log(`Transformation: ${te(s)}`);let c=Te(s,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 Or(y,r,t,o);l.push(...b);let w=await Fr(b,c.inputPattern.matchesClass,r);for(let $ of w){let _=Mr($);_&&!u.has(_)&&u.set(_,$)}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()],d=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 f=Dr(c.outputs,e.format);console.log(`Output format: ${f}`);let g=jn[f];if(!g)throw new Error(`Unknown format "${f}". Run \`kanonak transform formats\` to see what the runner supports.`);let k=await new Rr().run({transformation:s,instances:p,allKanonaks:d,transformationKanonaks:i,repository:r,parser:t,objectParser:o,outputFormat:f}),h=vr(e.out);br(h,{recursive:!0});for(let y of k){let b=Ur(y.fileName),w=$r(h,`${b}${g.extension}`);yr(w,y.content,"utf-8"),console.log(` wrote ${w}`)}console.log(`Done. ${k.length} artifact(s) written to ${h}`)}function Dr(n,e){if(e){if(!n.has(e))throw new Error(`Transformation does not declare --format "${e}" in its outputs. Declared outputs: ${Array.from(n).sort().join(", ")}`);return e}if(n.size===1)return Array.from(n)[0];throw new Error(`Transformation supports multiple output formats (${Array.from(n).sort().join(", ")}); pass --format <name> to select one.`)}function Tr(){return new Q("list").description("Scan the local workspace + cache for every Transformation instance and print a one-line summary per hit.").action(async()=>{try{await Er()}catch(n){console.error(`Error: ${n.message}`),process.exit(1)}})}async function Er(){let n=new Ie,e=new Ke,t=await v(process.cwd(),n),o=await t.getAllDocumentsAsync(),r=new Map;for(let s of o)try{let i=new Z(s,t),c=await e.parseKanonaks(i),l=xe(c);for(let u of l){let p=Ee(u);if(!p)continue;let d=r.get(p)??[];d.push({tx:u,kanonaks:c,doc:s}),r.set(p,d)}}catch{}let a=[];for(let s of r.values()){if(s.length===1){a.push(Dn(s[0].tx,s[0].kanonaks));continue}let i=De(s.map(l=>l.doc));if(!i.chosen)continue;let c=s.find(l=>l.doc===i.chosen);c&&a.push(Dn(c.tx,c.kanonaks))}if(a.length===0){console.log("No Transformation instances found in the current workspace.");return}a.sort((s,i)=>s.uri.localeCompare(i.uri));for(let s of a)console.log(`${s.uri}`),console.log(` matches: ${s.matchesClass}`),console.log(` outputs: ${s.outputs.join(", ")}`)}function jr(){return new Q("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 Ar(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Ar(n){let e=new Ie,t=new Ke,o=await v(process.cwd(),e),{transformation:r,transformationKanonaks:a}=await Nn(n,o,t),s=Te(r,a);if(console.log(`Transformation: ${te(r)}`),console.log(),console.log("Input pattern:"),console.log(` Matches class: ${ne(s.inputPattern.matchesClass)}`),s.inputPattern.requires.length>0){console.log(" Required properties:");for(let i of s.inputPattern.requires)console.log(` - ${ne(i)}`)}else console.log(" Required properties: (none)");if(console.log(),console.log(`Outputs: ${Array.from(s.outputs).sort().join(", ")}`),console.log(),s.overrides.size>0){console.log("Format overrides:");for(let[i,c]of s.overrides){if(console.log(` ${i}:`),c.metadataKeys&&console.log(` metadata keys: ${c.metadataKeys.join(", ")}`),c.metadataRenames.size>0){let l=[];for(let[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: ${s.rule.kind}`),s.rule.kind==="build-ast-node"&&(console.log(`Rule root AST class: ${ne(s.rule.astClass)}`),console.log(`Rule root bindings: ${s.rule.set.length} field(s)`)),console.log(`Artifact name root kind: ${s.artifactName.kind}`)}function Nr(){return new Q("formats").description("List the OutputFormat names the runner can serialize to.").action(()=>{console.log("Registered format backends:");let n=Object.entries(jn).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 Nn(n,e,t){let o,r,a;if(n.includes("/")){let d=n.indexOf("@"),f=n;if(d!==-1){let m=n.indexOf("/",d);if(m===-1)throw new Error(`Transformation URI "${n}" has @version but no trailing /<name>`);f=n.substring(0,d)+n.substring(m)}let g=f.split("/");if(g.length<3)throw new Error(`Invalid transformation URI "${n}" \u2014 expected publisher/package/name or publisher/package@version/name`);o=g[0],r=g[1],a=g.slice(2).join("/")}else a=n;if(o&&r){let d=await e.getDocumentsByNamespaceAsync(o,r);if(d.length===0)throw new Error(`Package ${o}/${r} not found in the local workspace or cache.`);let f=Lr(n),g=On(d,f,`${o}/${r}`),m=new Z(g,e),k=await t.parseKanonaks(m),h=_r(k,{publisher:o,package_:r,name:a,version:""});if(!h){let y=xe(k),b=y.find(w=>w.name===a);if(!b)throw new Error(`Transformation "${a}" not found in package ${o}/${r}. Package contains ${y.length} Transformation(s): ${y.map(w=>w.name).join(", ")||"(none)"}`);return{transformation:b,transformationKanonaks:k}}return{transformation:h,transformationKanonaks:k}}let s=await e.getAllDocumentsAsync(),i=new Map;for(let d of s)try{let f=new Z(d,e),g=await t.parseKanonaks(f),m=xe(g);for(let k of m){if(k.name!==a)continue;let h=Ee(k);if(!h)continue;let y=i.get(h)??[];y.push({tx:k,kanonaks:g,doc:d}),i.set(h,y)}}catch{}if(i.size===0)throw new Error(`No Transformation named "${a}" found in the workspace. Try \`kanonak transform list\` to see available transformations.`);if(i.size>1){let d=Array.from(i.keys()).sort().join(`
|
|
99
|
+
`);throw new Error(`Multiple Transformations named "${a}" in the workspace \u2014 disambiguate with a full publisher/package/name URI:
|
|
100
|
+
${d}`)}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(d=>[d.doc,d])),u=De(c.map(d=>d.doc));if(!u.chosen)throw new Error(`Could not select a Transformation version for "${a}".`);let p=l.get(u.chosen);if(u.multipleVersionsPresent){let d=m=>{let k=m.metadata.namespace_?.version;return k?En(k):""},f=p.tx.namespace??"",g=f.includes("@")?f.substring(0,f.indexOf("@")):f;console.warn(`Warning: Transformation "${a}" has ${c.length} versions present (${c.map(m=>d(m.doc)).filter(Boolean).join(", ")}); using @${d(u.chosen)}. Pin with ${g}@<version>/${a} to suppress this warning.`)}return{transformation:p.tx,transformationKanonaks:p.kanonaks}}async function Or(n,e,t,o){if(/^[.\/\\]/.test(n)||/^[A-Za-z]:/.test(n)||n.endsWith(".kan.yml")||In(n)&&wr(n).isFile()){if(!In(n))throw new Error(`Scope file not found: ${n}`);let g=kr(n,"utf-8"),m=t.parse(g),k=new Z(m,e);return o.parseKanonaks(k)}let a=n.indexOf("@"),s=a===-1?n:n.substring(0,a),i=a===-1?void 0:n.substring(a+1),c=s.indexOf("/");if(c===-1)throw new Error(`Invalid scope "${n}" \u2014 expected a file path or publisher/package[@version] URI`);let l=s.substring(0,c),u=s.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 d=On(p,i,`${l}/${u}`),f=new Z(d,e);return o.parseKanonaks(f)}function Lr(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 On(n,e,t){let o=a=>{let s=a.metadata.namespace_?.version;return s?En(s):""},r=De(n,{requestedVersion:e});if(r.exactRequestedVersionMissing){let a=n.map(o).filter(Boolean).sort().join(", ");throw new Error(`${t}@${e} not found in the local workspace or cache. Available versions: ${a||"(none with parseable namespace)"}`)}if(!r.chosen)throw new Error(`${t} not found in the local workspace or cache.`);return!e&&r.multipleVersionsPresent&&console.warn(`Warning: ${t} has ${n.length} versions present (${n.map(o).filter(Boolean).join(", ")}); using @${o(r.chosen)}. Pin with ${t}@<version> to suppress this warning.`),r.chosen}function Dn(n,e){try{let t=Te(n,e);return{uri:te(n),matchesClass:ne(t.inputPattern.matchesClass),outputs:Array.from(t.outputs).sort()}}catch(t){return{uri:te(n),matchesClass:`(compile error: ${t.message})`,outputs:[]}}}function te(n){let e=n.namespace||"",t=e.indexOf("@");return`${t===-1?e:e.substring(0,t)}/${n.name}`}function ne(n){return`${n.publisher}/${n.package_}/${n.name}`}function Ur(n){return n.replace(/[\\/:*?"<>|\s]+/g,"_").replace(/^_+|_+$/g,"")}async function Fr(n,e,t){let o=new Map;for(let s of n){if(!(s instanceof Sr))continue;let i=Ee(s);i&&o.set(i,s)}let r=[];try{r=(await new Pr({vocabulary:new Cr}).reason(t)).getInstancesOfClass(Tn(e.publisher,e.package_,e.name))}catch{}let a=[];for(let s of r){let i=o.get(s);i&&a.push(i)}return a.length>0?a:Re(n,e)}function Ee(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:Tn(o.substring(0,r),o.substring(r+1),n.name)}function Mr(n){let e=n.namespace??"";return!e||!n.name?null:`${e}/${n.name}`}import{Command as Hr}from"commander";import{writeFileSync as Vr,mkdirSync as zr}from"fs";import{join as Br,resolve as qr}from"path";import{KanonakParser as Wr,KanonakObjectParser as Gr,SubjectKanonak as Fn,findDerivation as Jr}from"@kanonak-protocol/sdk";import{TransformationRunnerV3 as Yr}from"@kanonak-protocol/sdk/transformations";var Xr={publisher:"kanonak.org",package_:"formats",name:"html"},Zr={publisher:"kanonak.org",package_:"derivation",name:"default"},Qr={html:".html",markdown:".md",json:".json",yaml:".yaml",xml:".xml",svg:".svg",typescript:".ts","c-sharp":".cs",rust:".rs",python:".py"};function es(n){return n==="markdown"?"markdown-with-frontmatter":n}function Mn(){return new Hr("derive").description("Materialize a derived artifact from a Kanonak resource by walking the polymorphic derivation discovery: instance overrides \u2192 class hierarchy \u2192 universal defaults. The result is written to disk.").argument("<resource>","Resource URI in the form publisher/package[@version]/name. Identifies the specific instance to derive.").option("--format <name>","Format instance name (e.g. html, markdown, json). Defaults to html.","html").option("--variant <name>","Variant instance name (e.g. default, compact, summary). Defaults to default.","default").option("--out <dir>","Directory to write the artifact into.",".").addHelpText("after",`
|
|
101
101
|
Examples:
|
|
102
102
|
|
|
103
103
|
# Render a resource as HTML using whatever derivation the discovery
|
|
@@ -108,28 +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
|
|
112
|
-
`,"utf-8");for(let l of e){let u=r.resolvePackageUrl(o,l.pkg,l.ver,He),p=P(n,Yn(u,o));M(Jn(p),{recursive:!0}),ha(l.file,p)}let a=Yn(r.resolveIndexUrl(o,He),o),i=e.map(l=>`${l.pkg}/${l.ver}`).sort(),c=P(n,a);M(Jn(c),{recursive:!0}),K(c,i.join(`
|
|
113
|
-
`)+`
|
|
114
|
-
`,"utf-8"),console.log(`Wrote publisher endpoints: ${a}, .well-known/kanonak.json, and ${e.length} raw package source(s).`)}function Yn(n,e){let t=`https://${e}/`;if(!n.startsWith(t))throw new Error(`Publisher config points "${n}" off-origin (expected ${t}\u2026); a static origin can only serve its own paths.`);return n.slice(t.length)}function Ra(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 g={verStr:p,major:m[0],minor:m[1],patch:m[2]};o.has(u)||o.set(u,[]),o.get(u).push({resource:i,ver:g});let k=r.get(u);(!k||g.major>k.ver.major||g.major===k.ver.major&&g.minor>k.ver.minor||g.major===k.ver.major&&g.minor===k.ver.minor&&g.patch>k.ver.patch)&&r.set(u,{resource:i,ver:g})}let s=(i,c)=>{try{return M(i,{recursive:!0}),K(P(i,"index.html"),t.renderDocument(c),"utf-8"),K(P(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},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(M(l,{recursive:!0}),t.hasDeclaredView(c))K(P(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8");else{let 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);K(P(l,"index.html"),t.renderPackageVersionList(i,u,c),"utf-8"),K(P(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}a+=1}catch{}}return a}function xa(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 u=(c[1]??"").split("@")[1]??"",p=u.split(".").map(Number);if(p.length!==3||p.some(k=>Number.isNaN(k)))continue;let m={verStr:u,major:p[0],minor:p[1],patch:p[2]},g=r.get(l);(!g||m.major>g.ver.major||m.major===g.ver.major&&m.minor>g.ver.minor||m.major===g.ver.major&&m.minor===g.ver.minor&&m.patch>g.ver.patch)&&r.set(l,{resource:a,ver:m})}if(!o||r.size===0)return;let s=t.publisherSubject(o);K(P(n,"index.html"),t.renderDocument(s,{rootIndex:!0}),"utf-8"),K(P(n,"index.css"),t.renderStylesheet(s),"utf-8")}function Ia(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];K(P(n,a,`${i}.html`),Ve(`/${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));M(m,{recursive:!0}),K(P(m,`${i}.html`),Ve(`/${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 g=P(n,a,m);M(g,{recursive:!0}),K(P(g,`${i}.html`),Ve(`/${a}/${p.verStr}/${i}`),"utf-8"),o+=1}}return o}function Ve(n){let e=n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");return`<!doctype html>
|
|
111
|
+
`).action(async(n,e)=>{try{await ns(n,e)}catch(t){console.error(`Error: ${t.message}`),process.exit(1)}})}async function ns(n,e){let t=T(n);if(!t||!t.instanceName)throw new Error(`Invalid resource URI "${n}". Expected publisher/package[@version]/instance.`);let o=new Wr,r=new Gr,a=await v(process.cwd(),o),s=await r.parseKanonaks(a),i=ts(s,t);if(!i)throw new Error(`Resource ${t.publisher}/${t.packageName}${t.version?`@${t.version}`:""}/${t.instanceName} not found in the workspace or cache.`);console.log(`Resource: ${Ln(i)}`);let c=rs(e.format),l=ss(e.variant),u=Jr(i,c,l,s);if(!u)throw new Error(`No derivation found for resource ${Ln(i)} at (format=${e.format}, variant=${e.variant}). The class hierarchy declares no binding and no universal default applies.`);console.log(`Derivation: ${as(u)} \u2192 ${Un(u.transformation)}`);let p=os(s,u.transformation);if(!p)throw new Error(`Transformation ${Un(u.transformation)} not found in the workspace or cache. The binding pointed at a transformation the resolver cannot locate.`);let d=es(e.format),g=await new Yr().run({transformation:p,instances:[i],allKanonaks:s,repository:a,parser:o,objectParser:r,outputFormat:d}),m=qr(e.out);zr(m,{recursive:!0});let k=Qr[e.format]??"";for(let h of g){let y=is(h.fileName),b=Br(m,`${y}${k}`);Vr(b,h.content,"utf-8"),console.log(` wrote ${b}`)}console.log(`Done. ${g.length} artifact(s) written to ${m}`)}function ts(n,e){for(let t of n){if(!(t instanceof Fn)||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 os(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Fn&&o.name===e.name&&o.namespace===t)return o}function rs(n){if(n.includes("/")){let e=T(n);if(!e||!e.instanceName)throw new Error(`Invalid --format URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...Xr,name:n}}function ss(n){if(n.includes("/")){let e=T(n);if(!e||!e.instanceName)throw new Error(`Invalid --variant URI "${n}".`);return{publisher:e.publisher,package_:e.packageName,name:e.instanceName}}return{...Zr,name:n}}function Ln(n){return`${n.namespace}/${n.name}`}function Un(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}function as(n){return n.source==="instance"?"instance override":`class ${n.source.publisher}/${n.source.package_}/${n.source.name}`}function is(n){return n.replace(/[^a-zA-Z0-9._@-]+/g,"_")}import{Command as cs}from"commander";import{writeFileSync as R,mkdirSync as L}from"fs";import{join as S,resolve as Hn,dirname as ls}from"path";import{SubjectKanonak as us}from"@kanonak-protocol/sdk";import{loadServerModel as ps,route as ds}from"@kanonak-protocol/sdk/server";function Vn(){return new cs("publish").description("Generate a static Kanonak site from the local workspace \u2014 the same origin `kanonak serve` produces (it shares serve's model + renderer), frozen to disk under --out.").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").option("--publisher <domain>","Publisher to publish (required only if the workspace has more than one).").action(async n=>{await ms(n)})}async function ms(n){let e=Hn(n.workspace),t=Hn(n.out),o=await ps(e,n.publisher?{publisher:n.publisher}:{}),{catalog:r,lookRenderer:a,localNamespaces:s,rawByNsKey:i,publisher:c}=o;L(t,{recursive:!0}),console.log(`Publishing ${c} \u2014 ${s.size} package version(s) to ${t}`);let l=r.filter(g=>g instanceof us&&s.has(g.namespace||""));console.log(`Rendering ${l.length} resource(s).`);let u=0,p=0;for(let g of l){let m=(g.namespace||"").split("/")[1]??"",[k,h]=m.split("@");if(!k||!h)continue;let y=S(t,k,h);L(y,{recursive:!0});try{let b=a.renderRawMarkdown(g);b!==void 0&&(R(S(y,`${g.name}.md`),b,"utf-8"),u+=1),R(S(y,`${g.name}.html`),a.renderDocument(g),"utf-8"),R(S(y,`${g.name}.css`),a.renderStylesheet(g),"utf-8"),R(S(y,`${g.name}.svg`),a.renderSvg(g),"utf-8"),u+=3}catch(b){console.warn(` ${g.namespace}/${g.name}: ${b.message}`),p+=1}}console.log(`Done. ${u} artifact(s) written, ${p} skipped.`);let d=gs(t,l,a);console.log(`Wrote ${d} package overview page(s).`),hs(t,l,a);let f=ks(t,l);console.log(`Wrote ${f} version-form redirect stub(s).`),fs(t,o)}function fs(n,e){if(e.rawByNsKey.size===0)return;let t=(o,r)=>{let a=S(n,r);L(ls(a),{recursive:!0}),R(a,ds(e,o).body,"utf-8")};t("/.well-known/kanonak.json",".well-known/kanonak.json"),t("/index.txt","index.txt");for(let o of e.rawByNsKey.keys()){let[r,a]=o.split("@");!r||!a||t(`/${r}/${a}.kan.yml`,`${r}/${a}.kan.yml`)}console.log(`Wrote publisher endpoints: index.txt, .well-known/kanonak.json, and ${e.rawByNsKey.size} raw package source(s).`)}function gs(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 d=p.split(".").map(Number);if(d.length!==3||d.some(m=>Number.isNaN(m)))continue;let f={verStr:p,major:d[0],minor:d[1],patch:d[2]};o.has(u)||o.set(u,[]),o.get(u).push({resource:i,ver:f});let g=r.get(u);(!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(u,{resource:i,ver:f})}let a=(i,c)=>{try{return L(i,{recursive:!0}),R(S(i,"index.html"),t.renderDocument(c),"utf-8"),R(S(i,`${c.name}.css`),t.renderStylesheet(c),"utf-8"),!0}catch{return!1}},s=0;for(let[i,c]of o)for(let{resource:l,ver:u}of c)a(S(n,i,u.verStr),l)&&(s+=1);for(let[i,{resource:c}]of r){let l=S(n,i);try{if(L(l,{recursive:!0}),t.hasDeclaredView(c))R(S(l,"index.html"),t.renderDocument(c,{bareOverview:!0}),"utf-8"),R(S(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8");else{let u=(o.get(i)??[]).slice().sort((p,d)=>d.ver.major-p.ver.major||d.ver.minor-p.ver.minor||d.ver.patch-p.ver.patch).map(p=>p.ver.verStr);R(S(l,"index.html"),t.renderPackageVersionList(i,u,c),"utf-8"),R(S(l,`${c.name}.css`),t.renderStylesheet(c),"utf-8")}s+=1}catch{}}return s}function hs(n,e,t){let o="",r=new Map;for(let s of e){let c=(s.namespace||"").split("/"),[l]=(c[1]??"").split("@");if(!c[0]||!l||(o||(o=c[0]),s.name!==l))continue;let u=(c[1]??"").split("@")[1]??"",p=u.split(".").map(Number);if(p.length!==3||p.some(g=>Number.isNaN(g)))continue;let d={verStr:u,major:p[0],minor:p[1],patch:p[2]},f=r.get(l);(!f||d.major>f.ver.major||d.major===f.ver.major&&d.minor>f.ver.minor||d.major===f.ver.major&&d.minor===f.ver.minor&&d.patch>f.ver.patch)&&r.set(l,{resource:s,ver:d})}if(!o||r.size===0)return;let a=t.publisherSubject(o);R(S(n,"index.html"),t.renderDocument(a,{rootIndex:!0}),"utf-8"),R(S(n,"index.css"),t.renderStylesheet(a),"utf-8")}function ks(n,e){let t=new Map;for(let r of e){let a=r.namespace||"",[,s]=a.split("/");if(!s)continue;let[i,c]=s.split("@");if(!i||!c)continue;let l=c.split(".").map(Number);if(l.length!==3||l.some(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,a]of t){let[s,i]=r.split("/");a.sort((p,d)=>d.major-p.major||d.minor-p.minor||d.patch-p.patch);let c=a[0];R(S(n,s,`${i}.html`),je(`/${s}/${c.verStr}/${i}`),"utf-8"),o+=1;let l=new Set;for(let p of a){if(l.has(p.major))continue;l.add(p.major);let d=S(n,s,String(p.major));L(d,{recursive:!0}),R(S(d,`${i}.html`),je(`/${s}/${p.verStr}/${i}`),"utf-8"),o+=1}let u=new Set;for(let p of a){let d=`${p.major}.${p.minor}`;if(u.has(d))continue;u.add(d);let f=S(n,s,d);L(f,{recursive:!0}),R(S(f,`${i}.html`),je(`/${s}/${p.verStr}/${i}`),"utf-8"),o+=1}}return o}function je(n){let e=n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");return`<!doctype html>
|
|
115
112
|
<meta charset="utf-8">
|
|
116
113
|
<title>Redirecting\u2026</title>
|
|
117
114
|
<meta http-equiv="refresh" content="0; url=${e}">
|
|
118
115
|
<link rel="canonical" href="${e}">
|
|
119
116
|
<p>If you are not redirected automatically, follow this <a href="${e}">link</a>.</p>
|
|
120
|
-
`}import{Command as tt}from"commander";import{writeFileSync as Be,mkdirSync as de}from"fs";import{join as ze,resolve as Ka,dirname as qe}from"path";import{KanonakParser as Ta,KanonakObjectParser as Da,SubjectKanonak as ot,ReferenceStatement as Ea,ReferenceKanonak as ja,ListStatement as Aa,StringStatement as rt,EmbeddedStatement as Na,findDerivation as Zn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Oa}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as La}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as fe}from"@kanonak-protocol/sdk/uri-helpers";var A="kanonak.org",N="site",Qn={publisher:"kanonak.org",package_:"formats",name:"html"},et={publisher:"kanonak.org",package_:"derivation",name:"default"};function at(){let n=new tt("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(Ua()),n}function Ua(){return new tt("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 Fa(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function Fa(n){let e=new Ta,t=new Da,o=await S(process.cwd(),e),r=await t.parseKanonaks(o),s=Ka(n.out);de(s,{recursive:!0});let a=await o.getAllDocumentsAsync(),i=new Set;for(let d of a){let h=d.metadata.namespace_?.toString();h&&i.add(h)}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||"")),g=fe(r,u).filter(d=>i.has(d.namespace||""));console.log(`Found ${p.length} StaticPage(s), ${m.length} ResourcePage(s), and ${g.length} AggregateView(s) in the workspace.`);let k=new La;for(let d of p){let h=We(d,A,N,"outputPath")??`${d.name}.html`,f=Zn(d,Qn,et,r);if(!f){console.warn(` [skip] ${d.name}: no HTML/default derivation found (check class hierarchy or universal-derivations is loaded)`);continue}let y=Ge(r,f.transformation);if(!y){console.warn(` [skip] ${d.name}: transformation ${Je(f.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=ze(s,h);de(qe(w),{recursive:!0}),Be(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${d.name})`)}for(let d of m){let h=We(d,A,N,"outputPath")??`${d.name}.html`,f=nt(d,A,N,"pageOf");if(!f){console.warn(` [skip] ${d.name}: no pageOf declared`);continue}let y=r.find(R=>R instanceof ot&&R.name===f.name&&(R.namespace||"").startsWith(`${f.publisher}/${f.package_}@`));if(!y){console.warn(` [skip] ${d.name}: pageOf target ${f.publisher}/${f.package_}/${f.name} not found`);continue}let b=Zn(y,Qn,et,r);if(!b){console.warn(` [skip] ${d.name}: no derivation for target ${y.name}`);continue}let w=Ge(r,b.transformation);if(!w){console.warn(` [skip] ${d.name}: transformation ${Je(b.transformation)} not found`);continue}let $=await k.run({transformation:w,instances:[y],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if($.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let v=ze(s,h);de(qe(v),{recursive:!0}),Be(v,$[0].content,"utf-8"),console.log(` wrote ${v} (ResourcePage ${d.name} \u2192 ${y.name})`)}for(let d of g){let h=We(d,A,N,"outputPath");if(!h){console.warn(` [skip] ${d.name}: no outputPath declared`);continue}let f=nt(d,A,N,"scopeClass");if(!f){console.warn(` [skip] ${d.name}: no scopeClass declared`);continue}let y={publisher:f.publisher,package_:f.package_,name:f.name},b=Ma(d,A,N,"scopeSources"),w=Ha(d);if(!w){console.warn(` [skip] ${d.name}: no transformation declared`);continue}let $=Ge(r,w);if(!$){console.warn(` [skip] ${d.name}: transformation ${Je(w)} not found`);continue}let v=await Ba(b,o),R=[],xe=new Set;for(let ce of v){let le=await za(ce,o,e,t),D=fe(le,y);for(let E of D){let L=`${E.namespace}/${E.name}`;xe.has(L)||(xe.add(L),R.push(E))}}console.log(` ${d.name}: ${R.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${v.length} scope(s)`);let ie=await k.run({transformation:$,instances:R,allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(ie.length===0){console.warn(` [skip] ${d.name}: transformation produced no artifacts`);continue}let O=ze(s,h);de(qe(O),{recursive:!0}),Be(O,ie[0].content,"utf-8"),console.log(` wrote ${O} (AggregateView ${d.name})`)}console.log("Site build complete.")}function We(n,e,t,o){for(let r of n.statement)if(r instanceof rt&&ge(r,e,t,o))return r.object}function Ma(n,e,t,o){for(let r of n.statement){if(!(r instanceof Aa)||!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 nt(n,e,t,o){for(let r of n.statement)if(r instanceof Ea&&ge(r,e,t,o)&&r.object instanceof ja)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Ha(n){for(let e of n.statement)if(e instanceof Na&&ge(e,A,N,"transformation"))return Va(e.object)}function Va(n){let e,t,o,r;for(let s of n.statement){if(!(s instanceof rt))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 Ge(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof ot&&o.name===e.name&&o.namespace===t)return o}function Je(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function Ba(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 za(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 Oa(u,e);return o.parseKanonaks(m)}}return[]}import{Command as qa}from"commander";import{createServer as Wa}from"http";import{watch as Ga}from"fs";import{resolve as Ja,join as Ya}from"path";import{homedir as Xa}from"os";import{loadServerModel as Za,route as Qa}from"@kanonak-protocol/sdk/server";import{SearchIndex as es}from"@kanonak-protocol/sdk/search";import{resolveDisplayValue as ns,subjectUri as ts}from"@kanonak-protocol/sdk";function st(){return new qa("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=Ja(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 es,p=await u.build(c.catalog,{cacheDir:Ya(Xa(),".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;Ga(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")}Wa(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:os(o.publisher,c),limit:30}),g=as(o,u,m);i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(g),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 os(n,e){let t=e.split("/").filter(Boolean);if(t.length!==0)return`${n}/${t[0]}@`}function rs(n,e){let t=ts(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 X(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function as(n,e,t){let o=t.map(r=>{let s=ns(n.catalog,r.subject),a=rs(n,r.subject),i=Math.max(0,Math.min(100,Math.round(r.score*100))),c=s.summary?`<span class="kan-pkg-card-comment">${X(s.summary.slice(0,160))}</span>`:"";return`<a class="kan-pkg-card" href="${X(a)}"><span class="kan-pkg-card-body"><span class="kan-pkg-card-title">${X(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: ${X(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="${X(e)}" placeholder="Search\u2026" style="width:100%;padding:.6rem .8rem;font-size:1rem;box-sizing:border-box"></form><h1>Results for \u201C${X(e)}\u201D</h1><section class="kan-pkg-grid">${o||"<p>No matches.</p>"}</section></main></body></html>`}import{Command as ss}from"commander";import{resolve as is,join as cs}from"path";import{homedir as ls}from"os";import{readFileSync as us}from"fs";import{KanonakParser as it,KanonakObjectParser as ps,PublisherIndex as ct,CredentialStore as lt,createAuthenticatedFetch as ut,FileSystemKanonakDocumentRepository as ms,Reasoner as ds,KanonakVocabulary as fs,getGlobalCachePath as gs,makeUriKey as hs,resolveDisplayValue as ks,subjectUri as ys,contextTypesOf as bs,collectKanonakFiles as ws}from"@kanonak-protocol/sdk";import{SearchIndex as $s}from"@kanonak-protocol/sdk/search";function vs(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 pt(){return new ss("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 Ss(e);return}n||(console.error(`Nothing to search. Either:
|
|
117
|
+
`}import{Command as Gn}from"commander";import{writeFileSync as Ae,mkdirSync as oe}from"fs";import{join as Ne,resolve as ys,dirname as Oe}from"path";import{KanonakParser as bs,KanonakObjectParser as ws,SubjectKanonak as Jn,ReferenceStatement as $s,ReferenceKanonak as vs,ListStatement as Ss,StringStatement as Yn,EmbeddedStatement as Ps,findDerivation as zn}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Cs}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as _s}from"@kanonak-protocol/sdk/transformations";import{findSubjectsByType as re}from"@kanonak-protocol/sdk/uri-helpers";var E="kanonak.org",j="site",Bn={publisher:"kanonak.org",package_:"formats",name:"html"},qn={publisher:"kanonak.org",package_:"derivation",name:"default"};function Xn(){let n=new Gn("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(Rs()),n}function Rs(){return new Gn("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 xs(n)}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}})}async function xs(n){let e=new bs,t=new ws,o=await v(process.cwd(),e),r=await t.parseKanonaks(o),a=ys(n.out);oe(a,{recursive:!0});let s=await o.getAllDocumentsAsync(),i=new Set;for(let m of s){let k=m.metadata.namespace_?.toString();k&&i.add(k)}let c={publisher:E,package_:j,name:"StaticPage"},l={publisher:E,package_:j,name:"ResourcePage"},u={publisher:E,package_:j,name:"AggregateView"},p=re(r,c).filter(m=>i.has(m.namespace||"")),d=re(r,l).filter(m=>i.has(m.namespace||"")),f=re(r,u).filter(m=>i.has(m.namespace||""));console.log(`Found ${p.length} StaticPage(s), ${d.length} ResourcePage(s), and ${f.length} AggregateView(s) in the workspace.`);let g=new _s;for(let m of p){let k=Le(m,E,j,"outputPath")??`${m.name}.html`,h=zn(m,Bn,qn,r);if(!h){console.warn(` [skip] ${m.name}: no HTML/default derivation found (check class hierarchy or universal-derivations is loaded)`);continue}let y=Ue(r,h.transformation);if(!y){console.warn(` [skip] ${m.name}: transformation ${Fe(h.transformation)} not found`);continue}let b=await g.run({transformation:y,instances:[m],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(b.length===0){console.warn(` [skip] ${m.name}: transformation produced no artifacts`);continue}let w=Ne(a,k);oe(Oe(w),{recursive:!0}),Ae(w,b[0].content,"utf-8"),console.log(` wrote ${w} (StaticPage ${m.name})`)}for(let m of d){let k=Le(m,E,j,"outputPath")??`${m.name}.html`,h=Wn(m,E,j,"pageOf");if(!h){console.warn(` [skip] ${m.name}: no pageOf declared`);continue}let y=r.find(K=>K instanceof Jn&&K.name===h.name&&(K.namespace||"").startsWith(`${h.publisher}/${h.package_}@`));if(!y){console.warn(` [skip] ${m.name}: pageOf target ${h.publisher}/${h.package_}/${h.name} not found`);continue}let b=zn(y,Bn,qn,r);if(!b){console.warn(` [skip] ${m.name}: no derivation for target ${y.name}`);continue}let w=Ue(r,b.transformation);if(!w){console.warn(` [skip] ${m.name}: transformation ${Fe(b.transformation)} not found`);continue}let $=await g.run({transformation:w,instances:[y],allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if($.length===0){console.warn(` [skip] ${m.name}: transformation produced no artifacts`);continue}let _=Ne(a,k);oe(Oe(_),{recursive:!0}),Ae(_,$[0].content,"utf-8"),console.log(` wrote ${_} (ResourcePage ${m.name} \u2192 ${y.name})`)}for(let m of f){let k=Le(m,E,j,"outputPath");if(!k){console.warn(` [skip] ${m.name}: no outputPath declared`);continue}let h=Wn(m,E,j,"scopeClass");if(!h){console.warn(` [skip] ${m.name}: no scopeClass declared`);continue}let y={publisher:h.publisher,package_:h.package_,name:h.name},b=Is(m,E,j,"scopeSources"),w=Ks(m);if(!w){console.warn(` [skip] ${m.name}: no transformation declared`);continue}let $=Ue(r,w);if(!$){console.warn(` [skip] ${m.name}: transformation ${Fe(w)} not found`);continue}let _=await Ts(b,o),K=[],Ye=new Set;for(let Ut of _){let Ft=await Es(Ut,o,e,t),Mt=re(Ft,y);for(let be of Mt){let Ze=`${be.namespace}/${be.name}`;Ye.has(Ze)||(Ye.add(Ze),K.push(be))}}console.log(` ${m.name}: ${K.length} instance(s) of ${y.publisher}/${y.package_}/${y.name} across ${_.length} scope(s)`);let Xe=await g.run({transformation:$,instances:K,allKanonaks:r,repository:o,parser:e,objectParser:t,outputFormat:"html"});if(Xe.length===0){console.warn(` [skip] ${m.name}: transformation produced no artifacts`);continue}let ye=Ne(a,k);oe(Oe(ye),{recursive:!0}),Ae(ye,Xe[0].content,"utf-8"),console.log(` wrote ${ye} (AggregateView ${m.name})`)}console.log("Site build complete.")}function Le(n,e,t,o){for(let r of n.statement)if(r instanceof Yn&&se(r,e,t,o))return r.object}function Is(n,e,t,o){for(let r of n.statement){if(!(r instanceof Ss)||!se(r,e,t,o))continue;let a=[];for(let s of r.object??[]){let i=s.value;typeof i=="string"&&a.push(i)}return a}return[]}function Wn(n,e,t,o){for(let r of n.statement)if(r instanceof $s&&se(r,e,t,o)&&r.object instanceof vs)return{publisher:r.object.subject.publisher,package_:r.object.subject.package_,name:r.object.subject.name}}function Ks(n){for(let e of n.statement)if(e instanceof Ps&&se(e,E,j,"transformation"))return Ds(e.object)}function Ds(n){let e,t,o,r;for(let a of n.statement){if(!(a instanceof Yn))continue;let s=a.predicate?.subject?.name;s==="publisher"?e=a.object:s==="package"?t=a.object:s==="version"?o=a.object:s==="name"&&(r=a.object)}if(!(!e||!t||!o||!r))return{publisher:e,package_:t,version:o,name:r}}function se(n,e,t,o){let r=n.predicate?.subject;return r?r.publisher===e&&r.package_===t&&r.name===o:!1}function Ue(n,e){let t=`${e.publisher}/${e.package_}@${e.version}`;for(let o of n)if(o instanceof Jn&&o.name===e.name&&o.namespace===t)return o}function Fe(n){return`${n.publisher}/${n.package_}@${n.version}/${n.name}`}async function Ts(n,e){let t=[];for(let o of n){let r=o.indexOf("@*");if(r===-1){t.push(o);continue}let a=o.substring(0,r),s=a.indexOf("/");if(s===-1){t.push(o);continue}let i=a.substring(0,s),c=a.substring(s+1),l=await e.getDocumentsByNamespaceAsync(i,c);for(let u of l){let p=u.metadata.namespace_;if(!p)continue;let d=p.version;t.push(`${p.publisher}/${p.package_}@${d.major}.${d.minor}.${d.patch}`)}}return t}async function Es(n,e,t,o){let r=n.indexOf("/"),a=n.indexOf("@");if(r===-1||a===-1)return[];let s=n.substring(0,r),i=n.substring(r+1,a),c=n.substring(a+1),l=await e.getDocumentsByNamespaceAsync(s,i);for(let u of l){let p=u.metadata.namespace_?.version;if(p&&`${p.major}.${p.minor}.${p.patch}`===c){let d=new Cs(u,e);return o.parseKanonaks(d)}}return[]}import{Command as js}from"commander";import{createServer as As}from"http";import{watch as Ns}from"fs";import{resolve as Os,join as Ls}from"path";import{homedir as Us}from"os";import{loadServerModel as Fs,route as Ms}from"@kanonak-protocol/sdk/server";import{SearchIndex as Hs}from"@kanonak-protocol/sdk/search";import{resolveDisplayValue as Vs,subjectUri as zs}from"@kanonak-protocol/sdk";function Zn(){return new js("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=Os(n.root),t=Number(n.port);if(!Number.isInteger(t)||t<=0||t>65535)throw new Error(`Invalid --port "${n.port}".`);let o,r,a=async s=>{let i=Date.now(),c=await Fs(e,n.publisher?{publisher:n.publisher}:{});if(o=c,n.search){let u=new Hs,p=await u.build(c.catalog,{cacheDir:Ls(Us(),".kanonak","search"),include:d=>c.localNamespaces.has(d.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)${s?` (${s})`:""} in ${Date.now()-i}ms`+(l.length?` [also in workspace: ${l.join(", ")} \u2014 switch with --publisher]`:""))};try{await a()}catch(s){console.error(`[error] ${s.message}`),process.exitCode=1;return}if(n.watch){let s;Ns(e,{recursive:!0},(i,c)=>{!c||!String(c).endsWith(".kan.yml")||(clearTimeout(s),s=setTimeout(()=>{a(`changed: ${c}`).catch(l=>console.error("[reload error]",l.message))},150))}),console.log("[watch] re-loading on .kan.yml changes")}As(async(s,i)=>{let c="/";try{let l=new URL(s.url??"/","http://localhost");c=decodeURIComponent(l.pathname);let u=l.searchParams.get("q");if(u&&r){let d=await r.query(u,{scope:Bs(o.publisher,c),limit:30}),f=Ws(o,u,d);i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),i.end(f),console.log(`200 ${s.method} ${c}?q=${u} (${d.length} hit(s))`);return}let p=Ms(o,c,s.headers.accept??"");i.writeHead(p.status,p.headers),i.end(p.body),console.log(`${p.status} ${s.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 Bs(n,e){let t=e.split("/").filter(Boolean);if(t.length!==0)return`${n}/${t[0]}@`}function qs(n,e){let t=zs(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 W(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function Ws(n,e,t){let o=t.map(r=>{let a=Vs(n.catalog,r.subject),s=qs(n,r.subject),i=Math.max(0,Math.min(100,Math.round(r.score*100))),c=a.summary?`<span class="kan-pkg-card-comment">${W(a.summary.slice(0,160))}</span>`:"";return`<a class="kan-pkg-card" href="${W(s)}"><span class="kan-pkg-card-body"><span class="kan-pkg-card-title">${W(a.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: ${W(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="${W(e)}" placeholder="Search\u2026" style="width:100%;padding:.6rem .8rem;font-size:1rem;box-sizing:border-box"></form><h1>Results for \u201C${W(e)}\u201D</h1><section class="kan-pkg-grid">${o||"<p>No matches.</p>"}</section></main></body></html>`}import{Command as Gs}from"commander";import{resolve as Js,join as Ys}from"path";import{homedir as Xs}from"os";import{readFileSync as Zs}from"fs";import{KanonakParser as Qn,KanonakObjectParser as Qs,PublisherIndex as et,CredentialStore as nt,createAuthenticatedFetch as tt,FileSystemKanonakDocumentRepository as ea,Reasoner as na,KanonakVocabulary as ta,getGlobalCachePath as oa,makeUriKey as ra,resolveDisplayValue as sa,subjectUri as aa,contextTypesOf as ia,collectKanonakFiles as ca}from"@kanonak-protocol/sdk";import{SearchIndex as la}from"@kanonak-protocol/sdk/search";function ua(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 ot(){return new Gs("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 pa(e);return}n||(console.error(`Nothing to search. Either:
|
|
121
118
|
\u2022 semantic-search your workspace: kanonak search -q "<keywords>"
|
|
122
119
|
\u2022 browse a publisher's catalogue: kanonak search <publisher>
|
|
123
|
-
\u2022 find instances of a class: kanonak search <publisher> --type <pub>/<pkg>/<Name>`),process.exit(1)),e.type?await
|
|
124
|
-
`)}catch(u){console.error(u.message),process.exit(1)}
|
|
125
|
-
`);for(let u of l)console.log(` ${u.score.toFixed(3)} ${u.label}${u.type?` (${u.type})`:""}`),console.log(` ${u.uri}`)}async function
|
|
126
|
-
`);let
|
|
127
|
-
`),
|
|
120
|
+
\u2022 find instances of a class: kanonak search <publisher> --type <pub>/<pkg>/<Name>`),process.exit(1)),e.type?await ma(n,e.type):await da(n)})}async function pa(n){let e=Js(n.root??"."),t=new Qn,o;try{let u=await v(e,t);o=await new Qs().parseKanonaks(u)}catch(u){console.error(`Failed to load workspace at ${e}: ${u.message}`),process.exit(1)}let r={cacheDir:Ys(Xs(),".kanonak","search"),onProgress:(u,p)=>process.stderr.write(`\r embedding ${u}/${p}\u2026 `)};if(!n.all){let u=new Set;for(let p of ca(e))try{let d=t.parse(Zs(p,"utf-8")).metadata?.namespace_;d?.version&&u.add(`${d.publisher}/${d.package_}@${d.version.major}.${d.version.minor}.${d.version.patch}`)}catch{}r.include=p=>u.has(p.namespace??"")}let a=new la,s;try{s=await a.build(o,r),s.size>0&&!s.cached&&process.stderr.write(`
|
|
121
|
+
`)}catch(u){console.error(u.message),process.exit(1)}s.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 a.query(n.query,{scope:n.scope,limit:i})).map(u=>{let p=sa(o,u.subject),d=aa(u.subject),f=ia(u.subject)[0]?.name;return{uri:d?`${d.publisher}/${d.package_}/${d.name}`:u.subject.name,label:p.label,type:f??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 da(n){let e=new nt,t=tt(e),o=new et({fetchFn:t}),r;try{r=await o.listLatestPackages(n)}catch(s){console.error(`Failed to fetch publisher index for ${n}: ${s.message}`),process.exit(1)}if(r.length===0){console.log(`No packages found at ${n}.`);return}console.log(`Packages published by ${n}:
|
|
123
|
+
`);let a=r.reduce((s,i)=>Math.max(s,i.packageName.length),0);for(let{packageName:s,version:i}of r)console.log(` ${s.padEnd(a)} @${i}`)}async function ma(n,e){let t=ua(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 Qn,r=new nt,a=tt(r),s=new et({fetchFn:a}),i=new D,c=new Set,l=[];try{l=await s.listLatestPackages(n)}catch(k){console.error(`Failed to fetch publisher index for ${n}: ${k.message}`),process.exit(1)}for(let{packageName:k,version:h}of l)c.add(`${n}|${k}|${h}`);await Me(s,i,a,"kanonak.org","core-rdf",c),await Me(s,i,a,"kanonak.org","core-owl",c),await Me(s,i,a,t.publisher,t.package_,c);for(let k of c){let[h,y,b]=k.split("|");if(!i.has(h,y,b))try{let w=await s.getPackageUrl(h,y,b),$=await a(w,h);if(!$.ok){console.error(`Warning: failed to fetch ${h}/${y}@${b}: ${$.status} ${$.statusText}`);continue}let _=await $.text();i.put(h,y,b,_)}catch(w){console.error(`Warning: failed to fetch ${h}/${y}@${b}: ${w.message}`)}}let u=new ea(oa(),!0,o),d=await new na({vocabulary:new ta}).reason(u),f=ra(t.publisher,t.package_,t.name),m=d.getInstancesOfClass(f).filter(k=>k!==f);if(m.length===0){console.log(`No instances of ${f} found in ${n}'s catalogue.`);return}console.log(`Instances of ${f} in ${n}'s catalogue:
|
|
124
|
+
`),m.sort();for(let k of m)console.log(` ${k}`)}async function Me(n,e,t,o,r,a){try{let s=await n.getHighestVersion(o,r);if(!s)return;a.add(`${o}|${r}|${s}`)}catch{}}import{existsSync as fa,readFileSync as ga}from"fs";import{dirname as ha,resolve as ka}from"path";import{KanonakObjectParser as ya,KanonakParser as ba,canonicalForm as wa,canonicalHash as $a,parseKanonakAddress as va,pickHighestDocument as Sa}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as Pa}from"@kanonak-protocol/sdk/uri-helpers";async function rt(n,e={}){let t=new ba,o=new ya,{document:r,source:a}=await Ca(n,t),s=await v(_a(a),t),i=new Pa(r,s),c=await o.parseKanonaks(i),l=$a(c);if(console.log(l),e.verbose){let u=wa(c);process.stderr.write(`# canonical form for ${a}
|
|
128
125
|
`),process.stderr.write(u),process.stderr.write(`
|
|
129
|
-
`)}}async function
|
|
130
|
-
`);for(let
|
|
131
|
-
Updated ${i} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=
|
|
132
|
-
`);let
|
|
133
|
-
`);let
|
|
134
|
-
`;function
|
|
135
|
-
`;function
|
|
126
|
+
`)}}async function Ca(n,e){if(n.endsWith(".kan.yml")){let i=ka(n);if(!fa(i))throw new Error(`kanonak hash: file not found: ${i}`);let c=ga(i,"utf-8");return{document:e.parse(c),source:i}}let t=va(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 a=t.version?`${t.version.major}.${t.version.minor}.${t.version.patch}`:void 0,s=Sa(r,a?{requestedVersion:a}:{});if(!s.chosen){let i=a?`@${a}`:"";throw new Error(`kanonak hash: no version of ${t.publisher}/${t.package_}${i} available across local/cache/HTTP`)}return{document:s.chosen,source:n}}function _a(n){return n.endsWith(".kan.yml")?O(ha(n)):process.cwd()}import{Command as st}from"commander";function G(n){return`${P}/${C}/${n}`}var He={[G("fetch-and-deploy")]:(n,e,t,o)=>n.add(e,t[0],o),[G("remove-deployed")]:(n,e,t,o)=>n.remove(e,t[0],o),[G("list-deployed")]:(n,e,t,o)=>n.list(e,o),[G("update-deployed")]:(n,e,t,o)=>n.update(e,t[0],o),[G("search-available")]:(n,e,t,o)=>n.search(e,o),[G("show-info")]:(n,e,t,o)=>n.info(e,t[0],o)};function at(n,e,t){for(let o of e){let r=new st(o.commandName).description(o.description.trim());for(let a of o.commands){let s=r.command(Ra(a));s.description(a.description);for(let i of a.arguments)if(i.isOption){let c=i.defaultValue!=null?`--${i.argumentName} [value]`:`--${i.argumentName} <value>`;s.option(c,"",i.defaultValue)}s.action(async(...i)=>{let c=xa(i);await Ia(t,o,a,i,c)})}n.addCommand(r)}}function Ra(n){let e=n.arguments.filter(t=>!t.isOption).map(t=>t.required?`<${t.argumentName}>`:`[${t.argumentName}]`);return[n.subcommandName,...e].join(" ")}function xa(n){for(let e=n.length-1;e>=0;e--)if(n[e]&&typeof n[e]=="object"&&!(n[e]instanceof st))return n[e];return{}}async function Ia(n,e,t,o,r){let a=[];for(let i of o)if(typeof i=="string")a.push(i);else break;t.actionKey||(console.error(`Capability subcommand '${t.subcommandName}' has no resolved \`performs:\` Action. Every CapabilityCommand must declare a performs value pointing at a named Action instance from the capabilities ontology. Known actions: ${Object.keys(He).join(", ")}.`),process.exit(1));let s=He[t.actionKey];s||(console.error(`Capability subcommand '${t.subcommandName}' references unknown Action '${t.actionKey}'. Known actions: ${Object.keys(He).join(", ")}.`),process.exit(1)),await s(n,e,a,r)}import{existsSync as it,readFileSync as Ka,statSync as ct}from"fs";import{resolve as Da}from"path";import{KanonakObjectParser as Ta,PublisherIndex as Ve,PublisherConfigResolver as Ea,formatVersion as lt,pickHighestDocument as ja}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as ut}from"@kanonak-protocol/sdk/uri-helpers";import{uriKey as J,findSubjectsByType as pt}from"@kanonak-protocol/sdk/uri-helpers";var ae=class{constructor(e,t,o,r,a,s){this.fileCache=e;this.parser=t;this.publisherIndex=o;this.fetchFn=r;this.handlerRegistry=a;this.repository=s}fileCache;parser;publisherIndex;fetchFn;handlerRegistry;repository;objectParser=new Ta;async add(e,t,o){let r=this.tryLoadFromLocalFile(t);if(r){this.fileCache.put(r.publisher,r.packageName,r.version,r.content),await this.deployFromDoc(e,r.doc,r.publisher,r.packageName,r.version,void 0,`local file ${t}`,o);return}let a=T(t);a||(console.error(`Invalid package reference: "${t}"`),console.error(""),console.error("Accepted forms:"),console.error(" publisher/package (install all instances, latest version)"),console.error(" publisher/package@version (install all instances, pinned)"),console.error(" publisher/package/instance (install one instance, latest version)"),console.error(" publisher/package@version/instance (install one instance, pinned)"),console.error(" ./path/to/file.kan.yml (install all instances from a local document)"),console.error(""),console.error("Tip: copy a URI directly from `kanonak "+e.commandName+" search`."),process.exit(1));let{publisher:s,packageName:i,version:c,instanceName:l}=a,u=await this.repository.getDocumentsByNamespaceAsync(s,i);if(u.length>0){let f=ja(u,{requestedVersion:c??void 0});if(f.chosen){let g=f.chosen.metadata.namespace_;(!g||!g.version)&&(console.error(`Document for ${s}/${i} is missing namespace metadata.`),process.exit(1));let m=lt(g.version);this.fileCache.put(s,i,m,this.parser.save(f.chosen)),await this.deployFromDoc(e,f.chosen,s,i,m,l??void 0,`${s}/${i}@${m}`,o);return}}let p=c??await this.publisherIndex.getHighestVersion(s,i);p||(console.error(`Could not resolve version for "${s}/${i}".`),await this.printPackageSuggestions(s,i,e.commandName),process.exit(1));let d=this.fileCache.get(s,i,p);if(!d){let f=await this.publisherIndex.getPackageUrl(s,i,p),g=await this.fetchFn(f,s);g.ok||(g.status===404?(console.error(`Package ${s}/${i}@${p} 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} (${g.status} ${g.statusText}).`),process.exit(1)),d=await g.text(),this.fileCache.put(s,i,p,d)}await this.deployFromDoc(e,this.parser.parse(d),s,i,p,l??void 0,`${s}/${i}@${p}`,o)}tryLoadFromLocalFile(e){if(!(/^[.\/\\]/.test(e)||/^[A-Za-z]:[\\/]/.test(e)||e.endsWith(".kan.yml")||it(e)&&ct(e).isFile()))return;let o=Da(e);(!it(o)||!ct(o).isFile())&&(console.error(`Local file not found: ${e}`),process.exit(1));let r=Ka(o,"utf-8"),a=this.parser.parse(r),s=a.metadata.namespace_;return(!s||!s.version)&&(console.error(`${e} has no namespace metadata; cannot determine publisher/package/version. A Kanonak document must declare \`type: Package\` with publisher and version.`),process.exit(1)),{doc:a,content:r,publisher:s.publisher,packageName:s.package_,version:lt(s.version)}}async deployFromDoc(e,t,o,r,a,s,i,c){let l=new ut(t,this.repository),u=await this.objectParser.parseKanonaks(l),p=dt(e.managesTypeKey);p||(console.error(`Capability "${e.commandName}" has no resolved managesType.`),process.exit(1));let d=pt(u,p);d.length===0&&(console.error(`${i} does not contain any ${J(p)} instances.`),process.exit(1));let f=d;if(s&&(f=d.filter(k=>k.name===s),f.length===0)){console.error(`Instance "${s}" not found in ${i}.`),console.error(""),console.error(`Available ${J(p)} instance(s):`);for(let k of d)console.error(` - ${k.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 g=s?`${s} from ${i}`:`${f.length} ${J(p)} instance(s) from ${i}`;console.log(`Installing ${g}...`);let m=this.handlerRegistry.get(e.deploymentTargetKey);m?await m.deploy({instances:f,allKanonaks:u,repository:this.repository,options:c}):console.log(`Cached ${o}/${r}@${a} (no deployment handler for "${e.deploymentTargetKey}")`)}async printPackageSuggestions(e,t,o){let r;try{r=await this.publisherIndex.listLatestPackages(e)}catch{return}let a=r.map(s=>({name:s.packageName,version:s.version,score:Aa(t,s.packageName)})).filter(s=>s.score>0).sort((s,i)=>i.score-s.score).slice(0,5);if(a.length!==0){console.error(""),console.error("Did you mean one of:");for(let s of a)console.error(` kanonak ${o} add ${e}/${s.name}`)}}async remove(e,t,o){await this.requireHandler(e).undeploy(t,{repository:this.repository,options:o})}async list(e,t){let r=await this.requireHandler(e).list({repository:this.repository,options:t}),a=e.managesTypeKey||"managed";if(r.length===0){console.log(`No ${a} instances installed.`);return}console.log(`Installed ${a} instances:
|
|
127
|
+
`);for(let s of r){let i=s.publisher?`${s.publisher}/${s.package_}@${s.version}`:"unmanaged";console.log(` ${s.name} (${i}) ${s.path}`)}}async update(e,t,o){let a=await this.requireHandler(e).list({repository:this.repository,options:o}),s=t?a.filter(c=>c.name===t):a.filter(c=>c.publisher);if(s.length===0){console.log(t?`"${t}" not found.`:"No managed instances to update.");return}let i=0;for(let c of s){let l=await this.publisherIndex.getHighestVersion(c.publisher,c.package_);!l||l===c.version||(console.log(`Updating ${c.name}: ${c.version} \u2192 ${l}`),await this.add(e,`${c.publisher}/${c.package_}@${l}`,o),i++)}console.log(i===0?"All instances are up to date.":`
|
|
128
|
+
Updated ${i} instance(s).`)}async search(e,t){let o=t.publisher??"kanonak.org",r=dt(e.managesTypeKey);if(!r){console.error("Capability has no resolved managesType; nothing to search for.");return}console.log(`Searching ${o} for ${J(r)} instances...
|
|
129
|
+
`);let a=new Ea,s=await a.getConfig(o),i=a.resolveIndexUrl(o,s),c=await this.fetchFn(i,o);if(!c.ok){console.error(`Failed to fetch package index from ${o}.`);return}let l=await c.text(),u=Ve.parseIndex(l);if(u.size===0){console.error(`No packages found for publisher "${o}".`);return}let p=new Map;for(let[m,k]of u){let h=[...k].sort((y,b)=>{let w=Ve.parseVersion(y),$=Ve.parseVersion(b);return!w||!$?0:w.major!==$.major?$.major-w.major:w.minor!==$.minor?$.minor-w.minor:$.patch-w.patch});p.set(m,h[0])}let d=[],f=0;for(let[m,k]of p){let h=this.fileCache.get(o,m,k);if(!h)try{let y=await this.publisherIndex.getPackageUrl(o,m,k),b=await this.fetchFn(y,o);if(!b.ok)continue;h=await b.text(),this.fileCache.put(o,m,k,h)}catch{continue}try{let y=this.parser.parse(h),b=new ut(y,this.repository),w=await this.objectParser.parseKanonaks(b),$=pt(w,r);for(let _ of $)d.push({publisher:o,package_:m,version:k,subject:_});f++}catch{continue}}if(d.length===0){console.log(`No ${J(r)} instances found across ${f} package(s).`);return}console.log(`Found ${d.length} ${J(r)} instance(s) in ${f} package(s):
|
|
130
|
+
`);let g=new Map;for(let m of d){let k=`${m.publisher}/${m.package_}@${m.version}`,h=g.get(k);h?h.push(m):g.set(k,[m])}for(let[m,k]of g){let h=k[0],y=`${h.publisher}/${h.package_}`,b=k.length===1;console.log(` ${m}`),console.log(` ${k.length} skill${b?"":"s"}:`);for(let w of k)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 k)console.log(` kanonak ${e.commandName} add ${y}/${w.subject.name}`);console.log(" install all of them:"),console.log(` kanonak ${e.commandName} add ${y}`)}console.log("")}}async info(e,t,o){let s=(await this.requireHandler(e).list({repository:this.repository,options:o})).find(i=>i.name===t);s||(console.error(`"${t}" is not installed.`),process.exit(1)),console.log(`Name: ${s.name}`),console.log(`Type: ${e.managesTypeKey||"n/a"}`),console.log(`Publisher: ${s.publisher||"unmanaged"}`),console.log(`Package: ${s.package_||"n/a"}`),console.log(`Version: ${s.version||"n/a"}`),console.log(`Path: ${s.path}`)}requireHandler(e){let t=this.handlerRegistry.get(e.deploymentTargetKey);return t||(console.error(`No deployment handler registered for "${e.deploymentTargetKey}". Ensure the capability's deploymentTarget resolves to a DeploymentTarget instance whose URI is registered in the CLI at startup.`),process.exit(1)),t}};function dt(n){if(!n)return;let e=n.split("/");if(e.length===3)return{publisher:e[0],package_:e[1],name:e[2]}}function Aa(n,e){let t=n.toLowerCase(),o=e.toLowerCase();if(t===o)return 100;if(o.includes(t)||t.includes(o))return 50;let r=new Set(t.split("-").filter(Boolean)),a=new Set(o.split("-").filter(Boolean)),s=0;for(let c of r)a.has(c)&&s++;if(s>0)return s*10;let i=Na(t,o);return i===0?100:i<=2?Math.max(1,20-i*5):0}function Na(n,e){if(n===e)return 0;if(n.length===0)return e.length;if(e.length===0)return n.length;let t=new Array(e.length+1),o=new Array(e.length+1);for(let r=0;r<=e.length;r++)t[r]=r;for(let r=0;r<n.length;r++){o[0]=r+1;for(let a=0;a<e.length;a++){let s=n[r]===e[a]?0:1;o[a+1]=Math.min(o[a]+1,t[a+1]+1,t[a]+s)}for(let a=0;a<=e.length;a++)t[a]=o[a]}return t[e.length]}var ie=class{handlers=new Map;register(e,t){this.handlers.set(e,t)}get(e){return this.handlers.get(e)??null}};import{mkdirSync as Ga,rmSync as Ja,existsSync as pe,readdirSync as Ya,writeFileSync as Xa}from"fs";import{join as de}from"path";import{KanonakObjectParser as Za,KanonakParser as Qa,computeIntegrity as ei,compareVersions as ni}from"@kanonak-protocol/sdk";import{findSubjectsByType as ti}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as oi}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as ri}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as si}from"@kanonak-protocol/sdk/transformations";import{join as ze}from"path";import{homedir as mt}from"os";import{KanonakObjectParser as Oa}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as La}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as gt,getStringValue as ce}from"@kanonak-protocol/sdk/uri-helpers";var U="kanonak.org",F="agent-skills",ht={publisher:U,package_:F,name:"Client"},kt={publisher:U,package_:F,name:"clientId"},Ua={publisher:U,package_:F,name:"projectSkillDir"},Fa={publisher:U,package_:F,name:"userSkillDir"},Ma={publisher:U,package_:F,name:"skillFileName"},yt="agents";async function ee(n,e){let t=(n.client??bt()??yt).toLowerCase(),o=n.scope??"project",r=await $t(t,e);if(!r){let i=await Ha(e);throw new Error(`Unknown client "${t}". Known clients: ${i.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=ce(r,o==="user"?Fa:Ua);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userSkillDir":"projectSkillDir"} declared.`);return Va(s)}async function le(n,e,t){let o=await ee(e,t);return ze(o,n)}async function Be(n,e){let t=(n.client??bt()??yt).toLowerCase(),o=await $t(t,e);return o?ce(o,Ma)??"SKILL.md":"SKILL.md"}function bt(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}var ft=new WeakMap;async function wt(n){let e=ft.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(U,F);if(t.length===0)throw new Error(`Could not find ${U}/${F} 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],a=new Oa,s=new La(r,n),i=await a.parseKanonaks(s);return ft.set(n,i),i}async function $t(n,e){let t=await wt(e),o=gt(t,ht);for(let r of o)if(ce(r,kt)===n)return r}async function Ha(n){let e=await wt(n),t=gt(e,ht),o=[];for(let r of t){let a=ce(r,kt);a&&o.push(a)}return o}function Va(n){return n.startsWith("~/")?ze(mt(),n.slice(2)):n==="~"?mt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:ze(process.cwd(),n)}import{readFileSync as za,writeFileSync as Ba,existsSync as qa}from"fs";import{join as vt}from"path";import St from"js-yaml";var Pt="skills.lock",Wa=`# This file is generated by Kanonak CLI. Do not edit manually.
|
|
131
|
+
`;function ue(n){let e=vt(n,Pt);if(!qa(e))return{version:"1",lastUpdated:new Date().toISOString(),skills:{}};let t=za(e,"utf-8"),o=St.load(t);return!o||typeof o!="object"||o.version!=="1"?{version:"1",lastUpdated:new Date().toISOString(),skills:{}}:{version:"1",lastUpdated:o.lastUpdated??new Date().toISOString(),skills:o.skills??{}}}function qe(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.skills).sort())t[a]=e.skills[a];e.skills=t;let o=vt(n,Pt),r=St.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});Ba(o,Wa+r,"utf-8")}var Ct="kanonak.org",_t="skill-to-skill-md",me=class{parser=new Qa;objectParser=new Za;runner=new ri;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:a}=e;if(t.length===0){console.error("No Skill instances to deploy.");return}let s=await ai(r,this.objectParser);if(!s){console.error(`Cannot deploy: ${Ct}/${_t}@3.0.0 is not installed in the workspace or cache.`);return}let i=await this.runner.run({transformation:s,instances:t,allKanonaks:o,repository:r,parser:this.parser,objectParser:this.objectParser,outputFormat:"markdown-with-frontmatter"});if(i.length===0){console.error("No skills could be transformed from the package.");return}let c=await ee(a,r),l=await Be(a,r),u=ue(c),p=t[0].namespace,{publisher:d,package_:f,version:g}=ii(p);for(let m of i){let k=await le(m.fileName,a,r),h=pe(de(k,l));Ga(k,{recursive:!0}),Xa(de(k,l),m.content,"utf-8"),u.skills[m.fileName]={publisher:d,package_:f,version:g,resolved:d?`kanonak://${d}/${f}@${g}`:"",integrity:ei(m.content)},console.log(` ${h?"Updated":"Installed"} skill "${m.fileName}" \u2192 ${k}`)}qe(c,u)}async undeploy(e,t){let{repository:o,options:r}=t,a=await le(e,r,o);pe(a)||(console.error(`Skill "${e}" is not installed at ${a}`),process.exit(1)),Ja(a,{recursive:!0,force:!0});let s=await ee(r,o),i=ue(s);delete i.skills[e],qe(s,i),console.log(`Removed skill "${e}" from ${a}`)}async list(e){let{repository:t,options:o}=e,r=await ee(o,t),a=ue(r),s=[];for(let[c,l]of Object.entries(a.skills))s.push({name:c,publisher:l.publisher,package_:l.package_,version:l.version,path:await le(c,o,t)});let i=await Be(o,t);if(pe(r))try{let c=Ya(r,{withFileTypes:!0});for(let l of c){if(!l.isDirectory()||a.skills[l.name])continue;let u=de(r,l.name,i);pe(u)&&s.push({name:l.name,publisher:"",package_:"",version:"",path:de(r,l.name)})}}catch{}return s}};async function ai(n,e){let t=await n.getDocumentsByNamespaceAsync(Ct,_t);if(t.length===0)return;let o=[...t].sort((r,a)=>{let s=r.metadata.namespace_?.version,i=a.metadata.namespace_?.version;return!s||!i?0:ni(i,s)});for(let r of o){let a=new oi(r,n),s=await e.parseKanonaks(a),i=ti(s,si.InstanceTransformation);if(i[0])return i[0]}}function ii(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 Si,rmSync as Pi,existsSync as Je,readdirSync as Ci,writeFileSync as _i,statSync as Ri}from"fs";import{join as he}from"path";import{KanonakObjectParser as xi,KanonakParser as Ii,computeIntegrity as Ki}from"@kanonak-protocol/sdk";import{findSubjectsByType as Di}from"@kanonak-protocol/sdk/uri-helpers";import{SingleDocumentRepository as Ti}from"@kanonak-protocol/sdk/uri-helpers";import{TransformationRunnerV3 as Ei}from"@kanonak-protocol/sdk/transformations";import{TX_V3 as ji}from"@kanonak-protocol/sdk/transformations";import{join as Rt}from"path";import{homedir as xt}from"os";import{KanonakObjectParser as ci}from"@kanonak-protocol/sdk";import{SingleDocumentRepository as li}from"@kanonak-protocol/sdk/uri-helpers";import{findSubjectsByType as Kt,getStringValue as We,getReferenceUri as ui}from"@kanonak-protocol/sdk/uri-helpers";var M="kanonak.org",H="agent-skills",Dt={publisher:M,package_:H,name:"Client"},Tt={publisher:M,package_:H,name:"clientId"},pi={publisher:M,package_:H,name:"projectAgentDir"},di={publisher:M,package_:H,name:"userAgentDir"},mi={publisher:M,package_:H,name:"agentFileFormat"},fi="agents";function gi(){if(process.env.CLAUDE_CODE||process.env.CLAUDE_PROJECT_DIR)return"claude-code"}async function fe(n,e){let t=(n.client??gi()??fi).toLowerCase(),o=n.scope??"project",r=await hi(t,e);if(!r){let u=await ki(e);throw new Error(`Unknown client "${t}". Known clients: ${u.join(", ")||"(none)"}. Add a Client instance to a package that imports kanonak.org/agent-skills and install that package to make it available.`)}let s=We(r,o==="user"?di:pi);if(!s)throw new Error(`Client "${t}" has no ${o==="user"?"userAgentDir":"projectAgentDir"} declared.`);let c=ui(r,mi)?.name==="toml"?"toml":"markdown-frontmatter",l=c==="toml"?".toml":".md";return{agentsDir:yi(s),format:c,fileExtension:l}}var It=new WeakMap;async function Et(n){let e=It.get(n);if(e)return e;let t=await n.getDocumentsByNamespaceAsync(M,H);if(t.length===0)throw new Error(`Could not find ${M}/${H} 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],a=new ci,s=new li(r,n),i=await a.parseKanonaks(s);return It.set(n,i),i}async function hi(n,e){let t=await Et(e),o=Kt(t,Dt);for(let r of o)if(We(r,Tt)===n)return r}async function ki(n){let e=await Et(n),t=Kt(e,Dt),o=[];for(let r of t){let a=We(r,Tt);a&&o.push(a)}return o}function yi(n){return n.startsWith("~/")?Rt(xt(),n.slice(2)):n==="~"?xt():n.startsWith("/")||/^[A-Za-z]:[\\/]/.test(n)?n:Rt(process.cwd(),n)}import{readFileSync as bi,writeFileSync as wi,existsSync as $i}from"fs";import{join as jt}from"path";import At from"js-yaml";var Nt="agents.lock",vi=`# This file is generated by Kanonak CLI. Do not edit manually.
|
|
132
|
+
`;function ge(n){let e=jt(n,Nt);if(!$i(e))return{version:"1",lastUpdated:new Date().toISOString(),agents:{}};let t=bi(e,"utf-8"),o=At.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 Ge(n,e){e.lastUpdated=new Date().toISOString();let t={};for(let a of Object.keys(e.agents).sort())t[a]=e.agents[a];e.agents=t;let o=jt(n,Nt),r=At.dump(e,{lineWidth:-1,sortKeys:!1,quotingType:'"'});wi(o,vi+r,"utf-8")}var Ot="kanonak.org",Lt="agent-to-agent-file",ke=class{parser=new Ii;objectParser=new xi;runner=new Ei;async deploy(e){let{instances:t,allKanonaks:o,repository:r,options:a}=e;if(t.length===0){console.error("No Agent instances to deploy.");return}let{agentsDir:s,format:i,fileExtension:c}=await fe(a,r),l=await Ai(r,this.objectParser);if(!l){console.error(`Cannot deploy: ${Ot}/${Lt}@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}Si(s,{recursive:!0});let d=ge(s),f=t[0].namespace,{publisher:g,package_:m,version:k}=Oi(f);for(let h of p){let y=`${h.fileName}${c}`,b=he(s,y),w=Je(b);_i(b,h.content,"utf-8"),d.agents[h.fileName]={publisher:g,package_:m,version:k,resolved:g?`kanonak://${g}/${m}@${k}`:"",integrity:Ki(h.content),fileName:y},console.log(` ${w?"Updated":"Installed"} agent "${h.fileName}" \u2192 ${b}`)}Ge(s,d)}async undeploy(e,t){let{repository:o,options:r}=t,{agentsDir:a}=await fe(r,o),s=ge(a),i=s.agents[e];i||(console.error(`Agent "${e}" is not installed at ${a}`),process.exit(1));let c=he(a,i.fileName);Je(c)&&Pi(c,{force:!0}),delete s.agents[e],Ge(a,s),console.log(`Removed agent "${e}" from ${c}`)}async list(e){let{repository:t,options:o}=e,{agentsDir:r}=await fe(o,t),a=ge(r),s=[];for(let[i,c]of Object.entries(a.agents))s.push({name:i,publisher:c.publisher,package_:c.package_,version:c.version,path:he(r,c.fileName)});if(Je(r))try{let i=Ci(r,{withFileTypes:!0});for(let c of i){if(!c.isFile()||c.name==="agents.lock")continue;let l=he(r,c.name),u=Ni(c.name);if(!a.agents[u]){try{if(!Ri(l).isFile())continue}catch{continue}s.push({name:u,publisher:"",package_:"",version:"",path:l})}}}catch{}return s}};async function Ai(n,e){let t=await n.getDocumentsByNamespaceAsync(Ot,Lt);if(t.length===0)return;let o=new Ti(t[0],n),r=await e.parseKanonaks(o);return Di(r,ji.InstanceTransformation)[0]}function Ni(n){let e=n.lastIndexOf(".");return e===-1?n:n.substring(0,e)}function Oi(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 Wi=Mi(Fi(import.meta.url)),Gi=JSON.parse(Ui(Hi(Wi,"..","package.json"),"utf-8")),x=new Li;x.name("kanonak").description("Kanonak Protocol CLI - Validate and resolve Kanonak ontology packages").version(Gi.version);x.command("validate <path>").description("Validate .kan.yml file(s). Resolves imports via HTTP from publisher domains.").action(async n=>{await on(n)});x.command("install [package]").description("Install a package and its dependencies, or install all from kanonak.lock.").action(async n=>{await rn(n)});x.command("deps <path>").description("Show resolved dependency tree for a .kan.yml file.").action(async n=>{await an(n)});x.command("login <publisher>").description("Authenticate with a package publisher using OAuth 2.0.").action(async n=>{await dn(n)});x.command("logout <publisher>").description("Revoke tokens and remove stored credentials for a publisher.").action(async n=>{await mn(n)});x.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 rt(n,e)});x.addCommand(xn());x.addCommand(An());x.addCommand(Mn());x.addCommand(Vn());x.addCommand(Xn());x.addCommand(Zn());x.addCommand(ot());async function Ji(){try{let n=new D,e=new Vi,t=new Bi,o=qi(t),r=new zi({fetchFn:o}),a=await v(process.cwd(),e),s=new ie;s.register("kanonak.org/capabilities/agent-skill-deployment",new me),s.register("kanonak.org/agent-capabilities/agent-instance-deployment",new ke);let i=await Cn(n,e,a),c=new ae(n,e,r,o,s,a);at(x,i,c)}catch{}}await Ji();x.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanonak-protocol/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.57.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.
|
|
38
|
-
"@kanonak-protocol/types": "^3.
|
|
37
|
+
"@kanonak-protocol/sdk": "^3.57.0",
|
|
38
|
+
"@kanonak-protocol/types": "^3.57.0",
|
|
39
39
|
"commander": "^13.0.0",
|
|
40
40
|
"js-yaml": "^4.1.1"
|
|
41
41
|
},
|