skillcraft 0.1.9 → 0.1.10
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 +56 -56
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
3
|
-
`)}async function j(e){try{await se.rm(e,{force:!0})}catch{}}async function Ae(e){try{await se.rm(e,{force:!0,recursive:!0})}catch{}}async function
|
|
2
|
+
import{Command as ns}from"commander";var jt={name:"skillcraft",version:"0.1.10",description:"Turn your work into verifiable AI credentials. Capture what you build, share your progress, and earn verifiable credentials that prove your AI coding skills.",keywords:["skillcraft","cli","ai","evidence","credentials","skills","loadout","git","verification","developer-tools"],repository:{type:"git",url:"git+https://github.com/skillcraft-gg/skillcraft.git"},homepage:"https://skillcraft.gg",bugs:{url:"https://github.com/skillcraft-gg/skillcraft/issues"},type:"module",bin:{skillcraft:"dist/index.js"},files:["dist/index.js","dist/index.js.map","README.md","LICENSE"],scripts:{build:"tsup",clean:"rm -rf dist",test:"npm run build && node --test tests/*.test.mjs",smoke:"npm test",format:"printf ''",start:"node dist/index.js",check:"tsc --noEmit",prepare:"sh ./scripts/install-git-hooks.sh",commitlint:"commitlint --from HEAD~1 --to HEAD",prepublishOnly:"npm run build"},publishConfig:{access:"public"},dependencies:{commander:"^13.1.0",ora:"^8.2.0",yaml:"^2.6.0",zod:"^3.24.2"},devDependencies:{"@commitlint/cli":"^20.5.0","@commitlint/config-conventional":"^20.5.0","@types/node":"^24.8.0",tsup:"^8.5.0",typescript:"^5.7.2"}};import ss from"fs/promises";import x from"path";import jn from"os";function Ln(){return x.resolve(process.env.HOME||jn.homedir(),".skillcraft")}function T(){return Ln()}function Be(){return x.join(T(),"config.json")}function Je(){return x.join(T(),"repos.json")}function Ge(){return x.join(T(),"credentials.json")}function Lt(){return x.join(T(),"cache","credentials","index.json")}function _n(e){return x.join(e,".skillcraft")}function q(e){return x.join(e,".git","skillcraft")}function G(e){return x.join(_n(e),".skillcraft.json")}function N(e){return x.join(q(e),"pending.json")}function I(e){return x.join(q(e),"context.json")}function ge(e){return x.join(q(e),"agent.json")}function Se(e){return x.join(e,".opencode","plugins","skillcraft.mjs")}function We(e){return x.join(e,".codex","config.toml")}function Ve(e){return x.join(e,".codex","hooks.json")}function Ze(e){return x.join(e,".agents","plugins","marketplace.json")}function Ce(e){return x.join(e,"plugins","skillcraft-codex")}function _t(e){return x.join(Ce(e),".codex-plugin","plugin.json")}function Nt(e){return x.join(Ce(e),"skills","skillcraft","SKILL.md")}function Re(e){return x.join(e,".agents","skills")}function Xe(e){return x.join(Re(e),".skillcraft-index.json")}function D(e){return x.join(q(e),"ai-model-context.json")}import{z as m}from"zod";var us=m.literal(1),Q="skillcraft/proofs/v1",Tt=m.object({skills:m.array(m.string()).default([])}),qt=m.object({activeLoadouts:m.array(m.string()).default([])}),ms=m.object({provider:m.string().optional()}),ps=m.object({provider:m.string().optional(),name:m.string().optional()}),Nn=m.enum(["opencode","codex"]),Ot=m.object({version:m.number().int().default(1),providers:m.array(Nn).default([]),enabled:m.boolean().default(!0)}),Tn=m.object({type:m.enum(["github-directory","local-directory"]),repo:m.string().optional(),ref:m.string().optional(),path:m.string()}),qn=m.object({id:m.string(),name:m.string(),path:m.string(),install:Tn,installedAt:m.string()}),Ft=m.object({version:m.number().int().default(1),skills:m.array(qn).default([])}),ee=m.object({githubUser:m.string().optional(),provider:m.enum(["gh"]).default("gh"),version:m.number().int().default(1),proofRef:m.string().default(Q)}),On=m.object({path:m.string(),remote:m.string().optional(),enabledAt:m.string().optional()}),Mt=m.object({repos:m.array(On).default([])}),Fn=m.object({id:m.string(),trackedAt:m.string().optional()}),zt=m.object({credentials:m.array(Fn).default([])});import se from"fs/promises";import Mn from"path";async function v(e){await se.mkdir(e,{recursive:!0})}async function te(e){return await se.readFile(e,"utf8")}async function U(e,t){await v(Mn.dirname(e)),await se.writeFile(e,t,"utf8")}async function S(e){try{return await se.access(e),!0}catch{return!1}}async function w(e){if(!await S(e))return null;let t=await te(e);return JSON.parse(t)}async function h(e,t){let r=JSON.stringify(t,null,2);await U(e,`${r}
|
|
3
|
+
`)}async function j(e){try{await se.rm(e,{force:!0})}catch{}}async function Ae(e){try{await se.rm(e,{force:!0,recursive:!0})}catch{}}async function O(){let e=await w(Be()),t=ee.safeParse(e??{});return t.success?t.data:ee.parse({})}async function Ie(e){let t=await w(G(e)),r=ee.safeParse(t??{});return r.success?r.data:ee.parse({})}async function Ht(e){await v(T()),await h(Be(),e)}async function K(){let e=await w(Je()),t=Mt.safeParse(e??{});return t.success?t.data:{repos:[]}}async function $e(e){await v(T()),await h(Je(),e)}async function Dt(e){let r=(await K()).repos.filter(n=>n.path!==e.path);r.push(e),await $e({repos:r})}async function Ut(e){let r=(await K()).repos.filter(n=>n.path!==e);await $e({repos:r})}async function Ee(){let e=await w(Ge()),t=zt.safeParse(e??{});return t.success?t.data:{credentials:[]}}async function Kt(e){await v(T()),await h(Ge(),e)}async function Bt(e){let t=await Ee();return t.credentials.some(r=>r.id===e)?!1:(t.credentials.push({id:e,trackedAt:new Date().toISOString()}),t.credentials.sort(zn),await Kt(t),!0)}async function Jt(e){let t=await Ee(),r=t.credentials.length,n=t.credentials.filter(o=>o.id!==e);return n.length===r?!1:(await Kt({credentials:n}),!0)}function zn(e,t){return e.id.localeCompare(t.id)}import{execSync as eo}from"child_process";import to from"path";import Wn from"fs/promises";import Xt from"path";import Jn from"path";var Hn=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*(?:@[^\s/]+)?$/,Dn=/^[a-zA-Z0-9][a-zA-Z0-9._-]*\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/,Un=/^([a-zA-Z0-9][a-zA-Z0-9._-]*):([a-zA-Z0-9][a-zA-Z0-9._-]*)(?:\/([a-zA-Z0-9][a-zA-Z0-9._-]*))?$/;function ae(e){let t=W(e);if(t.id)return`${t.id}${t.version?`@${t.version}`:""}`}function Ye(e){return Hn.test(e)}function Qe(e){return!!W(e).id}function W(e){let t=e.trim(),r=Bn(t),n=r.id||"";if(Kn(n)){let[a,d]=n.split("/");return{id:n,owner:a,slug:d,version:r.version}}let o=Un.exec(n);if(!o)return{id:"",slug:"",version:r.version};let i=o[1],s=o[2],c=o[3];return c===void 0?{id:`${i}:${s}`,source:i,slug:s,version:r.version}:{id:`${i}:${s}/${c}`,source:i,owner:s,slug:c,version:r.version}}function Kn(e){return Dn.test(e)}function F(e,t){let r=e.trim();if(!r)throw new Error(`Expected ${t} to be provided`);return r}function Bn(e){let t=e.split("@"),r=t[0]||"",n=t.length>1?t.slice(1).join("@"):void 0;return{id:r,version:n}}function je(e){let[t,r]=e.split("/");if(!t||!r)throw new Error(`Expected <owner>/<slug>, received ${e}`);return{owner:t,slug:r.trim()}}async function he(e){let t=await w(Xe(e)),r=Ft.safeParse(t??{version:1,skills:[]});return r.success?r.data.skills:[]}async function Gn(e,t){let r=[...t].sort((n,o)=>n.id.localeCompare(o.id));await h(Xe(e),{version:1,skills:r})}async function Gt(e,t){let n=(await he(e)).filter(o=>o.id!==t.id&&o.name!==t.name);n.push(t),await Gn(e,n)}async function Le(e,t){let r=ae(t);if(!r)throw new Error(`invalid skill id format: ${t}`);let n=await w(N(e)),o=n&&typeof n=="object"&&!Array.isArray(n)&&Array.isArray(n.skills)?n.skills:[],i=Array.from(new Set(o.map(s=>typeof s=="string"?ae(s):void 0).filter(s=>!!s).concat(r))).sort();await h(N(e),{skills:i})}function Wt(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")||"skillcraft-skill"}function Vt(e){return{id:e.id,name:e.name,path:Jn.posix.join(".agents","skills",e.name),install:e.install,installedAt:e.installedAt}}async function Yt(e,t){let r=await he(e);if(!r.length)return;let n=Vn(t);if(!n.hook_event_name)return;let o=new Set;if(n.hook_event_name==="Stop")for(let i of await Zn(e,r,n.transcript_path,n.turn_id))o.add(i);for(let i of o)await Le(e,i)}function Vn(e){if(!e||typeof e!="object"||Array.isArray(e))return{};let t=e,r=t.tool_input;return{hook_event_name:B(t.hook_event_name),turn_id:B(t.turn_id),cwd:B(t.cwd),transcript_path:B(t.transcript_path),tool_input:r&&typeof r=="object"&&!Array.isArray(r)?{command:B(r.command)}:void 0}}async function Zn(e,t,r,n){if(!r||!n)return[];let o=await Wn.readFile(r,"utf8").catch(()=>"");if(!o.trim())return[];let i=new Map,s=new Map;for(let d of t)s.set(d.name,d.id),i.set(Zt(Xt.join(e,d.path,"SKILL.md")),d.id);let c=new Set,a;for(let d of o.split(/\r?\n/)){if(!d.trim())continue;let l;try{l=JSON.parse(d)}catch{continue}if(!l||typeof l!="object"||Array.isArray(l))continue;let u=l;if(u.type==="turn_context"){a=Xn(u.payload);continue}if(!(u.type!=="response_item"||a!==n))for(let p of Yn(u.payload)){let f=(p.path?i.get(Zt(p.path)):void 0)||(p.name?s.get(p.name):void 0);f&&c.add(f)}}return Array.from(c).sort()}function Xn(e){if(!(!e||typeof e!="object"||Array.isArray(e)))return B(e.turn_id)}function Yn(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let t=e;if(t.type!=="message"||B(t.role)!=="user"||!Array.isArray(t.content))return[];let r=[];for(let n of t.content){if(!n||typeof n!="object"||Array.isArray(n))continue;let o=B(n.text);if(!o)continue;let i=o.matchAll(/<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>[\s\S]*?<\/skill>/g);for(let s of i)r.push({name:Qn(s[1]||""),path:B(s[2])})}return r}function Qn(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function Zt(e){return Xt.resolve(e)}function B(e){return(typeof e=="string"?e.trim():"")||void 0}var it=["codex","opencode"],rt="# skillcraft:begin codex",nt="# skillcraft:end codex",Qt="skillcraft _agent-hook codex",zs=[...it];function we(e){let t=e.trim().toLowerCase();return it.find(r=>r===t)}function ye(e){let t=e.flatMap(r=>r.split(",")).map(r=>we(r)).filter(r=>!!r);return Array.from(new Set(t)).sort()}function Ne(e){return e.flatMap(t=>t.split(",")).map(t=>t.trim()).filter(Boolean).filter(t=>!we(t))}async function ce(e){let t=await w(ge(e)),r=Ot.safeParse(t??{});if(r.success)return r.data.providers;if(!t||typeof t!="object"||Array.isArray(t))return[];let n=t;return Array.isArray(n.providers)?n.providers.map(o=>typeof o=="string"?we(o):void 0).filter(o=>!!o):[]}async function Te(e,t){let r=Array.from(new Set(t)).sort();await h(ge(e),{version:1,providers:r,enabled:r.length>0})}async function qe(){return it.filter(e=>ro(e))}async function er(e,t){if(t==="opencode"){await v(to.dirname(Se(e))),await U(Se(e),fo());return}await no(e)}async function tr(e,t){if(t==="opencode"){await j(Se(e));return}await oo(e)}async function rr(e,t){let r=await w(D(e));if(r&&typeof r=="object"&&!Array.isArray(r)){let n=r,o=n.agent&&typeof n.agent=="object"&&!Array.isArray(n.agent)?n.agent.provider:void 0;if(typeof o=="string"&&o.trim())return;await ot(e,{agent:{provider:t}});return}await h(D(e),{agent:{provider:t},model:{}})}async function ot(e,t){let r=await w(D(e)),n=r&&typeof r=="object"&&!Array.isArray(r)?r:{},o=n.agent&&typeof n.agent=="object"&&!Array.isArray(n.agent)?n.agent:{},i=n.model&&typeof n.model=="object"&&!Array.isArray(n.model)?n.model:{},s={...n,agent:{...o,...t.agent?.provider?{provider:t.agent.provider.trim().toLowerCase()}:{}},model:{...i,...t.model?.provider?{provider:t.model.provider.trim().toLowerCase()}:{},...t.model?.name?{name:t.model.name.trim()}:{}}};await h(D(e),s)}async function nr(e,t){if(!t||typeof t!="object"||Array.isArray(t)){await ot(e,{agent:{provider:"codex"}});return}let r=t,n=typeof r.model=="string"?r.model.trim():"",o=typeof r.model_provider=="string"?r.model_provider.trim().toLowerCase():typeof r.modelProvider=="string"?r.modelProvider.trim().toLowerCase():"";await ot(e,{agent:{provider:"codex"},model:{...o?{provider:o}:{},...n?{name:n}:{}}}),await Yt(e,t)}function ro(e){try{return eo(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}async function no(e){await Promise.all([uo(e),co(e),so(e),io(e)])}async function oo(e){await Promise.all([mo(e),lo(e),ao(e),Ae(Ce(e))])}async function io(e){await h(_t(e),{name:"skillcraft-codex",version:"0.1.0",description:"Repo-local Skillcraft workflow support for Codex CLI.",skills:"./skills/",interface:{displayName:"Skillcraft",shortDescription:"Skillcraft-aware repository guidance for Codex.",longDescription:"Adds Skillcraft repository guidance and pairs with repo-local hooks to record model provenance.",developerName:"Skillcraft",category:"Developer Tools",capabilities:["Read","Write"],defaultPrompt:["Use Skillcraft guidance while working in this repository."],brandColor:"#0f766e"}}),await U(Nt(e),`---
|
|
4
4
|
name: skillcraft
|
|
5
5
|
description: Use when working in a Skillcraft-enabled repository so Codex preserves normal git history and evidence-friendly commit workflows.
|
|
6
6
|
---
|
|
@@ -11,7 +11,7 @@ When Skillcraft is enabled in this repository:
|
|
|
11
11
|
- Prefer regular commits over rebases, squashes, or amends once Skillcraft evidence has been recorded.
|
|
12
12
|
- Keep work in this repository so repo-local Skillcraft hooks can capture model provenance.
|
|
13
13
|
- Let Skillcraft post-commit hooks attach proof references after meaningful commits.
|
|
14
|
-
`)}async function
|
|
14
|
+
`)}async function so(e){let t=Ze(e),r=await w(t);if(r&&(typeof r!="object"||Array.isArray(r)))throw new Error(`Invalid marketplace file: ${t}`);let n=r??{},o=Array.isArray(n.plugins)?[...n.plugins]:[],i={name:"skillcraft-codex",source:{source:"local",path:"./plugins/skillcraft-codex"},policy:{installation:"AVAILABLE",authentication:"ON_INSTALL"},category:"Developer Tools",interface:{displayName:"Skillcraft"}},s=o.filter(c=>c&&typeof c=="object"&&c.name!==i.name);s.push(i),await h(t,{name:n.name||"skillcraft-local",interface:n.interface||{displayName:"Skillcraft Local Plugins"},plugins:s})}async function ao(e){let t=Ze(e),r=await w(t);if(!r)return;if(typeof r!="object"||Array.isArray(r))throw new Error(`Invalid marketplace file: ${t}`);let n=r,o=Array.isArray(n.plugins)?n.plugins.filter(i=>!(i&&typeof i=="object"&&i.name==="skillcraft-codex")):[];if(!o.length){await j(t);return}await h(t,{...n,plugins:o})}async function co(e){let t=Ve(e),r=await w(t);if(r&&(typeof r!="object"||Array.isArray(r)))throw new Error(`Invalid hooks file: ${t}`);let n=r??{},o=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?{...n.hooks}:{};o.SessionStart=tt(o.SessionStart,{matcher:"startup|resume",hooks:[et("Updating Skillcraft session context")]}),o.UserPromptSubmit=tt(o.UserPromptSubmit,{hooks:[et("Updating Skillcraft prompt context")]}),o.Stop=tt(o.Stop,{hooks:[et("Recording Skillcraft turn evidence")]}),await h(t,{hooks:o})}async function lo(e){let t=Ve(e),r=await w(t);if(!r)return;if(typeof r!="object"||Array.isArray(r))throw new Error(`Invalid hooks file: ${t}`);let n=r,o=n.hooks&&typeof n.hooks=="object"&&!Array.isArray(n.hooks)?{...n.hooks}:{};for(let i of Object.keys(o)){let c=(Array.isArray(o[i])?o[i]:[]).map(a=>{let d=Array.isArray(a.hooks)?a.hooks.filter(l=>l.command!==Qt):[];return d.length?{...a,hooks:d}:void 0}).filter(a=>!!a);c.length?o[i]=c:delete o[i]}if(!Object.keys(o).length){await j(t);return}await h(t,{hooks:o})}async function uo(e){let t=We(e),r=await te(t).catch(()=>""),n=po(r);n!==r&&await U(t,n)}async function mo(e){let t=We(e);if(!await S(t))return;let r=await te(t),n=or(r);if(!n.trim()){await j(t);return}n!==r&&await U(t,n)}function et(e){return{type:"command",command:Qt,statusMessage:e,timeout:30}}function tt(e,t){let r=Array.isArray(e)?[...e]:[],n=r.findIndex(s=>(s.matcher||"")===(t.matcher||""));if(n===-1)return r.push(t),r;let o=r[n],i=Array.isArray(o.hooks)?[...o.hooks]:[];for(let s of t.hooks)i.some(c=>c.command===s.command)||i.push(s);return r[n]={...o,matcher:t.matcher??o.matcher,hooks:i},r}function po(e){let t=or(e);if(/^\s*features\.codex_hooks\s*=\s*false\s*$/m.test(t))return t.replace(/^\s*features\.codex_hooks\s*=\s*false\s*$/m,"features.codex_hooks = true");if(/^\s*features\.codex_hooks\s*=\s*true\s*$/m.test(t))return t;let r=t.split(/\r?\n/),n=!1;for(let c=0;c<r.length;c+=1){let a=r[c];if(/^\s*\[.*\]\s*$/.test(a)){n=a.trim()==="[features]";continue}if(n&&/^\s*codex_hooks\s*=\s*false\s*$/.test(a))return r[c]="codex_hooks = true",_e(r.join(`
|
|
15
15
|
`));if(n&&/^\s*codex_hooks\s*=\s*true\s*$/.test(a))return _e(r.join(`
|
|
16
16
|
`))}let o=r.findIndex(c=>c.trim()==="[features]"),i=[rt,"codex_hooks = true",nt];return o!==-1?(r.splice(o+1,0,...i),_e(r.join(`
|
|
17
17
|
`))):`${t.trim()?`${t.trimEnd()}
|
|
@@ -24,7 +24,7 @@ ${nt}
|
|
|
24
24
|
`).replace(/\n{3,}/g,`
|
|
25
25
|
|
|
26
26
|
`).trimEnd())}function _e(e){return e?`${e.replace(/\n+$/g,"")}
|
|
27
|
-
`:""}function
|
|
27
|
+
`:""}function fo(){return`import fs from 'node:fs/promises'
|
|
28
28
|
import path from 'node:path'
|
|
29
29
|
import { execFile } from 'node:child_process'
|
|
30
30
|
import { promisify } from 'node:util'
|
|
@@ -263,11 +263,11 @@ export default async function Skillcraft(context) {
|
|
|
263
263
|
},
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
-
`}import{execFile as
|
|
267
|
-
`).filter(Boolean):[]}catch{return[]}}async function
|
|
266
|
+
`}import{execFile as go,spawn as ho}from"child_process";import{promisify as wo}from"util";import ir from"path";var sr=wo(go);function ar(e,t){return t.disableHooks?["-c","core.hooksPath=/dev/null",...e]:[...e]}async function y(e,t,r={}){try{let{stdout:n}=await sr("git",ar(e,r),{cwd:t,encoding:"utf8",maxBuffer:10485760,env:r.env});return n.trim()}catch(n){let o=n.message??String(n);throw new Error(`git command failed in ${t}: ${o}`)}}async function yo(e,t,r,n={}){return await new Promise((o,i)=>{let s=ho("git",ar(e,n),{cwd:t,env:n.env,stdio:["pipe","pipe","pipe"]}),c="",a="";s.stdout.setEncoding("utf8"),s.stdout.on("data",d=>{c+=d}),s.stderr.setEncoding("utf8"),s.stderr.on("data",d=>{a+=d}),s.on("error",d=>{i(new Error(`git command failed in ${t}: ${d.message}`))}),s.on("close",d=>{if(d===0){o(c.trim());return}let l=a.trim()||c.trim()||`process exited with code ${d??"unknown"}`;i(new Error(`git command failed in ${t}: ${l}`))}),s.stdin.end(r)})}async function M(e){try{return await y(["rev-parse","--git-dir"],e),!0}catch{return!1}}async function z(e){return ir.resolve(await y(["rev-parse","--show-toplevel"],e))}async function V(e,t="origin"){try{return await y(["config","--get",`remote.${t}.url`],e)||void 0}catch{return}}async function cr(e){return y(["rev-parse","--git-path","hooks"],e)}async function lr(e,t="HEAD"){return y(["log","--format=%B","-n","1",t],e)}async function le(e){return(await y(["rev-parse","HEAD"],e)).trim()}async function J(e,t){try{return await y(["show-ref","--verify","--quiet",t],e),!0}catch{return!1}}async function Oe(e,t,r){let n=`refs/heads/${t}`;if(await J(e,n))return;let o=await yo(["hash-object","-t","tree","--stdin"],e,""),i=await y(["commit-tree",o,"-m",r],e);await y(["update-ref",n,i],e)}async function dr(e,t,r="HEAD"){try{return await y(["merge-base","--is-ancestor",t,r],e),!0}catch{return!1}}async function ur(e,t,r){try{let n=await y(["ls-tree","-r","--name-only",t,"--",...r?[r]:[]],e);return n?n.split(`
|
|
267
|
+
`).filter(Boolean):[]}catch{return[]}}async function mr(e,t,r){try{return await y(["show",`${t}:${r}`],e)}catch{return}}async function Fe(e,t){let r=t?String(t):"200",n=await y(["log",`--max-count=${r}`,"--pretty=%H%x00%B"],e);return n?n.split("\0").filter(Boolean).map(o=>{let[i,...s]=o.split(`
|
|
268
268
|
`),c=s.join(`
|
|
269
|
-
`).trimEnd();return{commit:i,message:c}}):[]}async function
|
|
270
|
-
`,"utf8"),await sr("git",["commit","--amend","--file",n,"--no-gpg-sign"],{cwd:e,encoding:"utf8",env:r}),le(e)}import de from"fs/promises";import $ from"path";var
|
|
269
|
+
`).trimEnd();return{commit:i,message:c}}):[]}async function pr(e,t){let r={...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},n=ir.join(e,".git","SKILLCRAFT_COMMIT_MESSAGE"),{writeFile:o}=await import("fs/promises");return await o(n,`${t}
|
|
270
|
+
`,"utf8"),await sr("git",["-c","core.hooksPath=/dev/null","commit","--amend","--file",n,"--no-gpg-sign"],{cwd:e,encoding:"utf8",env:r}),le(e)}import de from"fs/promises";import $ from"path";var fr="# skillcraft-managed-hook";function ct(e,t){let r=process.argv[1]||"skillcraft",n=JSON.stringify(r),o=e?JSON.stringify(e):void 0,i=o?`if [ -x ${o} ]; then
|
|
271
271
|
${o} "$@"
|
|
272
272
|
SKILLCRAFT_PREVIOUS_HOOK_EXIT=$?
|
|
273
273
|
if [ "$SKILLCRAFT_PREVIOUS_HOOK_EXIT" -ne 0 ]; then
|
|
@@ -276,7 +276,7 @@ export default async function Skillcraft(context) {
|
|
|
276
276
|
fi
|
|
277
277
|
|
|
278
278
|
`:"";return`#!/usr/bin/env sh
|
|
279
|
-
${
|
|
279
|
+
${fr}
|
|
280
280
|
if [ -n "$SKILLCRAFT_HOOK_DISABLED" ]; then
|
|
281
281
|
exit 0
|
|
282
282
|
fi
|
|
@@ -287,85 +287,85 @@ SKILLCRAFT_CLI=${n}
|
|
|
287
287
|
unset GIT_INDEX_FILE
|
|
288
288
|
|
|
289
289
|
${t}
|
|
290
|
-
`}var
|
|
291
|
-
"$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`),
|
|
292
|
-
"$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`);async function
|
|
290
|
+
`}var ko=e=>ct(e,'"$SKILLCRAFT_CLI" _hook post-commit "$SKILLCRAFT_HOOK_DIR" || true'),xo=e=>ct(e,`SKILLCRAFT_HOOK_REMOTE="$1"
|
|
291
|
+
"$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`),vo=e=>ct(e,`SKILLCRAFT_HOOK_REMOTE="$1"
|
|
292
|
+
"$SKILLCRAFT_CLI" _hook post-push "$SKILLCRAFT_HOOK_DIR" "$SKILLCRAFT_HOOK_REMOTE" || true`);async function gr(e){let t=await lt(e);await v(t),await st($.join(t,"post-commit"),ko),await st($.join(t,"post-push"),xo),await st($.join(t,"pre-push"),vo)}async function hr(e){let t=await lt(e).catch(()=>{});!t||t==="/dev/null"||await Promise.all([at($.join(t,"post-commit")),at($.join(t,"post-push")),at($.join(t,"pre-push"))])}async function wr(e){let t=await lt(e).catch(()=>{});if(!t||t==="/dev/null")return!1;let r=$.join(t,"post-commit");return await S(r)?kr(await te(r).catch(()=>"")):!1}async function lt(e){let t=await cr(e);if(t==="/dev/null")throw new Error("Git hooks are disabled for this repository (`core.hooksPath=/dev/null`). Re-enable hooks or unset `core.hooksPath` before running `skillcraft enable`.");let r=$.isAbsolute(t)?$.normalize(t):$.resolve(e,t),n=$.join(e,".git","hooks");if(r===n||bo(r,e))return r;throw new Error(`Git hooks path points outside this repository: ${r}. Skillcraft currently supports the default hooks directory or repo-local hooks paths such as .husky.`)}async function st(e,t){let r=await yr(e);if(r.exists&&r.isManaged){await U(e,`${t(r.backupExists?r.backupPath:void 0)}
|
|
293
293
|
`),await de.chmod(e,493);return}let n;r.exists&&(n=r.backupPath,await S(n)?await de.rm(e,{force:!0}):await de.rename(e,n)),await U(e,`${t(n)}
|
|
294
|
-
`),await de.chmod(e,493)}async function at(e){let t=await
|
|
295
|
-
`);return}await
|
|
296
|
-
`)}function
|
|
297
|
-
`),i,s,c=async()=>{!i||s!==r||await
|
|
294
|
+
`),await de.chmod(e,493)}async function at(e){let t=await yr(e);if(!(!t.exists||!t.isManaged)){if(t.backupExists){await de.rename(t.backupPath,e);return}await de.rm(e,{force:!0})}}async function yr(e){let t=`${e}.skillcraft.orig`;if(!await S(e))return{hookPath:e,backupPath:t,exists:!1,isManaged:!1,backupExists:await S(t)};let n=await te(e).catch(()=>"");return{hookPath:e,backupPath:t,exists:!0,isManaged:kr(n),backupExists:await S(t)}}function kr(e){return e.includes(fr)||e.includes("SKILLCRAFT_CLI=")&&(e.includes("_hook post-commit")||e.includes("_hook post-push"))}function bo(e,t){let r=$.relative(t,e);return r===""||!r.startsWith("..")&&!$.isAbsolute(r)}async function xr(e={}){let t=process.cwd();if(!await M(t))throw new Error("Current directory is not a git repository");let r=await z(t),n=await ce(r),o=Po(e.agents||[],n);for(let s of o)await tr(r,s);let i=n.filter(s=>!o.includes(s));if(i.length){await Te(r,i),process.stdout.write(`disabled skillcraft agents for ${r} (remaining: ${i.join(", ")})
|
|
295
|
+
`);return}await So(r),process.stdout.write(`disabled skillcraft for ${r}
|
|
296
|
+
`)}function Po(e,t){let r=Ne(e);if(r.length)throw new Error(`Unsupported agent value: ${r.join(", ")}`);if(!t.length)return[];let n=ye(e);if(!n.length)return t;let o=n.filter(i=>t.includes(i));if(!o.length)throw new Error(`None of the requested agents are enabled in this repository: ${n.join(", ")}`);return o}async function So(e){await Promise.all([j(G(e)),j(N(e)),j(I(e)),j(ge(e)),j(D(e)),Ae(q(e))]),await hr(e),await Ut(e)}import{createHash as Co}from"crypto";import Me from"path";import Ro from"os";import br from"fs/promises";var dt="proofs";function Pr(e){return(e?.trim()||Q).replace(/^refs\/heads\//,"")}function Sr(e){return`${dt}/${e}.json`}async function ze(e){let t=await Ie(e);return Pr(t.proofRef)}async function Cr(e,t){let r=Pr(t),n=`refs/heads/${r}`,o=`refs/remotes/origin/${r}`,i=[];return await J(e,n)&&i.push(r),await J(e,o)&&i.push(`origin/${r}`),i.length||i.push(r),i}async function Ao(e,t){let r=`refs/heads/${t}`;await J(e,r)||await Oe(e,t,"Initialize Skillcraft proofs branch")}async function Io(e,t,r){await $o(e,t);let n=await br.mkdtemp(Me.join(Ro.tmpdir(),"skillcraft-proof-"));try{return await y(["worktree","add","--quiet",n,t],e),await r(n)}finally{await Rr(e,n)}}async function Rr(e,t){try{await y(["worktree","remove","--force",t],e)}catch{await br.rm(t,{force:!0,recursive:!0})}}async function $o(e,t){let r=`refs/heads/${t}`;try{let o=(await y(["worktree","list","--porcelain"],e)).split(`
|
|
297
|
+
`),i,s,c=async()=>{!i||s!==r||await Rr(e,i)};for(let a of o){if(!a){i=void 0,s=void 0;continue}if(a.startsWith("worktree ")){await c(),i=a.slice(9),s=void 0;continue}a.startsWith("branch ")&&(s=a.slice(7))}await c()}catch{return}}async function ut(e){let t=await ze(e),r=await Cr(e,t),n=new Set;for(let i of r){let s=await ur(e,i,dt);for(let c of s)n.add(c)}let o=[];for(let i of n){if(!i.endsWith(".json"))continue;let s=Me.basename(i,".json"),c=await mt(e,s);c&&o.push(c)}return o}function Eo(e){let t=W(e);if(t.id&&Qe(t.id))return{id:t.id,version:t.version}}function jo(e){let t=e.filter(Boolean).map(r=>W(r)).filter(r=>!!r.id).map(r=>`${r.id}${r.version?`@${r.version}`:""}`);return Array.from(new Set(t)).filter(Qe).sort()}function Ar(e,t,r){let n={skills:e,loadouts:r,timestamp:t};return Co("sha256").update(JSON.stringify(n)).digest("hex").slice(0,8)}async function ke(e){let t=await w(N(e)),r=Tt.safeParse(t??{skills:[]});return r.success?jo(r.data.skills):[]}async function Lo(e){let t=await w(I(e)),r=qt.safeParse(t??{activeLoadouts:[]});return r.success?r.data.activeLoadouts:[]}async function _o(e){let t=await w(D(e));if(!t||typeof t!="object"||Array.isArray(t))return{};let r=t,n=r.agent&&typeof r.agent=="object"&&!Array.isArray(r.agent)?r.agent:void 0,o=r.model&&typeof r.model=="object"&&!Array.isArray(r.model)?r.model:void 0;return{agent:typeof n?.provider=="string"?{provider:vr(n.provider)}:void 0,model:typeof o?.provider=="string"||typeof o?.name=="string"?{provider:typeof o.provider=="string"?vr(o.provider):void 0,name:typeof o.name=="string"?No(o.name):void 0}:void 0}}function vr(e){return e.trim().toLowerCase()}function No(e){return e.trim()}function To(e){if(!e||typeof e!="object")return;let t=e;if(typeof t.version!="number"||typeof t.commit!="string"||!Array.isArray(t.skills)||!t.timestamp||typeof t.timestamp!="string")return;let r=Array.isArray(t.loadouts)?t.loadouts.map(String):[],n=t.skills.map(o=>{if(typeof o=="string")return{id:o};if(o&&typeof o=="object"&&"id"in o&&typeof o.id=="string")return{id:o.id,version:typeof o.version=="string"?o.version:void 0}}).filter(o=>!!o);return{version:t.version,commit:t.commit,skills:n,loadouts:r,timestamp:t.timestamp,agent:qo(t.agent),model:Oo(t.model)}}function qo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e.provider;if(typeof t!="string")return;let r=t.trim().toLowerCase();return r?{provider:r}:void 0}function Oo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r=typeof t.provider=="string"?t.provider.trim().toLowerCase():void 0,n=typeof t.name=="string"?t.name.trim():void 0;if(!(!r&&!n))return{provider:r,name:n}}async function mt(e,t){let r=await ze(e),n=Sr(t),o=await Cr(e,r);for(let i of o){let s=await mr(e,i,n);if(!s)continue;let c;try{c=JSON.parse(s)}catch{continue}let a=To(c);if(a)return a}}async function pt(e,t){let r=Ar(t.skills.map(i=>i.id),t.timestamp,t.loadouts),n=await ze(e);await Ao(e,n);let o=Sr(r);return await Io(e,n,async i=>{await v(Me.join(i,dt)),await h(Me.join(i,o),t),await y(["add",o],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}}),await y(["status","--porcelain","--",o],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"}})&&await y(["commit","--no-gpg-sign","-m",`add Skillcraft proof ${r}`],i,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},disableHooks:!0})}),r}async function Ir(e,t="origin"){let r=await ze(e);if(!(!await V(e,t)||!t))try{await y(["push",t,`${r}:${r}`],e,{env:{...process.env,SKILLCRAFT_HOOK_DISABLED:"1"},disableHooks:!0})}catch{return}}async function $r(e,t){let r=await ut(e);for(let n of r)if(n.commit===t)return Ar(n.skills.map(o=>o.id),n.timestamp,n.loadouts)}async function Er(e,t,r=new Date().toISOString()){let n=await ke(e),o=await Lo(e),i=await _o(e),s=n.map(d=>Eo(d)).filter(d=>!!d),c={version:1,commit:t,skills:s,loadouts:o,timestamp:r,...i};return{proofId:await pt(e,c),proof:c}}async function Fo(e){return e.replace(/\nSkillcraft-Ref: .*$/gm,"").trimEnd()}async function jr(e,t){let r=await lr(e),n=await Fo(r);return n.includes("Skillcraft-Ref:")?n:`${n}
|
|
298
298
|
|
|
299
299
|
Skillcraft-Ref: ${t}
|
|
300
|
-
`}async function R(e){let t=
|
|
300
|
+
`}async function R(e){let t=G(e);if(!await S(t))return!1;let r=await w(t);return ee.safeParse(r??{}).success}async function Lr(e){return S(q(e))}import X from"fs/promises";import ft from"path";import{execFile as Mo,execSync as zo}from"child_process";import{promisify as Ho}from"util";var Do=Ho(Mo);function Uo(){try{return zo("which gh",{stdio:"ignore"}),!0}catch{return!1}}async function Z(e){if(!Uo())throw new Error("gh CLI is required for this workflow");return(await Do("gh",e,{encoding:"utf8"})).stdout.trim()}async function _r(e,t){await X.mkdir(t,{recursive:!0});let r=await X.readdir(e,{withFileTypes:!0});for(let n of r){if(n.name===".git")continue;let o=ft.join(e,n.name),i=ft.join(t,n.name);if(n.isDirectory()){await _r(o,i);continue}if(n.isSymbolicLink()){let s=await X.readlink(o);await X.symlink(s,i);continue}n.isFile()&&await X.copyFile(o,i)}}var He=class{providerName(){return"gh"}async getUser(){return await Z(["api","user","--jq",".login"])}async getIssueUrl(t,r){return`https://github.com/${t}/issues/${r}`}async createIssue(t,r,n){let i=(await Z(["issue","create","-R",t,"--title",r,"--body",n])).match(/\b(\d+)$/);return i?Number(i[1]):0}async createPullRequest(t,r,n){let i=(await Z(["pr","create","--repo",t,"--head",r,"--base","main","--title",n,"--body",`Generated by skillcraft for ${n}`,"--fill-first"])).match(/\b(\d+)$/);return i?Number(i[1]):0}async openPullRequestForBranch(t,r,n,o,i){let c=(await Z(["pr","create","--repo",t,"--head",`${r}:${n}`,"--base","main","--title",o,"--body",i])).match(/\b(\d+)$/);return c?Number(c[1]):0}async getIssueStatus(t,r){let n=await Z(["issue","view",String(r),"--repo",t,"--json","state,labels,url"]),o=JSON.parse(n);return{state:o.state,labels:o.labels?.map(i=>i.name)??[],url:o.url}}async listClaimProcessingRuns(t,r){let n=await Z(["run","list","--repo",t,"--workflow","Process credential claims","--json","name,status,conclusion,url,createdAt,workflowName"]),o=JSON.parse(n),i=`#${r}`,s=o.filter(a=>{let d=a.name||"",l=a.workflowName||"";return d.includes(i)||l.includes(i)}),c=s.length>0?s:o.filter(a=>a.status&&["in_progress","queued","waiting","action_required","canceling"].includes(a.status));return c.length?c.filter(a=>a.url).map(a=>({status:a.status||"unknown",conclusion:a.conclusion??void 0,url:a.url,name:a.name,createdAt:a.createdAt,workflowName:a.workflowName})):[]}async listClaimIssues(t){let r=await Z(["issue","list","--repo",t,"--state","all","--json","number,title,state,body,labels,url","--limit","100"]);return JSON.parse(r).filter(o=>Ko(o.title)||Bo(o.labels,"skillcraft-claim"))}async cloneRepo(t,r){let n=ft.resolve(r);await Z(["repo","clone",t,n])}async copyDirectory(t,r){await X.readdir(r).catch(()=>{})&&await X.rm(r,{recursive:!0,force:!0}),await X.mkdir(r,{recursive:!0}),await _r(t,r)}};function gt(e){return String(e||"").trim().toLowerCase()}function Ko(e){return gt(e).startsWith("claim:")}function Bo(e,t){let r=gt(t);return(e||[]).some(n=>gt(n?.name)===r)}var Jo={gh:()=>new He};function L(e){return Jo[e]()}async function Nr(){let e=process.cwd(),t=await M(e);process.stdout.write(`git: ${t?"enabled":"not a repository"}
|
|
301
301
|
`);let r=t?await z(e):e,n=await R(r);if(process.stdout.write(`skillcraft: ${n?"enabled":"disabled"}
|
|
302
302
|
`),!t||!n)return;let o=await ke(r),i=await ce(r);process.stdout.write(`pending skills: ${o.length}
|
|
303
303
|
`),process.stdout.write(`agents: ${i.length?i.join(", "):"none"}
|
|
304
|
-
`);let s=await S(I(r)),c=await
|
|
304
|
+
`);let s=await S(I(r)),c=await wr(r);process.stdout.write(`context file: ${s?"present":"missing"}
|
|
305
305
|
`),process.stdout.write(`post-commit hook: ${c?"installed":"missing"}
|
|
306
|
-
`);let a=await le(r),d=await
|
|
306
|
+
`);let a=await le(r),d=await $r(r,a);process.stdout.write(`head: ${a}
|
|
307
307
|
`),process.stdout.write(`latest proof: ${d??"none"}
|
|
308
|
-
`);let u=(await
|
|
308
|
+
`);let u=(await Fe(r,20)).filter(P=>P.message.includes("Skillcraft-Ref:"));process.stdout.write(`recent commits with evidence: ${u.length}
|
|
309
309
|
`);let f=(await Ie(r)).proofRef?.replace(/^refs\/heads\//,"")||"skillcraft/proofs/v1",g=await J(r,`refs/heads/${f}`);process.stdout.write(`proof branch: ${g?"present":"missing"}
|
|
310
310
|
`),o.length>0&&process.stdout.write(`pending evidence queued: ${o.join(", ")}
|
|
311
|
-
`)}async function
|
|
311
|
+
`)}async function Tr(){let e=await Promise.all([ue("node"),ue("npm"),ue("git"),ue("gh"),ue("codex"),ue("opencode")]);for(let[o,i]of e)process.stdout.write(`${o}: ${i?"ok":"missing"}
|
|
312
312
|
`);let t=await qe();if(process.stdout.write(`detected agents: ${t.length?t.join(", "):"none"}
|
|
313
313
|
`),!(e.find(([o])=>o==="gh")?.[1]??!1)){process.stdout.write(`gh auth: missing
|
|
314
314
|
`),process.stdout.write(`github user: unknown
|
|
315
315
|
`);return}let n=await L("gh").getUser().catch(()=>"");process.stdout.write(`gh auth: ${n?"ok":"missing"}
|
|
316
316
|
`),process.stdout.write(`github user: ${n||"unknown"}
|
|
317
|
-
`)}async function ue(e){return[e,await
|
|
318
|
-
`)}async function
|
|
317
|
+
`)}async function ue(e){return[e,await Go(e)]}async function Go(e){try{let{execSync:t}=await import("child_process");return t(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}import{createInterface as Wo}from"readline/promises";import{stdin as qr,stdout as xe}from"process";async function Or(e={}){let t=process.cwd();if(!await M(t))throw new Error("Current directory is not a git repository");let r=await z(t),n=await Vo(e.agents||[]),o=await O();if(!o.githubUser){let l=await L(o.provider??"gh").getUser().catch(()=>process.env.GITHUB_USER||process.env.USER||"developer");await Ht({...o,githubUser:l})}await v(q(r));let i=`refs/heads/${Q}`;await J(r,i)||await Oe(r,Q,"Initialize Skillcraft proofs branch"),await h(G(r),{version:1,proofRef:Q}),await v(T()),await h(N(r),{skills:[]}),await h(I(r),{activeLoadouts:[]});let s=await ce(r),c=Fr([...s,...n]);for(let d of n)await er(r,d);await rr(r,c[0]||"opencode"),await Te(r,c),await gr(r);let a=await V(r);await Dt({path:r,remote:a,enabledAt:new Date().toISOString()}),process.stdout.write(`enabled skillcraft for ${r} (agents: ${c.join(", ")})
|
|
318
|
+
`)}async function Vo(e){let t=Ne(e);if(t.length)throw new Error(`Unsupported agent value: ${t.join(", ")}`);let r=ye(e);if(r.length)return r;let n=await qe();if(!n.length)throw new Error("No supported AI coding agents detected. Install opencode or codex, or pass --agent explicitly.");if(n.length===1)return n;if(!qr.isTTY||!xe.isTTY)throw new Error("Multiple supported agents detected (codex, opencode). Re-run with --agent codex, --agent opencode, or both.");return Zo(n)}async function Zo(e){let t=Wo({input:qr,output:xe});try{xe.write(`Multiple supported agents detected: ${e.join(", ")}
|
|
319
319
|
`),xe.write(`Select one or more agents to enable (comma-separated, e.g. 1,2):
|
|
320
320
|
`),e.forEach((o,i)=>{xe.write(`${i+1}. ${o}
|
|
321
|
-
`)});let r=await t.question("Agents: "),n=Fr(r.split(",").map(o=>{let i=o.trim(),s=Number.parseInt(i,10);return Number.isFinite(s)&&s>=1&&s<=e.length?e[s-1]:ye([i])[0]}).filter(o=>!!o));if(!n.length)throw new Error("No valid agent selection provided.");return n}finally{t.close()}}function Fr(e){return Array.from(new Set(e)).sort()}async function
|
|
321
|
+
`)});let r=await t.question("Agents: "),n=Fr(r.split(",").map(o=>{let i=o.trim(),s=Number.parseInt(i,10);return Number.isFinite(s)&&s>=1&&s<=e.length?e[s-1]:ye([i])[0]}).filter(o=>!!o));if(!n.length)throw new Error("No valid agent selection provided.");return n}finally{t.close()}}function Fr(e){return Array.from(new Set(e)).sort()}async function Mr(){let e=await K();if(!e.repos.length){process.stdout.write(`no repositories tracked
|
|
322
322
|
`);return}e.repos.forEach((t,r)=>{process.stdout.write(`${r+1}. ${t.path}`),t.remote&&process.stdout.write(` (${t.remote})`),process.stdout.write(`
|
|
323
|
-
`)})}async function
|
|
324
|
-
`)}async function me(e){return ut(e)}import
|
|
323
|
+
`)})}async function zr(){let e=await K(),t=[];for(let r of e.repos)await M(r.path)&&(await z(r.path),t.push(r));await $e({repos:t}),process.stdout.write(`pruned repo list: ${e.repos.length} -> ${t.length}
|
|
324
|
+
`)}async function me(e){return ut(e)}import Xo from"path";var Yo="https://skillcraft.gg/credential-ledger/credentials/index.json",Qo=360*60*1e3,wt=1,pe=Lt();function ei(){return process.env.SKILLCRAFT_CREDENTIAL_INDEX_URL?.trim()||Yo}async function Hr(e){try{let t=await w(e);if(!t||!re(t))return null;let r=ti(t.cachedAt);if(r===void 0||r<=0||t.version!==wt||!("entries"in t))return null;let n=De(t.entries);return{cachedAt:r,version:wt,entries:n}}catch{return null}}function ti(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e.trim()){let t=Number.parseInt(e,10);if(Number.isFinite(t))return t}}function ri(e){return Date.now()-e.cachedAt<Qo}async function ni(e={}){let t=process.env.SKILLCRAFT_CREDENTIAL_INDEX_PATH?.trim();if(t)return Dr(t);let r=e.refresh?null:await Hr(pe);if(r&&ri(r))return r.entries;try{let n=await oi(ei());return await ii(n),n}catch(n){if(await S(pe)){let o=await Hr(pe);return o?o.entries:Dr(pe)}throw n instanceof Error?n:new Error("failed to load credential index")}}async function oi(e){let t=await fetch(e,{headers:{"user-agent":"skillcraft-cli"}});if(!t.ok)throw new Error(`failed to download credential index from ${e}`);let r=await t.json();return De(r)}async function Dr(e){let t=await w(e);return t?re(t)&&Array.isArray(t.entries)?De(t.entries):De(t):[]}async function ii(e){await v(Xo.dirname(pe));let t={cachedAt:Date.now(),version:wt,entries:e};await h(pe,t)}function si(e){let t=re(e)?e:{};if(t.mode!==void 0)throw new Error("requirements.mode is not supported. Use nested and/or expressions instead.");let r=ai(t);return{minCommits:Br(t.min_commits??t.minCommits,0),minRepositories:Br(t.min_repositories??t.minRepositories,0),tree:r}}function ai(e){if(Object.prototype.hasOwnProperty.call(e,"tree"))return kt(e.tree,"requirements.tree");let t=Object.prototype.hasOwnProperty.call(e,"and"),r=Object.prototype.hasOwnProperty.call(e,"or");if(t&&r)throw new Error("requirements cannot include both and and or at the same level");if(t){let n=Object.keys(e).filter(o=>!["and","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(o));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{and:Ur(e.and,"requirements.and")}}if(r){let n=Object.keys(e).filter(o=>!["or","min_commits","min_repositories","minRepositories","minCommits","tree"].includes(o));if(n.length)throw new Error(`Unexpected requirement fields: ${n.join(", ")}`);return{or:Ur(e.or,"requirements.or")}}return{and:ci(e)}}function Ur(e,t){if(!Array.isArray(e))throw new Error(`Expected array at ${t}`);return e.map((r,n)=>kt(r,`${t}[${n}]`))}function Kr(e,t){if(e===void 0)return[];if(Array.isArray(e))return e.map(n=>{let o=_(n);if(o===void 0)throw new Error(`Expected text values for ${t}`);return o});let r=_(e);return r?[r]:[]}function ci(e){let t=[],r=["and","or","min_commits","min_repositories","minRepositories","minCommits","tree","skill","loadout","agent","model"];for(let a of Kr(e.skill,"requirements.skill"))t.push({skill:a});for(let a of Kr(e.loadout,"requirements.loadout"))t.push({loadout:a});let n=Object.prototype.hasOwnProperty.call(e,"agent"),o=Jr(e.agent);if(o)t.push(o);else if(n)throw new Error("requirements.agent must be an object with a provider");let i=Object.prototype.hasOwnProperty.call(e,"model"),s=Gr(e.model);if(s)t.push(s);else if(i)throw new Error("requirements.model must be an object with optional provider and/or name");let c=Object.keys(e).filter(a=>!r.includes(a)&&!a.startsWith("$"));if(c.length)throw new Error(`Unexpected requirement fields: ${c.join(", ")}`);return t}function kt(e,t){if(!re(e))throw new Error(`Invalid requirement node at ${t}`);let r=Object.keys(e);if(!r.length)throw new Error(`Empty requirement node at ${t}`);if(r.length>1)throw new Error(`Requirement node has multiple keys at ${t}`);let[n]=r;if(n==="and"||n==="or"){let o=e[n];if(!Array.isArray(o))throw new Error(`Requirement node ${t} expected array for ${n}`);return{[n]:o.map((i,s)=>kt(i,`${t}.${n}[${s}]`))}}if(n==="skill"){let o=_(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty skill`);return{skill:o}}if(n==="loadout"){let o=_(e[n]);if(!o)throw new Error(`Requirement node ${t} has empty loadout`);return{loadout:o}}if(n==="agent"){let o=Jr(e[n]);if(!o)throw new Error(`Requirement node ${t} has invalid agent requirement`);return o}if(n==="model"){let o=Gr(e[n]);if(!o)throw new Error(`Requirement node ${t} has invalid model requirement`);return o}throw new Error(`Unexpected requirement key ${n} at ${t}`)}function Jr(e){if(!re(e))return;let t=_(e.provider);if(t)return{agent:{provider:t.toLowerCase()}}}function Gr(e){if(!re(e))return;let t=_(e.provider),r=_(e.name);if(!(!t&&!r))return{model:{...t?{provider:t.toLowerCase()}:{},...r?{name:r}:{}}}}function Wr(e,t,r,n){let o=[],i=[],s=[],c=[],a=Array.from(new Set((t||[]).filter(Boolean))),d=Array.from(new Set((r||[]).filter(Boolean)));for(let f of e){let g=f.proof;for(let Y of g.skills){let ie=xt(Y.id);ie.id&&o.push({id:ie.id,version:ie.version})}for(let Y of g.loadouts){let ie=_(Y);ie&&i.push(ie)}g.agent?.provider&&typeof g.agent.provider=="string"&&s.push(g.agent.provider);let P=g.model?.provider,oe=g.model?.name;(typeof P=="string"||typeof oe=="string")&&c.push({provider:P,name:oe})}let l=yt(n.tree,{skills:o,loadouts:i,agents:s,models:c}),u=l.checks,p=[...li(u)];return n.minCommits>a.length&&(p.push(`minimum required commits not met: have ${a.length}, need ${n.minCommits}`),l.passed=!1),n.minRepositories>d.length&&(p.push(`minimum required repositories not met: have ${d.length}, need ${n.minRepositories}`),l.passed=!1),{passed:l.passed,proofs:e,provenCommits:a,provenRepos:d,checks:u,reasons:p,noExplicitChecks:l.noExplicitChecks}}function yt(e,t){if("and"in e){let r=[],n=[],o=!0;for(let i of e.and){let s=yt(i,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(o=!1)}return{passed:n.every(i=>i.passed),checks:r,noExplicitChecks:o}}if("or"in e){let r=[],n=[],o=!0;for(let i of e.or){let s=yt(i,t);r.push(...s.checks),n.push(s),s.noExplicitChecks||(o=!1)}return{passed:n.some(i=>i.passed),checks:r,noExplicitChecks:o}}if("skill"in e){let r=xt(e.skill),n=di(t.skills,r);return{passed:n,checks:[{type:"skill",requirement:e.skill,satisfied:n}],noExplicitChecks:!1}}if("loadout"in e){let r=mi(e.loadout),n=t.loadouts.includes(e.loadout)||r&&r.id!==""&&t.loadouts.includes(r.id);return{passed:n,checks:[{type:"loadout",requirement:e.loadout,satisfied:n}],noExplicitChecks:!1}}if("agent"in e){let r=ht(e.agent.provider),n=t.agents.some(o=>o===r);return{passed:n,checks:[{type:"agent",requirement:`provider=${r}`,satisfied:n}],noExplicitChecks:!1}}if("model"in e){let r=ht(e.model.provider),n=ht(e.model.name),o=t.models.some(s=>{let c=!r||s.provider===r,a=!n||s.name&&s.name===n;return c&&a}),i=[];return r&&i.push(`provider=${r}`),n&&i.push(`name=${n}`),{passed:o,checks:[{type:"model",requirement:i.join(",")||"model",satisfied:o}],noExplicitChecks:!1}}throw new Error("Unknown requirement node encountered during evaluation")}function li(e){return e.filter(t=>!t.satisfied).map(t=>`${t.type} ${t.requirement} not met`)}function di(e,t){return e.some(r=>ui(r.id,r.version,t))}function ui(e,t,r){return e!==r.id?!1:r.version?t===r.version:!0}function mi(e){return xt(e)}function xt(e){let t=_(e);if(!t)return{id:""};let r=t.split("@");return{id:r[0],version:r.length>1?r.slice(1).join("@"):void 0}}function ht(e){return typeof e=="string"?e.trim().toLowerCase():""}function _(e){return typeof e!="string"?void 0:e.trim()||void 0}function Br(e,t){return typeof e!="number"||!Number.isFinite(e)||e<0?t:Math.floor(e)}function re(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function De(e){if(!Array.isArray(e))return[];let t=[];for(let r of e){let n=pi(r);n&&t.push(n)}return t.sort((r,n)=>r.id.localeCompare(n.id))}function pi(e){if(!re(e))return;let t=_(e.id);if(t)try{return{id:t,name:_(e.name),description:_(e.description),requirements:si(e.requirements)}}catch{return}}async function vt(e={}){return ni(e)}function Vr(e){process.stdout.write(`${e.join(`
|
|
325
325
|
`)}
|
|
326
|
-
`)}async function
|
|
327
|
-
`);return}let o=
|
|
326
|
+
`)}async function fi(){let e=await K(),t=new Set,r=[];for(let n of e.repos)t.has(n.path)||(t.add(n.path),await R(n.path)&&r.push(n.path));return r}async function Yr(e={}){let t=await fi(),n=(await Ee()).credentials;if(!n.length){if(e.outputMode==="json"){Xr(Zr({tracked:t,trackedCredentialsCount:0,proofFiles:0,provenCommits:0,provenRepositories:0,evaluated:[]}));return}process.stdout.write(`no credentials tracked
|
|
327
|
+
`);return}let o=tn(await vt({refresh:e.refreshIndex})),i=0,s=[],c=new Set,a=new Set;for(let g of t){let P=await me(g);if(i+=P.length,!P.length)continue;let oe=await V(g)||g;c.add(oe);for(let Y of P)Y?.commit&&a.add(Y.commit),s.push({proof:Y})}let d=Array.from(a),l=Array.from(c),u=Zr({tracked:t,trackedCredentialsCount:n.length,proofFiles:i,provenCommits:d.length,provenRepositories:l.length,evaluated:[]}),p=[];for(let g of n){let P=o.get(g.id);if(!P){p.push(gi(g.id,s.length,d.length,l.length));continue}let oe=Wr(s,d,l,P.requirements);p.push(hi(g.id,P,oe,s.length,d.length,l.length))}if(u.credentials=p,e.outputMode==="json"){Xr(u);return}let f=[];f.push(`tracked credentials: ${n.length}`),f.push(`tracked repositories: ${t.length}`),f.push(`proof files: ${i}`),f.push(`proof commits: ${d.length}`),f.push(`proof repositories: ${l.length}`),f.push("");for(let g of p){if(f.push(`${g.credentialId}: ${g.status}`),f.push(` checks: ${g.passed?"passed":"blocked"}`),f.push(` proof scope: ${g.proofFiles} proofs, ${g.provenCommits}/${g.requiredMinCommits} commits, ${g.provenRepositories}/${g.requiredMinRepositories} repositories`),g.reasons.length){f.push(" reasons:");for(let P of g.reasons)f.push(` - ${P}`)}f.push("")}Vr(f)}async function Qr(e){let t=F(e,"credential id");if(!tn(await vt()).has(t))throw new Error(`credential not found in credential index: ${t}`);if(!await Bt(t)){process.stdout.write(`credential already tracked: ${t}
|
|
328
328
|
`);return}process.stdout.write(`tracking credential: ${t}
|
|
329
|
-
`)}async function
|
|
329
|
+
`)}async function en(e){let t=F(e,"credential id");if(!await Jt(t)){process.stdout.write(`credential not tracked: ${t}
|
|
330
330
|
`);return}process.stdout.write(`untracked credential: ${t}
|
|
331
|
-
`)}function
|
|
332
|
-
`)}function
|
|
331
|
+
`)}function Zr(e){return{trackedCredentials:e.trackedCredentialsCount,trackedRepositories:e.tracked.length,evidence:{proofFiles:e.proofFiles,provenCommits:e.provenCommits,provenRepositories:e.provenRepositories},credentials:e.evaluated}}function Xr(e){process.stdout.write(`${JSON.stringify(e)}
|
|
332
|
+
`)}function tn(e){return new Map(e.map(t=>[t.id,t]))}function gi(e,t,r,n){return{credentialId:e,passed:!1,status:"blocked",reasons:["credential definition is not available"],checks:[],requiredMinCommits:0,requiredMinRepositories:0,provenCommits:r,provenRepositories:n,proofFiles:t}}function hi(e,t,r,n,o,i){return{credentialId:e,name:t.name,description:t.description,passed:r.passed,status:r.passed?"eligible":"blocked",reasons:r.reasons,checks:r.checks,requiredMinCommits:t.requirements.minCommits,requiredMinRepositories:t.requirements.minRepositories,provenCommits:o,provenRepositories:i,proofFiles:n}}import b from"path";import A from"fs/promises";import wi from"os";import{execFile as yi}from"child_process";import{promisify as ki}from"util";import xi from"ora";var vi=ki(yi);async function an(e){let t=F(e,"skill id"),{owner:r,slug:n}=je(t),o=process.cwd();if(!await R(o))throw new Error("Repository is not enabled");let i=await Promise.all([A.access(b.join(o,"SKILL.md")).then(()=>!0).catch(()=>!1),A.access(b.join(o,"skill.yaml")).then(()=>!0).catch(()=>!1)]);if(!i[0]||!i[1])throw new Error("SKILL.md and skill.yaml are required for publishing");let s=await O(),c=L(s.provider??"gh");await c.getUser();let a="skillcraft-gg/skills-registry",d=`skillcraft-skill-${r}-${n}`,l=b.join(process.cwd(),".skillcraft-temp-skill-publish");try{await A.rm(l,{force:!0,recursive:!0}),await c.cloneRepo(a,l),await ve(l,["checkout","-B",d]);let u=b.join(l,"skills",r,n);await A.rm(u,{force:!0,recursive:!0}),await A.mkdir(b.dirname(u),{recursive:!0}),await A.cp(o,u,{recursive:!0}),await ve(l,["add",`skills/${r}/${n}`]),await ve(l,["commit","-m",`Publish skill ${t}`]).catch(()=>{throw new Error("nothing to commit; skill may already be published")}),await ve(l,["push","-u","origin",d]).catch(()=>{throw new Error("unable to push skill publish branch")}),await c.createPullRequest(a,d,`Publish skill: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
|
|
333
333
|
`)}),process.stdout.write(`published skill ${t} from ${a}
|
|
334
|
-
`)}finally{await A.rm(l,{force:!0,recursive:!0})}}async function
|
|
335
|
-
`)}async function
|
|
336
|
-
`)}async function
|
|
334
|
+
`)}finally{await A.rm(l,{force:!0,recursive:!0})}}async function cn(e){let t=process.cwd();if(!await R(t))throw new Error("Repository is not enabled");let r=F(e,"skill id"),n=W(r);if(!n.id)throw new Error("invalid skill id format");if(n.version)throw new Error("skill versions are not supported for installation yet");let i=(await bt("text")).find(l=>l.id===n.id);if(!i)throw new Error(`skill ${n.id} is not listed in the search index`);let s=mn(i),c=Wt(i.id),a=b.join(Re(t),c);if(await be(a))throw new Error(`skill ${i.id} is already installed at ${b.posix.join(".agents","skills",c)}`);let d=await A.mkdtemp(b.join(wi.tmpdir(),"skillcraft-skill-"));try{let l=await $i(i,d);await v(Re(t)),await A.cp(l,a,{recursive:!0}),await ji(b.join(a,"SKILL.md"),c),await Gt(t,Vt({id:i.id,name:c,install:s,installedAt:new Date().toISOString()}))}finally{await A.rm(d,{force:!0,recursive:!0})}process.stdout.write(`installed skill: ${i.id} -> ${b.posix.join(".agents","skills",c)}
|
|
335
|
+
`)}async function bi(){let e=process.cwd(),t=[["SKILL.md",await be(b.join(e,"SKILL.md"))],["skill.yaml",await be(b.join(e,"skill.yaml"))]];for(let[r,n]of t)process.stdout.write(`${r}: ${n?"ok":"missing"}
|
|
336
|
+
`)}async function ln(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");let[t,r,n]=await Promise.all([me(e),ke(e),he(e)]),o=new Set;for(let s of t)for(let c of s.skills)o.add(c.id);for(let s of r)o.add(s);for(let s of n)o.add(s.id);if(!o.size){process.stdout.write(`no skills detected
|
|
337
337
|
`);return}let i=Array.from(o).sort().join(`
|
|
338
338
|
`);process.stdout.write(`skills detected (${o.size}):
|
|
339
339
|
${i}
|
|
340
|
-
`)}async function
|
|
340
|
+
`)}async function dn(e,t={}){let r=await bt(t.outputMode);if(!r.length){t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:sn(t.limit),count:0,results:[],message:"no skills indexed"})}
|
|
341
341
|
`):process.stdout.write(`no skills indexed
|
|
342
|
-
`);return}let n=e?.trim().toLowerCase(),o=t.source?.trim().toLowerCase(),i=
|
|
342
|
+
`);return}let n=e?.trim().toLowerCase(),o=t.source?.trim().toLowerCase(),i=sn(t.limit),c=[...r.filter(u=>o&&Pt(u.id)!==o?!1:n?[u.id,u.name,u.owner,u.slug,u.path,u.url,...u.runtime||[],...u.tags||[]].filter(f=>!!f).map(f=>f.toLowerCase()).some(f=>f.includes(n)):!0)].sort((u,p)=>{let f=(u.name||u.id).toLowerCase(),g=(p.name||p.id).toLowerCase();return f===g?u.id.localeCompare(p.id):f.localeCompare(g)}),a=c.slice(0,i);if(!a.length){let u=n?`no skills match "${e?.trim()}"`:"no skills match current filters";t.outputMode==="json"?process.stdout.write(`${JSON.stringify({query:e?.trim(),source:t.source?.trim(),limit:i,count:0,results:[],message:u})}
|
|
343
343
|
`):process.stdout.write(`${u}
|
|
344
|
-
`);return}let d=n?`skills matching "${e?.trim()}"`:"skills index",l=a.map(u=>{let p=(u.runtime||[]).length?` [${u.runtime.join(", ")}]`:"",f=(u.tags||[]).length?` {${u.tags.join(", ")}}`:"",g=
|
|
344
|
+
`);return}let d=n?`skills matching "${e?.trim()}"`:"skills index",l=a.map(u=>{let p=(u.runtime||[]).length?` [${u.runtime.join(", ")}]`:"",f=(u.tags||[]).length?` {${u.tags.join(", ")}}`:"",g=Oi(u.updatedAt),P=Ti(u);return`${u.id}${P?` \u2014 ${P}`:""}${p}${f}${g}`});if(t.outputMode==="json"){let u={query:e?.trim(),source:t.source?.trim(),limit:i,count:a.length,total:c.length,results:a.map(p=>({id:p.id,name:p.name,path:p.path,url:p.url,owner:p.owner,slug:p.slug,runtime:p.runtime,tags:p.tags}))};process.stdout.write(`${JSON.stringify(u)}
|
|
345
345
|
`);return}process.stdout.write(`${d} (${a.length}):
|
|
346
346
|
${l.join(`
|
|
347
347
|
`)}
|
|
348
|
-
`)}async function
|
|
349
|
-
`);return}let c=
|
|
350
|
-
`)}function
|
|
351
|
-
`)}async function
|
|
348
|
+
`)}async function un(e,t={}){let r=F(e,"skill id"),n=W(r);if(!n.id)throw new Error("invalid skill id format");let i=(await bt(t.outputMode)).find(a=>a.id===n.id);if(!i)throw new Error(`skill ${n.id} is not listed in the search index`);let s=await Si(i);if(t.outputMode==="json"){let a={id:i.id,name:i.name,source:Pt(i.id),owner:i.owner,slug:i.slug,path:i.path,url:i.url,runtime:i.runtime,tags:i.tags,install:i.install,updatedAt:i.updatedAt,manifest:s,version:n.version};process.stdout.write(`${JSON.stringify(a)}
|
|
349
|
+
`);return}let c=Pi(i,s);process.stdout.write(`${c}
|
|
350
|
+
`)}function Pi(e,t){let r=[];r.push(`skill: ${e.id}`),e.name&&r.push(`name: ${e.name}`);let n=Pt(e.id);return n&&r.push(`source: ${n}`),e.owner&&r.push(`owner: ${e.owner}`),e.slug&&r.push(`slug: ${e.slug}`),e.runtime&&e.runtime.length&&r.push(`runtime: ${e.runtime.join(", ")}`),e.tags&&e.tags.length&&r.push(`tags: ${e.tags.join(", ")}`),e.updatedAt&&r.push(`updated: ${e.updatedAt}`),e.path&&r.push(`path: ${e.path}`),e.url&&r.push(`url: ${e.url}`),e.install?.type&&r.push(`install type: ${e.install.type}`),e.install?.repo&&r.push(`install repo: ${e.install.repo}`),e.install?.path&&r.push(`install path: ${e.install.path}`),t&&(r.push(`manifest: ${t.url}`),t.title&&r.push(`manifest title: ${t.title}`),t.summary&&r.push(`manifest summary: ${t.summary}`),t.error&&r.push(`manifest fetch: ${t.error}`)),r.join(`
|
|
351
|
+
`)}async function Si(e){let t=Ci(e.url);if(!t)return;let r=new AbortController,n=setTimeout(()=>{r.abort()},5e3);try{let o=await fetch(t,{headers:{"user-agent":"skillcraft-cli"},signal:r.signal});if(!o.ok)return{url:t,error:`unable to fetch manifest (${o.status})`};let i=await o.text();if(Ai(i))return{url:t,error:"unable to parse manifest (not markdown)"};let s=Ii(i);return{url:t,title:s.title,summary:s.summary}}catch(o){return o instanceof Error&&o.name==="AbortError"?{url:t,error:"manifest fetch timed out"}:{url:t,error:o instanceof Error?o.message:"failed to fetch manifest"}}finally{clearTimeout(n)}}function Ci(e){if(!e)return;let t=e.trim();if(!t)return;let r=t.endsWith("/SKILL.md")?t:t.endsWith("/")?`${t}SKILL.md`:`${t}/SKILL.md`;return Ri(r)}function Ri(e){try{let t=new URL(e);if(t.hostname!=="github.com")return e;let r=t.pathname.split("/").filter(Boolean),n=r.indexOf("blob");if(n!==2||r.length<n+2)return e;let o=r[0],i=r[1],s=r.slice(n+1);if(!o||!i||!s.length)return e;let c=[o,i,"raw","refs","heads",...s];return`${t.protocol}//${t.host}/${c.join("/")}`}catch{return e}}function Ai(e){let t=e.replace(/^\s+/,"").toLowerCase();return t.startsWith("<!doctype html")||t.startsWith("<html")}function Ii(e){let r=e.replace(/\r\n/g,`
|
|
352
352
|
`).split(`
|
|
353
|
-
`),n=0;if((r[0]||"").trim()==="---"){for(n=1;n<r.length&&r[n].trim()!=="---";)n+=1;n<r.length&&r[n].trim()==="---"&&(n+=1)}let o,i;for(let s=n;s<r.length;s+=1){let c=r[s].trim();if(!c){if(i)break;continue}if(!o&&c.startsWith("#")){o=c.replace(/^#+\s*/,"").trim();continue}if(!i&&!c.startsWith(">")){i=c;break}}return{title:o,summary:i}}function
|
|
353
|
+
`),n=0;if((r[0]||"").trim()==="---"){for(n=1;n<r.length&&r[n].trim()!=="---";)n+=1;n<r.length&&r[n].trim()==="---"&&(n+=1)}let o,i;for(let s=n;s<r.length;s+=1){let c=r[s].trim();if(!c){if(i)break;continue}if(!o&&c.startsWith("#")){o=c.replace(/^#+\s*/,"").trim();continue}if(!i&&!c.startsWith(">")){i=c;break}}return{title:o,summary:i}}function mn(e){let t=e.install;if(!t?.type||!t.path)throw new Error(`skill ${e.id} does not include install metadata in the search index`);if(t.type==="github-directory"&&(!t.repo||!t.ref))throw new Error(`skill ${e.id} has incomplete github install metadata`);return{type:t.type,...t.repo?{repo:t.repo}:{},...t.ref?{ref:t.ref}:{},path:t.path}}async function $i(e,t){let r=mn(e);if(r.type==="local-directory"){let i=Ei(r.path);if(!await be(i))throw new Error(`local skill source does not exist: ${i}`);return i}let n=b.join(t,"source");await ve(t,["clone","--depth","1","--branch",r.ref,`https://github.com/${r.repo}.git`,n]);let o=b.join(n,r.path);if(!await be(o))throw new Error(`skill source path does not exist in ${r.repo}@${r.ref}: ${r.path}`);return o}function Ei(e){if(b.isAbsolute(e))return e;let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim();return t?b.resolve(b.dirname(t),e):b.resolve(e)}async function ji(e,t){let o=(await A.readFile(e,"utf8").catch(()=>{throw new Error(`installed skill is missing SKILL.md: ${e}`)})).replace(/\r\n/g,`
|
|
354
354
|
`).split(`
|
|
355
355
|
`);if((o[0]||"").trim()!=="---")throw new Error(`skill manifest is missing YAML frontmatter: ${e}`);let i=-1;for(let d=1;d<o.length;d+=1)if(o[d].trim()==="---"){i=d;break}if(i===-1)throw new Error(`skill manifest frontmatter is not closed: ${e}`);let s=!1,c=o.slice(1,i).map(d=>/^\s*name\s*:/.test(d)?(s=!0,`name: ${t}`):d);s||c.unshift(`name: ${t}`);let a=["---",...c,"---",...o.slice(i+1)].join(`
|
|
356
356
|
`);await A.writeFile(e,a.endsWith(`
|
|
357
357
|
`)?a:`${a}
|
|
358
|
-
`,"utf8")}function
|
|
359
|
-
`).map(r=>r.trim()).filter(Boolean).map(r=>{let n=r.indexOf(" ");if(n===-1)return;let o=r.slice(0,n),i=r.slice(n+1).trim(),s=o.slice(7,-4);if(!(!i||!s))return{name:s,url:i}}).filter(r=>!!r)}catch{return[]}}async function
|
|
358
|
+
`,"utf8")}function rn(e){return Array.isArray(e)}async function bt(e=void 0){let t=process.env.SKILLCRAFT_SEARCH_INDEX_PATH?.trim(),r=t||process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",n=async()=>{if(t){let d=await A.readFile(t,"utf8"),l=JSON.parse(d);return nn(rn(l)?l:[])}let s=process.env.SKILLCRAFT_SEARCH_INDEX_URL||"https://skillcraft.gg/skills-registry/search/index.json",c=await fetch(s,{headers:{"user-agent":"skillcraft-cli"}});if(!c.ok)throw new Error(`failed to download search index from ${s}`);let a=await c.json();return nn(rn(a)?a:[])};if(!Li(e))return n();let o=t?`reading local index from ${r}`:`downloading index from ${r}`,i=xi({text:`Loading ${o}...`}).start();try{let s=await n();return i.succeed(`loaded ${s.length} indexed entries`),s}catch(s){throw i.fail("failed to load search index"),s}}function Li(e){return e!=="text"?!1:process.stdout.isTTY===!0||process.stderr.isTTY===!0}function nn(e){return e.map(t=>_i(t)).filter(t=>!!t)}function _i(e){let t=pn(e.id),r=ae(t);if(r)return{id:r,name:H(e.name),path:H(e.path),url:H(e.url),owner:H(e.owner),slug:H(e.slug),runtime:on(e.runtime),tags:on(e.tags),install:Ni(e.install),updatedAt:H(e.updatedAt)}}function Ni(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t=e,r=H(t.type),n=H(t.path);if(!(!r||!n)&&!(r!=="github-directory"&&r!=="local-directory"))return{type:r,repo:H(t.repo),ref:H(t.ref),path:n}}function pn(e){return String(e||"").trim()}function H(e){return pn(e)||void 0}function on(e){if(e===void 0)return[];if(typeof e=="string")return e.split(",").map(r=>r.trim()).filter(Boolean);if(!Array.isArray(e))return[];let t=[];for(let r of e){if(typeof r!="string")continue;let n=r.trim();n&&t.push(n)}return t}function Pt(e){let t=e.indexOf(":");if(t<1)return;let r=e.slice(0,t).trim();if(r)return r.toLowerCase()}function sn(e){let t=e===void 0?20:Math.floor(e);return Number.isFinite(t)&&t>0?t:20}function Ti(e){let t=(e.name||"").trim();if(!t)return"";let r=qi(e);return r&&t.toLowerCase()===r.toLowerCase()?"":t}function qi(e){if(e.slug&&e.slug.trim())return e.slug.trim();let t=e.id.trim(),r=t.indexOf(":"),n=r>=0?t.slice(r+1):t,o=n.split("/").filter(Boolean);return o.length?o[o.length-1]:n}function Oi(e){if(!e)return"";let t=new Date(e);return Number.isNaN(t.getTime())?"":` (updated ${t.toISOString().slice(0,10)})`}async function be(e){try{return await A.access(e),!0}catch{return!1}}async function fn(e,t=process.cwd()){let r=ae(F(e,"skill id"));if(!r)throw new Error("invalid skill id format");await Le(t,r)}async function ve(e,t){let{stdout:r}=await vi("git",t,{cwd:e});return r.trim()}async function gn(){await bi()}import{mkdtemp as Fi,rm as Mi}from"fs/promises";import zi from"os";import Hi from"path";function Di(e){let t=e.trim();if(t&&!(/^[a-zA-Z]:[\\/]/.test(t)||t.startsWith("/")||t.startsWith("./")||t.startsWith("../"))&&(/^[a-z][a-z0-9+.-]*:/.test(t)||t.startsWith("git@")||t.startsWith("ssh://")||t.startsWith("http://")||t.startsWith("https://")||t.startsWith("file://")))return t}async function hn(e){try{return(await y(["config","--get-regexp","^remote..*.url$"],e)).split(`
|
|
359
|
+
`).map(r=>r.trim()).filter(Boolean).map(r=>{let n=r.indexOf(" ");if(n===-1)return;let o=r.slice(0,n),i=r.slice(n+1).trim(),s=o.slice(7,-4);if(!(!i||!s))return{name:s,url:i}}).filter(r=>!!r)}catch{return[]}}async function wn(e){return St(e,{normalize:!0})}async function St(e,t={}){let r=t.normalize??!0,n=[];for(let o of e){let i=r?Di(o.repo):o.repo;if(!i){for(let a of o.commits)n.push({repo:o.repo,commit:a});continue}let s=Array.from(new Set(o.commits.map(a=>a.trim()).filter(Boolean)));if(!s.length)continue;let c=await Ui(i,s);for(let a of c)n.push({repo:i,commit:a})}return n}async function Ui(e,t){let r=Array.from(new Set(t.map(o=>o.trim()).filter(Boolean)));if(!r.length)return[];let n=await Fi(Hi.join(zi.tmpdir(),"skillcraft-remote-check-"));try{try{await y(["clone","--quiet","--no-checkout",e,n],process.cwd())}catch{return r}let o=[];for(let i of r)await Ki(n,i)||o.push(i);return o}finally{await Mi(n,{recursive:!0,force:!0})}}async function Ki(e,t){try{await y(["cat-file","-e",`${t}^{commit}`],e)}catch{return!1}try{return!!await y(["branch","-r","--contains",t],e)}catch{return!1}}async function yn(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");let r=(await Fe(e,200)).map(l=>l.message.match(/Skillcraft-Ref:\s*(\S+)/)?.[1]).filter(Boolean),n=0,o=[];for(let l of r){let u=await mt(e,l);if(!u){n+=1,process.stdout.write(`missing proof object: ${l}
|
|
360
360
|
`);continue}if(!u.commit||!u.timestamp){n+=1,process.stdout.write(`invalid proof object: ${l}
|
|
361
361
|
`);continue}o.push(u.commit)}if(n>0){process.stdout.write(`verify failed: ${n} missing/invalid proofs
|
|
362
362
|
`),process.exitCode=1;return}process.stdout.write(`verify passed: ${r.length} commit proofs resolved
|
|
363
|
-
`);let i=await
|
|
363
|
+
`);let i=await hn(e);if(!i.length){process.stdout.write(`\u26A0\uFE0F Warning: no git remotes configured for repository
|
|
364
364
|
`);return}let s=i.map(l=>({repo:l.url,commits:o})),c=await St(s,{normalize:!1}),a=new Map;for(let{repo:l,commit:u}of c){let p=a.get(l);p?p.push(u):a.set(l,[u])}let d=l=>{let u=a.get(l);return u?Array.from(new Set(u)):[]};for(let l of i){let u=d(l.url);u.length>0?process.stdout.write(`\u26A0\uFE0F Warning: proof commits not pushed to ${l.url}: ${u.join(", ")}
|
|
365
365
|
`):process.stdout.write(`remote status: ${l.url} (all referenced proof commits present)
|
|
366
|
-
`)}}import{createHash as
|
|
366
|
+
`)}}import{createHash as Bi}from"crypto";import kn from"yaml";async function Ct(){let e=await O(),t=L(e.provider??"gh"),r=await Rt(t,e.githubUser),o=(await t.listClaimIssues("skillcraft-gg/credential-ledger")).filter(i=>{let s=Ue(i.body);return s?.claimant===E(r)&&!!s?.credential});if(!o.length){process.stdout.write(`no claims found for ${r||"user"}
|
|
367
367
|
`);return}for(let i of o)process.stdout.write(`#${i.number} ${i.title} (${At(i.labels?.map(s=>s?.name)||[])})
|
|
368
|
-
`)}async function
|
|
368
|
+
`)}async function xn(e){let t=E(e);if(!t)throw new Error("claim status requires a credential identifier");let r=await O(),n=L(r.provider??"gh"),o=await Rt(n,r.githubUser),i=await Ji(n,t,o);if(!i)throw new Error(`No claim found for credential ${t} for user ${o||"unknown"}. Run "skillcraft claim" to see your claims.`);let s=await n.getIssueStatus("skillcraft-gg/credential-ledger",i),c=await n.listClaimProcessingRuns("skillcraft-gg/credential-ledger",i);if(process.stdout.write(`issue #${i}
|
|
369
369
|
`),process.stdout.write(`state: ${At(s.labels)}
|
|
370
370
|
`),process.stdout.write(`labels: ${s.labels.join(", ")||"none"}
|
|
371
371
|
`),process.stdout.write(`url: ${s.url}
|
|
@@ -373,20 +373,20 @@ ${l.join(`
|
|
|
373
373
|
`);return}let a=c[0],d=a.conclusion?` (${a.conclusion})`:"";process.stdout.write(`processing actions: ${a.status}${d}
|
|
374
374
|
`),process.stdout.write(`latest run: ${a.url}
|
|
375
375
|
`),c.length>1&&process.stdout.write(`previous attempts: ${c.length-1}
|
|
376
|
-
`)}async function
|
|
376
|
+
`)}async function Ji(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),o=E(t),i=E(r);return n.map(c=>{let a=Ue(c.body);if(!(!a||a.claimant!==i||a.credential!==o))return c.number}).filter(c=>!!c).sort((c,a)=>a-c)[0]}async function Gi(e,t,r){let n=await e.listClaimIssues("skillcraft-gg/credential-ledger"),o=E(t),i=E(r);return n.filter(c=>{if(E(c.state)!=="open")return!1;let a=Ue(c.body);return!!a&&a.claimant===i&&a.credential===o}).sort((c,a)=>c.number-a.number)[0]}async function vn(e,t){let r=await O(),n=L(r.provider??"gh"),o=await Rt(n,r.githubUser),i=await Zi(e,{allRepos:t?.allRepos,repo:t?.repo},o),s=E(e),c=E(o),a=await wn(i.sources);if(a.length>0){process.stdout.write(`\u26A0\uFE0F Warning: some claim commits may not be pushed yet. Please push recent commits before re-submitting the claim.
|
|
377
377
|
`);for(let u of a)process.stdout.write(`- ${u.commit} in ${u.repo}
|
|
378
|
-
`);process.exitCode=1;return}if(s&&c){let u=await
|
|
378
|
+
`);process.exitCode=1;return}if(s&&c){let u=await Gi(n,s,c);if(u){let p=u.url||await n.getIssueUrl("skillcraft-gg/credential-ledger",u.number);process.stdout.write(`claim already submitted
|
|
379
379
|
`),process.stdout.write(`issue: #${u.number}
|
|
380
380
|
`),process.stdout.write(`state: ${At(u.labels?.map(f=>f?.name)||[])}
|
|
381
381
|
`),process.stdout.write(`url: ${p}
|
|
382
|
-
`);return}await Wi(n,s,c)}let d=
|
|
382
|
+
`);return}await Wi(n,s,c)}let d=kn.stringify(i),l=await n.createIssue("skillcraft-gg/credential-ledger",`claim: ${e}`,d);process.stdout.write(`opened claim: #${l}
|
|
383
383
|
`),process.stdout.write(`payload:
|
|
384
384
|
${d}
|
|
385
|
-
`)}async function Rt(e,t){let r=process.env.GITHUB_USER||process.env.USER||"";try{let n=await e.getUser();if(n)return n}catch{}return t||r||"unknown"}function E(e){return(e||"").trim().toLowerCase()}async function Wi(e,t,r){let o=(await e.listClaimIssues("skillcraft-gg/credential-ledger")).find(s=>{if(!
|
|
386
|
-
`),r=
|
|
387
|
-
`)}async function
|
|
388
|
-
`)}async function
|
|
385
|
+
`)}async function Rt(e,t){let r=process.env.GITHUB_USER||process.env.USER||"";try{let n=await e.getUser();if(n)return n}catch{}return t||r||"unknown"}function E(e){return(e||"").trim().toLowerCase()}async function Wi(e,t,r){let o=(await e.listClaimIssues("skillcraft-gg/credential-ledger")).find(s=>{if(!Vi(s,"skillcraft-issued"))return!1;let c=Ue(s.body);return c?c.credential===t&&c.claimant===r:!1});if(!o)return;let i=o.url?` (${o.url})`:"";throw new Error(`You already have an issued claim for ${t}. Existing issue: #${o.number}${i}`)}function Ue(e){if(e)try{let t=String(e).replace(/\\n/g,`
|
|
386
|
+
`),r=kn.parse(t);if(!r||typeof r!="object")return;let n=r.credential&&typeof r.credential=="string"?r.credential:r.credential?.id,o=r.claimant?.github,i=E(n),s=E(o);return!i||!s?void 0:{credential:i,claimant:s}}catch{return}}function Vi(e,t){let r=t.toLowerCase();return(e.labels||[]).some(n=>E(n?.name)===r)}function At(e){let t=new Set((e||[]).map(r=>E(r)));return t.has("skillcraft-issued")?"issued":t.has("skillcraft-rejected")?"rejected":t.has("skillcraft-verified")?"verified":t.has("skillcraft-processing")?"processing":"pending"}async function Zi(e,t,r="unknown"){let n=await Xi(t),o=[];for(let a of n){let d=await me(a),l=await V(a)||a,u=await Promise.all(d.map(async f=>await dr(a,f.commit)?f:void 0)),p=Array.from(new Set(u.map(f=>f?.commit).filter(Boolean)));o.push({repo:l,commits:p})}let i=r,s=`${i}:${e}:${o.map(a=>`${a.repo}:${a.commits.length}`).join("|")}:${Date.now()}`,c=Bi("sha256").update(s).digest("hex").slice(0,8);return{claim_version:1,claimant:{github:i},credential:{id:e},sources:o,claim_id:`sha256:${c}`}}async function Xi(e){let t=e.allRepos?(await K()).repos.map(o=>o.path):[process.cwd()],r=e.repo?e.repo:t,n=[];for(let o of r)await Lr(o)&&n.push(o);return n}import Pe from"path";import ne from"fs/promises";import{execFile as Yi}from"child_process";import{promisify as Qi}from"util";var es=Qi(Yi);async function bn(e){if(!Ye(e))throw new Error("loadout id must be <owner>/<slug>");let t=process.cwd();if(!await R(t))throw new Error("Repository is not enabled");let r=await w(I(t)),n=Array.isArray(r?.activeLoadouts)?r.activeLoadouts.filter(Boolean):[];n.includes(e)||n.push(e),await h(I(t),{activeLoadouts:n}),process.stdout.write(`activated loadout: ${e}
|
|
387
|
+
`)}async function Pn(){let e=process.cwd();if(!await R(e))throw new Error("Repository is not enabled");await h(I(e),{activeLoadouts:[]}),process.stdout.write(`cleared active loadouts
|
|
388
|
+
`)}async function Sn(e){let t=F(e,"loadout id");if(!Ye(t))throw new Error("loadout id must be <owner>/<slug>");let{owner:r,slug:n}=je(t),o=process.cwd(),i=Pe.join(o,"loadout.yaml");if(await ne.access(i),!(await ne.stat(i)).isFile())throw new Error("loadout.yaml not found in current directory");let c=await O(),a=L(c.provider??"gh"),d="skillcraft-gg/loadouts",l=Pe.join(process.cwd(),".skillcraft-temp-loadout-share"),u=`skillcraft-loadout-${r}-${n}`;try{await ne.rm(l,{force:!0,recursive:!0}),await a.cloneRepo(d,l),await Ke(l,["checkout","-B",u]);let p=Pe.join(l,"loadouts",r,n);await ne.rm(p,{force:!0,recursive:!0}).catch(()=>{}),await ne.mkdir(Pe.dirname(p),{recursive:!0}),await ne.copyFile(i,Pe.join(p,"loadout.yaml")),await Ke(l,["add",p]),await Ke(l,["commit","-m",`Loadout: publish ${t}`]).catch(async()=>{throw new Error("nothing to commit; loadout may already be published")}),await Ke(l,["push","-u","origin",u]).catch(()=>{throw new Error("unable to push loadout publish branch")}),await a.createPullRequest(d,u,`Loadout publish: ${t}`).catch(()=>{process.stdout.write(`unable to create PR automatically. Please open one manually from your branch.
|
|
389
389
|
`)}),process.stdout.write(`loadout publish workflow completed for ${t}
|
|
390
|
-
`)}finally{await ne.rm(l,{force:!0,recursive:!0})}}async function Ke(e,t){let{stdout:r}=await
|
|
391
|
-
`),process.exitCode=1})}}function
|
|
390
|
+
`)}finally{await ne.rm(l,{force:!0,recursive:!0})}}async function Ke(e,t){let{stdout:r}=await es("git",t,{cwd:e});return r.trim()}async function Cn(e){if(!await R(e))return;let t=await le(e),r=new Date().toISOString(),n=await Er(e,t,r);if(!n)return;let o=await jr(e,n.proofId);await pr(e,o);let i=await le(e);i!==t&&await pt(e,{...n.proof,commit:i}),await h(N(e),{skills:[]})}async function Rn(e,t="origin"){await Ir(e,t)}async function An(e,t){let r=we(e);if(!r)throw new Error(`Unsupported agent hook: ${e}`);let n=await ts(),o=n&&typeof n=="object"&&!Array.isArray(n)&&typeof n.cwd=="string"?String(n.cwd):void 0,i=await rs(o||t||process.cwd());r==="codex"&&await nr(i,n)}async function ts(){let e=[];for await(let r of process.stdin)e.push(Buffer.isBuffer(r)?r:Buffer.from(String(r)));let t=Buffer.concat(e).toString("utf8").trim();return t?JSON.parse(t):{}}async function rs(e){return await M(e)?z(e):e}var C=new ns;C.name("skillcraft").description("Skillcraft CLI").version(jt.version);C.option("--json","machine-readable JSON output");C.command("enable").description("Enable Skillcraft in the current repository").option("--agent <name>","enable a specific agent integration (repeatable or comma-separated)",$n,[]).action(e=>k(()=>Or({agents:e.agent}))());C.command("disable").description("Disable Skillcraft in the current repository").option("--agent <name>","disable a specific agent integration (repeatable or comma-separated)",$n,[]).action(e=>k(()=>xr({agents:e.agent}))());C.command("status").description("Show repository Skillcraft status").action(k(Nr));C.command("doctor").description("Check environment and integration readiness").action(k(Tr));var In=C.command("repos").description("Manage tracked repositories");In.command("list").description("List tracked repositories").action(k(Mr));In.command("prune").description("Remove unavailable repository entries").action(k(zr));var It=C.command("progress").description("Show progress for tracked credentials");It.option("--refresh","refresh the local credential index cache before evaluating progress").action((e,t)=>{let r=t.parent?.opts()?.json?"json":"text";k(()=>Yr({outputMode:r,refreshIndex:e.refresh}))()});It.command("track <credential-id>").description("Track a credential for local progress evaluation").action(e=>k(()=>Qr(e))());It.command("untrack <credential-id>").description("Untrack a credential from local progress evaluation").action(e=>k(()=>en(e))());var fe=C.command("skills").description("Manage local skill publishing");fe.command("add <id>").description("Add a local or external skill from the registry index").action(e=>k(()=>cn(e))());fe.command("publish <owner-slug>").description("Publish a skill to the registry").action(e=>k(()=>an(e))());fe.command("validate").description("Validate local skill layout").action(k(gn));fe.command("list").description("List detected skills in the current repository").action(k(ln));fe.command("inspect <id>").description("Show detailed information for a registry skill").action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";k(()=>un(e,{outputMode:n}))()});fe.command("search [query]").description("Search the published skill index").option("--source <source>","filter to a registry source").option("--limit <n>","limit number of results",e=>Number.parseInt(e,10)).action((e,t,r)=>{let n=r.parent?.parent?.opts()?.json?"json":"text";k(()=>dn(e,{source:t.source,limit:t.limit,outputMode:n}))()});C.command("verify").description("Verify local Skillcraft proofs and trailers").action(k(yn));var $t=C.command("claim").description("Claim a credential or inspect your claims");$t.argument("[credential]","credential identifier").option("--all-repos","include tracked repositories").option("--repo <path...>","explicit repositories to include").action((e,t)=>{if(!e){k(()=>Ct())();return}k(()=>vn(e,{allRepos:t.allRepos,repo:t.repo}))()});$t.command("list").description("List your claims in the credentials repository").action(k(Ct));$t.command("status <credential>").description("Show claim status by credential identifier").action(e=>k(()=>xn(e))());var Et=C.command("loadout").description("Manage active loadouts");Et.command("use <id>").description("Activate a loadout in local context").action(e=>k(()=>bn(e))());Et.command("clear").description("Clear active loadouts").action(k(Pn));Et.command("share <id>").description("Publish local loadout to registry").action(e=>k(()=>Sn(e))());C.command("_hook <name> [repoPath] [remote]",{hidden:!0}).description("internal hook command").action((e,t,r)=>k(async()=>{e==="post-commit"&&await Cn(t||process.cwd()),(e==="pre-push"||e==="post-push")&&await Rn(t||process.cwd(),r||"origin")})());C.command("_agent-hook <agent> [repoPath]",{hidden:!0}).description("internal agent hook command").action((e,t)=>k(()=>An(e,t||process.cwd()))());C.command("_skill-used <id> [repoPath]",{hidden:!0}).description("internal skill evidence command").action((e,t)=>k(()=>fn(e,t||process.cwd()))());function k(e){return(...t)=>{Promise.resolve(e(...t)).catch(r=>{process.stderr.write(`${r instanceof Error?r.message:String(r)}
|
|
391
|
+
`),process.exitCode=1})}}function $n(e,t){return[...t,e]}C.parse(process.argv);
|
|
392
392
|
//# sourceMappingURL=index.js.map
|