@pithosai/pithosai 1.0.10 → 1.0.33

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.
@@ -2,10 +2,10 @@
2
2
  import{createRequire as e}from"node:module";let t=e(import.meta.url);var r,n,a,i,s,l,o,c={5590(e){e.exports=import("chalk").then(function(e){return e})},8703(e){e.exports=import("marked").then(function(e){return e})},1421(e){e.exports=t("node:child_process")},1455(e){e.exports=t("node:fs/promises")},6760(e){e.exports=t("node:path")},6885(e,t,r){r.a(e,async function(e,t){try{var n=r(1421),a=r(1455),i=r(6760),s=r(161),l=e([s]);async function o({text:e,showAll:t}){let r,a=e.endsWith("\n")?e:`${e}
3
3
  `;if(t||!process.stdout.isTTY)return void process.stdout.write(a);let i=(r=process.env.PAGER?.trim())||"less -RFX",s=(0,n.spawn)(i,{shell:!0,stdio:["pipe","inherit","inherit"],env:process.env});await new Promise(e=>{let t=!1,r=()=>{t||(t=!0,e())};s.once("error",e=>{process.stderr.write(`pager failed (${e.message}); printing full output to stdout
4
4
  `),process.stdout.write(a),r()}),s.once("close",()=>r());let n=s.stdin;if(!n){process.stdout.write(a),r();return}new Promise((e,t)=>{n.end(a,"utf8",r=>{r?t(r):e()})}).catch(e=>{process.stderr.write(`pager write failed (${e.message}); printing full output to stdout
5
- `),process.stdout.write(a),r()})})}async function c(){var e;let t,r,n=(t=(e=process.argv.slice(2)).includes("--show-all"),r=e.filter(e=>"--show-all"!==e),0===r.length?{ok:!1,message:"Usage: node scripts/render-markdown.js [--show-all] <path-to-file.md>"}:r.length>1?{ok:!1,message:"Expected a single markdown file path."}:{ok:!0,filePath:r[0],showAll:t});n.ok||(console.error(n.message),process.exit(1));let{filePath:l,showAll:c}=n,p=(0,i.resolve)(process.cwd(),l);try{let e=await (0,a.readFile)(p,"utf-8"),t=(0,s.o)(e);await o({text:t,showAll:c})}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}}s=(l.then?(await l)():l)[0],function(e=process.argv[1]){if(!e)return!1;let t=(0,i.basename)((0,i.resolve)(e));return"render-markdown"===t||"render-markdown.js"===t||"render-markdown.mjs"===t}()&&c(),t()}catch(e){t(e)}})},5935(e,t,r){r.d(t,{$0:()=>s,dE:()=>i});let n=RegExp("\\x1b\\[[0-9;]*m","g"),a=RegExp("\\x1b\\]8;;.*?\\x1b\\\\|\\x1b\\]8;;\\x1b\\\\","g");function i(e){return 0===e||e<32||e>=127&&e<160||8205===e||8204===e||e>=65024&&e<=65039||e>=917760&&e<=917999||e>=768&&e<=879||e>=6832&&e<=6911||e>=7616&&e<=7679||e>=8400&&e<=8447||e>=65056&&e<=65071?0:e>=127744&&e<=129791||e>=9728&&e<=10175||e>=65280&&e<=65519?2:e<4352?e>=12288&&e<=12351?2:1:e>=4352&&e<=4607||e>=11904&&e<=42191||e>=44032&&e<=55215||e>=63744&&e<=64255||e>=65040&&e<=65135||e>=131072&&e<=196605||e>=196608&&e<=262141?2:1}function s(e){let t=e.replace(a,"").replace(n,""),r=0;for(let e=0;e<t.length;){let n=t.codePointAt(e)??0;r+=i(n),e+=n>65535?2:1}return r}},161(e,t,r){r.a(e,async function(e,n){try{r.d(t,{o:()=>o});var a=r(8703),i=r(1483),s=r(6022),l=e([i,a]);[i,a]=l.then?(await l)():l;let c="\x1b]8;;",p=!1;function o(e){if("string"!=typeof e||!e.trim())return e??"";p||(a.marked.use({renderer:{heading({tokens:e,depth:t}){let r=this.parser.parseInline(e),n=i.w4.heading(r);return 1===t?`
5
+ `),process.stdout.write(a),r()})})}async function c(){var e;let t,r,n=(t=(e=process.argv.slice(2)).includes("--show-all"),r=e.filter(e=>"--show-all"!==e),0===r.length?{ok:!1,message:"Usage: node scripts/render-markdown.js [--show-all] <path-to-file.md>"}:r.length>1?{ok:!1,message:"Expected a single markdown file path."}:{ok:!0,filePath:r[0],showAll:t});n.ok||(console.error(n.message),process.exit(1));let{filePath:l,showAll:c}=n,u=(0,i.resolve)(process.cwd(),l);try{let e=await (0,a.readFile)(u,"utf-8"),t=(0,s.oq)(e);await o({text:t,showAll:c})}catch(e){console.error(`Error: ${e.message}`),process.exit(1)}}s=(l.then?(await l)():l)[0],function(e=process.argv[1]){if(!e)return!1;let t=(0,i.basename)((0,i.resolve)(e));return"render-markdown"===t||"render-markdown.js"===t||"render-markdown.mjs"===t}()&&c(),t()}catch(e){t(e)}})},5935(e,t,r){r.d(t,{$0:()=>s,dE:()=>i});let n=RegExp("\\x1b\\[[0-9;]*m","g"),a=RegExp("\\x1b\\]8;;.*?\\x1b\\\\|\\x1b\\]8;;\\x1b\\\\","g");function i(e){return 0===e||e<32||e>=127&&e<160||8205===e||8204===e||e>=65024&&e<=65039||e>=917760&&e<=917999||e>=768&&e<=879||e>=6832&&e<=6911||e>=7616&&e<=7679||e>=8400&&e<=8447||e>=65056&&e<=65071?0:e>=127744&&e<=129791||e>=9728&&e<=10175||e>=65280&&e<=65519?2:e<4352?e>=12288&&e<=12351?2:1:e>=4352&&e<=4607||e>=11904&&e<=42191||e>=44032&&e<=55215||e>=63744&&e<=64255||e>=65040&&e<=65135||e>=131072&&e<=196605||e>=196608&&e<=262141?2:1}function s(e){let t=e.replace(a,"").replace(n,""),r=0;for(let e=0;e<t.length;){let n=t.codePointAt(e)??0;r+=i(n),e+=n>65535?2:1}return r}},161(e,t,r){r.a(e,async function(e,n){try{r.d(t,{oq:()=>c});var a=r(8703),i=r(1483),s=r(6022),l=e([i,a]);[i,a]=l.then?(await l)():l;let u="\x1b]8;;",p=!1;function o(e){let t=String(e??"");return!(!/^-/.test(t)&&!/\|/.test(t)||/[A-Za-z0-9]/.test(t))&&/-/.test(t)}function c(e){if("string"!=typeof e||!e.trim())return e??"";p||(a.marked.use({renderer:{heading({tokens:e,depth:t}){let r=this.parser.parseInline(e),n=i.w4.heading(r);return 1===t?`
6
6
  ${n}
7
7
  `:`${n}
8
- `},strong({tokens:e}){return i.w4.strong(this.parser.parseInline(e))},em({tokens:e}){return i.w4.muted(this.parser.parseInline(e))},codespan:({text:e})=>i.w4.muted(e),link({tokens:e,href:t}){var r,n;return r=this.parser.parseInline(e),n=t??"",n?.trim()?(0,i.D8)()?`${c}${n}\x1b\\${r}${c}\x1b\\`:`${r} (${n})`:r},blockquote({tokens:e}){let t=this.parser.parse(e).trimEnd().split("\n").map(e=>i.w4.muted("│ ")+e).join("\n");return`
8
+ `},strong({tokens:e}){return i.w4.strong(this.parser.parseInline(e))},em({tokens:e}){return i.w4.muted(this.parser.parseInline(e))},codespan:({text:e})=>i.w4.muted(e),link({tokens:e,href:t}){var r,n;return r=this.parser.parseInline(e),n=t??"",n?.trim()?(0,i.D8)()?`${u}${n}\x1b\\${r}${u}\x1b\\`:`${r} (${n})`:r},blockquote({tokens:e}){let t=this.parser.parse(e).trimEnd().split("\n").map(e=>i.w4.muted("│ ")+e).join("\n");return`
9
9
  ${t}
10
10
 
11
11
  `},hr(){let e=Math.min(process.stdout?.columns??80,80)-2;return"\n"+i.w4.muted("─".repeat(Math.max(0,e)))+"\n"},code({text:e,lang:t}){let r=(t??"").trim().toLowerCase(),n=/^(bash|sh|shell|zsh)$/.test(r),a=/^(javascript|js|typescript|ts|python|py|java|rust|rs|c|cpp|c\+\+)$/.test(r),s=n?i.w4.command:a?i.w4.info:i.w4.muted,l=t?i.w4.muted(`[${t}] `):"",o=e.replace(/\n$/,"").split("\n").map(e=>s(e)).join("\n");return`
@@ -16,8 +16,8 @@ ${r}
16
16
 
17
17
  `},listitem({tokens:e,task:t,checked:r}){return(t?i.w4[r?"success":"muted"](r?"[x] ":"[ ] "):"")+this.parser.parse(e)},paragraph({tokens:e}){return this.parser.parseInline(e)+"\n\n"},table(e){let t=e?.header??[],r=e?.rows??[],n=e?.align,a=e=>e?null!=e.tokens?this.parser.parseInline(e.tokens):"string"==typeof e.text?e.text:String(e):"";if(!Array.isArray(t)||!Array.isArray(r)||0===t.length){let e=[t,...r].filter(Array.isArray).map(e=>e.map(a).join(" | ")).join("\n");return e?`
18
18
  ${i.w4.muted(e)}
19
- `:"\n"}let l=t.length,o=t.map(a),c={left:"left",center:"center",right:"right"},p=o.map((e,t)=>({key:String(t),header:i.w4.heading(e),align:c[n?.[t]]??"left"})),u=r.map(e=>{let t={},r=Array.isArray(e)?e:[];for(let e=0;e<l;e+=1)t[String(e)]=i.w4.muted(a(r[e]));return t}),h=(0,s.b)({columns:p,rows:u,padding:1,border:"unicode"});return`
20
- ${h}
21
- `},tablerow:({text:e})=>e,tablecell({tokens:e}){return this.parser.parseInline(e)},br:()=>"\n",text(e){return e.tokens&&e.tokens.length>0?this.parser.parseInline(e.tokens):e.text??""},html:()=>"",checkbox:({checked:e})=>i.w4[e?"success":"muted"](e?"[x]":"[ ]")+" "}}),a.marked.setOptions({gfm:!0,breaks:!0}),p=!0);let t="string"!=typeof e?"":e.trim().replace(/\r\n/g,"\n").replace(/\r/g,"\n");try{let e=a.marked.parse(t,{async:!1});return"string"==typeof e?e:String(e)}catch{return e}}n()}catch(e){n(e)}})},9005(e,t,r){r.d(t,{A:()=>n});let n={accent:"#FF5A2D",accentBright:"#FF7A3D",accentDim:"#D14A22",info:"#FF8A5B",success:"#2FBF71",warn:"#FFB020",error:"#E23D2D",muted:"#8B7F77"}},6022(e,t,r){r.d(t,{b:()=>i});var n=r(5935);function a(e,t){return t<=0?"":e.repeat(t)}function i(e){let t=e.rows.map(e=>{let t={};for(let[r,n]of Object.entries(e))t[r]=null==n?"":String(n);return t}),r=e.border??"unicode";if("none"===r){let r=e.columns,n=[r.map(e=>e.header).join(" | "),...t.map(e=>r.map(t=>e[t.key]??"").join(" | "))];return`${n.join("\n")}
22
- `}let i=Math.max(0,e.padding??1),s=e.columns,l=s.map(e=>({headerW:(0,n.$0)(e.header),cellW:Math.max(0,...t.map(t=>(0,n.$0)(t[e.key]??"")))})),o=s.map((e,t)=>{let r=l[t],n=Math.max(r?.headerW??0,r?.cellW??0)+2*i,a=e.maxWidth?Math.min(n,e.maxWidth):n;return Math.max(e.minWidth??3,a)}),c=function(e){if(null!=e&&Number.isFinite(e)&&!(e<=0))return Math.floor(e)}(e.width),p=s.length+1,u=o.reduce((e,t)=>e+t,0)+p,h=e=>Math.max((l[e]?.headerW??0)+2*i,(l[e]?.cellW??0)+2*i,3),m=s.map((e,t)=>Math.max(e.minWidth??3,h(t))),d=s.map((e,t)=>h(t));if(c&&u>c){let e=u-c,t=s.map((e,t)=>({i:t,w:o[t]??0})).filter(({i:e})=>!!s[e]?.flex).sort((e,t)=>t.w-e.w).map(e=>e.i),r=s.map((e,t)=>({i:t,w:o[t]??0})).filter(({i:e})=>!s[e]?.flex).sort((e,t)=>t.w-e.w).map(e=>e.i),n=(t,r)=>{for(;e>0;){let n=!1;for(let a of t)if(!((o[a]??0)<=(r[a]??0))&&(o[a]=(o[a]??0)-1,n=!0,(e-=1)<=0))break;if(!n)break}};n(t,m),n(t,d),n(r,m),n(r,d)}if(c){let e=s.length+1,t=c-(o.reduce((e,t)=>e+t,0)+e);if(t>0){let e=s.map((e,t)=>({c:e,i:t})).filter(({c:e})=>!!e.flex).map(({i:e})=>e);if(e.length>0){let r=s.map(e=>"number"==typeof e.maxWidth&&e.maxWidth>0?Math.floor(e.maxWidth):1/0);for(;t>0;){let n=!1;for(let a of e)if(!((o[a]??0)>=(r[a]??1/0))&&(o[a]=(o[a]??0)+1,n=!0,(t-=1)<=0))break;if(!n)break}}}}let f="ascii"===r?{tl:"+",tr:"+",bl:"+",br:"+",h:"-",v:"|",t:"+",ml:"+",m:"+",mr:"+",b:"+"}:{tl:"┌",tr:"┐",bl:"└",br:"┘",h:"─",v:"│",t:"┬",ml:"├",m:"┼",mr:"┤",b:"┴"},g=(e,t,r)=>`${e}${o.map(e=>a(f.h,e)).join(t)}${r}`,w=e=>Math.max(1,o[e]-2*i),x=a(" ",i),b=(e,t=!1)=>{let r=s.map(r=>t?r.header:e[r.key]??"").map((e,t)=>(function(e,t){if(t<=0)return[e];let r=[];for(let t=0;t<e.length;){if("\x1b"===e[t]){if("["===e[t+1]){let n=t+2;for(;n<e.length;){let t=e[n];if("m"===t)break;if(t&&t>="0"&&t<="9"||";"===t){n+=1;continue}break}if("m"===e[n]){r.push({kind:"ansi",value:e.slice(t,n+1)}),t=n+1;continue}}if("]"===e[t+1]&&"8;;"===e.slice(t+2,t+5)){let n=e.indexOf("\x1b\\",t+5);if(n>=0){r.push({kind:"ansi",value:e.slice(t,n+2)}),t=n+2;continue}}}let a=e.codePointAt(t)??0,i=String.fromCodePoint(a);r.push({kind:"char",value:i,w:(0,n.dE)(a)}),t+=a>65535?2:1}let a=r.findIndex(e=>"char"===e.kind);if(a<0)return[e];let i=-1;for(let e=r.length-1;e>=0;e-=1)if(r[e]?.kind==="char"){i=e;break}let s=r.slice(0,a).filter(e=>"ansi"===e.kind).map(e=>e.value).join(""),l=r.slice(i+1).filter(e=>"ansi"===e.kind).map(e=>e.value).join(""),o=r.slice(a,i+1),c=[],p=e=>" "===e||" "===e||"/"===e||"-"===e||"_"===e||"."===e,u=e=>" "===e||" "===e,h=[],m=0,d=null,f=e=>(e??h).map(e=>e.value).join(""),g=e=>{let t=e.replace(/\s+$/,"");0!==t.trim().length&&c.push(t)},w=e=>{if(0===h.length)return;if(null==e||e<=0){g(f()),h.length=0,m=0,d=null;return}let t=h.slice(0,e),r=h.slice(e);for(g(f(t));r.length>0&&r[0]?.kind==="char"&&u(r[0].value);)r.shift();h.length=0,h.push(...r),m=r.filter(e=>"char"===e.kind).reduce((e,t)=>e+(t.w??1),0),d=null};for(let e of o){if("ansi"===e.kind){h.push(e);continue}let r=e.value,n=e.w??1;if("\n"===r||"\r"===r){w(h.length);continue}m+n>t&&m>0&&w(d),h.push(e),m+=n,p(r)&&(d=h.length)}return(w(h.length),c.length)?s||l?c.map(e=>e?`${s}${e}${l}`:e):c:[""]})(e,w(t))),i=Math.max(...r.map(e=>e.length)),l=[];for(let e=0;e<i;e+=1){let t=r.map((t,r)=>{let i=function(e,t,r){let i=(0,n.$0)(e);if(i>=t)return e;let s=t-i;if("right"===r)return`${a(" ",s)}${e}`;if("center"===r){let t=Math.floor(s/2),r=s-t;return`${a(" ",t)}${e}${a(" ",r)}`}return`${e}${a(" ",s)}`}(t[e]??"",w(r),s[r]?.align??"left");return`${x}${i}${x}`});l.push(`${f.v}${t.join(f.v)}${f.v}`)}return l},k=[];for(let e of(k.push(g(f.tl,f.t,f.tr)),k.push(...b({},!0)),k.push(g(f.ml,f.m,f.mr)),t))k.push(...b(e,!1));return k.push(g(f.bl,f.b,f.br)),`${k.join("\n")}
23
- `}},1483(e,t,r){r.a(e,async function(e,n){try{let l,o,c,p,u,h,m,d,f,g;r.d(t,{D8:()=>k,w4:()=>b});var a=r(8691),i=r(9005),s=e([a]);a=(s.then?(await s)():s)[0];let w="string"==typeof process.env.FORCE_COLOR&&process.env.FORCE_COLOR.trim().length>0&&"0"!==process.env.FORCE_COLOR.trim(),x=process.env.NO_COLOR&&!w?new a.g({level:0}):a.m,b={accent:(l=i.A.accent,x.hex(l)),accentBright:(o=i.A.accentBright,x.hex(o)),accentDim:(c=i.A.accentDim,x.hex(c)),info:(p=i.A.info,x.hex(p)),success:(u=i.A.success,x.hex(u)),warn:(h=i.A.warn,x.hex(h)),error:(m=i.A.error,x.hex(m)),muted:(d=i.A.muted,x.hex(d)),heading:x.bold.hex(i.A.accent),strong:x.bold.hex(i.A.accentBright),command:(f=i.A.accentBright,x.hex(f)),option:(g=i.A.warn,x.hex(g))},k=()=>x.level>0;n()}catch(e){n(e)}})},8691(e,t,r){r.a(e,async function(e,n){try{r.d(t,{g:()=>a.Chalk,m:()=>s});var a=r(5590),i=e([a]);a=(i.then?(await i)():i)[0];let s=function(){if("function"==typeof a.default.hex)return a.default;let e=a.default.default;return e&&"function"==typeof e.hex?e:a.default}();n()}catch(e){n(e)}})}},p={};function u(e){var t=p[e];if(void 0!==t)return t.exports;var r=p[e]={exports:{}};return c[e](r,r.exports,u),r.exports}n=(r="function"==typeof Symbol)?Symbol("rspack queues"):"__rspack_queues",a=u.aE=r?Symbol("rspack exports"):"__webpack_exports__",i=r?Symbol("rspack error"):"__rspack_error",s=r?Symbol("rspack done"):"__rspack_done",l=u.zS=r?Symbol("rspack defer"):"__rspack_defer",o=e=>{e&&e.d<1&&(e.d=1,e.forEach(e=>e.r--),e.forEach(e=>e.r--?e.r++:e()))},u.a=(e,t,r)=>{r&&((c=[]).d=-1);var c,h,m,d,f=new Set,g=e.exports,w=new Promise((e,t)=>{d=t,m=e});w[a]=g,w[n]=e=>{c&&e(c),f.forEach(e),w.catch(()=>{})},e.exports=w,t(e=>{h=e.map(e=>{if(null!==e&&"object"==typeof e){if(!e[n]&&e[l]){var t=e[l];if(!t.some(e=>{var t=p[e];return!t||!1===t[s]}))return e;var r=e;e={then(e){Promise.all(t.map(u)).then(()=>e(r))}}}if(e[n])return e;if(e.then){var c=[];c.d=0,e.then(e=>{h[a]=e,o(c)},e=>{h[i]=e,o(c)});var h={};return h[l]=!1,h[n]=e=>e(c),h}}var m={};return m[n]=()=>{},m[a]=e,m});var t,r=()=>h.map(e=>{if(e[l])return e;if(e[i])throw e[i];return e[a]}),m=new Promise(e=>{(t=()=>e(r)).r=0;var a=e=>e!==c&&!f.has(e)&&(f.add(e),e&&!e.d&&(t.r++,e.push(t)));h.map(e=>e[l]||e[n](a))});return t.r?m:r()},e=>(e?d(w[i]=e):m(g),o(c),w[s]=!0)),c&&c.d<0&&(c.d=0)},u.d=(e,t)=>{for(var r in t)u.o(t,r)&&!u.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},u.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),u.rv=()=>"1.7.6",u.ruid="bundler=rspack@1.7.6",u(6885);
19
+ `:"\n"}let l=t.length,o=t.map(a),c={left:"left",center:"center",right:"right"},u=o.map((e,t)=>({key:String(t),header:i.w4.heading(e),align:c[n?.[t]]??"left"})),p=r.map(e=>{let t={},r=Array.isArray(e)?e:[];for(let e=0;e<l;e+=1)t[String(e)]=i.w4.muted(a(r[e]));return t}),h=process.stdout?.columns??80,m=u.map(e=>({...e,flex:!0})),f=(0,s.b)({columns:m,rows:p,width:h,padding:1,border:"unicode"});return`
20
+ ${f}
21
+ `},tablerow:({text:e})=>e,tablecell({tokens:e}){return this.parser.parseInline(e)},br:()=>"\n",text(e){return e.tokens&&e.tokens.length>0?this.parser.parseInline(e.tokens):e.text??""},html:()=>"",checkbox:({checked:e})=>i.w4[e?"success":"muted"](e?"[x]":"[ ]")+" "}}),a.marked.setOptions({gfm:!0,breaks:!0}),p=!0);let t=function(e){if("string"!=typeof e)return"";let t=e.trim().replace(/\r\n/g,"\n").replace(/\r/g,"\n").replace(/^(\s*\d+\.)\n(?!\s*\d+\.)(\S[^\n]*)/gm,"$1 $2");var r=function(e){let t=String(e).split("\n"),r=[],n=!1;for(let e=0;e<t.length;e++){let a=t[e];if(/^\s*(```|~~~)/.test(a)){n=!n,r.push(a);continue}if(n){r.push(a);continue}for(;e+1<t.length&&function(e){let t=String(e??"").replace(/```[\s\S]*?```/g,""),r=t.match(/`/g);if(r&&r.length%2==1)return!0;let n=t.match(/\*\*/g);if(n&&n.length%2==1)return!0;let a=t.replace(/\*\*/g,"").replace(/^[ \t]*\*[ \t]/gm,"").match(/\*/g);return!!a&&a.length%2==1}(a);){let r=t[e+=1];if(""===r)continue;let n=/[`*_({\[]$/u.test(a)||/^[`*_)\]]/u.test(r)||/\d$/u.test(a)&&/^\d/u.test(r)?"":" ";a=`${a}${n}${r}`}r.push(a)}return r.join("\n")}(t);let n="",a=r;for(;a!==n;)n=a,a=a.replace(/^(\|[^\n]*?)\n(?!\s*\|)(\S[^\n]*\|[^\n]*)$/gm,(e,t,r)=>{let n=String(t).replace(/\s+$/u,""),a=String(r).replace(/^\s+/u,""),i=o(n)||o(a)?"":" ";return`${n}${i}${a}`});return a}(e);try{let e=a.marked.parse(t,{async:!1});return"string"==typeof e?e:String(e)}catch{return e}}n()}catch(e){n(e)}})},9005(e,t,r){r.d(t,{A:()=>n});let n={accent:"#FF5A2D",accentBright:"#FF7A3D",accentDim:"#D14A22",info:"#FF8A5B",success:"#2FBF71",warn:"#FFB020",error:"#E23D2D",muted:"#8B7F77"}},6022(e,t,r){r.d(t,{b:()=>i});var n=r(5935);function a(e,t){return t<=0?"":e.repeat(t)}function i(e){let t=e.rows.map(e=>{let t={};for(let[r,n]of Object.entries(e))t[r]=null==n?"":String(n);return t}),r=e.border??"unicode";if("none"===r){let r=e.columns,n=[r.map(e=>e.header).join(" | "),...t.map(e=>r.map(t=>e[t.key]??"").join(" | "))];return`${n.join("\n")}
22
+ `}let i=Math.max(0,e.padding??1),s=e.columns,l=s.map(e=>({headerW:(0,n.$0)(e.header),cellW:Math.max(0,...t.map(t=>(0,n.$0)(t[e.key]??"")))})),o=s.map((e,t)=>{let r=l[t],n=Math.max(r?.headerW??0,r?.cellW??0)+2*i,a=e.maxWidth?Math.min(n,e.maxWidth):n;return Math.max(e.minWidth??3,a)}),c=function(e){if(null!=e&&Number.isFinite(e)&&!(e<=0))return Math.floor(e)}(e.width),u=s.length+1,p=o.reduce((e,t)=>e+t,0)+u,h=e=>Math.max((l[e]?.headerW??0)+2*i,(l[e]?.cellW??0)+2*i,3),m=s.map((e,t)=>Math.max(e.minWidth??3,h(t))),f=s.map((e,t)=>h(t));if(c&&p>c){let e=p-c,t=s.map((e,t)=>({i:t,w:o[t]??0})).filter(({i:e})=>!!s[e]?.flex).sort((e,t)=>t.w-e.w).map(e=>e.i),r=s.map((e,t)=>({i:t,w:o[t]??0})).filter(({i:e})=>!s[e]?.flex).sort((e,t)=>t.w-e.w).map(e=>e.i),n=(t,r)=>{for(;e>0;){let n=!1;for(let a of t)if(!((o[a]??0)<=(r[a]??0))&&(o[a]=(o[a]??0)-1,n=!0,(e-=1)<=0))break;if(!n)break}};if(n(t,m),n(t,f),n(r,m),n(r,f),e>0){let e=s.map((e,t)=>Math.max(3,e.minWidth??0));n(t,e),n(r,e)}}if(c){let e=s.length+1,t=c-(o.reduce((e,t)=>e+t,0)+e);if(t>0){let e=s.map((e,t)=>({c:e,i:t})).filter(({c:e})=>!!e.flex).map(({i:e})=>e);if(e.length>0){let r=s.map(e=>"number"==typeof e.maxWidth&&e.maxWidth>0?Math.floor(e.maxWidth):1/0);for(;t>0;){let n=!1;for(let a of e)if(!((o[a]??0)>=(r[a]??1/0))&&(o[a]=(o[a]??0)+1,n=!0,(t-=1)<=0))break;if(!n)break}}}}let d="ascii"===r?{tl:"+",tr:"+",bl:"+",br:"+",h:"-",v:"|",t:"+",ml:"+",m:"+",mr:"+",b:"+"}:{tl:"┌",tr:"┐",bl:"└",br:"┘",h:"─",v:"│",t:"┬",ml:"├",m:"┼",mr:"┤",b:"┴"},g=(e,t,r)=>`${e}${o.map(e=>a(d.h,e)).join(t)}${r}`,x=e=>Math.max(1,o[e]-2*i),w=a(" ",i),$=(e,t=!1)=>{let r=s.map(r=>t?r.header:e[r.key]??"").map((e,t)=>(function(e,t){if(t<=0)return[e];let r=[];for(let t=0;t<e.length;){if("\x1b"===e[t]){if("["===e[t+1]){let n=t+2;for(;n<e.length;){let t=e[n];if("m"===t)break;if(t&&t>="0"&&t<="9"||";"===t){n+=1;continue}break}if("m"===e[n]){r.push({kind:"ansi",value:e.slice(t,n+1)}),t=n+1;continue}}if("]"===e[t+1]&&"8;;"===e.slice(t+2,t+5)){let n=e.indexOf("\x1b\\",t+5);if(n>=0){r.push({kind:"ansi",value:e.slice(t,n+2)}),t=n+2;continue}}}let a=e.codePointAt(t)??0,i=String.fromCodePoint(a);r.push({kind:"char",value:i,w:(0,n.dE)(a)}),t+=a>65535?2:1}let a=r.findIndex(e=>"char"===e.kind);if(a<0)return[e];let i=-1;for(let e=r.length-1;e>=0;e-=1)if(r[e]?.kind==="char"){i=e;break}let s=r.slice(0,a).filter(e=>"ansi"===e.kind).map(e=>e.value).join(""),l=r.slice(i+1).filter(e=>"ansi"===e.kind).map(e=>e.value).join(""),o=r.slice(a,i+1),c=[],u=e=>" "===e||" "===e||"/"===e||"-"===e||"_"===e||"."===e,p=e=>" "===e||" "===e,h=[],m=0,f=null,d=e=>(e??h).map(e=>e.value).join(""),g=e=>{let t=e.replace(/\s+$/,"");0!==t.trim().length&&c.push(t)},x=e=>{if(0===h.length)return;if(null==e||e<=0){g(d()),h.length=0,m=0,f=null;return}let t=h.slice(0,e),r=h.slice(e);for(g(d(t));r.length>0&&r[0]?.kind==="char"&&p(r[0].value);)r.shift();h.length=0,h.push(...r),m=r.filter(e=>"char"===e.kind).reduce((e,t)=>e+(t.w??1),0),f=null};for(let e of o){if("ansi"===e.kind){h.push(e);continue}let r=e.value,n=e.w??1;if("\n"===r||"\r"===r){x(h.length);continue}m+n>t&&m>0&&x(f),h.push(e),m+=n,u(r)&&(f=h.length)}return(x(h.length),c.length)?s||l?c.map(e=>e?`${s}${e}${l}`:e):c:[""]})(e,x(t))),i=Math.max(...r.map(e=>e.length)),l=[];for(let e=0;e<i;e+=1){let t=r.map((t,r)=>{let i=function(e,t,r){let i=(0,n.$0)(e);if(i>=t)return e;let s=t-i;if("right"===r)return`${a(" ",s)}${e}`;if("center"===r){let t=Math.floor(s/2),r=s-t;return`${a(" ",t)}${e}${a(" ",r)}`}return`${e}${a(" ",s)}`}(t[e]??"",x(r),s[r]?.align??"left");return`${w}${i}${w}`});l.push(`${d.v}${t.join(d.v)}${d.v}`)}return l},b=[];for(let e of(b.push(g(d.tl,d.t,d.tr)),b.push(...$({},!0)),b.push(g(d.ml,d.m,d.mr)),t))b.push(...$(e,!1));return b.push(g(d.bl,d.b,d.br)),`${b.join("\n")}
23
+ `}},1483(e,t,r){r.a(e,async function(e,n){try{let l,o,c,u,p,h,m,f,d,g;r.d(t,{D8:()=>b,w4:()=>$});var a=r(8691),i=r(9005),s=e([a]);a=(s.then?(await s)():s)[0];let x="string"==typeof process.env.FORCE_COLOR&&process.env.FORCE_COLOR.trim().length>0&&"0"!==process.env.FORCE_COLOR.trim(),w=process.env.NO_COLOR&&!x?new a.g({level:0}):a.m,$={accent:(l=i.A.accent,w.hex(l)),accentBright:(o=i.A.accentBright,w.hex(o)),accentDim:(c=i.A.accentDim,w.hex(c)),info:(u=i.A.info,w.hex(u)),success:(p=i.A.success,w.hex(p)),warn:(h=i.A.warn,w.hex(h)),error:(m=i.A.error,w.hex(m)),muted:(f=i.A.muted,w.hex(f)),heading:w.bold.hex(i.A.accent),strong:w.bold.hex(i.A.accentBright),command:(d=i.A.accentBright,w.hex(d)),option:(g=i.A.warn,w.hex(g))},b=()=>w.level>0;n()}catch(e){n(e)}})},8691(e,t,r){r.a(e,async function(e,n){try{r.d(t,{g:()=>a.Chalk,m:()=>s});var a=r(5590),i=e([a]);a=(i.then?(await i)():i)[0];let s=function(){if("function"==typeof a.default.hex)return a.default;let e=a.default.default;return e&&"function"==typeof e.hex?e:a.default}();n()}catch(e){n(e)}})}},u={};function p(e){var t=u[e];if(void 0!==t)return t.exports;var r=u[e]={exports:{}};return c[e](r,r.exports,p),r.exports}n=(r="function"==typeof Symbol)?Symbol("rspack queues"):"__rspack_queues",a=p.aE=r?Symbol("rspack exports"):"__webpack_exports__",i=r?Symbol("rspack error"):"__rspack_error",s=r?Symbol("rspack done"):"__rspack_done",l=p.zS=r?Symbol("rspack defer"):"__rspack_defer",o=e=>{e&&e.d<1&&(e.d=1,e.forEach(e=>e.r--),e.forEach(e=>e.r--?e.r++:e()))},p.a=(e,t,r)=>{r&&((c=[]).d=-1);var c,h,m,f,d=new Set,g=e.exports,x=new Promise((e,t)=>{f=t,m=e});x[a]=g,x[n]=e=>{c&&e(c),d.forEach(e),x.catch(()=>{})},e.exports=x,t(e=>{h=e.map(e=>{if(null!==e&&"object"==typeof e){if(!e[n]&&e[l]){var t=e[l];if(!t.some(e=>{var t=u[e];return!t||!1===t[s]}))return e;var r=e;e={then(e){Promise.all(t.map(p)).then(()=>e(r))}}}if(e[n])return e;if(e.then){var c=[];c.d=0,e.then(e=>{h[a]=e,o(c)},e=>{h[i]=e,o(c)});var h={};return h[l]=!1,h[n]=e=>e(c),h}}var m={};return m[n]=()=>{},m[a]=e,m});var t,r=()=>h.map(e=>{if(e[l])return e;if(e[i])throw e[i];return e[a]}),m=new Promise(e=>{(t=()=>e(r)).r=0;var a=e=>e!==c&&!d.has(e)&&(d.add(e),e&&!e.d&&(t.r++,e.push(t)));h.map(e=>e[l]||e[n](a))});return t.r?m:r()},e=>(e?f(x[i]=e):m(g),o(c),x[s]=!0)),c&&c.d<0&&(c.d=0)},p.d=(e,t)=>{for(var r in t)p.o(t,r)&&!p.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},p.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),p.rv=()=>"1.7.6",p.ruid="bundler=rspack@1.7.6",p(6885);
@@ -0,0 +1,140 @@
1
+ # Install kRouter (`@sifxprime/krouter`)
2
+
3
+ Pithosai talks to **Kiro provider** models through a local [kRouter](https://github.com/sifxprime/krouter) gateway (`@sifxprime/krouter` on npm). Krouter is **on by default** (`http://localhost:20128/v1`). The gateway must be running for `--model krouter-*` requests to succeed. Set `KROUTER_DISABLED=1` to hide curated keys and skip Krouter in the env-walk.
4
+
5
+ Official project docs: [github.com/sifxprime/krouter](https://github.com/sifxprime/krouter), [npmjs.com/package/@sifxprime/krouter](https://www.npmjs.com/package/@sifxprime/krouter), [krouter.kodelyht.com](https://krouter.kodelyht.com).
6
+
7
+ Pithosai CLI keys and model pick guide: [`src/models/krouter.README.md`](../src/models/krouter.README.md).
8
+
9
+ ## Requirements
10
+
11
+ - **Node.js ≥ 20** (same floor as pithosai)
12
+ - A provider in the kRouter dashboard (Kiro OAuth for curated `kr/glm-5*`, `kr/minimax-*`, `kr/deepseek-*` keys)
13
+
14
+ ## Install and start
15
+
16
+ ```bash
17
+ # Pin 0.5.118: @latest (0.5.143) crashes — npm tarball omits app/server-peer-patch.js
18
+ npm install -g @sifxprime/krouter@0.5.118
19
+
20
+ # Background (system tray); dashboard at http://localhost:20128/dashboard
21
+ # --skip-update prevents the CLI from upgrading back to 0.5.143
22
+ krouter -t --skip-update
23
+
24
+ # Or foreground with live logs
25
+ krouter --skip-update
26
+ ```
27
+
28
+ Default listen address is `http://127.0.0.1:20128`. OpenAI-compatible API: `http://localhost:20128/v1`.
29
+
30
+ | Flag | Meaning |
31
+ |------|---------|
32
+ | `-t`, `--tray` | Run in the system tray |
33
+ | `-p`, `--port <port>` | Port (default `20128`) |
34
+ | `-l`, `--log` | Show server logs (hidden by default) |
35
+ | `--skip-update` | Skip the auto-update check |
36
+
37
+ ```bash
38
+ krouter --help
39
+ krouter --version
40
+ ```
41
+
42
+ ### Other install paths
43
+
44
+ **From source**
45
+
46
+ ```bash
47
+ git clone https://github.com/sifxprime/krouter.git
48
+ cd krouter
49
+ npm install
50
+ npm run dev
51
+ ```
52
+
53
+ **Docker**
54
+
55
+ ```bash
56
+ docker run -d \
57
+ -p 20128:20128 \
58
+ -v "$HOME/.krouter:/app/data" \
59
+ --name krouter \
60
+ sifxprime/krouter:latest
61
+ ```
62
+
63
+ **PM2**
64
+
65
+ ```bash
66
+ npm install -g @sifxprime/krouter pm2
67
+ pm2 start krouter --name krouter -- --skip-update
68
+ pm2 save
69
+ pm2 startup
70
+ ```
71
+
72
+ **VPS (bind all interfaces)**
73
+
74
+ ```bash
75
+ npm install -g @sifxprime/krouter
76
+ export PORT=20128 HOSTNAME=0.0.0.0
77
+ krouter --skip-update
78
+ ```
79
+
80
+ Put HTTPS in front (Nginx / Caddy / Cloudflare Tunnel). Set `REQUIRE_API_KEY=true` if the `/v1` endpoint is reachable from the network.
81
+
82
+ ## Add a provider
83
+
84
+ 1. Open [http://localhost:20128/dashboard](http://localhost:20128/dashboard).
85
+ 2. **Providers → Add**. For pithosai curated `kr/…` keys, add **Kiro** and complete OAuth.
86
+ 3. **Test Connection**.
87
+
88
+ Dashboard combos (`RD` / `ARCH` / `PM` / `QA`) are configured here. Pithosai maps them to `--model krouter-rd` / `krouter-arch` / `krouter-pm` / `krouter-qa`. Other `/v1/models` ids use `--model krouter/<id>`.
89
+
90
+ ## Point pithosai at kRouter
91
+
92
+ ```bash
93
+ # optional: override the default http://localhost:20128/v1
94
+ export KROUTER_API_BASE=http://localhost:20128/v1
95
+ # opt out: export KROUTER_DISABLED=1
96
+ # optional, if the dashboard requires a key:
97
+ # export KROUTER_API_KEY=sk-krouter-...
98
+
99
+ pithosai --no-interactive --model krouter-rd "Add tests for this file"
100
+ pithosai --no-interactive --model krouter/cu/default "Summarize this module"
101
+ ```
102
+
103
+ Legacy aliases `KIRO_API_BASE` / `KIRO_DISABLED` / `KIRO_API_KEY` still work.
104
+
105
+ Local kRouter with `REQUIRE_API_KEY` unset does not require a key. Pithosai then sends the dummy key `krouter`. If you created a key in **Dashboard → API Keys**, set `KROUTER_API_KEY` to that value.
106
+
107
+ | Pithosai env | Role |
108
+ |--------------|------|
109
+ | `KROUTER_API_BASE` | OpenAI-compatible base URL (default `http://localhost:20128/v1`) |
110
+ | `KROUTER_DISABLED` | `1` / `true` / `yes` to hide curated keys and skip Krouter in the env-walk |
111
+ | `KROUTER_API_KEY` | Bearer token when kRouter auth is on |
112
+
113
+ kRouter process env (`PORT`, `HOSTNAME`, `DATA_DIR`, `REQUIRE_API_KEY`, …) is documented in the [upstream README](https://github.com/sifxprime/krouter#environment-variables).
114
+
115
+ ## Check the gateway
116
+
117
+ ```bash
118
+ curl -sS http://localhost:20128/v1/models
119
+ ```
120
+
121
+ You should see configured providers and combos. If this fails, pithosai `--model krouter-*` will fail the same way.
122
+
123
+ ## Uninstall kRouter
124
+
125
+ ```bash
126
+ # Stop first: tray → Quit, or `pkill -f krouter` / `docker stop krouter`
127
+ npm uninstall -g @sifxprime/krouter
128
+ rm -rf ~/.krouter # optional: wipe kRouter data
129
+ ```
130
+
131
+ ## Troubleshooting
132
+
133
+ | Symptom | What to try |
134
+ |---------|-------------|
135
+ | Connection refused on `20128` | Start `krouter` or `krouter -t`; confirm `PORT` |
136
+ | `No active credentials for provider` | Reconnect Kiro (or another provider) in the dashboard |
137
+ | 401 from `/v1` | Set `KROUTER_API_KEY` to a Dashboard API key, or turn off `REQUIRE_API_KEY` |
138
+ | Curated `kr/…` missing from `/v1/models` | Add the provider in the dashboard; use `krouter/<id>` for whatever `/v1/models` lists; combos `RD`/`ARCH`/`PM`/`QA` are dashboard names |
139
+
140
+ Full upstream troubleshooting: [krouter.kodelyht.com](https://krouter.kodelyht.com).
@@ -0,0 +1,335 @@
1
+ # Pithosai hook system
2
+
3
+ Hooks run custom logic at agent lifecycle points: debugging, security, observability, and JSON command hooks (including the shipped Git AI CLI).
4
+
5
+ There are two layers:
6
+
7
+ 1. **In-process `HookManager`** — JavaScript handlers registered on pithos core hook types. Built-in plugins and CLI debug/security presets use this.
8
+ 2. **JSON command hooks** — `*.json` files that spawn a `command` (or call a registered in-process adapter). Git AI is **not** a core in-process adapter; it is an external CLI spawned from bundled/user JSON.
9
+
10
+ JS constants live on `HookType` in `src/agent/hooks/index.js` (for example `HookType.BEFORE_TOOL_EXECUTE`). Values and JSON `hookType` fields are **camelCase** (`beforeToolExecute`). CLI `hooks test` / `hooks register` require those camelCase values, not `BEFORE_TOOL_EXECUTE`.
11
+
12
+ ## Hook types
13
+
14
+ | Value | `HookType` constant | When it fires |
15
+ |-------|---------------------|---------------|
16
+ | `beforeSystemPromptBuild` | `BEFORE_SYSTEM_PROMPT_BUILD` | Before the system prompt is assembled |
17
+ | `afterSystemPromptBuild` | `AFTER_SYSTEM_PROMPT_BUILD` | After the system prompt is assembled |
18
+ | `beforeModelCall` | `BEFORE_MODEL_CALL` | Assistant `message_start` |
19
+ | `afterModelCall` | `AFTER_MODEL_CALL` | Assistant `message_end` |
20
+ | `messageUpdate` | `MESSAGE_UPDATE` | Streaming chunks (`text_delta`, `thinking_delta`). Fire-and-forget so handlers do not block the stream |
21
+ | `beforeToolCall` | `BEFORE_TOOL_CALL` | Agent `tool_call` event (model requested a tool) |
22
+ | `afterToolCall` | `AFTER_TOOL_CALL` | Agent `tool_result` event |
23
+ | `beforeToolExecute` | `BEFORE_TOOL_EXECUTE` | Immediately before `tool.execute`. Can **block** the tool |
24
+ | `afterToolExecute` | `AFTER_TOOL_EXECUTE` | After `tool.execute` (success or thrown error) |
25
+ | `beforeAgentRun` | `BEFORE_AGENT_RUN` | Before `agent.prompt` |
26
+ | `afterAgentRun` | `AFTER_AGENT_RUN` | After `agent.prompt` (success or thrown error) |
27
+ | `beforeCachedAgentReuse` | `BEFORE_CACHED_AGENT_REUSE` | Each cached-agent run cycle (system-prompt rebuild uses this) |
28
+
29
+ There is no `AGENT_ERROR`, `BEFORE_MESSAGE_SEND`, or `AFTER_MESSAGE_RECEIVE` type. Model I/O uses `beforeModelCall` / `afterModelCall` / `messageUpdate`. Tool failures are delivered on `afterToolExecute` with an `error` field.
30
+
31
+ JSON configs may use `postToolExecute` as an alias of `afterToolExecute`, and `preToolExecute` as an alias of `beforeToolExecute`. Kiro names (`PreToolUse`, `PostToolUse`, `PostFileSave`) are rejected.
32
+
33
+ ## How agent runs load hooks
34
+
35
+ `initializeHooks(settings)` runs once during bootstrap (`src/agent/hooks/agent-wrapper.js`):
36
+
37
+ 1. Clear the global manager.
38
+ 2. Register **built-in plugins** (`registerBuiltinHookPlugins`): system-prompt rebuild, then JSON command hooks.
39
+ 3. If `.settings.json` has `hooks.active`, register that debug/security preset.
40
+ 4. Otherwise, if no `hooks.active`, fall back to env vars (`PITHOSAI_DEBUG_HOOKS`, `PITHOSAI_SECURITY_HOOKS`).
41
+
42
+ `wrapAgentWithHooks` binds a per-run ALS context (`cwd`, `role`, `lang`, `taskId`, `model`, `messages`) around `agent.prompt` and maps agent events onto hook types. `wrapToolWithHooks` fires `beforeToolExecute` with `{ abortOnError: true }` (a thrown handler error returns a JSON `{ ok: false, error }` result and skips the tool) and then `afterToolExecute`.
43
+
44
+ ## Add a pithosai core agent hook
45
+
46
+ Do **not** put pithos-owned logic in `~/.pithosai/hooks/` or `<cwd>/.pithosai/hooks/`. Those dirs are for user/project overrides. Core hooks live in `src/agent/hooks/` and register through `registerBuiltinHookPlugins()`.
47
+
48
+ Pick one of two core paths.
49
+
50
+ ### Path A — lifecycle plugin (HookManager)
51
+
52
+ Use this when the hook is pithos runtime logic and does not need a JSON `command` (system prompt rebuild is this path).
53
+
54
+ 1. Add `src/agent/hooks/<name>.js`. Export a `register…()` that calls `globalHookManager.register(HookType.…, handler)` or `registerAll`.
55
+ 2. Handler signature: `async (context) => { …; return context.data; }`. Throw from `beforeToolExecute` to block the tool.
56
+ 3. Call that `register…()` from `registerBuiltinHookPlugins()` in `src/agent/hooks/builtin-hook-plugins.js`.
57
+ 4. Add a unit test next to the plugin.
58
+
59
+ Do not edit `wrapAgentWithHooks` or `bootstrap.js` to attach a new core hook.
60
+
61
+ ### Path B — in-process command adapter (core mapping)
62
+
63
+ Use this when the hook should stay a JSON `command` but run **inside** the agent process (no spawn). The mapping is `CORE_COMMAND_HOOK_ADAPTERS` in `src/agent/hooks/command-hook-plugin.js`. Agent bootstrap passes that map into `registerCommandHookPlugin`. Git AI is **not** in this map.
64
+
65
+ 1. Write an adapter:
66
+
67
+ ```javascript
68
+ /**
69
+ * @param {string[]} args
70
+ * @param {object} event
71
+ * @returns {Promise<{ ok: boolean; exitCode: number; skipped?: boolean }>}
72
+ */
73
+ export async function runMyCoreAdapter(args, event) {
74
+ // args = tokens after the command name, e.g. ["rebuild"]
75
+ // event = stdin-shaped payload: hookType, cwd, taskId, name, params, model, messages
76
+ return { ok: true, exitCode: 0, skipped: false };
77
+ }
78
+ ```
79
+
80
+ Return `exitCode: 2` from `beforeToolExecute` to block the tool. Other non-zero codes are logged and ignored.
81
+
82
+ 2. Register the **first argv token** on the core map:
83
+
84
+ ```javascript
85
+ export const CORE_COMMAND_HOOK_ADAPTERS = {
86
+ "pithosai-my-adapter": runMyCoreAdapter,
87
+ };
88
+ ```
89
+
90
+ 3. Add bundled JSON under `src/agent/hooks/configs/<name>.json` whose `command` starts with that token, then list the file on `BUNDLED_COMMAND_HOOK_FILES`:
91
+
92
+ ```javascript
93
+ export const BUNDLED_COMMAND_HOOK_FILES = {
94
+ "git-ai.json": bundledGitAi,
95
+ "my-adapter.json": bundledMyAdapter,
96
+ };
97
+ ```
98
+
99
+ ```json
100
+ {
101
+ "version": "v1",
102
+ "hooks": [
103
+ {
104
+ "name": "my-core-before-write",
105
+ "enabled": true,
106
+ "matcher": "^write$",
107
+ "timeout": 30,
108
+ "hookType": "beforeToolExecute",
109
+ "command": "pithosai-my-adapter rebuild"
110
+ }
111
+ ]
112
+ }
113
+ ```
114
+
115
+ `resolveCommandHookAction` treats the command as in-process **only** when `argv[0]` is a function on the adapter map. Users can still override or disable that bundled file with a same-name JSON in `~/.pithosai/hooks/` or `<cwd>/.pithosai/hooks/`.
116
+
117
+ 4. Add unit tests for the adapter and for the bundled JSON command token.
118
+
119
+ ### Path C — external CLI (not core)
120
+
121
+ Use this for integrations that should run out-of-process (Git AI). Put the CLI in `scripts/`, ship it via rspack + `package.json` `bin`, leave `CORE_COMMAND_HOOK_ADAPTERS` empty for that name, and set bundled JSON `command` to `{pithosaiCli:<bin-name>} …`.
122
+
123
+ | Kind | Where it is registered | JSON `command` |
124
+ |------|------------------------|----------------|
125
+ | Core lifecycle | `registerBuiltinHookPlugins()` → `HookManager` | none |
126
+ | Core command adapter | `CORE_COMMAND_HOOK_ADAPTERS` + `BUNDLED_COMMAND_HOOK_FILES` | `pithosai-my-adapter …` |
127
+ | External CLI | `scripts/` + rspack `bin` | `{pithosaiCli:pithosai-git-ai-adapter} …` |
128
+ | User/project override | `~/.pithosai/hooks` or `.pithosai/hooks` | any shell or `{pithosaiCli:…}` |
129
+
130
+ ## JSON command hooks
131
+
132
+ Put `*.json` files in:
133
+
134
+ - `~/.pithosai/hooks/` (user)
135
+ - `<cwd>/.pithosai/hooks/` (project)
136
+
137
+ **Precedence by filename:** bundled defaults &lt; user dir &lt; project dir. A project `git-ai.json` replaces the bundled file of the same name. Set `"enabled": false` on every hook in an override file to disable that integration.
138
+
139
+ Invalid JSON files are logged and skipped. Disabled entries and unknown `hookType` values are skipped.
140
+
141
+ ### Schema (`version: "v1"`)
142
+
143
+ ```json
144
+ {
145
+ "version": "v1",
146
+ "hooks": [
147
+ {
148
+ "name": "git-ai-before-tool",
149
+ "description": "Optional human-readable description.",
150
+ "enabled": true,
151
+ "matcher": "^(write|edit|read)$",
152
+ "timeout": 30,
153
+ "hookType": "beforeToolExecute",
154
+ "command": "{pithosaiCli:pithosai-git-ai-adapter} checkpoint pre"
155
+ }
156
+ ]
157
+ }
158
+ ```
159
+
160
+ | Field | Meaning |
161
+ |-------|---------|
162
+ | `name` | Label used in logs and block errors. Defaults to `unnamed-hook`. |
163
+ | `enabled` | `false` skips the entry. Default is enabled. |
164
+ | `matcher` | Optional regex tested against the **tool name**. Empty/`null` matches every tool. If `matcher` is set and the event has no tool name, the hook is skipped. |
165
+ | `timeout` | Seconds. Default `60`. `0` means no timeout. |
166
+ | `hookType` | CamelCase pithos HookType (see table above). |
167
+ | `command` | Shell command, `{pithosaiCli:…}` placeholder, or a registered in-process adapter token. Legacy `action.command` is accepted. |
168
+
169
+ ### Stdin event
170
+
171
+ The process receives pithos tool-hook JSON on stdin (not Kiro’s payload):
172
+
173
+ ```json
174
+ {
175
+ "hookType": "beforeToolExecute",
176
+ "cwd": "/repo",
177
+ "taskId": "task-1",
178
+ "name": "write",
179
+ "params": { "path": "src/a.js" },
180
+ "model": "deepseek-v4-flash",
181
+ "messages": [],
182
+ "timestamp": 1710000000000
183
+ }
184
+ ```
185
+
186
+ `afterToolExecute` may also include `result` or `error` (error is a string). External CLIs must read these fields from stdin; they do not share the agent’s in-process ALS.
187
+
188
+ ### Blocking and failures
189
+
190
+ - **`beforeToolExecute` + exit code `2`** blocks the tool (`Hook "<name>" blocked tool "<tool>"`).
191
+ - Any other non-zero exit is logged and **does not** block.
192
+ - Spawn/timeout failures are logged and do not block unless the process exits `2` on `beforeToolExecute`.
193
+ - In-process `beforeToolExecute` handlers that **throw** also block the tool (`abortOnError: true`).
194
+
195
+ ### Core in-process adapters vs shell
196
+
197
+ The command-hook runner keeps a generic **adapter map** for pithos core hooks (`CORE_COMMAND_HOOK_ADAPTERS`). A command runs in-process only when its first argv token is a key in that map. The map starts empty: Git AI is not registered there.
198
+
199
+ Anything else is spawned with `shell: true`.
200
+
201
+ `{pithosaiCli:name}` expands to the current Node binary plus the shipped CLI path (`scripts/<name>.js` in a source checkout, `dist/<name>.mjs` after publish). Path-like names (`../…`) are rejected.
202
+
203
+ To add a pithos-owned in-process adapter, see [Add a pithosai core agent hook](#add-a-pithosai-core-agent-hook).
204
+
205
+ ### Git AI (external CLI)
206
+
207
+ Git AI is a bundled JSON config plus a shipped CLI, not a pithos core adapter.
208
+
209
+ - Source: `scripts/pithosai-git-ai-adapter.js`
210
+ - Release bin: `pithosai-git-ai-adapter` → `dist/pithosai-git-ai-adapter.mjs`
211
+ - Bundled config: `src/agent/hooks/configs/git-ai.json`
212
+ - Example override: `examples/hooks/git-ai.json`
213
+
214
+ Requires [`git-ai`](https://usegitai.com/docs/agents/add-your-agent) on `PATH`. Which tools are checkpointed is controlled only by the JSON `matcher` (bundled default: `write` / `edit` / `read`). The adapter still needs a file path on tool params. Set `PITHOSAI_GIT_AI=0` (or `false` / `no` / `off`) to skip checkpoints; JSON hooks still load. The CLI always exits `0` so Git AI never blocks a tool.
215
+
216
+ Usage: `pithosai-git-ai-adapter checkpoint pre|post` with hook JSON on stdin.
217
+
218
+ ## Built-in plugins
219
+
220
+ Registered by `registerBuiltinHookPlugins()` (do not wire new integrations inside `wrapAgentWithHooks`):
221
+
222
+ - **System prompt rebuild** — `beforeCachedAgentReuse` rebuilds the system prompt from DB role prompts, `.pithosai/rules/*.md`, role `memory.md`, and skills.
223
+ - **JSON command hooks** — loads bundled + user + project JSON, and runs `CORE_COMMAND_HOOK_ADAPTERS` in-process when the command token matches.
224
+
225
+ NPC platform shell policy is a separate in-process plugin (`createNpcSecurityRulesHooks` on `beforeToolExecute`), registered from bootstrap when security rules apply — not via JSON command hooks.
226
+
227
+ ## Agent run context
228
+
229
+ Per-run ALS (`src/agent/hooks/agent-run-context.js`) holds `cwd`, `role`, `lang`, `taskId`, `model`, and `messages`. Tool payloads get `taskId` / `model` / `messages` copied on so in-process plugins can read them without ALS. Child processes only see the stdin JSON.
230
+
231
+ ## CLI (`pithosai hooks`)
232
+
233
+ Alias: `pithosai hook`.
234
+
235
+ `hooks list` / `status` load **built-in plugins** (system prompt rebuild) and **JSON command hooks** via `registerBuiltinHookPlugins()` and print to stdout — the same plugins an agent run gets from bootstrap. They do **not** read deprecated `.settings.json` `hooks.active`.
236
+
237
+ `hooks debug` / `security` / `clear` still persist a debug/security preset in `<project>/.settings.json` (`hooks.active`). The next agent run may load that preset **after** built-in plugins (legacy path).
238
+
239
+ ```bash
240
+ pithosai hooks list
241
+ pithosai hooks list --verbose
242
+ pithosai hooks status
243
+
244
+ pithosai hooks debug
245
+ pithosai hooks debug --data
246
+ pithosai hooks debug --performance
247
+ pithosai hooks debug --stats
248
+ pithosai hooks debug --all
249
+
250
+ pithosai hooks security --block "exec,bash,write"
251
+ pithosai hooks security --max-prompt 5000
252
+
253
+ pithosai hooks clear
254
+
255
+ pithosai hooks test
256
+ pithosai hooks test beforeAgentRun
257
+
258
+ pithosai hooks register beforeAgentRun ./examples/hooks/custom-logger.js
259
+ ```
260
+
261
+ `hooks register` requires a default-export function and a camelCase `hookType`. It registers in the **current process** and appends `{ type, file, timestamp }` to `hooks.customHandlers`. Agent bootstrap does **not** re-import those files. For persistent custom behavior, use JSON command hooks.
262
+
263
+ ## Environment variables
264
+
265
+ Used when `.settings.json` has **no** `hooks.active`:
266
+
267
+ | Variable | Role |
268
+ |----------|------|
269
+ | `PITHOSAI_DEBUG_HOOKS` | `1` / `true` — debug + performance + stats handlers |
270
+ | `PITHOSAI_DEBUG_HOOKS_DATA` | `1` — log full hook payloads |
271
+ | `PITHOSAI_SECURITY_HOOKS` | `1` / `true` — block listed tools; warn on long prompts / sensitive-looking params |
272
+ | `PITHOSAI_BLOCKED_TOOLS` | Comma-separated tool names (with `PITHOSAI_SECURITY_HOOKS`) |
273
+ | `PITHOSAI_MAX_PROMPT_LENGTH` | Max system-prompt length warning (default `10000`) |
274
+ | `PITHOSAI_GIT_AI` | Git AI CLI checkpoints (on by default). Disable: `0` / `false` / `no` / `off` |
275
+
276
+ ## Project settings (`.settings.json`)
277
+
278
+ | Field | Role |
279
+ |-------|------|
280
+ | `hooks.active` | Preset from `pithosai hooks debug` / `security` (`type`: `debug`, `debug-basic`, or `security`, plus `options`) |
281
+ | `hooks.customHandlers` | Metadata from `pithosai hooks register` (not auto-loaded on agent runs) |
282
+
283
+ JSON command hooks are **not** stored here; they live under `~/.pithosai/hooks/` and `<cwd>/.pithosai/hooks/`.
284
+
285
+ ## In-process handler shape
286
+
287
+ Handlers receive a **context object**, not the payload as the first argument:
288
+
289
+ ```javascript
290
+ /** @param {{ hookType: string; data: object; timestamp: number }} context */
291
+ export default async function customHook(context) {
292
+ const { hookType, data } = context;
293
+ // mutate data when needed
294
+ return data;
295
+ }
296
+ ```
297
+
298
+ - Return `data` (optionally modified). Returning `undefined` leaves the previous payload unchanged.
299
+ - Throw from `beforeToolExecute` to block the tool.
300
+ - Keep handlers fast. `messageUpdate` must not await heavy work.
301
+ - Prefer `logErrorToFile` / `logInfoToFile` / `logDebugToFile` over console for TUI runs.
302
+
303
+ ### Payload fields (in `context.data`)
304
+
305
+ **`beforeAgentRun` / `afterAgentRun`**
306
+
307
+ `request`, `images`, `cwd`, `role`, `lang`, `timestamp`. After: `result` on success, or `error` on failure.
308
+
309
+ **`beforeToolExecute` / `afterToolExecute`**
310
+
311
+ `name`, `description`, `params`, `toolCallId`, `cwd`, `role`, `lang`, `timestamp`, plus `taskId`, `model`, `messages` when a run context is bound. After: `result` or `error`.
312
+
313
+ **`beforeModelCall` / `afterModelCall` / `messageUpdate`**
314
+
315
+ `messages`, `model`, `cwd`, `role`, `lang`, `timestamp`. After model: `message`. Streaming: `message`, `assistantMessageEvent`.
316
+
317
+ **`beforeToolCall` / `afterToolCall`**
318
+
319
+ `toolCall`, `messages`, `cwd`, `role`, `lang`, `timestamp`. After: `result`.
320
+
321
+ ## Troubleshooting
322
+
323
+ - JSON hook not running: confirm the file is `*.json`, `hookType` is camelCase, `enabled` is not `false`, and `matcher` matches the tool name.
324
+ - Tool not blocked: only `beforeToolExecute` exit `2` (JSON) or a thrown in-process handler blocks execution.
325
+ - Git AI skipped: install `git-ai` on `PATH`, leave `PITHOSAI_GIT_AI` unset or on, and keep `git-ai.json` enabled.
326
+ - `hooks list` / `status` show zero handlers: confirm `registerBuiltinHookPlugins` can load (cwd has access; command-hook JSON under `~/.pithosai/hooks` or `<cwd>/.pithosai/hooks`). Builtins always register system-prompt-rebuild when the CLI loads successfully.
327
+ - `hooks register` / `test` “invalid type”: pass `beforeToolExecute`, not `BEFORE_TOOL_EXECUTE`.
328
+
329
+ ## Examples
330
+
331
+ - `examples/hooks/git-ai.json` — Git AI JSON command hooks (same shape as the bundled default)
332
+ - `examples/hooks/custom-logger.js` — sketch for `pithosai hooks register` (must default-export a function that accepts hook **context**)
333
+ - `src/agent/hooks/configs/git-ai.json` — bundled default loaded when no user/project file of the same name exists
334
+ - `src/agent/hooks/command-hook-plugin.js` — `CORE_COMMAND_HOOK_ADAPTERS` (pithos core in-process command map) and `BUNDLED_COMMAND_HOOK_FILES`
335
+ - `src/agent/hooks/builtin-hook-plugins.js` — register core lifecycle plugins here
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pithosai/pithosai",
3
- "version": "1.0.10",
3
+ "version": "1.0.33",
4
4
  "description": "Pithos AI CLI — multi-role coding and product agents (bundled distribution).",
5
5
  "keywords": [
6
6
  "ai",
@@ -22,10 +22,17 @@
22
22
  "email-monitor": "./dist/heartbeat.mjs",
23
23
  "wrsai": "./dist/wrsai",
24
24
  "render-markdown": "./dist/render-markdown.mjs",
25
- "init": "./dist/init.mjs"
25
+ "init": "./dist/init.mjs",
26
+ "pithosai-git-ai-adapter": "./dist/pithosai-git-ai-adapter.mjs"
26
27
  },
27
28
  "files": [
28
29
  "LICENSE",
30
+ "CHANGELOG.md",
31
+ "docs/hooks-usage.md",
32
+ "docs/KROUTER.md",
33
+ "src/models/README.md",
34
+ "src/models/krouter.README.md",
35
+ "src/agent-orch/READEM.md",
29
36
  "dist",
30
37
  "!dist/npc-platform-client",
31
38
  "shims",
@@ -38,29 +45,37 @@
38
45
  },
39
46
  "dependencies": {
40
47
  "@clack/prompts": "^1.0.1",
41
- "@journeyapps/sqlcipher": "^5.3.1",
48
+ "@earendil-works/pi-agent-core": "0.85.1",
49
+ "@earendil-works/pi-ai": "0.85.1",
50
+ "@earendil-works/pi-coding-agent": "0.85.1",
51
+ "@earendil-works/pi-tui": "0.85.1",
42
52
  "@marianmeres/actor": "^1.6.1",
43
- "@mariozechner/pi-agent-core": "^0.70.6",
44
- "@mariozechner/pi-ai": "^0.70.6",
45
- "@mariozechner/pi-coding-agent": "^0.70.6",
46
- "@mariozechner/pi-tui": "^0.70.6",
47
53
  "@sinclair/typebox": "^0.34.49",
54
+ "adm-zip": "^0.5.18",
48
55
  "better-sqlite3": "^12.6.2",
49
56
  "chalk": "^5.6.2",
50
57
  "chokidar": "^5.0.0",
58
+ "cli-table3": "^0.6.5",
51
59
  "commander": "^14.0.3",
60
+ "cron-parser": "^4.9.0",
52
61
  "date-fns": "^4.1.0",
53
62
  "handlebars": "^4.7.8",
54
63
  "i18next": "^25.8.4",
55
64
  "imap": "^0.8.19",
65
+ "isomorphic-git": "^1.38.6",
66
+ "json5": "^2.2.3",
56
67
  "log4js": "^6.9.1",
68
+ "lookpath": "^1.2.3",
57
69
  "mailparser": "^3.7.1",
58
70
  "marked": "^17.0.2",
71
+ "node-cron": "^3.0.3",
59
72
  "nodemailer": "^6.9.16",
73
+ "ollama": "^0.6.3",
60
74
  "pdf-parse": "^1.1.1",
61
75
  "playwright": "^1.58.2",
62
76
  "proper-lockfile": "^4.1.2",
63
77
  "readdirp": "^5.0.0",
78
+ "tinyld": "^1.3.4",
64
79
  "uuid": "^14.0.0",
65
80
  "ws": "^8.20.0"
66
81
  },
@@ -73,8 +88,11 @@
73
88
  "vitest": "^4.0.18",
74
89
  "webpack-node-externals": "^3.0.0"
75
90
  },
91
+ "optionalDependencies": {
92
+ "@journeyapps/sqlcipher": "5.3.1"
93
+ },
76
94
  "engines": {
77
- "node": ">=20.0.0"
95
+ "node": ">=22.19.0"
78
96
  },
79
97
  "publishConfig": {
80
98
  "access": "public"