@anmol-srv/sigil 0.10.3 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,42 +1,43 @@
1
1
  #!/usr/bin/env node
2
- var oo=Object.defineProperty;var m=(e,t)=>()=>(e&&(t=e(e=0)),t);var E=(e,t)=>{for(var o in t)oo(e,o,{get:t[o],enumerable:!0})};import{fileURLToPath as co}from"node:url";import{dirname as ge,join as h}from"node:path";import{existsSync as ye}from"node:fs";import{homedir as uo}from"node:os";function lo(){let e=ge(co(import.meta.url));for(let t=0;t<10;t++){if(ye(h(e,"package.json"))&&ye(h(e,"prompts")))return e;let o=ge(e);if(o===e)break;e=o}return process.cwd()}var we,Oe,br,Ie,T,H,Rr,Dr,Lr,Se,Te,Ae,Nr,be,Re,vr,Pr,L=m(()=>{we=lo(),Oe=h(we,"prompts"),br=h(we,"src","db","migrations"),Ie=uo(),T=h(Ie,".sigil"),H=h(T,".env"),Rr=h(T,"db"),Dr=h(T,"CLAUDE.md"),Lr=h(T,"schemas"),Se=h(T,".hook-errors.log"),Te=h(T,".last-clean-doctor"),Ae=h(T,".active-session.json"),Nr=h(T,".stop-cursor.json"),be=h(T,".hook-dedup.json"),Re=h(Ie,".claude"),vr=h(Re,"settings.json"),Pr=h(Re,"CLAUDE.md")});var Pe={};E(Pe,{default:()=>a});var g,ve,mo,a,y=m(()=>{g=(e,t)=>process.env[e]??t,ve=g("SIGIL_DB_TYPE","postgres");if(ve!=="postgres")throw new Error(`SIGIL_DB_TYPE=${ve} is no longer supported. Sigil 0.10.0+ is Postgres-only.
2
+ import { createRequire as __sigilCreateRequire } from 'node:module'; const require = __sigilCreateRequire(import.meta.url);
3
+ var wn=Object.defineProperty;var m=(e,t)=>()=>(e&&(t=e(e=0)),t);var y=(e,t)=>{for(var n in t)wn(e,n,{get:t[n],enumerable:!0})};function N(e){if(!e||typeof e!="string")return e;let t=e;for(let n of yn)t=t.replace(n,k);return t=t.replace(In,(n,o)=>`${o}=${k}`),t=t.replace(Sn,(n,o)=>`${o}${k}:${k}@`),t=t.replace(An,(n,o)=>`${o}=${k}`),t}var k,yn,In,Sn,On,An,$=m(()=>{k="***MASKED***",yn=[/\b(sk-(?:proj-|ant-)?[A-Za-z0-9_\-]{20,})\b/g,/\b(ghp_[A-Za-z0-9]{36,})\b/g,/\b(github_pat_[A-Za-z0-9_]{20,})\b/g,/\b(gho_[A-Za-z0-9]{36,})\b/g,/\b(glpat-[A-Za-z0-9_\-]{20,})\b/g,/\b(xox[baprs]-[A-Za-z0-9\-]{10,})\b/g,/\b(whsec_[A-Za-z0-9]{20,})\b/g,/\b(rk_(?:live|test)_[A-Za-z0-9]{20,})\b/g,/\b(AKIA[A-Z0-9]{16})\b/g,/\b(ASIA[A-Z0-9]{16})\b/g,/\b(eyJ[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,})\b/g,/\b([A-Za-z0-9]{24}\.[A-Za-z0-9_\-]{6}\.[A-Za-z0-9_\-]{27})\b/g,/\b(\d{8,12}:[A-Za-z0-9_\-]{35})\b/g],In=new RegExp(`\\b(api[_-]?key|api[_-]?secret|secret[_-]?key|secret|token|password|passwd|pwd|auth[_-]?token|access[_-]?token|refresh[_-]?token|bearer|private[_-]?key|client[_-]?secret)\\s*[=:]\\s*["']?([^\\s"']{8,})["']?`,"gi"),Sn=/(\w+:\/\/)([^:/\s]+):([^@\s]{3,})@/g,On=["DATABASE_URL","REDIS_URL","MONGODB_URI","MONGO_URI","POSTGRES_URL","DSN","CONNECTION_STRING","ENCRYPTION_KEY","JWT_SECRET","SIGIL_ENCRYPTION_KEY","SESSION_SECRET","WEBHOOK_SECRET"],An=new RegExp(`\\b(${On.join("|")})\\s*[=:]\\s*["']?([^\\s"']+)["']?`,"gi")});import{fileURLToPath as Tn}from"node:url";import{dirname as Ae,join as _}from"node:path";import{existsSync as Te}from"node:fs";import{homedir as bn}from"node:os";function Dn(){let e=Ae(Tn(import.meta.url));for(let t=0;t<10;t++){if(Te(_(e,"package.json"))&&Te(_(e,"prompts")))return e;let n=Ae(e);if(n===e)break;e=n}return process.cwd()}var H,be,Vr,De,w,K,Jr,qr,Zr,Re,Le,Ne,zr,ve,Xr,Qr,es,ts,ns,os,rs,ss,is,as,Pe,cs,us,v=m(()=>{H=Dn(),be=_(H,"prompts"),Vr=_(H,"src","db","migrations"),De=bn(),w=_(De,".sigil"),K=_(w,".env"),Jr=_(w,"db"),qr=_(w,"CLAUDE.md"),Zr=_(w,"schemas"),Re=_(w,".hook-errors.log"),Le=_(w,".last-clean-doctor"),Ne=_(w,".active-session.json"),zr=_(w,".stop-cursor.json"),ve=_(w,".hook-dedup.json"),Xr=_(w,"sock"),Qr=_(w,"sigild.pid"),es=_(w,"sigild.log"),ts=_(w,"heartbeat.json"),ns=_(w,"onboarding-state.json"),os=_(w,"gui.token"),rs=_(H,"dist","gui"),ss=_(H,"src","gui","web"),is=_(w,"iroh"),as=_(w,"identity.key"),Pe=_(De,".claude"),cs=_(Pe,"settings.json"),us=_(Pe,"CLAUDE.md")});var Ue={};y(Ue,{default:()=>c});var E,ke,Ln,c,I=m(()=>{E=(e,t)=>process.env[e]??t,ke=E("SIGIL_DB_TYPE","postgres");if(ke!=="postgres")throw new Error(`SIGIL_DB_TYPE=${ke} is no longer supported. Sigil 0.10.0+ is Postgres-only.
3
4
  PGlite was deprecated; existing PGlite data at ~/.sigil/db is preserved but unreachable from this version.
4
5
  Set SIGIL_DB_TYPE=postgres in ~/.sigil/.env and configure SIGIL_DB_HOST / PORT / NAME / USER / PASSWORD.
5
- Run \`sigil init\` for an interactive setup.`);mo={db:{type:"postgres",host:g("SIGIL_DB_HOST","localhost"),port:Number(g("SIGIL_DB_PORT",5432)),database:g("SIGIL_DB_NAME","sigil"),user:g("SIGIL_DB_USER","sigil_app"),password:g("SIGIL_DB_PASSWORD","")},embedding:{provider:process.env.EMBEDDING_PROVIDER||"",model:process.env.EMBEDDING_MODEL||"nomic-embed-text",dimensions:Number(process.env.EMBEDDING_DIMENSIONS)||768,ollamaHost:process.env.OLLAMA_HOST||"http://localhost:11434",openaiApiKey:process.env.OPENAI_API_KEY||"",voyageApiKey:process.env.VOYAGE_API_KEY||"",openrouterApiKey:process.env.OPENROUTER_API_KEY||"",openrouterBaseUrl:process.env.EMBEDDING_OPENROUTER_BASE_URL||process.env.LLM_OPENROUTER_BASE_URL||"",openrouterReferer:process.env.EMBEDDING_OPENROUTER_REFERER||process.env.LLM_OPENROUTER_REFERER||"https://github.com/Anmol-Srv/sigil",openrouterTitle:process.env.EMBEDDING_OPENROUTER_TITLE||process.env.LLM_OPENROUTER_TITLE||"Sigil"},llm:{provider:process.env.LLM_PROVIDER||"",openaiApiKey:process.env.OPENAI_API_KEY||"",openaiModel:process.env.LLM_OPENAI_MODEL||"gpt-4o-mini",ollamaHost:process.env.LLM_OLLAMA_HOST||process.env.OLLAMA_HOST||"http://localhost:11434",ollamaModel:process.env.LLM_OLLAMA_MODEL||"qwen2.5:7b",cliModel:process.env.LLM_CLI_MODEL||"haiku",apiKey:process.env.ANTHROPIC_API_KEY||"",openrouterApiKey:process.env.OPENROUTER_API_KEY||"",openrouterModel:process.env.LLM_OPENROUTER_MODEL||"google/gemini-flash-latest",openrouterBaseUrl:process.env.LLM_OPENROUTER_BASE_URL||"",openrouterReferer:process.env.LLM_OPENROUTER_REFERER||"https://github.com/Anmol-Srv/sigil",openrouterTitle:process.env.LLM_OPENROUTER_TITLE||"Sigil",extractionModel:process.env.LLM_EXTRACTION_MODEL||"",decisionModel:process.env.LLM_DECISION_MODEL||"",entityModel:process.env.LLM_ENTITY_MODEL||"",maxRetries:Number(process.env.LLM_MAX_RETRIES)||3,cliTimeout:Number(process.env.LLM_CLI_TIMEOUT)||12e4},output:{storage:process.env.OUTPUT_STORAGE||"local",dir:process.env.OUTPUT_DIR||"./output",s3:{endpoint:process.env.S3_ENDPOINT||"",bucket:process.env.S3_BUCKET||"",region:process.env.S3_REGION||"us-east-1",accessKey:process.env.S3_ACCESS_KEY||"",secretKey:process.env.S3_SECRET_KEY||"",publicUrl:process.env.S3_PUBLIC_URL||""}},server:{port:Number(process.env.PORT)||4e3,host:process.env.HOST||"0.0.0.0",logLevel:process.env.LOG_LEVEL||"info"},defaults:{namespace:process.env.DEFAULT_NAMESPACE||"default"},memory:{skipThreshold:Number(process.env.MEMORY_SKIP_THRESHOLD)||.88,ambiguousThreshold:Number(process.env.MEMORY_AMBIGUOUS_THRESHOLD)||.78,minFactSimilarity:Number(process.env.MEMORY_MIN_FACT_SIMILARITY)||.45},search:{synthesize:g("SIGIL_SYNTHESIZE","true")!=="false",synthesizeModel:g("SIGIL_SYNTH_MODEL","")},ingest:{eagerExtract:g("SIGIL_EAGER_EXTRACT","true")!=="false"},hebbian:{entity:{enabled:g("SIGIL_HEBBIAN_ENTITY_ENABLED",null,"true")!=="false",eta:Number(g("SIGIL_HEBBIAN_ENTITY_ETA",null,1)),cap:Number(g("SIGIL_HEBBIAN_ENTITY_CAP",null,50)),halfLifeDays:Number(g("SIGIL_HEBBIAN_ENTITY_HALF_LIFE_DAYS",null,30)),minEffective:Number(g("SIGIL_HEBBIAN_ENTITY_MIN_EFFECTIVE",null,.5)),rrfWeight:Number(g("SIGIL_HEBBIAN_ENTITY_RRF_WEIGHT",null,.3)),maxWriteEntities:Number(g("SIGIL_HEBBIAN_ENTITY_MAX_WRITE",null,12)),expandPerSeed:Number(g("SIGIL_HEBBIAN_ENTITY_EXPAND_PER_SEED",null,3))}}},a=mo});var G={};E(G,{default:()=>d});import fo from"knex";function Eo(e){return Array.isArray(e)?e.map(z):e&&typeof e=="object"?z(e):e}function ho(e,t){return t(go(e))}function z(e){if(!e||typeof e!="object"||e instanceof Date)return e;if(Array.isArray(e))return e.map(z);let t={};for(let[o,n]of Object.entries(e))t[o.replace(/_([a-z])/g,(r,s)=>s.toUpperCase())]=n;return t}function go(e){return e.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}var _o,d,R=m(()=>{y();_o=fo({client:"pg",connection:{host:a.db.host,port:a.db.port,database:a.db.database,user:a.db.user,password:a.db.password},pool:{min:2,max:10},postProcessResponse:Eo,wrapIdentifier:ho});d=_o});var Be={};E(Be,{validateConfig:()=>ke,validateConfigDeep:()=>yo});function ke(){let e=[];return wo(e),Oo(e),Io(e),e}async function yo(){let e=ke();if(a.db.type==="postgres"&&!e.some(t=>t.code.startsWith("DB_")))try{await(await Promise.resolve().then(()=>(R(),G))).default.raw("SELECT 1")}catch(t){e.push({level:"fail",code:"DB_UNREACHABLE",message:`Postgres at ${a.db.host}:${a.db.port}/${a.db.database} unreachable: ${t.message.split(`
6
- `)[0]}`,fix:"Start Postgres (e.g. `docker start sigil-pg` or your equivalent) and verify SIGIL_DB_HOST/PORT/NAME/USER/PASSWORD in ~/.sigil/.env"})}return e}function wo(e){let{provider:t,model:o}=a.embedding;if(t&&o){let n=Object.keys(Ce).find(r=>Ce[r].some(s=>s.test(o)));n&&n!==t&&e.push({level:"fail",code:"EMBEDDING_PROVIDER_MODEL_MISMATCH",message:`EMBEDDING_PROVIDER=${t} but EMBEDDING_MODEL=${o} is a ${n} model.`,fix:So(t,o,n)})}if(t&&xe[t]){let n=xe[t];a.embedding[n]||e.push({level:"fail",code:"EMBEDDING_PROVIDER_MISSING_KEY",message:`EMBEDDING_PROVIDER=${t} but no ${$(n)} found.`,fix:`Set ${$(n)} in ~/.sigil/.env, or run 'sigil init' to reconfigure.`})}}function Oo(e){let{provider:t}=a.llm;if(t&&Me[t]){let o=Me[t];a.llm[o]||e.push({level:"fail",code:"LLM_PROVIDER_MISSING_KEY",message:`LLM_PROVIDER=${t} but no ${$(o)} found.`,fix:`Set ${$(o)} in ~/.sigil/.env, or run 'sigil init' to reconfigure.`})}t==="openrouter"&&a.llm.openrouterModel&&(a.llm.openrouterModel.includes("/")||e.push({level:"warn",code:"OPENROUTER_MODEL_FORMAT",message:`LLM_OPENROUTER_MODEL=${a.llm.openrouterModel} doesn't look like vendor/model format.`,fix:'Use format like "anthropic/claude-haiku-4-5" or "google/gemini-2.5-flash".'}))}function Io(e){a.db.type==="postgres"&&(!a.db.host||!a.db.database||!a.db.user)&&e.push({level:"fail",code:"DB_CONFIG_INCOMPLETE",message:"SIGIL_DB_TYPE=postgres but host/database/user missing.",fix:"Set SIGIL_DB_HOST, SIGIL_DB_NAME, SIGIL_DB_USER, SIGIL_DB_PASSWORD in ~/.sigil/.env. Run `sigil init` for an interactive setup."})}function $(e){return{openaiApiKey:"OPENAI_API_KEY",apiKey:"ANTHROPIC_API_KEY",openrouterApiKey:"OPENROUTER_API_KEY",voyageApiKey:"VOYAGE_API_KEY"}[e]||e}function So(e,t,o){let n={voyage:"voyage-3.5, voyage-3-large, voyage-code-3.5",openai:"text-embedding-3-large, text-embedding-3-small",ollama:"nomic-embed-text, mxbai-embed-large"}[e]||"(see provider docs)";return`Either set EMBEDDING_PROVIDER=${o} (matches your current model), or change EMBEDDING_MODEL to one of: ${n}`}var Ce,Me,xe,Ue=m(()=>{y();Ce={voyage:[/^voyage-/],openai:[/^text-embedding-/],ollama:[/^nomic-embed/,/^mxbai-embed/,/^all-minilm/,/^bge-/,/^snowflake-/,/^granite-embedding/]},Me={openai:"openaiApiKey",anthropic:"apiKey",openrouter:"openrouterApiKey"},xe={openai:"openaiApiKey",voyage:"voyageApiKey",openrouter:"openrouterApiKey"}});var Q={};E(Q,{HOOK_ERROR_LOG:()=>K,LAST_CLEAN_DOCTOR_PATH:()=>F,clearLastCleanDoctor:()=>Po,failClosedOnBadConfig:()=>Do,getUnackedErrorCount:()=>No,markDoctorClean:()=>vo,readRecentHookErrors:()=>Lo,recordHookError:()=>He});import{appendFile as To,readFile as X,writeFile as Ao,unlink as bo}from"node:fs/promises";import{createHash as Ro}from"node:crypto";async function He(e,t,o=null){try{let n={ts:new Date().toISOString(),hook:e,error:t?.message||String(t),input_hash:o?Co(o):null};await To(K,JSON.stringify(n)+`
7
- `,"utf8")}catch{}}async function Do(e,t=null){try{let{validateConfig:o}=await Promise.resolve().then(()=>(Ue(),Be)),n=o().filter(r=>r.level==="fail");if(n.length===0)return!1;for(let r of n){let s=new Error(`${r.code}: ${r.message} \u2014 fix: ${r.fix}`);await He(e,s,t)}return!0}catch{return!1}}async function Lo(e=10){let t;try{t=await X(K,"utf8")}catch{return[]}let o=t.split(`
8
- `).filter(Boolean),n=[];for(let r of o.slice(-e))try{n.push(JSON.parse(r))}catch{}return n}async function No(){let e=0;try{let n=await X(F,"utf8");e=new Date(n.trim()).getTime()}catch{}let t;try{t=await X(K,"utf8")}catch{return 0}let o=0;for(let n of t.split(`
9
- `))if(n.trim())try{let r=JSON.parse(n);(r.ts?new Date(r.ts).getTime():0)>e&&(o+=1)}catch{}return o}async function vo(){try{await Ao(F,new Date().toISOString(),"utf8")}catch{}}async function Po(){try{await bo(F)}catch{}}function Co(e){try{let t=typeof e=="string"?e:JSON.stringify(e);return Ro("sha256").update(t).digest("hex").slice(0,12)}catch{return null}}var K,F,ee=m(()=>{L();K=Se,F=Te});var Ge,$e=m(()=>{Ge="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"});import{webcrypto as Ke}from"node:crypto";function xo(e){!D||D.length<e?(D=Buffer.allocUnsafe(e*Mo),Ke.getRandomValues(D),N=0):N+e>D.length&&(Ke.getRandomValues(D),N=0),N+=e}function Y(e=21){xo(e|=0);let t="";for(let o=N-e;o<N;o++)t+=Ge[D[o]&63];return t}var Mo,D,N,te=m(()=>{$e();Mo=128});var Fe={};E(Fe,{chat:()=>ko,meta:()=>Bo,setup:()=>Uo});async function ko(e,{model:t,jsonMode:o=!1}={}){let n=t||a.llm.openaiModel,r=[{role:"user",content:e}];o&&!e.toLowerCase().includes("json")&&r.unshift({role:"system",content:"Respond with valid JSON."});let s={model:n,messages:r};o&&(s.response_format={type:"json_object"});let c=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a.llm.openaiApiKey}`},body:JSON.stringify(s)});if(!c.ok){let p=await c.text();throw new Error(`OpenAI error ${c.status}: ${p}`)}let i=await c.json(),u=i.choices[0].message.content.trim(),l=i.usage||{};return{text:u,inputTokens:l.prompt_tokens||0,outputTokens:l.completion_tokens||0,model:n}}async function Uo({existing:e,clack:t}){let o=e.OPENAI_API_KEY||"",n=await t.text({message:"OpenAI API key (paste, then Enter)",placeholder:o?"(keep existing \u2014 press Enter)":"sk-proj-...",validate:r=>{if(!r&&!o)return"API key is required";if(r&&!r.startsWith("sk-"))return'OpenAI keys start with "sk-" \u2014 check paste'}});return t.isCancel(n)?null:{env:{OPENAI_API_KEY:n||o}}}var Bo,Ye=m(()=>{y();Bo={id:"openai",label:"OpenAI",hint:"gpt-4o-mini"}});function A(e){return Math.ceil((e||"").length/4)}function je(e,t,o){let n=Ho[e];return n?(t*n.input+o*n.output)/1e6:0}function oe({provider:e,model:t,caller:o,input:n,response:r,inputTokens:s,outputTokens:c,cost:i,durationMs:u,status:l,error:p}){d("llm_log").insert({provider:e,model:t,caller:o,input:n?.slice(0,1e4),response:r?.slice(0,1e4),inputTokens:s,outputTokens:c,cost:i,durationMs:u,status:l,error:p?.slice(0,2e3)}).catch(w=>console.error("[llm-log] Write failed:",w.message))}async function We(e,t=3){for(let o=1;o<=t;o++)try{return await e()}catch(n){if(o===t)throw n;let r=Math.min(1e3*2**(o-1),1e4);await new Promise(s=>setTimeout(s,r))}}var Ho,C=m(()=>{R();Ho={"gpt-4o-mini":{input:.15,output:.6},"gpt-4o":{input:2.5,output:10},"gpt-4.1-nano":{input:.1,output:.4},"gpt-4.1-mini":{input:.4,output:1.6},"claude-haiku-4-5-20251001":{input:.8,output:4},"claude-sonnet-4-6":{input:3,output:15},"claude-opus-4-6":{input:15,output:75}}});var Ve={};E(Ve,{chat:()=>$o,meta:()=>Ko,setup:()=>Fo});async function Go(){if(!ne){let{default:e}=await import("@anthropic-ai/sdk");ne=new e({apiKey:a.llm.apiKey})}return ne}async function $o(e,{model:t,jsonMode:o=!1}={}){let n=t||"claude-haiku-4-5-20251001",r=await Go(),s=[{role:"user",content:e}],c=o?"Respond with valid JSON only. No explanation or wrapping.":void 0,i=await r.messages.create({model:n,max_tokens:4096,messages:s,...c&&{system:c}});return{text:i.content[0].text.trim(),inputTokens:i.usage?.input_tokens||A(e),outputTokens:i.usage?.output_tokens||A(i.content[0].text),model:n}}async function Fo({existing:e,clack:t}){let o=e.ANTHROPIC_API_KEY||"",n=await t.text({message:"Anthropic API key (paste, then Enter)",placeholder:o?"(keep existing \u2014 press Enter)":"sk-ant-...",validate:r=>{if(!r&&!o)return"API key is required";if(r&&!r.startsWith("sk-ant-"))return'Anthropic keys start with "sk-ant-" \u2014 check paste'}});return t.isCancel(n)?null:{env:{ANTHROPIC_API_KEY:n||o}}}var ne,Ko,Je=m(()=>{y();C();ne=null;Ko={id:"anthropic",label:"Anthropic",hint:"Claude Haiku \u2014 requires API key"}});var qe={};E(qe,{chat:()=>jo,meta:()=>Wo,setup:()=>Vo});async function jo(e,{model:t,jsonMode:o=!1}={}){let n=t||a.llm.openrouterModel;if(!a.llm.openrouterApiKey)throw new Error("OPENROUTER_API_KEY is not set");if(!n)throw new Error("No OpenRouter model resolved. Set LLM_OPENROUTER_MODEL or pass `model`.");let r=[{role:"user",content:e}];o&&!e.toLowerCase().includes("json")&&r.unshift({role:"system",content:"Respond with valid JSON."});let s={model:n,messages:r};o&&(s.response_format={type:"json_object"});let c=(a.llm.openrouterBaseUrl||Yo).replace(/\/+$/,""),i={"Content-Type":"application/json",Authorization:`Bearer ${a.llm.openrouterApiKey}`};a.llm.openrouterReferer&&(i["HTTP-Referer"]=a.llm.openrouterReferer),a.llm.openrouterTitle&&(i["X-Title"]=a.llm.openrouterTitle);let u=await fetch(`${c}/chat/completions`,{method:"POST",headers:i,body:JSON.stringify(s)});if(!u.ok){let f=await u.text();throw new Error(`OpenRouter error ${u.status}: ${f}`)}let l=await u.json(),w=(l.choices?.[0]?.message?.content||"").trim(),_=l.usage||{};return{text:w,inputTokens:_.prompt_tokens||0,outputTokens:_.completion_tokens||0,model:l.model||n}}async function Vo({existing:e,clack:t}){let o={},n=e.OPENROUTER_API_KEY||"",r=await t.text({message:"OpenRouter API key (paste, then Enter)",placeholder:n?"(keep existing \u2014 press Enter)":"sk-or-v1-...",validate:u=>{if(!u&&!n)return"API key is required";if(u&&!u.startsWith("sk-or-"))return'OpenRouter keys start with "sk-or-" \u2014 check paste'}});if(t.isCancel(r))return null;o.OPENROUTER_API_KEY=r||n;let s=e.LLM_OPENROUTER_MODEL||"",c=await t.text({message:"OpenRouter model (vendor/model)",placeholder:s||Ze,validate:u=>{if(u&&!u.includes("/"))return'OpenRouter models are "vendor/model" \u2014 e.g. google/gemini-flash-latest'}});if(t.isCancel(c))return null;o.LLM_OPENROUTER_MODEL=c||s||Ze;let i=await t.select({message:"Configure per-task model overrides? (advanced \u2014 better quality / cost)",options:[{value:"no",label:"No, use one model everywhere",hint:"simpler \u2014 debug one model"},{value:"yes",label:"Yes, configure smart split",hint:"~5\xD7 cheaper extraction + better AUDM/synthesis"}],initialValue:"no"});if(t.isCancel(i))return null;if(i==="yes"){let u=await t.text({message:"Extraction model (high-volume; cheap matters)",placeholder:e.LLM_EXTRACTION_MODEL||v.extraction});if(t.isCancel(u))return null;o.LLM_EXTRACTION_MODEL=u||e.LLM_EXTRACTION_MODEL||v.extraction;let l=await t.text({message:"Decision model (AUDM; smart matters)",placeholder:e.LLM_DECISION_MODEL||v.decision});if(t.isCancel(l))return null;o.LLM_DECISION_MODEL=l||e.LLM_DECISION_MODEL||v.decision;let p=await t.text({message:"Synthesis model (read-time answer composition)",placeholder:e.SIGIL_SYNTH_MODEL||v.synthesis});if(t.isCancel(p))return null;o.SIGIL_SYNTH_MODEL=p||e.SIGIL_SYNTH_MODEL||v.synthesis}return t.note(`OpenRouter can drive both LLM calls and embeddings.
6
+ Run \`sigil init\` for an interactive setup.`);Ln={db:{type:"postgres",get url(){return E("SIGIL_DATABASE_URL",E("DATABASE_URL",""))||null},get host(){return E("SIGIL_DB_HOST","localhost")},get port(){return Number(E("SIGIL_DB_PORT",5432))},get database(){return E("SIGIL_DB_NAME","sigil")},get user(){return E("SIGIL_DB_USER","sigil_app")},get password(){return E("SIGIL_DB_PASSWORD","")}},embedding:{get provider(){return process.env.EMBEDDING_PROVIDER||""},get model(){return process.env.EMBEDDING_MODEL||"nomic-embed-text"},get dimensions(){return Number(process.env.EMBEDDING_DIMENSIONS)||768},get ollamaHost(){return process.env.OLLAMA_HOST||"http://localhost:11434"},get openaiApiKey(){return process.env.OPENAI_API_KEY||""},get voyageApiKey(){return process.env.VOYAGE_API_KEY||""},openrouterApiKey:process.env.OPENROUTER_API_KEY||"",openrouterBaseUrl:process.env.EMBEDDING_OPENROUTER_BASE_URL||process.env.LLM_OPENROUTER_BASE_URL||"",openrouterReferer:process.env.EMBEDDING_OPENROUTER_REFERER||process.env.LLM_OPENROUTER_REFERER||"https://github.com/Anmol-Srv/sigil",openrouterTitle:process.env.EMBEDDING_OPENROUTER_TITLE||process.env.LLM_OPENROUTER_TITLE||"Sigil"},llm:{get provider(){return process.env.LLM_PROVIDER||""},get openaiApiKey(){return process.env.OPENAI_API_KEY||""},get openaiModel(){return process.env.LLM_OPENAI_MODEL||"gpt-4o-mini"},get ollamaHost(){return process.env.LLM_OLLAMA_HOST||process.env.OLLAMA_HOST||"http://localhost:11434"},get ollamaModel(){return process.env.LLM_OLLAMA_MODEL||"qwen2.5:7b"},get cliModel(){return process.env.LLM_CLI_MODEL||"haiku"},get apiKey(){return process.env.ANTHROPIC_API_KEY||""},get openrouterApiKey(){return process.env.OPENROUTER_API_KEY||""},get openrouterModel(){return process.env.LLM_OPENROUTER_MODEL||"google/gemini-flash-latest"},get openrouterBaseUrl(){return process.env.LLM_OPENROUTER_BASE_URL||""},get openrouterReferer(){return process.env.LLM_OPENROUTER_REFERER||"https://github.com/Anmol-Srv/sigil"},get openrouterTitle(){return process.env.LLM_OPENROUTER_TITLE||"Sigil"},get extractionModel(){return process.env.LLM_EXTRACTION_MODEL||""},get decisionModel(){return process.env.LLM_DECISION_MODEL||""},get entityModel(){return process.env.LLM_ENTITY_MODEL||""},get maxRetries(){return Number(process.env.LLM_MAX_RETRIES)||3},get cliTimeout(){return Number(process.env.LLM_CLI_TIMEOUT)||12e4}},output:{storage:process.env.OUTPUT_STORAGE||"local",dir:process.env.OUTPUT_DIR||"./output",s3:{endpoint:process.env.S3_ENDPOINT||"",bucket:process.env.S3_BUCKET||"",region:process.env.S3_REGION||"us-east-1",accessKey:process.env.S3_ACCESS_KEY||"",secretKey:process.env.S3_SECRET_KEY||"",publicUrl:process.env.S3_PUBLIC_URL||""}},server:{port:Number(process.env.PORT)||4e3,host:process.env.HOST||"0.0.0.0",logLevel:process.env.LOG_LEVEL||"info"},http:{enabled:E("SIGIL_HTTP_ENABLED","true")!=="false",host:E("SIGIL_HTTP_HOST","127.0.0.1"),port:Number(E("SIGIL_HTTP_PORT",7777))},network:{mode:E("SIGIL_MODE","solo"),enabled:E("SIGIL_NETWORK_ENABLED",null)===null?E("SIGIL_MODE","solo")!=="solo":E("SIGIL_NETWORK_ENABLED","false")!=="false",masterNodeId:E("SIGIL_MASTER_NODE_ID","")||null},defaults:{namespace:process.env.DEFAULT_NAMESPACE||"default"},memory:{skipThreshold:Number(process.env.MEMORY_SKIP_THRESHOLD)||.88,ambiguousThreshold:Number(process.env.MEMORY_AMBIGUOUS_THRESHOLD)||.78,minFactSimilarity:Number(process.env.MEMORY_MIN_FACT_SIMILARITY)||.45,injectionFloor:Number(process.env.MEMORY_INJECTION_FLOOR)||.6},search:{synthesize:E("SIGIL_SYNTHESIZE","true")!=="false",synthesizeModel:E("SIGIL_SYNTH_MODEL","")},ingest:{eagerExtract:E("SIGIL_EAGER_EXTRACT","true")!=="false"},hebbian:{entity:{enabled:E("SIGIL_HEBBIAN_ENTITY_ENABLED",null,"true")!=="false",eta:Number(E("SIGIL_HEBBIAN_ENTITY_ETA",null,1)),cap:Number(E("SIGIL_HEBBIAN_ENTITY_CAP",null,50)),halfLifeDays:Number(E("SIGIL_HEBBIAN_ENTITY_HALF_LIFE_DAYS",null,30)),minEffective:Number(E("SIGIL_HEBBIAN_ENTITY_MIN_EFFECTIVE",null,.5)),rrfWeight:Number(E("SIGIL_HEBBIAN_ENTITY_RRF_WEIGHT",null,.3)),maxWriteEntities:Number(E("SIGIL_HEBBIAN_ENTITY_MAX_WRITE",null,12)),expandPerSeed:Number(E("SIGIL_HEBBIAN_ENTITY_EXPAND_PER_SEED",null,3))}}},c=Ln});function Be(e){return{host:e.db.host,port:e.db.port,database:e.db.database,user:e.db.user,password:e.db.password}}var Ge=m(()=>{});function He(e){if(!e)throw new Error("url driver: SIGIL_DATABASE_URL is empty");let t;try{t=new URL(e)}catch(s){throw new Error(`url driver: invalid URL \u2014 ${s.message}`)}if(!/^postgres(ql)?:$/i.test(t.protocol))throw new Error(`url driver: expected postgres:// or postgresql:// scheme, got ${t.protocol}`);let n=t.searchParams.get("sslmode"),o=vn(t.hostname,n),r={host:t.hostname,port:t.port?Number(t.port):5432,database:t.pathname.replace(/^\//,"")||"postgres",user:decodeURIComponent(t.username),password:decodeURIComponent(t.password)};return o!==void 0&&(r.ssl=o),t.searchParams.get("application_name")||(r.application_name="sigil"),r}function vn(e,t){if(t==="disable")return!1;if(t==="require"||t==="verify-full"||t==="verify-ca")return{rejectUnauthorized:!0};if(t==="no-verify"||t==="prefer")return{rejectUnauthorized:!1};if(!$e.some(n=>n.test(e)))return Nn.some(n=>n.test(e))?{rejectUnauthorized:!0}:{rejectUnauthorized:!1}}function Ke(e){try{let t=new URL(e).hostname;return/\.neon\.tech$/i.test(t)?"neon":/\.pooler\.supabase\.com$/i.test(t)?"supabase-pooler":/\.supabase\.co$/i.test(t)||/\.supabase\.com$/i.test(t)?"supabase":/\.rds\.amazonaws\.com$/i.test(t)?"aws-rds":/\.render\.com$/i.test(t)?"render":/\.railway\.app$/i.test(t)?"railway":/\.cockroachlabs\.cloud$/i.test(t)?"cockroachdb":$e.some(n=>n.test(t))?"local":"unknown"}catch{return"unknown"}}var Nn,$e,Fe=m(()=>{Nn=[/\.neon\.tech$/i,/\.supabase\.co$/i,/\.supabase\.com$/i,/\.pooler\.supabase\.com$/i,/\.rds\.amazonaws\.com$/i,/\.render\.com$/i,/\.railway\.app$/i,/\.cockroachlabs\.cloud$/i],$e=[/^localhost$/i,/^127\.0\.0\.1$/,/^::1$/,/\.local$/i]});function Ye(e){let t=e.db.url;return t?{kind:"url",provider:Ke(t),connection:He(t)}:{kind:"local",provider:"local",connection:Be(e)}}var je=m(()=>{Ge();Fe()});var F={};y(F,{default:()=>d});import Pn from"knex";function Cn(e){return Array.isArray(e)?e.map(te):e&&typeof e=="object"?te(e):e}function xn(e,t){return t(Mn(e))}function te(e){if(!e||typeof e!="object"||e instanceof Date)return e;if(Array.isArray(e))return e.map(te);let t={};for(let[n,o]of Object.entries(e))t[n.replace(/_([a-z])/g,(r,s)=>s.toUpperCase())]=o;return t}function Mn(e){return e.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}var We,Ve,d,R=m(()=>{I();je();We=Ye(c),Ve=Pn({client:"pg",connection:We.connection,pool:{min:2,max:10},postProcessResponse:Cn,wrapIdentifier:xn});Ve.__sigilDriver=We;d=Ve});var Xe={};y(Xe,{validateConfig:()=>ze,validateConfigDeep:()=>kn});function ze(){let e=[];return Un(e),Bn(e),Gn(e),e}async function kn(){let e=ze();if(c.db.type==="postgres"&&!e.some(t=>t.code.startsWith("DB_")))try{await(await Promise.resolve().then(()=>(R(),F))).default.raw("SELECT 1")}catch(t){e.push({level:"fail",code:"DB_UNREACHABLE",message:`Postgres at ${c.db.host}:${c.db.port}/${c.db.database} unreachable: ${t.message.split(`
7
+ `)[0]}`,fix:"Start Postgres (e.g. `docker start sigil-pg` or your equivalent) and verify SIGIL_DB_HOST/PORT/NAME/USER/PASSWORD in ~/.sigil/.env"})}return e}function Un(e){let{provider:t,model:n}=c.embedding;if(t&&n){let o=Object.keys(Je).find(r=>Je[r].some(s=>s.test(n)));o&&o!==t&&e.push({level:"fail",code:"EMBEDDING_PROVIDER_MODEL_MISMATCH",message:`EMBEDDING_PROVIDER=${t} but EMBEDDING_MODEL=${n} is a ${o} model.`,fix:$n(t,n,o)})}if(t&&Ze[t]){let o=Ze[t];c.embedding[o]||e.push({level:"fail",code:"EMBEDDING_PROVIDER_MISSING_KEY",message:`EMBEDDING_PROVIDER=${t} but no ${Y(o)} found.`,fix:`Set ${Y(o)} in ~/.sigil/.env, or run 'sigil init' to reconfigure.`})}}function Bn(e){let{provider:t}=c.llm;if(t&&qe[t]){let n=qe[t];c.llm[n]||e.push({level:"fail",code:"LLM_PROVIDER_MISSING_KEY",message:`LLM_PROVIDER=${t} but no ${Y(n)} found.`,fix:`Set ${Y(n)} in ~/.sigil/.env, or run 'sigil init' to reconfigure.`})}t==="openrouter"&&c.llm.openrouterModel&&(c.llm.openrouterModel.includes("/")||e.push({level:"warn",code:"OPENROUTER_MODEL_FORMAT",message:`LLM_OPENROUTER_MODEL=${c.llm.openrouterModel} doesn't look like vendor/model format.`,fix:'Use format like "anthropic/claude-haiku-4-5" or "google/gemini-2.5-flash".'}))}function Gn(e){c.db.type==="postgres"&&(!c.db.host||!c.db.database||!c.db.user)&&e.push({level:"fail",code:"DB_CONFIG_INCOMPLETE",message:"SIGIL_DB_TYPE=postgres but host/database/user missing.",fix:"Set SIGIL_DB_HOST, SIGIL_DB_NAME, SIGIL_DB_USER, SIGIL_DB_PASSWORD in ~/.sigil/.env. Run `sigil init` for an interactive setup."})}function Y(e){return{openaiApiKey:"OPENAI_API_KEY",apiKey:"ANTHROPIC_API_KEY",openrouterApiKey:"OPENROUTER_API_KEY",voyageApiKey:"VOYAGE_API_KEY"}[e]||e}function $n(e,t,n){let o={voyage:"voyage-3.5, voyage-3-large, voyage-code-3.5",openai:"text-embedding-3-large, text-embedding-3-small",ollama:"nomic-embed-text, mxbai-embed-large"}[e]||"(see provider docs)";return`Either set EMBEDDING_PROVIDER=${n} (matches your current model), or change EMBEDDING_MODEL to one of: ${o}`}var Je,qe,Ze,Qe=m(()=>{I();Je={voyage:[/^voyage-/],openai:[/^text-embedding-/],ollama:[/^nomic-embed/,/^mxbai-embed/,/^all-minilm/,/^bge-/,/^snowflake-/,/^granite-embedding/]},qe={openai:"openaiApiKey",anthropic:"apiKey",openrouter:"openrouterApiKey"},Ze={openai:"openaiApiKey",voyage:"voyageApiKey",openrouter:"openrouterApiKey"}});var oe={};y(oe,{HOOK_ERROR_LOG:()=>j,LAST_CLEAN_DOCTOR_PATH:()=>W,clearLastCleanDoctor:()=>qn,failClosedOnBadConfig:()=>jn,getUnackedErrorCount:()=>Vn,markDoctorClean:()=>Jn,readRecentHookErrors:()=>Wn,recordHookError:()=>et});import{appendFile as Hn,readFile as ne,writeFile as Kn,unlink as Fn}from"node:fs/promises";import{createHash as Yn}from"node:crypto";async function et(e,t,n=null){try{let o={ts:new Date().toISOString(),hook:e,error:N(t?.message||String(t)),input_hash:n?Zn(n):null};await Hn(j,JSON.stringify(o)+`
8
+ `,"utf8")}catch{}}async function jn(e,t=null){try{let{validateConfig:n}=await Promise.resolve().then(()=>(Qe(),Xe)),o=n().filter(r=>r.level==="fail");if(o.length===0)return!1;for(let r of o){let s=new Error(`${r.code}: ${r.message} \u2014 fix: ${r.fix}`);await et(e,s,t)}return!0}catch{return!1}}async function Wn(e=10){let t;try{t=await ne(j,"utf8")}catch{return[]}let n=t.split(`
9
+ `).filter(Boolean),o=[];for(let r of n.slice(-e))try{o.push(JSON.parse(r))}catch{}return o}async function Vn(){let e=0;try{let o=await ne(W,"utf8");e=new Date(o.trim()).getTime()}catch{}let t;try{t=await ne(j,"utf8")}catch{return 0}let n=0;for(let o of t.split(`
10
+ `))if(o.trim())try{let r=JSON.parse(o);(r.ts?new Date(r.ts).getTime():0)>e&&(n+=1)}catch{}return n}async function Jn(){try{await Kn(W,new Date().toISOString(),"utf8")}catch{}}async function qn(){try{await Fn(W)}catch{}}function Zn(e){try{let t=typeof e=="string"?e:JSON.stringify(e);return Yn("sha256").update(t).digest("hex").slice(0,12)}catch{return null}}var j,W,re=m(()=>{v();$();j=Re,W=Le});var tt,nt=m(()=>{tt="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"});import{webcrypto as ot}from"node:crypto";function Xn(e){if(e<0||e>1024)throw new RangeError("Wrong ID size");!L||L.length<e?(L=Buffer.allocUnsafe(e*zn),ot.getRandomValues(L),P=0):P+e>L.length&&(ot.getRandomValues(L),P=0),P+=e}function V(e=21){Xn(e|=0);let t="";for(let n=P-e;n<P;n++)t+=tt[L[n]&63];return t}var zn,L,P,se=m(()=>{nt();zn=128});var rt={};y(rt,{chat:()=>Qn,meta:()=>eo,setup:()=>to});async function Qn(e,{model:t,jsonMode:n=!1}={}){let o=t||c.llm.openaiModel,r=[{role:"user",content:e}];n&&!e.toLowerCase().includes("json")&&r.unshift({role:"system",content:"Respond with valid JSON."});let s={model:o,messages:r};n&&(s.response_format={type:"json_object"});let i=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c.llm.openaiApiKey}`},body:JSON.stringify(s)});if(!i.ok){let f=await i.text();throw new Error(`OpenAI error ${i.status}: ${f}`)}let a=await i.json(),u=a.choices[0].message.content.trim(),l=a.usage||{};return{text:u,inputTokens:l.prompt_tokens||0,outputTokens:l.completion_tokens||0,model:o}}async function to({existing:e,clack:t}){let n=e.OPENAI_API_KEY||"",o=await t.text({message:"OpenAI API key (paste, then Enter)",placeholder:n?"(keep existing \u2014 press Enter)":"sk-proj-...",validate:r=>{if(!r&&!n)return"API key is required";if(r&&!r.startsWith("sk-"))return'OpenAI keys start with "sk-" \u2014 check paste'}});return t.isCancel(o)?null:{env:{OPENAI_API_KEY:o||n}}}var eo,st=m(()=>{I();eo={id:"openai",label:"OpenAI",hint:"gpt-4o-mini"}});function T(e){return Math.ceil((e||"").length/4)}function it(e,t,n){let o=no[e];return o?(t*o.input+n*o.output)/1e6:0}function ie({provider:e,model:t,caller:n,input:o,response:r,inputTokens:s,outputTokens:i,cost:a,durationMs:u,status:l,error:f}){d("llm_log").insert({provider:e,model:t,caller:n,input:o?.slice(0,1e4),response:r?.slice(0,1e4),inputTokens:s,outputTokens:i,cost:a,durationMs:u,status:l,error:f?.slice(0,2e3)}).catch(p=>console.error("[llm-log] Write failed:",p.message))}async function at(e,t=3){for(let n=1;n<=t;n++)try{return await e()}catch(o){if(n===t)throw o;let r=Math.min(1e3*2**(n-1),1e4);await new Promise(s=>setTimeout(s,r))}}var no,U=m(()=>{R();no={"gpt-4o-mini":{input:.15,output:.6},"gpt-4o":{input:2.5,output:10},"gpt-4.1-nano":{input:.1,output:.4},"gpt-4.1-mini":{input:.4,output:1.6},"claude-haiku-4-5-20251001":{input:.8,output:4},"claude-sonnet-4-6":{input:3,output:15},"claude-opus-4-6":{input:15,output:75}}});var ct={};y(ct,{chat:()=>ro,meta:()=>so,setup:()=>io});async function oo(){if(!ae){let{default:e}=await import("@anthropic-ai/sdk");ae=new e({apiKey:c.llm.apiKey})}return ae}async function ro(e,{model:t,jsonMode:n=!1}={}){let o=t||"claude-haiku-4-5-20251001",r=await oo(),s=[{role:"user",content:e}],i=n?"Respond with valid JSON only. No explanation or wrapping.":void 0,a=await r.messages.create({model:o,max_tokens:4096,messages:s,...i&&{system:i}});return{text:a.content[0].text.trim(),inputTokens:a.usage?.input_tokens||T(e),outputTokens:a.usage?.output_tokens||T(a.content[0].text),model:o}}async function io({existing:e,clack:t}){let n=e.ANTHROPIC_API_KEY||"",o=await t.text({message:"Anthropic API key (paste, then Enter)",placeholder:n?"(keep existing \u2014 press Enter)":"sk-ant-...",validate:r=>{if(!r&&!n)return"API key is required";if(r&&!r.startsWith("sk-ant-"))return'Anthropic keys start with "sk-ant-" \u2014 check paste'}});return t.isCancel(o)?null:{env:{ANTHROPIC_API_KEY:o||n}}}var ae,so,ut=m(()=>{I();U();ae=null;so={id:"anthropic",label:"Anthropic",hint:"Claude Haiku \u2014 requires API key"}});var dt={};y(dt,{chat:()=>co,meta:()=>uo,setup:()=>lo});async function co(e,{model:t,jsonMode:n=!1}={}){let o=t||c.llm.openrouterModel;if(!c.llm.openrouterApiKey)throw new Error("OPENROUTER_API_KEY is not set");if(!o)throw new Error("No OpenRouter model resolved. Set LLM_OPENROUTER_MODEL or pass `model`.");let r=[{role:"user",content:e}];n&&!e.toLowerCase().includes("json")&&r.unshift({role:"system",content:"Respond with valid JSON."});let s={model:o,messages:r};n&&(s.response_format={type:"json_object"});let i=(c.llm.openrouterBaseUrl||ao).replace(/\/+$/,""),a={"Content-Type":"application/json",Authorization:`Bearer ${c.llm.openrouterApiKey}`};c.llm.openrouterReferer&&(a["HTTP-Referer"]=c.llm.openrouterReferer),c.llm.openrouterTitle&&(a["X-Title"]=c.llm.openrouterTitle);let u=await fetch(`${i}/chat/completions`,{method:"POST",headers:a,body:JSON.stringify(s)});if(!u.ok){let h=await u.text();throw new Error(`OpenRouter error ${u.status}: ${h}`)}let l=await u.json(),p=(l.choices?.[0]?.message?.content||"").trim(),g=l.usage||{};return{text:p,inputTokens:g.prompt_tokens||0,outputTokens:g.completion_tokens||0,model:l.model||o}}async function lo({existing:e,clack:t}){let n={},o=e.OPENROUTER_API_KEY||"",r=await t.text({message:"OpenRouter API key (paste, then Enter)",placeholder:o?"(keep existing \u2014 press Enter)":"sk-or-v1-...",validate:u=>{if(!u&&!o)return"API key is required";if(u&&!u.startsWith("sk-or-"))return'OpenRouter keys start with "sk-or-" \u2014 check paste'}});if(t.isCancel(r))return null;n.OPENROUTER_API_KEY=r||o;let s=e.LLM_OPENROUTER_MODEL||"",i=await t.text({message:"OpenRouter model (vendor/model)",placeholder:s||lt,validate:u=>{if(u&&!u.includes("/"))return'OpenRouter models are "vendor/model" \u2014 e.g. google/gemini-flash-latest'}});if(t.isCancel(i))return null;n.LLM_OPENROUTER_MODEL=i||s||lt;let a=await t.select({message:"Configure per-task model overrides? (advanced \u2014 better quality / cost)",options:[{value:"no",label:"No, use one model everywhere",hint:"simpler \u2014 debug one model"},{value:"yes",label:"Yes, configure smart split",hint:"~5\xD7 cheaper extraction + better AUDM/synthesis"}],initialValue:"no"});if(t.isCancel(a))return null;if(a==="yes"){let u=await t.text({message:"Extraction model (high-volume; cheap matters)",placeholder:e.LLM_EXTRACTION_MODEL||C.extraction});if(t.isCancel(u))return null;n.LLM_EXTRACTION_MODEL=u||e.LLM_EXTRACTION_MODEL||C.extraction;let l=await t.text({message:"Decision model (AUDM; smart matters)",placeholder:e.LLM_DECISION_MODEL||C.decision});if(t.isCancel(l))return null;n.LLM_DECISION_MODEL=l||e.LLM_DECISION_MODEL||C.decision;let f=await t.text({message:"Synthesis model (read-time answer composition)",placeholder:e.SIGIL_SYNTH_MODEL||C.synthesis});if(t.isCancel(f))return null;n.SIGIL_SYNTH_MODEL=f||e.SIGIL_SYNTH_MODEL||C.synthesis}return t.note(`OpenRouter can drive both LLM calls and embeddings.
10
11
  You will pick an embedding provider in the next step \u2014 "openrouter" is an option,
11
- or you can use a direct provider (Ollama / OpenAI / Voyage) for embeddings.`,"OpenRouter scope"),{env:o}}var Yo,Wo,Ze,v,ze=m(()=>{y();Yo="https://openrouter.ai/api/v1";Wo={id:"openrouter",label:"OpenRouter",hint:"one key, many models (Anthropic / OpenAI / Meta / ...)"},Ze="google/gemini-flash-latest",v={extraction:"openrouter:qwen/qwen3.5-flash",decision:"openrouter:anthropic/claude-sonnet-latest",synthesis:"openrouter:anthropic/claude-sonnet-latest"}});var Xe={};E(Xe,{chat:()=>Xo,meta:()=>Qo,setup:()=>en});import{spawn as Jo}from"node:child_process";function zo(e,t){let o=a.llm.cliTimeout||12e4;return new Promise((n,r)=>{let s=Jo("claude",e,{stdio:["pipe","pipe","pipe"]}),c=setTimeout(()=>{s.kill("SIGTERM"),r(new Error(`claude CLI timed out after ${o}ms`))},o),i="",u="";s.stdout.on("data",l=>{i+=l}),s.stderr.on("data",l=>{u+=l}),s.on("error",l=>{clearTimeout(c),r(new Error(`Failed to spawn claude CLI: ${l.message}`))}),s.on("close",l=>{clearTimeout(c),n({stdout:i,stderr:u,code:l})}),s.stdin.write(t),s.stdin.end()})}async function Xo(e,{model:t,jsonMode:o=!1}={}){let n=t||a.llm.cliModel||"haiku",r=Zo[n]||n,s=["-p","--model",r,"--output-format","json"];o&&s.push("--json-schema",qo);let{stdout:c,stderr:i,code:u}=await zo(s,e);if(u!==0)throw new Error(`claude CLI exited ${u}: ${(i||c).slice(0,500)}`);let l;try{l=JSON.parse(c)}catch{return{text:c.trim(),inputTokens:A(e),outputTokens:A(c),model:r}}if(l.is_error)throw new Error(`claude CLI error: ${l.result||"unknown error"}`);let p=o&&l.structured_output?JSON.stringify(l.structured_output):(l.result||"").trim(),w=l.usage||{};return{text:p,inputTokens:w.input_tokens||A(e),outputTokens:w.output_tokens||A(p),model:r,cost:l.total_cost_usd||0}}async function en(){return{env:{}}}var Zo,qo,Qo,Qe=m(()=>{y();C();Zo={"claude-haiku-4-5-20251001":"haiku","claude-sonnet-4-6":"sonnet","claude-opus-4-6":"opus"},qo=JSON.stringify({type:"object",additionalProperties:!0});Qo={id:"claude-cli",label:"Claude Code",hint:"uses your existing subscription \u2014 no extra API key"}});var et={};E(et,{chat:()=>tn,meta:()=>on,setup:()=>nn});async function tn(e,{model:t,jsonMode:o=!1}={}){let n=t||a.llm.ollamaModel,r=`${a.llm.ollamaHost}/api/chat`,s={model:n,messages:[{role:"user",content:e}],stream:!1};o&&(s.format="json");let c=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!c.ok){let u=await c.text();throw new Error(`Ollama error ${c.status}: ${u}`)}let i=await c.json();return{text:i.message.content.trim(),inputTokens:i.prompt_eval_count||A(e),outputTokens:i.eval_count||A(i.message.content),model:n}}async function nn({existing:e,clack:t}){let o=e.OLLAMA_HOST||"http://localhost:11434",n=await t.text({message:"Ollama host",placeholder:o,initialValue:o,validate:r=>{if(r&&!/^https?:\/\//.test(r))return"Must start with http:// or https://"}});return t.isCancel(n)?null:{env:{OLLAMA_HOST:n||o}}}var on,tt=m(()=>{y();C();on={id:"ollama",label:"Ollama",hint:"local models \u2014 no API cost"}});function j(e,t){if(t<1)return[];let o=[];for(let n=0;n<e.length;n+=t)o.push(e.slice(n,n+t));return o}var re=m(()=>{});var ot={};E(ot,{embedBatch:()=>sn});async function sn(e,{model:t,ollamaHost:o}){let n=j(e,rn),r=[];for(let s of n){let c=await fetch(`${o}/api/embed`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,input:s})});if(!c.ok)throw new Error(`Ollama embed failed: ${c.status} ${await c.text()}`);let i=await c.json();r.push(...i.embeddings)}return r}var rn,nt=m(()=>{re();rn=50});var rt={};E(rt,{embedBatch:()=>an});async function an(e,{model:t,openaiApiKey:o,dimensions:n}={}){let r={model:t,input:e};n&&/^text-embedding-3/.test(t)&&(r.dimensions=n);let s=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(r)});if(!s.ok)throw new Error(`OpenAI embed failed: ${s.status} ${await s.text()}`);return(await s.json()).data.map(i=>i.embedding)}var st=m(()=>{});var it={};E(it,{embedBatch:()=>un});async function un(e,{model:t,voyageApiKey:o,inputType:n="document",dimensions:r}={}){if(!o)throw new Error("VOYAGE_API_KEY is not set. Get one at dashboard.voyageai.com.");let s=j(e,cn),c=[];for(let i of s){let u={input:i,model:t||"voyage-3-large",input_type:n==="query"?"query":"document"};r&&(u.output_dimension=r);let l=await fetch("https://api.voyageai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(u)});if(!l.ok){let _=await l.text();throw new Error(`Voyage embed failed: ${l.status} ${_}`)}let w=[...(await l.json()).data].sort((_,f)=>_.index-f.index);c.push(...w.map(_=>_.embedding))}return c}var cn,at=m(()=>{re();cn=50});var ct={};E(ct,{embedBatch:()=>dn});async function dn(e,{model:t,openrouterApiKey:o,openrouterBaseUrl:n,openrouterReferer:r,openrouterTitle:s,dimensions:c}={}){if(!o)throw new Error("OPENROUTER_API_KEY is not set");if(!t)throw new Error('No OpenRouter embedding model resolved. Set EMBEDDING_MODEL (e.g. "openai/text-embedding-3-large").');let i={model:t,input:e};c&&/(^|\/)text-embedding-3/.test(t)&&(i.dimensions=c);let u=(n||ln).replace(/\/+$/,""),l={"Content-Type":"application/json",Authorization:`Bearer ${o}`};r&&(l["HTTP-Referer"]=r),s&&(l["X-Title"]=s);let p=await fetch(`${u}/embeddings`,{method:"POST",headers:l,body:JSON.stringify(i)});if(!p.ok)throw new Error(`OpenRouter embed failed: ${p.status} ${await p.text()}`);return[...(await p.json()).data].sort((f,S)=>f.index-S.index).map(f=>f.embedding)}var ln,ut=m(()=>{ln="https://openrouter.ai/api/v1"});import{spawn as pn}from"node:child_process";async function dt(e){if(!se[e]){let t=ae[e];if(!t)throw new Error(`Unknown LLM provider: "${e}". Available: ${Object.keys(ae).join(", ")}`);let o=await t();se[e]=o.chat}return se[e]}async function pt(e){if(!ie[e]){let t=lt[e];if(!t)throw new Error(`Unknown embedding provider: "${e}". Available: ${Object.keys(lt).join(", ")}`);let o=await t();ie[e]=o.embedBatch}return ie[e]}function mt(e,t){if(!e)return{provider:t,model:null};let o=e.indexOf(":");return o>0&&ae[e.slice(0,o)]?{provider:e.slice(0,o),model:e.slice(o+1)}:{provider:t,model:e}}async function ft(){let e=a.llm.ollamaHost||a.embedding.ollamaHost||"http://localhost:11434";try{return(await fetch(`${e}/api/tags`,{signal:AbortSignal.timeout(2e3)})).ok}catch{return!1}}function mn(){return new Promise(e=>{let t=pn("claude",["--version"],{stdio:"pipe"});t.on("error",()=>e(!1)),t.on("close",o=>e(o===0)),setTimeout(()=>{t.kill(),e(!1)},3e3)})}async function _t(){if(O)return O;if(a.llm.provider)return O=a.llm.provider,O;if(a.llm.openrouterApiKey)return O="openrouter",O;if(a.llm.apiKey)return O="anthropic",O;if(a.llm.openaiApiKey)return O="openai",O;if(await ft())return O="ollama",O;if(await mn())return O="claude-cli",O;throw new Error(`No LLM provider available. Either:
12
+ or you can use a direct provider (Ollama / OpenAI / Voyage) for embeddings.`,"OpenRouter scope"),{env:n}}var ao,uo,lt,C,pt=m(()=>{I();ao="https://openrouter.ai/api/v1";uo={id:"openrouter",label:"OpenRouter",hint:"one key, many models (Anthropic / OpenAI / Meta / ...)"},lt="google/gemini-flash-latest",C={extraction:"openrouter:qwen/qwen3.5-flash",decision:"openrouter:anthropic/claude-sonnet-latest",synthesis:"openrouter:anthropic/claude-sonnet-latest"}});var mt={};y(mt,{chat:()=>Eo,meta:()=>ho,setup:()=>go});import{spawn as po}from"node:child_process";function _o(e,t){let n=c.llm.cliTimeout||12e4;return new Promise((o,r)=>{let s=po("claude",e,{stdio:["pipe","pipe","pipe"]}),i=setTimeout(()=>{s.kill("SIGTERM"),r(new Error(`claude CLI timed out after ${n}ms`))},n),a="",u="";s.stdout.on("data",l=>{a+=l}),s.stderr.on("data",l=>{u+=l}),s.on("error",l=>{clearTimeout(i),r(new Error(`Failed to spawn claude CLI: ${l.message}`))}),s.on("close",l=>{clearTimeout(i),o({stdout:a,stderr:u,code:l})}),s.stdin.write(t),s.stdin.end()})}async function Eo(e,{model:t,jsonMode:n=!1}={}){let o=t||c.llm.cliModel||"haiku",r=mo[o]||o,s=["-p","--model",r,"--output-format","json"];n&&s.push("--json-schema",fo);let{stdout:i,stderr:a,code:u}=await _o(s,e);if(u!==0)throw new Error(`claude CLI exited ${u}: ${(a||i).slice(0,500)}`);let l;try{l=JSON.parse(i)}catch{return{text:i.trim(),inputTokens:T(e),outputTokens:T(i),model:r}}if(l.is_error)throw new Error(`claude CLI error: ${l.result||"unknown error"}`);let f=n&&l.structured_output?JSON.stringify(l.structured_output):(l.result||"").trim(),p=l.usage||{};return{text:f,inputTokens:p.input_tokens||T(e),outputTokens:p.output_tokens||T(f),model:r,cost:l.total_cost_usd||0}}async function go(){return{env:{}}}var mo,fo,ho,ft=m(()=>{I();U();mo={"claude-haiku-4-5-20251001":"haiku","claude-sonnet-4-6":"sonnet","claude-opus-4-6":"opus"},fo=JSON.stringify({type:"object",additionalProperties:!0});ho={id:"claude-cli",label:"Claude Code",hint:"uses your existing subscription \u2014 no extra API key"}});var _t={};y(_t,{chat:()=>wo,meta:()=>yo,setup:()=>Io});async function wo(e,{model:t,jsonMode:n=!1}={}){let o=t||c.llm.ollamaModel,r=`${c.llm.ollamaHost}/api/chat`,s={model:o,messages:[{role:"user",content:e}],stream:!1};n&&(s.format="json");let i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!i.ok){let u=await i.text();throw new Error(`Ollama error ${i.status}: ${u}`)}let a=await i.json();return{text:a.message.content.trim(),inputTokens:a.prompt_eval_count||T(e),outputTokens:a.eval_count||T(a.message.content),model:o}}async function Io({existing:e,clack:t}){let n=e.OLLAMA_HOST||"http://localhost:11434",o=await t.text({message:"Ollama host",placeholder:n,initialValue:n,validate:r=>{if(r&&!/^https?:\/\//.test(r))return"Must start with http:// or https://"}});return t.isCancel(o)?null:{env:{OLLAMA_HOST:o||n}}}var yo,Et=m(()=>{I();U();yo={id:"ollama",label:"Ollama",hint:"local models \u2014 no API cost"}});function J(e,t){if(t<1)return[];let n=[];for(let o=0;o<e.length;o+=t)n.push(e.slice(o,o+t));return n}var ce=m(()=>{});var ht={};y(ht,{embedBatch:()=>Oo});async function Oo(e,{model:t,ollamaHost:n}){let o=J(e,So),r=[];for(let s of o){let i=await fetch(`${n}/api/embed`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:t,input:s})});if(!i.ok)throw new Error(`Ollama embed failed: ${i.status} ${await i.text()}`);let a=await i.json();r.push(...a.embeddings)}return r}var So,gt=m(()=>{ce();So=50});var wt={};y(wt,{embedBatch:()=>Ao});async function Ao(e,{model:t,openaiApiKey:n,dimensions:o}={}){let r={model:t,input:e};o&&/^text-embedding-3/.test(t)&&(r.dimensions=o);let s=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(r)});if(!s.ok)throw new Error(`OpenAI embed failed: ${s.status} ${await s.text()}`);return(await s.json()).data.map(a=>a.embedding)}var yt=m(()=>{});var It={};y(It,{embedBatch:()=>bo});async function bo(e,{model:t,voyageApiKey:n,inputType:o="document",dimensions:r}={}){if(!n)throw new Error("VOYAGE_API_KEY is not set. Get one at dashboard.voyageai.com.");let s=J(e,To),i=[];for(let a of s){let u={input:a,model:t||"voyage-3-large",input_type:o==="query"?"query":"document"};r&&(u.output_dimension=r);let l=await fetch("https://api.voyageai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(u)});if(!l.ok){let g=await l.text();throw new Error(`Voyage embed failed: ${l.status} ${g}`)}let p=[...(await l.json()).data].sort((g,h)=>g.index-h.index);i.push(...p.map(g=>g.embedding))}return i}var To,St=m(()=>{ce();To=50});var Ot={};y(Ot,{embedBatch:()=>Ro});async function Ro(e,{model:t,openrouterApiKey:n,openrouterBaseUrl:o,openrouterReferer:r,openrouterTitle:s,dimensions:i}={}){if(!n)throw new Error("OPENROUTER_API_KEY is not set");if(!t)throw new Error('No OpenRouter embedding model resolved. Set EMBEDDING_MODEL (e.g. "openai/text-embedding-3-large").');let a={model:t,input:e};i&&/(^|\/)text-embedding-3/.test(t)&&(a.dimensions=i);let u=(o||Do).replace(/\/+$/,""),l={"Content-Type":"application/json",Authorization:`Bearer ${n}`};r&&(l["HTTP-Referer"]=r),s&&(l["X-Title"]=s);let f=await fetch(`${u}/embeddings`,{method:"POST",headers:l,body:JSON.stringify(a)});if(!f.ok)throw new Error(`OpenRouter embed failed: ${f.status} ${await f.text()}`);return[...(await f.json()).data].sort((h,S)=>h.index-S.index).map(h=>h.embedding)}var Do,At=m(()=>{Do="https://openrouter.ai/api/v1"});import{spawn as Lo}from"node:child_process";async function bt(e){if(!ue[e]){let t=de[e];if(!t)throw new Error(`Unknown LLM provider: "${e}". Available: ${Object.keys(de).join(", ")}`);let n=await t();ue[e]=n.chat}return ue[e]}async function Dt(e){if(!le[e]){let t=Tt[e];if(!t)throw new Error(`Unknown embedding provider: "${e}". Available: ${Object.keys(Tt).join(", ")}`);let n=await t();le[e]=n.embedBatch}return le[e]}function Rt(e,t){if(!e)return{provider:t,model:null};let n=e.indexOf(":");return n>0&&de[e.slice(0,n)]?{provider:e.slice(0,n),model:e.slice(n+1)}:{provider:t,model:e}}async function Lt(){let e=c.llm.ollamaHost||c.embedding.ollamaHost||"http://localhost:11434";try{return(await fetch(`${e}/api/tags`,{signal:AbortSignal.timeout(2e3)})).ok}catch{return!1}}function No(){return new Promise(e=>{let t=Lo("claude",["--version"],{stdio:"pipe"});t.on("error",()=>e(!1)),t.on("close",n=>e(n===0)),setTimeout(()=>{t.kill(),e(!1)},3e3)})}async function Nt(){if(O)return O;if(c.llm.provider)return O=c.llm.provider,O;if(c.llm.openrouterApiKey)return O="openrouter",O;if(c.llm.apiKey)return O="anthropic",O;if(c.llm.openaiApiKey)return O="openai",O;if(await Lt())return O="ollama",O;if(await No())return O="claude-cli",O;throw new Error(`No LLM provider available. Either:
12
13
  - Set LLM_PROVIDER (openai, anthropic, openrouter, ollama, claude-cli)
13
14
  - Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or OPENROUTER_API_KEY
14
15
  - Start Ollama locally
15
- - Install the Claude CLI (claude)`)}async function Et(){if(I)return I;if(a.embedding.provider)return I=a.embedding.provider,I;if(a.embedding.voyageApiKey)return I="voyage",I;if(await ft())return I="ollama",I;if(a.embedding.openaiApiKey)return I="openai",I;if(a.embedding.openrouterApiKey)return I="openrouter",I;throw new Error(`No embedding provider available. Either:
16
+ - Install the Claude CLI (claude)`)}async function vt(){if(A)return A;if(c.embedding.provider)return A=c.embedding.provider,A;if(c.embedding.voyageApiKey)return A="voyage",A;if(await Lt())return A="ollama",A;if(c.embedding.openaiApiKey)return A="openai",A;if(c.embedding.openrouterApiKey)return A="openrouter",A;throw new Error(`No embedding provider available. Either:
16
17
  - Set EMBEDDING_PROVIDER (voyage, ollama, openai, openrouter)
17
18
  - Set VOYAGE_API_KEY (recommended \u2014 best quality)
18
19
  - Start Ollama locally
19
20
  - Set OPENAI_API_KEY
20
- - Set OPENROUTER_API_KEY (and EMBEDDING_MODEL like "openai/text-embedding-3-large")`)}var ae,lt,se,ie,O,I,ce=m(()=>{y();ae={openai:()=>Promise.resolve().then(()=>(Ye(),Fe)),anthropic:()=>Promise.resolve().then(()=>(Je(),Ve)),openrouter:()=>Promise.resolve().then(()=>(ze(),qe)),"claude-cli":()=>Promise.resolve().then(()=>(Qe(),Xe)),ollama:()=>Promise.resolve().then(()=>(tt(),et))},lt={ollama:()=>Promise.resolve().then(()=>(nt(),ot)),openai:()=>Promise.resolve().then(()=>(st(),rt)),voyage:()=>Promise.resolve().then(()=>(at(),it)),openrouter:()=>Promise.resolve().then(()=>(ut(),ct))},se={},ie={};O=null,I=null});function M(e){return e?`[${e.join(",")}]`:null}function ht(){let e=Number(a.embedding.dimensions)||768;if(!Number.isInteger(e)||e<=0)throw new Error(`Invalid EMBEDDING_DIMENSIONS: ${a.embedding.dimensions}`);return e}function gt(e="embedding"){return`(${e}::halfvec(${ht()}))`}function yt(){return`?::halfvec(${ht()})`}var ue=m(()=>{y()});import{createHash as fn}from"node:crypto";function En(e,t,o,n="document"){let r=fn("sha256");return r.update(e),r.update("\0"),r.update(t),r.update("\0"),r.update(n),r.update("\0"),r.update(o),r.digest("hex")}async function hn(e){if(!e.length)return new Map;let t=await d("embedding_cache").whereIn("key",e).select("key","embedding");return new Map(t.map(o=>[o.key,gn(o.embedding)]))}function gn(e){return Array.isArray(e)||typeof e!="string"?e:(e.startsWith("[")?e.slice(1,-1):e).split(",").map(Number)}async function yn(e){e.length&&await d("embedding_cache").whereIn("key",e).update({hits:d.raw("hits + 1"),lastUsedAt:d.fn.now()})}async function wn(e,t,o){if(e.length){for(let{key:n,embedding:r}of e)await d.raw(`
21
+ - Set OPENROUTER_API_KEY (and EMBEDDING_MODEL like "openai/text-embedding-3-large")`)}var de,Tt,ue,le,O,A,pe=m(()=>{I();de={openai:()=>Promise.resolve().then(()=>(st(),rt)),anthropic:()=>Promise.resolve().then(()=>(ut(),ct)),openrouter:()=>Promise.resolve().then(()=>(pt(),dt)),"claude-cli":()=>Promise.resolve().then(()=>(ft(),mt)),ollama:()=>Promise.resolve().then(()=>(Et(),_t))},Tt={ollama:()=>Promise.resolve().then(()=>(gt(),ht)),openai:()=>Promise.resolve().then(()=>(yt(),wt)),voyage:()=>Promise.resolve().then(()=>(St(),It)),openrouter:()=>Promise.resolve().then(()=>(At(),Ot))},ue={},le={};O=null,A=null});function B(e){return e?`[${e.join(",")}]`:null}function Pt(){let e=Number(c.embedding.dimensions)||768;if(!Number.isInteger(e)||e<=0)throw new Error(`Invalid EMBEDDING_DIMENSIONS: ${c.embedding.dimensions}`);return e}function Ct(e="embedding"){return`(${e}::halfvec(${Pt()}))`}function xt(){return`?::halfvec(${Pt()})`}var me=m(()=>{I()});import{createHash as vo}from"node:crypto";function Co(e,t,n,o="document"){let r=vo("sha256");return r.update(e),r.update("\0"),r.update(t),r.update("\0"),r.update(o),r.update("\0"),r.update(n),r.digest("hex")}async function xo(e){if(!e.length)return new Map;let t=await d("embedding_cache").whereIn("key",e).select("key","embedding");return new Map(t.map(n=>[n.key,Mo(n.embedding)]))}function Mo(e){return Array.isArray(e)||typeof e!="string"?e:(e.startsWith("[")?e.slice(1,-1):e).split(",").map(Number)}async function ko(e){e.length&&await d("embedding_cache").whereIn("key",e).update({hits:d.raw("hits + 1"),lastUsedAt:d.fn.now()})}async function Uo(e,t,n){if(e.length){for(let{key:o,embedding:r}of e)await d.raw(`
21
22
  INSERT INTO embedding_cache (key, provider, model, embedding, hits, created_at, last_used_at)
22
23
  VALUES (?, ?, ?, ?, 0, NOW(), NOW())
23
24
  ON CONFLICT (key) DO UPDATE
24
25
  SET last_used_at = NOW(),
25
26
  hits = embedding_cache.hits + 1
26
- `,[n,t,o,M(r)]);await In()}}async function In(){let e=Date.now();if(e-Ot<On)return;Ot=e;let[{count:t}]=await d("embedding_cache").count("key as count"),o=Number(t);if(o<=wt)return;let n=Math.min(o-wt,_n);await d.raw(`
27
+ `,[o,t,n,B(r)]);await Go()}}async function Go(){let e=Date.now();if(e-kt<Bo)return;kt=e;let[{count:t}]=await d("embedding_cache").count("key as count"),n=Number(t);if(n<=Mt)return;let o=Math.min(n-Mt,Po);await d.raw(`
27
28
  DELETE FROM embedding_cache WHERE key IN (
28
29
  SELECT key FROM embedding_cache ORDER BY last_used_at ASC LIMIT ?
29
30
  )
30
- `,[n])}async function It(e,t,o,n,r,s={}){if(!e.length)return[];let c=s.inputType||r?.inputType||"document",i=e.map(f=>En(t,o,f,c)),u=await hn(i),l=[],p=[],w=new Array(e.length);for(let f=0;f<e.length;f++){let S=u.get(i[f]);S?w[f]=S:(l.push(e[f]),p.push(f))}if(l.length){let f=await n(l,r),S=[];for(let b=0;b<l.length;b++){let U=p[b];w[U]=f[b],S.push({key:i[U],embedding:f[b]})}wn(S,t,o).catch(b=>{process.stderr.write(`[embedding-cache] store failed: ${b.message}
31
- `)})}let _=i.filter(f=>u.has(f));return _.length&&yn(_).catch(()=>{}),w}var wt,_n,Ot,On,St=m(()=>{ue();R();wt=1e4,_n=500;Ot=0,On=6e4});var At={};E(At,{dimensions:()=>Sn,embed:()=>le,embedBatch:()=>Tt});async function le(e,t={}){let[o]=await Tt([e],t);return o}async function Tt(e,{inputType:t="document"}={}){if(!e.length)return[];let o=await Et(),n=await pt(o),r=a.embedding.model,s={...a.embedding,inputType:t};return It(e,o,r,n,s,{inputType:t})}var Sn,de=m(()=>{y();ce();St();({dimensions:Sn}=a.embedding)});async function Tn(e){let t=await _t();return mt(e,t)}async function bt(e,{model:t,caller:o}={}){let{provider:n,model:r}=await Tn(t),s=await dt(n),c=Date.now();try{let i=await We(()=>s(e,{model:r,jsonMode:!1}),a.llm.maxRetries),u=i.cost||je(i.model,i.inputTokens,i.outputTokens);return oe({provider:n,model:i.model,caller:o,input:e,response:i.text,inputTokens:i.inputTokens,outputTokens:i.outputTokens,cost:u,durationMs:Date.now()-c,status:"success"}),i.text}catch(i){throw oe({provider:n,model:r,caller:o,input:e,response:null,inputTokens:0,outputTokens:0,cost:0,durationMs:Date.now()-c,status:"error",error:i.message}),i}}var Rt=m(()=>{y();ce();C()});var Ct={};E(Ct,{deleteFact:()=>Un,deleteNamespace:()=>Gn,findByUid:()=>vn,findSimilar:()=>Pt,getFactCount:()=>Bn,getHotFacts:()=>xn,insertFact:()=>x,listByCategory:()=>Pn,listByDocument:()=>Cn,listFacts:()=>kn,listNamespaces:()=>Hn,markContradicted:()=>Nt,markSuperseded:()=>vt,recordAccess:()=>Mn,saveFact:()=>Ln});import{readFile as An}from"node:fs/promises";import bn from"node:path";async function Ln({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:i}){let u=i||await le(e),l=await Pt(u,{namespace:r});if(!l.length)return{action:"ADD",fact:await x({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:u})};let p=l[0];if(p.similarity>=Dn)return{action:"SKIP",existing:p};if(p.similarity>=Lt){let _=await Nn(e,p.content);if(_==="UPDATE"){let f=await x({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:u});return await vt(p.id,f.id),await Dt({targetType:"fact",targetId:p.id,event:"UPDATE",oldContent:p.content,newContent:e,triggeredBy:`audm:sim=${p.similarity.toFixed(3)}`}),{action:"UPDATE",fact:f,supersededId:p.id}}if(_==="CONTRADICT"){let f=await x({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:u});return await Nt(p.id,f.id),await Dt({targetType:"fact",targetId:p.id,event:"CONTRADICT",oldContent:p.content,newContent:e,triggeredBy:`audm:sim=${p.similarity.toFixed(3)}`}),{action:"CONTRADICT",fact:f,contradictedId:p.id}}}return{action:"ADD",fact:await x({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:u})}}async function Nn(e,t){let n=`${await An(Rn,"utf8")}
31
+ `,[o])}async function Ut(e,t,n,o,r,s={}){if(!e.length)return[];let i=s.inputType||r?.inputType||"document",a=e.map(h=>Co(t,n,h,i)),u=await xo(a),l=[],f=[],p=new Array(e.length);for(let h=0;h<e.length;h++){let S=u.get(a[h]);S?p[h]=S:(l.push(e[h]),f.push(h))}if(l.length){let h=await o(l,r),S=[];for(let b=0;b<l.length;b++){let D=f[b];p[D]=h[b],S.push({key:a[D],embedding:h[b]})}Uo(S,t,n).catch(b=>{process.stderr.write(`[embedding-cache] store failed: ${b.message}
32
+ `)})}let g=a.filter(h=>u.has(h));return g.length&&ko(g).catch(()=>{}),p}var Mt,Po,kt,Bo,Bt=m(()=>{me();R();Mt=1e4,Po=500;kt=0,Bo=6e4});var $t={};y($t,{dimensions:()=>$o,embed:()=>fe,embedBatch:()=>Gt});async function fe(e,t={}){let[n]=await Gt([e],t);return n}async function Gt(e,{inputType:t="document"}={}){if(!e.length)return[];let n=await vt(),o=await Dt(n),r=c.embedding.model,s={...c.embedding,inputType:t};return Ut(e,n,r,o,s,{inputType:t})}var $o,_e=m(()=>{I();pe();Bt();({dimensions:$o}=c.embedding)});async function Ho(e){let t=await Nt();return Rt(e,t)}async function Ht(e,{model:t,caller:n}={}){let{provider:o,model:r}=await Ho(t),s=await bt(o),i=Date.now();try{let a=await at(()=>s(e,{model:r,jsonMode:!1}),c.llm.maxRetries),u=a.cost||it(a.model,a.inputTokens,a.outputTokens);return ie({provider:o,model:a.model,caller:n,input:e,response:a.text,inputTokens:a.inputTokens,outputTokens:a.outputTokens,cost:u,durationMs:Date.now()-i,status:"success"}),a.text}catch(a){throw ie({provider:o,model:r,caller:n,input:e,response:null,inputTokens:0,outputTokens:0,cost:0,durationMs:Date.now()-i,status:"error",error:a.message}),a}}var Kt=m(()=>{I();pe();U()});var Ft={};y(Ft,{currentAgent:()=>Wo,currentDeviceId:()=>jo,currentRequestContext:()=>Yo,runWithRequestContext:()=>Fo});import{AsyncLocalStorage as Ko}from"node:async_hooks";function Fo(e,t){return q.run(e,t)}function Yo(){return q.getStore()||null}function jo(){return q.getStore()?.device?.id??null}function Wo(){return q.getStore()?.agent??process.env.SIGIL_AGENT??null}var q,Yt=m(()=>{q=new Ko});var qt={};y(qt,{deleteFact:()=>sr,deleteNamespace:()=>ar,findByUid:()=>Xo,findSimilar:()=>Jt,getFactCount:()=>rr,getHotFacts:()=>nr,insertFact:()=>x,listByCategory:()=>Qo,listByDocument:()=>Wt,listFacts:()=>or,listNamespaces:()=>ir,markContradicted:()=>Vt,markSuperseded:()=>ge,recordAccess:()=>tr,saveFact:()=>Zo,supersedeStaleDocFacts:()=>er});import{readFile as Vo}from"node:fs/promises";import Jo from"node:path";async function Zo({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:a}){e=N(e);let u=a||await fe(e),l=await Jt(u,{namespace:r}),f={skip:jt,ambiguous:Ee};if(!l.length)return{action:"ADD",fact:await x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:u}),audm:{topSimilarity:null,matchCount:0,decision:"no-match",thresholds:f}};let p=l[0],g={topSimilarity:Number(p.similarity),matchCount:l.length,existingId:p.id,existingContent:p.content,thresholds:f};if(p.similarity>=jt)return{action:"SKIP",existing:p,audm:{...g,decision:"skip-duplicate"}};if(p.similarity>=Ee){let S=await zo(e,p.content);if(S==="UPDATE"){let D=await x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:u});return await ge(p.id,D.id),await he({targetType:"fact",targetId:p.id,event:"UPDATE",oldContent:p.content,newContent:e,triggeredBy:`audm:sim=${p.similarity.toFixed(3)}`}),{action:"UPDATE",fact:D,supersededId:p.id,audm:{...g,decision:"llm:UPDATE"}}}if(S==="CONTRADICT"){let D=await x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:u});return await Vt(p.id,D.id),await he({targetType:"fact",targetId:p.id,event:"CONTRADICT",oldContent:p.content,newContent:e,triggeredBy:`audm:sim=${p.similarity.toFixed(3)}`}),{action:"CONTRADICT",fact:D,contradictedId:p.id,audm:{...g,decision:"llm:CONTRADICT"}}}return{action:"ADD",fact:await x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:u}),audm:{...g,decision:"llm:ADD"}}}return{action:"ADD",fact:await x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:u}),audm:{...g,decision:"below-ambiguous"}}}async function zo(e,t){let o=`${await Vo(qo,"utf8")}
32
33
 
33
34
  **EXISTING FACT:** ${t}
34
35
 
35
- **NEW FACT:** ${e}`,s=(await bt(n,{model:a.llm.decisionModel,caller:"audm"})).trim().toUpperCase();return s.includes("UPDATE")?"UPDATE":s.includes("CONTRADICT")?"CONTRADICT":"ADD"}async function x({content:e,category:t,confidence:o,importance:n,namespace:r,sourceDocumentIds:s,sourceSection:c,embedding:i}){let u=`fact-${Y(16)}`,[l]=await d("fact").insert({uid:u,content:e,category:t,confidence:o||"medium",importance:n||"supplementary",namespace:r,status:"active",sourceDocumentIds:s||[],sourceSection:c||null,embedding:M(i),validFrom:new Date}).returning("*");return await d.raw(`
36
+ **NEW FACT:** ${e}`,s=(await Ht(o,{model:c.llm.decisionModel,caller:"audm"})).trim().toUpperCase();return s.includes("UPDATE")?"UPDATE":s.includes("CONTRADICT")?"CONTRADICT":"ADD"}async function x({content:e,category:t,confidence:n,importance:o,namespace:r,sourceDocumentIds:s,sourceSection:i,embedding:a}){let u=`fact-${V(16)}`,l=null,f=null;try{let{currentDeviceId:g,currentAgent:h}=await Promise.resolve().then(()=>(Yt(),Ft));l=g(),f=h()}catch{}let[p]=await d("fact").insert({uid:u,content:e,category:t,confidence:n||"medium",importance:o||"supplementary",namespace:r,status:"active",sourceDocumentIds:s||[],sourceSection:i||null,embedding:B(a),validFrom:new Date,embeddingModel:c.embedding.model||null,embeddingDim:Number(c.embedding.dimensions)||null,createdByDeviceId:l,createdByAgent:f}).returning("*");return await d.raw(`
36
37
  UPDATE fact
37
38
  SET search_vector = to_tsvector('english', content)
38
39
  WHERE id = ?
39
- `,[l.id]),l}async function vn(e){let[t]=await d("fact").where({uid:e});return t||null}async function Pn(e,{namespace:t,limit:o=50}={}){let n=d("fact").where({category:e,status:"active"}).orderBy("createdAt","desc").limit(o);return t&&n.where({namespace:t}),n}async function Cn(e){return d("fact").whereRaw("? = ANY(source_document_ids)",[e]).where({status:"active"}).orderBy("createdAt","desc")}async function Nt(e,t){await d("fact").where({id:e}).update({status:"contradicted",contradictedById:t,validUntil:d.fn.now()})}async function vt(e,t){await d("fact").where({id:e}).update({status:"superseded",supersededById:t,validUntil:d.fn.now()})}async function Pt(e,{namespace:t,threshold:o=Lt,limit:n=5}){let r=M(e),s=`${gt("embedding")} <=> ${yt()}`;return d.transaction(async c=>{await c.raw("SET LOCAL hnsw.ef_search = 40");let{rows:i}=await c.raw(`
40
+ `,[p.id]),p}async function Xo(e){let[t]=await d("fact").where({uid:e});return t||null}async function Qo(e,{namespace:t,limit:n=50}={}){let o=d("fact").where({category:e,status:"active"}).orderBy("createdAt","desc").limit(n);return t&&o.where({namespace:t}),o}async function Wt(e){return d("fact").whereRaw("? = ANY(source_document_ids)",[e]).where({status:"active"}).orderBy("createdAt","desc")}async function Vt(e,t){await d("fact").where({id:e}).update({status:"contradicted",contradictedById:t,validUntil:d.fn.now()})}async function ge(e,t){await d("fact").where({id:e}).update({status:"superseded",supersededById:t,validUntil:d.fn.now()})}async function er(e,t=[]){let n=new Set((t||[]).filter(i=>i!=null)),o=await Wt(e),r=0,s=0;for(let i of o){if(n.has(i.id))continue;(Array.isArray(i.sourceDocumentIds)?i.sourceDocumentIds:[]).length<=1?(await ge(i.id,null),await he({targetType:"fact",targetId:i.id,event:"SUPERSEDE",oldContent:i.content,newContent:null,triggeredBy:`reingest:doc=${e}`}),r++):(await d("fact").where({id:i.id}).update({sourceDocumentIds:d.raw("array_remove(source_document_ids, ?)",[e])}),s++)}return{superseded:r,dissociated:s}}async function Jt(e,{namespace:t,threshold:n=Ee,limit:o=5}){let r=B(e),s=`${Ct("embedding")} <=> ${xt()}`;return d.transaction(async i=>{await i.raw("SET LOCAL hnsw.ef_search = 40");let{rows:a}=await i.raw(`
40
41
  SELECT id, uid, content, category, status,
41
42
  1 - (${s}) as similarity
42
43
  FROM fact
@@ -46,25 +47,22 @@ or you can use a direct provider (Ollama / OpenAI / Voyage) for embeddings.`,"Op
46
47
  AND 1 - (${s}) >= ?
47
48
  ORDER BY ${s}
48
49
  LIMIT ?
49
- `,[r,t,r,o,r,n]);return i})}async function Dt({targetType:e,targetId:t,event:o,oldContent:n,newContent:r,triggeredBy:s}){await d("history").insert({targetType:e,targetId:t,event:o,oldContent:n||null,newContent:r||null,triggeredBy:s||null})}async function Mn(e){e.length&&await d.raw(`UPDATE fact_lifecycle
50
+ `,[r,t,r,n,r,o]);return a})}async function he({targetType:e,targetId:t,event:n,oldContent:o,newContent:r,triggeredBy:s}){await d("history").insert({targetType:e,targetId:t,event:n,oldContent:o||null,newContent:r||null,triggeredBy:s||null})}async function tr(e){e.length&&await d.raw(`UPDATE fact_lifecycle
50
51
  SET access_count = access_count + 1,
51
52
  last_accessed_at = NOW(),
52
53
  stage = CASE WHEN stage = 'stable' THEN 'editing' ELSE stage END,
53
54
  stage_entered_at = CASE WHEN stage = 'stable' THEN NOW() ELSE stage_entered_at END
54
- WHERE fact_id = ANY(?)`,[e])}async function xn(e,{limit:t=10,since:o}={}){let n=d("fact as f").join("fact_lifecycle as fl","fl.fact_id","f.id").where({"f.status":"active"}).where("fl.access_count",">",0).orderBy("fl.access_count","desc").limit(t).select("f.*");return e&&n.where({"f.namespace":e}),o&&n.where("fl.last_accessed_at",">=",o),n}async function kn({namespace:e,limit:t=50,offset:o=0,category:n}={}){let r=d("fact").where({status:"active"}).select("id","uid","content","category","confidence","importance","createdAt","namespace").orderBy("createdAt","desc").limit(t).offset(o);return e&&r.where({namespace:e}),n&&r.where({category:n}),r}async function Bn(e){let t=d("fact").where({status:"active"});e&&t.where({namespace:e});let[{count:o}]=await t.count("id as count");return Number(o)}async function Un(e){let o=typeof e=="string"&&e.length>8?{uid:e}:{id:Number(e)},n=await d("fact").where(o).first();return n?(await d("fact_entity").where({factId:n.id}).del(),await d("fact").where({id:n.id}).del(),n):null}async function Hn(){return(await d("fact").where({status:"active"}).select("namespace").count("id as factCount").groupBy("namespace").orderBy("namespace")).map(t=>({namespace:t.namespace,factCount:Number(t.factCount)}))}async function Gn(e){await d.raw("DELETE FROM relation WHERE source_fact_id IN (SELECT id FROM fact WHERE namespace = ?)",[e]),await d.raw("DELETE FROM fact_entity WHERE fact_id IN (SELECT id FROM fact WHERE namespace = ?)",[e]),await d.raw("DELETE FROM relation WHERE source_id IN (SELECT id FROM entity WHERE namespace = ?) OR target_id IN (SELECT id FROM entity WHERE namespace = ?)",[e,e]);let t=await d("fact").where({namespace:e}).del(),o=await d("chunk").where({namespace:e}).del(),n=await d("document").where({namespace:e}).del(),r=await d("entity").where({namespace:e}).del();return{factsDeleted:t,chunksDeleted:o,docsDeleted:n,entitiesDeleted:r}}var Rn,Dn,Lt,Mt=m(()=>{te();R();de();Rt();ue();y();L();Rn=bn.join(Oe,"audm-decision.md"),Dn=a.memory.skipThreshold,Lt=a.memory.ambiguousThreshold});async function W({podType:e,externalId:t,name:o,namespace:n,attrs:r={},entityId:s=null,connectionId:c=null,startedAt:i=null}){if(!t)throw new Error("upsertPod requires externalId; use insertPod for custom pods");let u=`pod-${Y(16)}`,l=n||a.defaults.namespace,{rows:[p]}=await d.raw(`
55
+ WHERE fact_id = ANY(?)`,[e])}async function nr(e,{limit:t=10,since:n}={}){let o=d("fact as f").join("fact_lifecycle as fl","fl.fact_id","f.id").where({"f.status":"active"}).where("fl.access_count",">",0).orderBy("fl.access_count","desc").limit(t).select("f.*");return e&&o.where({"f.namespace":e}),n&&o.where("fl.last_accessed_at",">=",n),o}async function or({namespace:e,limit:t=50,offset:n=0,category:o}={}){let r=d("fact").where({status:"active"}).select("id","uid","content","category","confidence","importance","createdAt","namespace").orderBy("createdAt","desc").limit(t).offset(n);return e&&r.where({namespace:e}),o&&r.where({category:o}),r}async function rr(e){let t=d("fact").where({status:"active"});e&&t.where({namespace:e});let[{count:n}]=await t.count("id as count");return Number(n)}async function sr(e){let n=typeof e=="string"&&e.length>8?{uid:e}:{id:Number(e)},o=await d("fact").where(n).first();return o?(await d("fact_entity").where({factId:o.id}).del(),await d("fact").where({id:o.id}).del(),o):null}async function ir(){return(await d("fact").where({status:"active"}).select("namespace").count("id as factCount").groupBy("namespace").orderBy("namespace")).map(t=>({namespace:t.namespace,factCount:Number(t.factCount)}))}async function ar(e){await d.raw("DELETE FROM relation WHERE source_fact_id IN (SELECT id FROM fact WHERE namespace = ?)",[e]),await d.raw("DELETE FROM fact_entity WHERE fact_id IN (SELECT id FROM fact WHERE namespace = ?)",[e]),await d.raw("DELETE FROM relation WHERE source_id IN (SELECT id FROM entity WHERE namespace = ?) OR target_id IN (SELECT id FROM entity WHERE namespace = ?)",[e,e]);let t=await d("fact").where({namespace:e}).del(),n=await d("chunk").where({namespace:e}).del(),o=await d("document").where({namespace:e}).del(),r=await d("entity").where({namespace:e}).del();return{factsDeleted:t,chunksDeleted:n,docsDeleted:o,entitiesDeleted:r}}var qo,jt,Ee,Zt=m(()=>{se();R();_e();Kt();me();$();I();v();qo=Jo.join(be,"audm-decision.md"),jt=c.memory.skipThreshold,Ee=c.memory.ambiguousThreshold});async function Z({podType:e,externalId:t,name:n,namespace:o,attrs:r={},entityId:s=null,connectionId:i=null,startedAt:a=null}){if(!t)throw new Error("upsertPod requires externalId; use insertPod for custom pods");let u=`pod-${V(16)}`,l=o||c.defaults.namespace,{rows:[f]}=await d.raw(`
55
56
  INSERT INTO pod (uid, pod_type, name, namespace, attrs, entity_id, connection_id, external_id, started_at, created_at, updated_at)
56
57
  VALUES (?, ?, ?, ?, ?::jsonb, ?, ?, ?, ?, NOW(), NOW())
57
58
  ON CONFLICT (pod_type, external_id, namespace) WHERE external_id IS NOT NULL DO UPDATE SET
58
59
  attrs = pod.attrs || EXCLUDED.attrs,
59
60
  updated_at = NOW()
60
61
  RETURNING *, (xmax = 0) AS "isNew"
61
- `,[u,e,o,l,JSON.stringify(r),s,c,t,i]);return{pod:p,isNew:p.isNew}}async function xt(e){return d("pod").where({uid:e}).first()||null}async function kt(e,t){await d.raw("UPDATE pod SET attrs = attrs || ?::jsonb, updated_at = NOW() WHERE id = ?",[JSON.stringify(t),e])}async function k(e,{docs:t=0,facts:o=0}){!t&&!o||await d.raw(`UPDATE pod
62
+ `,[u,e,n,l,JSON.stringify(r),s,i,t,a]);return{pod:f,isNew:f.isNew}}async function zt(e){return d("pod").where({uid:e}).first()||null}async function Xt(e,t){await d.raw("UPDATE pod SET attrs = attrs || ?::jsonb, updated_at = NOW() WHERE id = ?",[JSON.stringify(t),e])}async function G(e,{docs:t=0,facts:n=0}){!t&&!n||await d.raw(`UPDATE pod
62
63
  SET member_doc_count = member_doc_count + ?,
63
64
  member_fact_count = member_fact_count + ?,
64
65
  updated_at = NOW()
65
- WHERE id = ?`,[t,o,e])}var V=m(()=>{te();R();y()});function Ht({sessionId:e,transcriptPath:t=null,cwd:o=null,turnCount:n=0,model:r=null,conclusion:s=null,summary:c=null}){return{session_id:e,transcript_path:t,cwd:o,turn_count:n,model:r,conclusion:s,summary:c}}function Gt({sessionId:e,startedAt:t=new Date}={}){let n=(t instanceof Date?t:new Date(t)).toISOString().replace("T"," ").slice(0,16),r=e?e.slice(0,8):"unknown";return`claude-session ${n} (${r})`}var Ut,$t=m(()=>{pe();Ut="claude_session"});import{writeFile as Kn,readFile as Fn,unlink as $s}from"node:fs/promises";import{existsSync as Yn,mkdirSync as jn}from"node:fs";import{dirname as Kt}from"node:path";async function Wn(){try{let e=await Fn(J,"utf8");return JSON.parse(e)}catch{return null}}async function Ft(e){Yn(Kt(J))||jn(Kt(J),{recursive:!0}),await Kn(J,JSON.stringify(e,null,2),"utf8")}async function Yt({sessionId:e,transcriptPath:t=null,cwd:o=null,model:n=null,namespace:r=null}){if(!e)throw new Error("ensureActiveSession requires sessionId from hook stdin");let s=r||a.defaults.namespace,c=await Wn();if(c&&c.session_id===e&&c.namespace===s){let l=await xt(c.pod_uid);if(l)return await kt(l.id,{turn_count:(Jn(l.attrs)||0)+1}),await Vn(c),l}let i=new Date,{pod:u}=await W({podType:Ut,externalId:e,name:Gt({sessionId:e,startedAt:i}),namespace:s,attrs:Ht({sessionId:e,transcriptPath:t,cwd:o,turnCount:1,model:n}),startedAt:i});return await Ft({session_id:e,pod_uid:u.uid,namespace:s,started_at:u.startedAt??i.toISOString(),last_seen_at:new Date().toISOString()}),u}async function Vn(e){await Ft({...e,last_seen_at:new Date().toISOString()})}function Jn(e){if(!e)return 0;if(typeof e=="object")return e.turn_count??0;try{return JSON.parse(e).turn_count??0}catch{return 0}}var J,Ws,pe=m(()=>{V();$t();y();L();J=Ae,Ws=360*60*1e3});var me={};E(me,{attach:()=>Z,attachDocument:()=>qn,attachEntity:()=>zn,attachFact:()=>Zn,detach:()=>Xn,factIdsInPod:()=>tr,listMembers:()=>Qn,listPodsForMember:()=>er});async function Z(e,t,o,n="primary"){let{rowCount:r}=await d.raw(`INSERT INTO pod_membership (pod_id, member_type, member_id, role)
66
+ WHERE id = ?`,[t,n,e])}var z=m(()=>{se();R();I()});function tn({sessionId:e,transcriptPath:t=null,cwd:n=null,turnCount:o=0,model:r=null,conclusion:s=null,summary:i=null}){return{session_id:e,transcript_path:t,cwd:n,turn_count:o,model:r,conclusion:s,summary:i}}function nn({sessionId:e,startedAt:t=new Date}={}){let o=(t instanceof Date?t:new Date(t)).toISOString().replace("T"," ").slice(0,16),r=e?e.slice(0,8):"unknown";return`claude-session ${o} (${r})`}var en,on=m(()=>{we();en="claude_session"});import{writeFile as ur,readFile as lr,unlink as Di}from"node:fs/promises";import{existsSync as dr,mkdirSync as pr}from"node:fs";import{dirname as rn}from"node:path";async function mr(){try{let e=await lr(X,"utf8");return JSON.parse(e)}catch{return null}}async function sn(e){dr(rn(X))||pr(rn(X),{recursive:!0}),await ur(X,JSON.stringify(e,null,2),"utf8")}async function an({sessionId:e,transcriptPath:t=null,cwd:n=null,model:o=null,namespace:r=null}){if(!e)throw new Error("ensureActiveSession requires sessionId from hook stdin");let s=r||c.defaults.namespace,i=await mr();if(i&&i.session_id===e&&i.namespace===s){let l=await zt(i.pod_uid);if(l)return await Xt(l.id,{turn_count:(_r(l.attrs)||0)+1}),await fr(i),l}let a=new Date,{pod:u}=await Z({podType:en,externalId:e,name:nn({sessionId:e,startedAt:a}),namespace:s,attrs:tn({sessionId:e,transcriptPath:t,cwd:n,turnCount:1,model:o}),startedAt:a});return await sn({session_id:e,pod_uid:u.uid,namespace:s,started_at:u.startedAt??a.toISOString(),last_seen_at:new Date().toISOString()}),u}async function fr(e){await sn({...e,last_seen_at:new Date().toISOString()})}function _r(e){if(!e)return 0;if(typeof e=="object")return e.turn_count??0;try{return JSON.parse(e).turn_count??0}catch{return 0}}var X,Pi,we=m(()=>{z();on();I();v();X=Ne,Pi=360*60*1e3});var ye={};y(ye,{attach:()=>Q,attachDocument:()=>hr,attachEntity:()=>gr,attachFact:()=>Er,detach:()=>wr,factIdsInPod:()=>Sr,listMembers:()=>yr,listPodsForMember:()=>Ir});async function Q(e,t,n,o="primary"){let{rowCount:r}=await d.raw(`INSERT INTO pod_membership (pod_id, member_type, member_id, role)
66
67
  VALUES (?, ?, ?, ?)
67
- ON CONFLICT (pod_id, member_type, member_id) DO NOTHING`,[e,t,o,n]);return r>0&&(t==="fact"?await k(e,{facts:1}):t==="document"&&await k(e,{docs:1})),{attached:r>0}}async function Xn(e,t,o){let n=await d("pod_membership").where({podId:e,memberType:t,memberId:o}).del();return n>0&&(t==="fact"?await k(e,{facts:-1}):t==="document"&&await k(e,{docs:-1})),{detached:n>0}}async function Qn(e,{memberType:t,limit:o=20}={}){if(!t)throw new Error("listMembers requires a memberType filter");return d(`${t} as t`).join("pod_membership as pm",function(){this.on("pm.member_id","=","t.id").andOnVal("pm.member_type","=",t)}).where("pm.pod_id",e).orderBy("pm.createdAt","desc").limit(o).select("t.*","pm.role as podRole","pm.createdAt as attachedAt")}async function er(e,t){return d("pod as p").join("pod_membership as pm","pm.pod_id","p.id").where("pm.memberType",e).where("pm.memberId",t).select("p.*","pm.role as podRole")}async function tr(e){return await d("pod_membership").where({podId:e,memberType:"fact"}).pluck("memberId")}var Zn,qn,zn,fe=m(()=>{R();V();Zn=(e,t,o)=>Z(e,"fact",t,o),qn=(e,t,o)=>Z(e,"document",t,o),zn=(e,t,o)=>Z(e,"entity",t,o)});import{execFileSync as or}from"node:child_process";import{basename as jt}from"node:path";async function Wt({cwd:e,namespace:t=null}){if(!e)return null;let o=rr(e),n=t||a.defaults.namespace,s=(o!==e?!1:_e(e)===e)?o:_e(e),{pod:c}=await W({podType:nr,externalId:o,name:jt(o)||o,namespace:n,attrs:{root_path:o,git_root:s||null,display_name:jt(o)||o,discovered_at:new Date().toISOString()},startedAt:new Date});return c}function rr(e){return _e(e)||e}function _e(e){try{return or("git",["rev-parse","--show-toplevel"],{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}var nr,Vt=m(()=>{V();fe();y();nr="project"});var Jt={};E(Jt,{ensureActivePodsForHook:()=>sr});async function sr({sessionId:e,cwd:t=null,transcriptPath:o=null,model:n=null,namespace:r=null}){let s=null;if(e)try{s=await Yt({sessionId:e,transcriptPath:o,cwd:t,model:n,namespace:r})}catch{s=null}let c=null;if(t)try{c=await Wt({cwd:t,namespace:r})}catch{c=null}let i=[s,c].filter(Boolean).map(u=>u.uid);return{sessionPod:s,projectPod:c,podUids:i}}var Zt=m(()=>{pe();Vt()});import{readFileSync as ir,writeFileSync as ar,mkdirSync as cr}from"node:fs";import{createHash as ur}from"node:crypto";var P="***MASKED***",no=[/\b(sk-(?:proj-|ant-)?[A-Za-z0-9_\-]{20,})\b/g,/\b(ghp_[A-Za-z0-9]{36,})\b/g,/\b(github_pat_[A-Za-z0-9_]{20,})\b/g,/\b(gho_[A-Za-z0-9]{36,})\b/g,/\b(glpat-[A-Za-z0-9_\-]{20,})\b/g,/\b(xox[baprs]-[A-Za-z0-9\-]{10,})\b/g,/\b(whsec_[A-Za-z0-9]{20,})\b/g,/\b(rk_(?:live|test)_[A-Za-z0-9]{20,})\b/g,/\b(AKIA[A-Z0-9]{16})\b/g,/\b(ASIA[A-Z0-9]{16})\b/g,/\b(eyJ[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,})\b/g,/\b([A-Za-z0-9]{24}\.[A-Za-z0-9_\-]{6}\.[A-Za-z0-9_\-]{27})\b/g,/\b(\d{8,12}:[A-Za-z0-9_\-]{35})\b/g],ro=new RegExp(`\\b(api[_-]?key|api[_-]?secret|secret[_-]?key|secret|token|password|passwd|pwd|auth[_-]?token|access[_-]?token|refresh[_-]?token|bearer|private[_-]?key|client[_-]?secret)\\s*[=:]\\s*["']?([^\\s"']{8,})["']?`,"gi"),so=/(\w+:\/\/)([^:/\s]+):([^@\s]{3,})@/g,io=["DATABASE_URL","REDIS_URL","MONGODB_URI","MONGO_URI","POSTGRES_URL","DSN","CONNECTION_STRING","ENCRYPTION_KEY","JWT_SECRET","SIGIL_ENCRYPTION_KEY","SESSION_SECRET","WEBHOOK_SECRET"],ao=new RegExp(`\\b(${io.join("|")})\\s*[=:]\\s*["']?([^\\s"']+)["']?`,"gi");function he(e){if(!e||typeof e!="string")return e;let t=e;for(let o of no)t=t.replace(o,P);return t=t.replace(ro,(o,n)=>`${n}=${P}`),t=t.replace(so,(o,n)=>`${n}${P}:${P}@`),t=t.replace(ao,(o,n)=>`${n}=${P}`),t}L();import{resolve as po}from"node:path";import{existsSync as De}from"node:fs";import{config as Le}from"dotenv";function Ne(){let e=po(process.cwd(),".env");De(e)&&Le({path:e,quiet:!0}),De(H)&&H!==e&&Le({path:H,quiet:!0})}L();Ne();var lr=new Set(["Read","Glob","Grep","WebFetch","WebSearch","TaskCreate","TaskUpdate","TaskList","TaskGet","TaskOutput","ToolSearch","Skill","Agent"]),dr=new Set(["ls","pwd","cd","cat","head","tail","wc","echo","date","whoami","which","type","clear","history","find","grep","rg","file","stat","diff","man","sigil","vitest"]),pr=new Set(["commit","push","merge","rebase","tag","release","reset","revert","cherry-pick"]),mr=new Set(["add","status","diff","log","show","branch","checkout","switch","fetch","pull","stash","blame","config"]),fr=["error","fail","fix","decided","refactor","migrate","deploy","docker","kubernetes","kubectl","k8s","pip install","npm install","yarn add","pnpm add","brew install","apt install","rm -rf","sudo","systemctl","launchctl"],zt=300*1e3,Xt=be;function _r(){try{let e=JSON.parse(ir(Xt,"utf8")),t=Date.now();for(let o of Object.keys(e))t-e[o]>zt&&delete e[o];return e}catch{return{}}}function qt(e){try{cr(T,{recursive:!0}),ar(Xt,JSON.stringify(e),"utf8")}catch{}}function Er(e){let t=_r(),o=t[e],n=Date.now();return o&&n-o<zt?(t[e]=n,qt(t),!0):(t[e]=n,qt(t),!1)}function hr(e){return(e.replace(/^(\w+=\S+\s+)+/,"").trim().split(/\s+/)[0]||"").split("/").pop()}function gr(e,t){if(lr.has(e))return null;if(e==="Edit"||e==="Write"){let o=t.file_path||"unknown file";return{content:`${e==="Write"?"Created":"Edited"} ${o}`,dedupKey:`${e}:${o}`}}if(e==="NotebookEdit"){let o=t.notebook_path||"unknown notebook";return{content:`Edited notebook ${o}`,dedupKey:`NotebookEdit:${o}`}}if(e==="Bash"){let o=(t.command||"").trim();if(!o)return null;let n=hr(o);if(dr.has(n))return null;if(n==="git"||n==="gh"){let i=o.replace(/^(git|gh)\s+/,"").split(/\s+/)[0];if(mr.has(i))return null;if(pr.has(i))return{content:`Ran: ${o.slice(0,200)}`,dedupKey:`Bash:${n} ${i}`}}if(["npm","pnpm","yarn"].includes(n)){let i=o.replace(/^\S+\s+/,"").split(/\s+/)[0];if(["test","run","start","lint"].includes(i))return null}let r=o.toLowerCase();return fr.some(i=>r.includes(i))?{content:`Ran: ${o.slice(0,200)}`,dedupKey:`Bash:${n}:${ur("md5").update(o).digest("hex").slice(0,8)}`}:null}return null}async function yr(){let e=[];for await(let u of process.stdin)e.push(u);let t=Buffer.concat(e).toString("utf8").trim();if(!t)return B();let o=JSON.parse(t),n=o.tool_name||"",r=o.tool_input||{},s=gr(n,r);if(!s||Er(s.dedupKey))return B();let{failClosedOnBadConfig:c}=await Promise.resolve().then(()=>(ee(),Q));if(await c("post-tool-use",t))return B();let i=he(s.content);try{let{saveFact:u}=await Promise.resolve().then(()=>(Mt(),Ct)),{embed:l}=await Promise.resolve().then(()=>(de(),At)),p=(await Promise.resolve().then(()=>(y(),Pe))).default,w=await l(i),_=await u({content:i,category:"observation",confidence:"medium",importance:"supplementary",namespace:p.defaults.namespace,sourceDocumentIds:[],sourceSection:"session",embedding:w});try{let{ensureActivePodsForHook:S}=await Promise.resolve().then(()=>(Zt(),Jt)),b=await Promise.resolve().then(()=>(fe(),me)),{sessionPod:U,projectPod:Qt}=await S({sessionId:o.session_id,cwd:o.cwd||null,transcriptPath:o.transcript_path||null}),Ee=_?.fact?.id??_?.existing?.id,eo=_?.action==="SKIP"?"mention":"primary";if(Ee){for(let q of[U,Qt])if(q)try{await b.attachFact(q.id,Ee,eo)}catch(to){process.stderr.write(`[sigil:post-tool-use] attach to ${q.uid} failed: ${to.message}
68
- `)}}}catch(S){process.stderr.write(`[sigil:post-tool-use] pod dispatch failed: ${S.message}
69
- `)}await(await Promise.resolve().then(()=>(R(),G))).default.destroy()}catch(u){process.stderr.write(`[sigil:post-tool-use] ${u.message}
70
- `);try{let{recordHookError:l}=await Promise.resolve().then(()=>(ee(),Q));await l("post-tool-use",u,o)}catch{}try{await(await Promise.resolve().then(()=>(R(),G))).default.destroy()}catch{}}return B()}function B(){let e={hookSpecificOutput:{hookEventName:"PostToolUse"}};process.stdout.write(JSON.stringify(e))}yr();
68
+ ON CONFLICT (pod_id, member_type, member_id) DO NOTHING`,[e,t,n,o]);return r>0&&(t==="fact"?await G(e,{facts:1}):t==="document"&&await G(e,{docs:1})),{attached:r>0}}async function wr(e,t,n){let o=await d("pod_membership").where({podId:e,memberType:t,memberId:n}).del();return o>0&&(t==="fact"?await G(e,{facts:-1}):t==="document"&&await G(e,{docs:-1})),{detached:o>0}}async function yr(e,{memberType:t,limit:n=20}={}){if(!t)throw new Error("listMembers requires a memberType filter");return d(`${t} as t`).join("pod_membership as pm",function(){this.on("pm.member_id","=","t.id").andOnVal("pm.member_type","=",t)}).where("pm.pod_id",e).orderBy("pm.createdAt","desc").limit(n).select("t.*","pm.role as podRole","pm.createdAt as attachedAt")}async function Ir(e,t){return d("pod as p").join("pod_membership as pm","pm.pod_id","p.id").where("pm.memberType",e).where("pm.memberId",t).select("p.*","pm.role as podRole")}async function Sr(e){return await d("pod_membership").where({podId:e,memberType:"fact"}).pluck("memberId")}var Er,hr,gr,Ie=m(()=>{R();z();Er=(e,t,n)=>Q(e,"fact",t,n),hr=(e,t,n)=>Q(e,"document",t,n),gr=(e,t,n)=>Q(e,"entity",t,n)});import{execFileSync as Or}from"node:child_process";import{basename as cn}from"node:path";async function un({cwd:e,namespace:t=null}){if(!e)return null;let n=Tr(e),o=t||c.defaults.namespace,s=(n!==e?!1:Se(e)===e)?n:Se(e),{pod:i}=await Z({podType:Ar,externalId:n,name:cn(n)||n,namespace:o,attrs:{root_path:n,git_root:s||null,display_name:cn(n)||n,discovered_at:new Date().toISOString()},startedAt:new Date});return i}function Tr(e){return Se(e)||e}function Se(e){try{return Or("git",["rev-parse","--show-toplevel"],{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}var Ar,ln=m(()=>{z();Ie();I();Ar="project"});var dn={};y(dn,{ensureActivePodsForHook:()=>br});async function br({sessionId:e,cwd:t=null,transcriptPath:n=null,model:o=null,namespace:r=null}){let s=null;if(e)try{s=await an({sessionId:e,transcriptPath:n,cwd:t,model:o,namespace:r})}catch{s=null}let i=null;if(t)try{i=await un({cwd:t,namespace:r})}catch{i=null}let a=[s,i].filter(Boolean).map(u=>u.uid);return{sessionPod:s,projectPod:i,podUids:a}}var pn=m(()=>{we();ln()});$();import{readFileSync as Dr,writeFileSync as Rr,mkdirSync as Lr}from"node:fs";import{createHash as Nr}from"node:crypto";v();import{resolve as Rn}from"node:path";import{existsSync as Ce}from"node:fs";import{config as xe}from"dotenv";function Me(){let e=Rn(process.cwd(),".env");Ce(e)&&xe({path:e,quiet:!0}),Ce(K)&&K!==e&&xe({path:K,quiet:!0}),process.env.SIGIL_AGENT||(process.env.SIGIL_AGENT="claude-code")}v();Me();var vr=new Set(["Read","Glob","Grep","WebFetch","WebSearch","TaskCreate","TaskUpdate","TaskList","TaskGet","TaskOutput","ToolSearch","Skill","Agent"]),Pr=new Set(["ls","pwd","cd","cat","head","tail","wc","echo","date","whoami","which","type","clear","history","find","grep","rg","file","stat","diff","man","sigil","vitest"]),Cr=new Set(["commit","push","merge","rebase","tag","release","reset","revert","cherry-pick"]),xr=new Set(["add","status","diff","log","show","branch","checkout","switch","fetch","pull","stash","blame","config"]),Mr=["error","fail","fix","decided","refactor","migrate","deploy","docker","kubernetes","kubectl","k8s","pip install","npm install","yarn add","pnpm add","brew install","apt install","rm -rf","sudo","systemctl","launchctl"],fn=300*1e3,_n=ve;function kr(){try{let e=JSON.parse(Dr(_n,"utf8")),t=Date.now();for(let n of Object.keys(e))t-e[n]>fn&&delete e[n];return e}catch{return{}}}function mn(e){try{Lr(w,{recursive:!0}),Rr(_n,JSON.stringify(e),"utf8")}catch{}}function Ur(e){let t=kr(),n=t[e],o=Date.now();return n&&o-n<fn?(t[e]=o,mn(t),!0):(t[e]=o,mn(t),!1)}function Br(e){return(e.replace(/^(\w+=\S+\s+)+/,"").trim().split(/\s+/)[0]||"").split("/").pop()}function Gr(e,t){if(vr.has(e))return null;if(e==="Edit"||e==="Write"){let n=t.file_path||"unknown file";return{content:`${e==="Write"?"Created":"Edited"} ${n}`,dedupKey:`${e}:${n}`}}if(e==="NotebookEdit"){let n=t.notebook_path||"unknown notebook";return{content:`Edited notebook ${n}`,dedupKey:`NotebookEdit:${n}`}}if(e==="Bash"){let n=(t.command||"").trim();if(!n)return null;let o=Br(n);if(Pr.has(o))return null;if(o==="git"||o==="gh"){let a=n.replace(/^(git|gh)\s+/,"").split(/\s+/)[0];if(xr.has(a))return null;if(Cr.has(a))return{content:`Ran: ${n.slice(0,200)}`,dedupKey:`Bash:${o} ${a}`}}if(["npm","pnpm","yarn"].includes(o)){let a=n.replace(/^\S+\s+/,"").split(/\s+/)[0];if(["test","run","start","lint"].includes(a))return null}let r=n.toLowerCase();return Mr.some(a=>r.includes(a))?{content:`Ran: ${n.slice(0,200)}`,dedupKey:`Bash:${o}:${Nr("md5").update(n).digest("hex").slice(0,8)}`}:null}return null}async function $r(){let e=[];for await(let u of process.stdin)e.push(u);let t=Buffer.concat(e).toString("utf8").trim();return M()}function M(){let e={hookSpecificOutput:{hookEventName:"PostToolUse"}};process.stdout.write(JSON.stringify(e))}$r();