toolnet-memory 0.2.21 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +66 -46
- package/bundle/agy.js +61 -43
- package/bundle/api.js +52 -0
- package/bundle/claude-hook.js +37 -32
- package/bundle/codex-context.js +29 -24
- package/bundle/codex.js +78 -60
- package/bundle/context-runtime.js +38 -33
- package/bundle/doctor.js +5 -4
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/mcp.js +18 -16
- package/bundle/memory-agent.js +8 -8
- package/bundle/memory-query.js +6 -6
- package/bundle/opencode.js +69 -51
- package/bundle/runtime.js +11 -11
- package/dist/sdk/public.d.ts +2 -0
- package/dist/sdk/public.js +2 -0
- package/dist/sdk/remote-client.d.ts +41 -0
- package/dist/sdk/remote-client.js +185 -0
- package/dist/sdk/types.d.ts +402 -0
- package/dist/sdk/types.js +1 -0
- package/package.json +14 -5
package/bundle/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function co(){let r=process.env.TOOLNET_GLOBAL_ENV??io(so(),".config","toolnet-memory",".env");if(!oo(r))return;let e=no(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=ao(o.slice(n+1)))}}co();function G(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function U(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function dt(){return{memory:{autoCapture:G(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:G(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:G(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:G(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:U(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:U(process.env.MEMORY_RERANK_TOP,10),finalContext:U(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:U(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:G(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:U(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var lo={critical:100,high:75,normal:50,temporary:20};function mt(r){return lo[r]}function pt(r,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":r==="rule"||r==="decision"?"high":r==="todo"?"normal":r==="activity"||r==="summary"?"temporary":"normal"}import{createHash as mo}from"node:crypto";import{existsSync as qe,mkdirSync as po,readFileSync as uo,renameSync as fo,writeFileSync as go}from"node:fs";import{basename as ho,dirname as se,join as ae,parse as gt,resolve as B}from"node:path";var ht=".toolnet",yo="project.json";function bo(r){return mo("sha256").update(r).digest("hex").slice(0,16)}function He(r){return ae(r,ht,yo)}function So(r){return qe(He(r))}function vo(r,e){let t=B(r),o=gt(t).root;for(;;){if(So(t))return t;if(t===o||e&&t===B(e))break;let n=se(t);if(n===t)break;t=n}return null}function wo(r){let e=B(r),t=gt(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>qe(ae(e,s))))return e;if(e===t)break;let n=se(e);if(n===e)break;e=n}return B(r)}function ko(r){let e;try{e=JSON.parse(uo(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:se(se(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function ut(r,e){let t=ae(r,ht);po(t,{recursive:!0});let o=He(r),n=`${o}.tmp-${process.pid}`;go(n,JSON.stringify(e,null,2)+`
|
|
3
|
-
`,{encoding:"utf8",mode:384}),fo(n,o)}function ft(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var ie=class{detect(e=process.cwd()){let t=B(e),o=wo(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>qe(ae(o,l))),i=vo(t,s?o:void 0);if(i){let l=He(i),u=ko(l);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),ut(i,u)),ft(u,i)}let a=new Date().toISOString(),c=ho(o),d={version:1,id:bo(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return ut(o,d),ft(d,o)}};import{randomUUID as Fo}from"node:crypto";var xo=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ce=class{scan(e){let t=[];for(let o of xo){let n=new RegExp(o.regex.source,o.regex.flags);for(let s of e.matchAll(n))t.push({type:o.type,value:s[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var O=class{scanner=new ce;sanitize(e){let t=e,o=this.scanner.scan(e),n=new Set;for(let s of o)n.add(s.type),t=t.split(s.value).join(`[REDACTED:${s.type}]`);return{text:t,redacted:o.length,secretTypes:[...n]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e)){let s=o.toLowerCase();s.includes("password")||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")?t[o]="[REDACTED]":t[o]=this.sanitizeValue(n)}return t}return e}};var Co=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Eo=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function yt(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Eo.has(e)))}function Po(r,e){let t=yt(r),o=yt(e);if(t.size===0||o.size===0)return 0;let n=0;for(let i of t)o.has(i)&&n++;let s=new Set([...t,...o]).size;return n/s}function bt(r){return new Set(r.tags.filter(e=>!Co.has(e.toLowerCase())))}var le=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let o=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,n=bt(e);return t.filter(s=>{if(s.id===e.id||s.projectId!==e.projectId||s.type!==e.type||s.metadata?.supersededBy)return!1;let i=typeof s.metadata?.topic=="string"?s.metadata.topic:void 0;if(o&&i&&o===i)return!0;let a=bt(s);for(let c of n)if(a.has(c))return!0;return Po(e.content,s.content)>=.6})}};var Ao=new Set(["code","decision","rule","todo","summary"]);function Mo(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function St(r){return r.tags.includes("class:permanent")?4:r.tags.includes("class:task")?3:r.tags.includes("class:session")?2:r.tags.includes("class:transient")?1:0}function Ro(r,e){let t=St(e)-St(r);if(t!==0)return t;let o=e.importanceScore-r.importanceScore;if(o!==0)return o;let n=e.updatedAt.localeCompare(r.updatedAt);if(n!==0)return n;let s=e.createdAt.localeCompare(r.createdAt);return s!==0?s:r.id.localeCompare(e.id)}function vt(r){let e=new Set,t=[];for(let o of r){let n=o.trim();if(!n)continue;let s=n.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(n))}return t}function wt(r){let e=new Map;for(let n of r){if(!Ao.has(n.type)||n.metadata?.supersededBy)continue;let s=Mo(n.content);if(!s)continue;let i=[n.projectId,n.type,s].join("\0"),a=e.get(i)??[];a.push(n),e.set(i,a)}let t=[],o=0;for(let n of e.values()){if(n.length<2)continue;let s=[...n].sort(Ro),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:vt(s.flatMap(c=>c.tags)),mergedSources:vt(s.map(c=>c.source))}),o+=a.length}return{groups:t,duplicates:o}}function We(r){if(r.tags.includes("class:permanent"))return"permanent";if(r.tags.includes("class:task"))return"task";if(r.tags.includes("class:session"))return"session";if(r.tags.includes("class:transient"))return"transient"}function To(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function Io(r){let e=We(r);if(e==="permanent")return 730;if(e==="task")return 180;if(e==="session")return 45;if(e==="transient")return 7;switch(r.type){case"rule":return 730;case"decision":return 365;case"code":return 180;case"todo":return 120;case"summary":return 45;case"activity":return 14}}function jo(r){return We(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function _o(r){let e=r.normalize("NFKC").toLowerCase().trim();return e.length<8?!0:[/^ok(?:ay)?[.!]?$/u,/^done[.!]?$/u,/^thanks?[.!]?$/u,/^test(?:ing)?[.!]?$/u,/^npm notice\b/u,/^changed \d+ packages?/u,/^packages? are looking for funding/u].some(t=>t.test(e))}function kt(r,e=Date.now()){let t=50,o=[],n=We(r);switch(n==="permanent"?(t+=25,o.push("permanent project knowledge")):n==="task"?(t+=15,o.push("active task knowledge")):n==="session"?(t+=2,o.push("session-scoped knowledge")):n==="transient"&&(t-=25,o.push("transient knowledge")),r.importance){case"critical":t+=25,o.push("critical importance");break;case"high":t+=15,o.push("high importance");break;case"normal":break;case"temporary":t-=15,o.push("temporary importance");break}(r.type==="rule"||r.type==="decision")&&(t+=10,o.push("durable knowledge type"));let s=r.content.trim().length;s<12?(t-=30,o.push("very short content")):s<30?(t-=10,o.push("limited context")):s<=1200?(t+=8,o.push("useful context density")):s>5e3&&(t-=15,o.push("excessively large memory")),_o(r.content)&&(t-=35,o.push("matches transient/noise pattern"));let i=r.metadata?.consolidation;i&&typeof i=="object"&&Array.isArray(i.sources)&&i.sources.length>1&&(t+=10,o.push("confirmed across multiple sources"));let a=To(r,e)>=Io(r);a&&(t-=15,o.push("stale for lifecycle class"));let c=jo(r);t=Math.max(0,Math.min(100,Math.round(t)));let d;t>=80?d="trusted":t>=55?d="useful":t>=30?d="weak":d="noise";let l=r.importance==="temporary"||r.type==="activity"||n==="transient";return{score:t,tier:d,stale:a,protected:c,pruneEligible:!c&&(d==="noise"&&l||a&&(d==="noise"||d==="weak")),reasons:o}}var Lo={critical:100,high:75,normal:50,temporary:20},No={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function xt(r,e,t=new Date){let o;if(e==="temporary"&&(o=30),r==="activity"&&(o=Math.min(o??14,14)),r==="summary"&&(o=Math.min(o??30,30)),!!o)return new Date(t.getTime()+o*864e5).toISOString()}function Ve(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Oo(r){return!!r.metadata?.supersededBy}function Ye(r,e=Date.now()){return!Ve(r,e)&&!Oo(r)}function z(r,e=Date.now()){if(!Ye(r,e))return 0;let t=Lo[r.importance];if(r.importance==="critical")return t;let o=No[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/o);return t*i}var de=class{memories=new Map;sanitizer=new O;conflicts=new le;remember(e){let t=new Date().toISOString(),o=this.sanitizer.sanitize(e.content.trim()).text,n=e.importance??pt(e.type,o),s={id:Fo(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:mt(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??xt(e.type,n,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},i=this.conflicts.findSuperseded(s,this.list(e.projectId));if(i.length){s.metadata={...s.metadata??{},supersedes:i.map(a=>a.id)};for(let a of i)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:s.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let o of e)o?.id&&(this.memories.set(o.id,o),t++);return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,o)=>o.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>Ye(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(o=>o.type===t)}search(e){let t=e.query.trim().toLowerCase(),o=e.limit??10,n=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(s=>{if(e.types&&!e.types.includes(s.type))return!1;let i=z(s);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>s.tags.includes(c)))}).map(s=>{let i=s.content.toLowerCase(),a=n.filter(l=>i.includes(l)).length,c=n.length===0?0:a/n.length,d=z(s)/500;return{memory:s,score:c+d,source:"memory"}}).filter(s=>t.length===0||s.score>0).sort((s,i)=>i.score-s.score).slice(0,o)}consolidate(e,t=Date.now()){let o=wt(this.list(e)),n=[],s=0;for(let i of o.groups){let a=this.memories.get(i.canonicalId);if(a){a.tags=i.mergedTags,a.metadata={...a.metadata??{},consolidation:{version:1,consolidatedAt:new Date(t).toISOString(),mergedIds:i.duplicateIds,sources:i.mergedSources}},this.memories.set(a.id,a),n.push(a.id);for(let c of i.duplicateIds)this.memories.delete(c)&&(s+=1)}}return{groupsConsolidated:n.length,duplicatesRemoved:s,canonicalIds:n}}reviewLifecycle(e,t=Date.now()){let o={reviewed:0,trusted:0,useful:0,weak:0,noise:0,stale:0,protected:0,pruned:0};for(let n of this.list(e)){let s=kt(n,t);o.reviewed+=1,o[s.tier]+=1,s.stale&&(o.stale+=1),s.protected&&(o.protected+=1),n.metadata={...n.metadata??{},lifecycle:{version:1,reviewedAt:new Date(t).toISOString(),qualityScore:s.score,tier:s.tier,stale:s.stale,protected:s.protected,reasons:s.reasons}},this.memories.set(n.id,n),s.pruneEligible&&this.memories.delete(n.id)&&(o.pruned+=1)}return o}pruneExpired(e,t=Date.now()){let o=0;for(let[n,s]of this.memories)s.projectId===e&&Ve(s,t)&&(this.memories.delete(n),o++);return o}pruneSuperseded(e,t=30,o=Date.now()){let n=0,s=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;o-new Date(c).getTime()>=s&&(this.memories.delete(i),n++)}return n}clearProject(e){let t=0;for(let[o,n]of this.memories)n.projectId===e&&(this.memories.delete(o),t++);return t}};function F(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var me=class{score(e,t){let o=F(e),n=F([t.content,...t.tags??[],t.type].join(" "));if(o.length===0||n.length===0)return 0;let s=new Map;for(let a of n)s.set(a,(s.get(a)??0)+1);let i=0;for(let a of o){let c=s.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/o.length}};function Ct(r,e=Date.now()){let t=r.updatedAt??r.createdAt,o=new Date(t).getTime();if(!Number.isFinite(o))return 0;let n=Math.max(0,e-o)/864e5;return Math.exp(-Math.LN2*n/30)}function Et(r){return z(r)/100}var Do={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function Pt(r){return Do[r]??.4}var pe=class{analyze(e){let t=e.toLowerCase(),o=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&o.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&o.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&o.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&o.push("summary"),{query:e,preferredTypes:o}}};var ue=class{bm25=new me;analyzer=new pe;search(e,t,o={}){let n=o.topK??8,s=o.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(o.types?.length&&!o.types.includes(c.type))continue;let d=this.bm25.score(e,c),l=Ct(c),u=Et(c),p=Pt(c.type);i.preferredTypes.includes(c.type)&&(p=Math.min(1,p+.25));let f=d*.55+u*.2+l*.15+p*.1;d<=0||f<s||a.push({memory:c,score:f,scores:{keyword:d,recency:l,importance:u,type:p}})}return a.sort((c,d)=>d.score-c.score).slice(0,n)}};var fe=class{build(e,t=6e3){let o=[],n=0;for(let s of e){let i=s.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(n+a.length>t)break;o.push(a),n+=a.length}return o.join(`
|
|
4
|
-
`)}};var ge=class{constructor(e){this.memory=e}memory;searcher=new ue;contextBuilder=new fe;search(e,t,o={}){return this.searcher.search(t,this.memory.list(e),o)}context(e,t,o={}){let n=this.search(e,t,o);return this.contextBuilder.build(n)}};var At=[{id:"openai-compatible",label:"OpenAI-compatible",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"alibaba",label:"Alibaba / DashScope",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"openrouter",label:"OpenRouter",defaultBaseUrl:"https://openrouter.ai/api/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"groq",label:"Groq",defaultBaseUrl:"https://api.groq.com/openai/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"deepseek",label:"DeepSeek",defaultBaseUrl:"https://api.deepseek.com",defaultModel:"deepseek-v4-flash",requiresApiKey:!0,transport:"openai-compatible"},{id:"nvidia",label:"NVIDIA NIM",defaultBaseUrl:"https://integrate.api.nvidia.com/v1",defaultModel:"deepseek-ai/deepseek-v4-pro",requiresApiKey:!0,transport:"openai-compatible"},{id:"gemini",label:"Gemini",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta",requiresApiKey:!0,transport:"gemini"},{id:"huggingface",label:"Hugging Face",defaultBaseUrl:"https://router.huggingface.co/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"ollama",label:"Ollama / Local",defaultBaseUrl:"http://127.0.0.1:11434/v1",requiresApiKey:!1,transport:"openai-compatible"},{id:"custom",label:"Custom endpoint",requiresApiKey:!1,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"cloudflare",label:"Cloudflare Workers AI",requiresApiKey:!0,requiresAccountId:!0,transport:"cloudflare"}];function _(r){let e=At.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function q(r){return At.some(e=>e.id===r)}function m(r){return process.env[r]?.trim()||void 0}function h(...r){return r.find(e=>!!e?.trim())}function Mt(){if(m("GROQ_API_KEY"))return"groq";if(m("DEEPSEEK_API_KEY"))return"deepseek";if(m("NVIDIA_API_KEY")||m("NVIDIA_NIM_API_KEY"))return"nvidia";if(m("OPENROUTER_API_KEY"))return"openrouter";if(m("ALIBABA_API_KEY")||m("DASHSCOPE_API_KEY"))return"alibaba";if(m("GEMINI_API_KEY")||m("GOOGLE_API_KEY"))return"gemini";if(m("CLOUDFLARE_API_TOKEN")&&m("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(m("HF_TOKEN"))return"huggingface";if(m("OLLAMA_MODEL")||m("OLLAMA_BASE_URL"))return"ollama"}function Rt(){let r=m("TOOLNET_LLM_PROVIDER");return r&&q(r)?r:Mt()??"openai-compatible"}function he(r){let e=_(r);switch(r){case"alibaba":return{provider:r,apiKey:h(m("ALIBABA_API_KEY"),m("DASHSCOPE_API_KEY")),baseUrl:h(m("ALIBABA_BASE_URL"),m("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:h(m("ALIBABA_MODEL"),m("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:m("OPENROUTER_API_KEY"),baseUrl:h(m("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:m("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:m("GROQ_API_KEY"),baseUrl:h(m("GROQ_BASE_URL"),e.defaultBaseUrl),model:m("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:m("DEEPSEEK_API_KEY"),baseUrl:h(m("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:h(m("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:h(m("NVIDIA_API_KEY"),m("NVIDIA_NIM_API_KEY")),baseUrl:h(m("NVIDIA_BASE_URL"),m("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:h(m("NVIDIA_MODEL"),m("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:h(m("GEMINI_API_KEY"),m("GOOGLE_API_KEY")),baseUrl:h(m("GEMINI_BASE_URL"),e.defaultBaseUrl),model:m("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:m("HF_TOKEN"),baseUrl:h(m("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:h(m("HF_LLM_MODEL"),m("HF_MODEL"))};case"ollama":return{provider:r,apiKey:m("OLLAMA_API_KEY"),baseUrl:h(m("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:m("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:m("CLOUDFLARE_ACCOUNT_ID"),apiKey:m("CLOUDFLARE_API_TOKEN"),baseUrl:m("CLOUDFLARE_AI_BASE_URL"),model:m("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:m("CUSTOM_AI_API_KEY"),baseUrl:m("CUSTOM_AI_BASE_URL"),model:m("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:h(m("OPENAI_API_KEY"),m("MODEL_API_KEY")),baseUrl:h(m("OPENAI_BASE_URL"),m("MODEL_BASE_URL")),model:h(m("OPENAI_MODEL"),m("MODEL_NAME"))}}}function $o(){let r=m("TOOLNET_LLM_PROVIDER"),e=r&&q(r)?r:Rt(),t=_(e),o=he(e);return{provider:e,apiKey:h(m("TOOLNET_LLM_API_KEY"),o.apiKey),baseUrl:h(m("TOOLNET_LLM_BASE_URL"),o.baseUrl,t.defaultBaseUrl),model:h(m("TOOLNET_LLM_MODEL"),o.model,t.defaultModel),accountId:h(m("TOOLNET_LLM_ACCOUNT_ID"),o.accountId)}}function Ko(){let r=m("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&q(r)?r:m("HF_TOKEN")||m("HF_EMBEDDING_MODEL")?"huggingface":"local"}function Go(){let r=Ko();if(r==="local")return{provider:"local",model:h(m("TOOLNET_EMBEDDING_MODEL"),m("LOCAL_EMBEDDING_MODEL"))};let e=_(r),t,o,n,s;switch(r){case"huggingface":t=m("HF_TOKEN"),o=m("HF_INFERENCE_BASE_URL"),n=m("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=m("OPENAI_API_KEY"),o=m("OPENAI_BASE_URL"),n=m("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=m("CLOUDFLARE_API_TOKEN"),o=m("CLOUDFLARE_AI_BASE_URL"),n=m("CLOUDFLARE_EMBEDDING_MODEL"),s=m("CLOUDFLARE_ACCOUNT_ID");break;default:t=he(r).apiKey,o=he(r).baseUrl,n=m(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let i=h(m("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),a=h(m("TOOLNET_EMBEDDING_BASE_URL"),o,e.defaultBaseUrl),c=r==="cloudflare"&&!a&&i?`https://api.cloudflare.com/client/v4/accounts/${i}/ai/v1`:a;return{provider:r,apiKey:h(m("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:h(m("TOOLNET_EMBEDDING_MODEL"),n),accountId:i}}function W(){let r=$o(),e=Go();return{llm:r,embedding:e,legacy:{llm:!m("TOOLNET_LLM_PROVIDER")&&!!Mt(),embedding:!m("TOOLNET_EMBEDDING_PROVIDER")&&!!(m("HF_TOKEN")||m("HF_EMBEDDING_MODEL"))}}}function Tt(r=Rt()){let e=W().llm;if(r===e.provider)return{id:r,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId};let t=he(r);return{id:r,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}function H(r,e){return m(`TOOLNET_LLM_FALLBACK_${r}_${e}`)}function It(){let r=[];for(let e of[1,2]){let t=H(e,"PROVIDER");if(!t||!q(t))continue;let o=_(t);r.push({slot:e,config:{provider:t,apiKey:H(e,"API_KEY"),baseUrl:h(H(e,"BASE_URL"),o.defaultBaseUrl),model:h(H(e,"MODEL"),o.defaultModel),accountId:H(e,"ACCOUNT_ID")}})}return r}function jt(){let r=m("TOOLNET_LLM_FALLBACK_COOLDOWN_MS"),e=m("TOOLNET_LLM_MAX_RETRIES"),t=Number(r??6e4),o=Number(e??1);return{cooldownMs:Number.isFinite(t)&&t>=0?t:6e4,maxRetries:Number.isFinite(o)&&o>=0?Math.floor(o):1}}var ye=class{constructor(e){this.options=e}options;name="gemini";async embed(e){let t=this.options.model.replace(/^models\//,""),n=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(t)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,s=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!s.ok)throw new Error(`Gemini embedding failed: ${s.status} ${await s.text()}`);let a=(await s.json()).embedding?.values;if(!Array.isArray(a)||a.length===0)throw new Error("Gemini embedding returned invalid response");return a}async embedMany(e){let t=[];for(let o of e)t.push(await this.embed(o));return t}};import{createHash as Uo}from"node:crypto";var be=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),o=e.toLowerCase().split(/\s+/).filter(Boolean);for(let n of o){let i=Uo("sha256").update(n).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Bo(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function Bo(r){let e=Math.sqrt(r.reduce((t,o)=>t+o*o,0));return e===0?r:r.map(t=>t/e)}var Se=class{constructor(e){this.options=e;this.dimensions=e.dimensions}options;name="openai-compatible";dimensions;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=this.options.baseUrl.replace(/\/+$/,""),o=await fetch(`${t}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{}},body:JSON.stringify({model:this.options.model,input:e})});if(!o.ok)throw new Error(`Embedding failed: ${o.status} ${await o.text()}`);let s=(await o.json()).data?.sort((i,a)=>(i.index??0)-(a.index??0)).map(i=>i.embedding);if(!s||s.length!==e.length||s.some(i=>!Array.isArray(i)))throw new Error("Embedding provider returned invalid response");return s}};var ve=class{constructor(e){this.options=e}options;name="huggingface";dimensions=384;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,o=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:e,options:{wait_for_model:!0}})});if(!o.ok)throw new Error(`HF embedding failed: ${o.status} ${await o.text()}`);let n=await o.json();if(!Array.isArray(n))throw new Error("HF embedding returned invalid response");return n.map(s=>zo(s))}};function zo(r){if(!Array.isArray(r))throw new Error("Invalid embedding");if(r.length>0&&typeof r[0]=="number")return r;if(r.length>0&&Array.isArray(r[0])){let e=r;if(e.length===0)return[];let t=e[0].length,o=new Array(t).fill(0);for(let n of e)for(let s=0;s<t;s++)o[s]+=n[s]??0;for(let n=0;n<t;n++)o[n]/=e.length;return o}throw new Error("Unsupported embedding shape")}var Qe=class{constructor(e,t=new be){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function qo(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Ho(){let r=W().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new ve({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new ye({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=qo(r.accountId)),e&&r.model?new Se({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function _t(){return new Qe(Ho())}import*as k from"typescript";var D=class{symbols=new Map;edges=new Map;addSymbol(e){this.symbols.set(e.id,e)}addEdge(e){this.edges.set(e.id,e)}getSymbol(e){return this.symbols.get(e)}findByName(e,t){return[...this.symbols.values()].filter(o=>o.projectId===e&&(o.name===t||o.qualifiedName===t))}allSymbols(e){return[...this.symbols.values()].filter(t=>t.projectId===e)}allEdges(e){return[...this.edges.values()].filter(t=>t.projectId===e)}import(e,t){for(let o of e)this.addSymbol(o);for(let o of t)this.addEdge(o)}clearProject(e){for(let[t,o]of this.symbols)o.projectId===e&&this.symbols.delete(t);for(let[t,o]of this.edges)o.projectId===e&&this.edges.delete(t)}};function we(r,e){let t=r.allSymbols(e),o=r.allEdges(e),n=i=>t.filter(a=>a.type===i).length,s=i=>o.filter(a=>a.type===i).length;return{files:n("file"),classes:n("class"),interfaces:n("interface"),functions:n("function"),methods:n("method"),properties:n("property"),routes:n("route"),symbols:t.length,edges:o.length,calls:s("CALLS"),callReferences:s("CALL_REFERENCE"),imports:s("IMPORTS"),inherits:s("INHERITS"),implements:s("IMPLEMENTS"),usesType:s("USES_TYPE"),tests:s("TESTS"),routeEdges:s("ROUTE"),writes:s("WRITES")}}var ke=class{constructor(e){this.graph=e}graph;callees(e,t,o=3){return this.walk(e,t,"out",o)}callers(e,t,o=3){return this.walk(e,t,"in",o)}walk(e,t,o,n){let s=[],i=new Set([t]),a=[{id:t,depth:0}],c=this.graph.allEdges(e).filter(d=>d.type==="CALLS"||d.type==="CALL_REFERENCE");for(;a.length;){let d=a.shift();if(d.depth>=n)continue;let l=o==="out"?c.filter(u=>u.from===d.id):c.filter(u=>u.to===d.id);for(let u of l){let p=o==="out"?u.to:u.from;if(i.has(p))continue;i.add(p);let f=this.graph.getSymbol(p);if(!f)continue;let S=d.depth+1;s.push({symbol:f,depth:S}),a.push({id:p,depth:S})}}return s}};var xe=class{constructor(e){this.graph=e}graph;findSymbol(e,t){return this.graph.findByName(e,t)}findCallers(e,t){return this.graph.allEdges(e).filter(n=>n.type==="CALLS"&&n.to===t).map(n=>n.from).map(n=>this.graph.getSymbol(n)).filter(n=>!!n)}};var Ce=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Set([t]),i=[{id:t,depth:0}],a=[];for(;i.length;){let c=i.shift();if(c.depth>=o)continue;let d=n.filter(l=>l.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(l.type));for(let l of d){if(s.has(l.from))continue;s.add(l.from);let u=this.graph.getSymbol(l.from);if(!u)continue;let p=c.depth+1;a.push({symbol:u,depth:p,relation:l.type}),i.push({id:l.from,depth:p})}}return a}};function Qo(r,e){return e.ranges.length===0?!0:typeof r.startLine!="number"||typeof r.endLine!="number"?!1:e.ranges.some(t=>r.startLine<=t.endLine&&r.endLine>=t.startLine)}var Ee=class{constructor(e){this.graph=e}graph;map(e,t){let o=this.graph.allSymbols(e),n=[];for(let s of t){let i=o.filter(d=>d.filePath===s.filePath),c=i.filter(d=>d.type!=="file").filter(d=>Qo(d,s));if(c.length===0){let d=i.find(l=>l.type==="file");d&&n.push({symbol:d,fileStatus:s.status,direct:!0});continue}for(let d of c)n.push({symbol:d,fileStatus:s.status,direct:!0})}return n}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var Jo={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Zo(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function Lt(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Pe=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Map,i=0;for(let l of t){l.fileStatus==="deleted"?i+=8:l.fileStatus==="renamed"?i+=5:i+=2,l.symbol.type==="interface"&&(i+=5),l.symbol.type==="class"&&(i+=3);let u=new Set([l.symbol.id]),p=[{id:l.symbol.id,depth:0}];for(;p.length;){let f=p.shift();if(f.depth>=o)continue;let S=n.filter(v=>v.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(v.type));for(let v of S){if(u.has(v.from))continue;u.add(v.from);let A=this.graph.getSymbol(v.from);if(!A)continue;let M=f.depth+1,ne=`${l.symbol.id}:${A.id}`;s.set(ne,{symbol:A,relation:v.type,depth:M,sourceSymbolId:l.symbol.id});let j=Jo[v.type]??1;i+=Math.max(1,j-(M-1)),p.push({id:A.id,depth:M})}}}let a=[...s.values()].sort((l,u)=>l.depth-u.depth),c=[...new Set(a.map(l=>l.symbol.filePath))],d=c.filter(Lt);return d.length===0&&d.push(...c.filter(l=>!Lt(l)).slice(0,10)),{risk:Zo(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:d}}};import{execFile as Xo}from"node:child_process";import{promisify as en}from"node:util";var Je=en(Xo);function tn(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let o of r.matchAll(t)){let n=Number(o[1]),s=Number(o[2]??1);e.push({startLine:n,endLine:Math.max(n,n+s-1)})}return e}function rn(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function Nt(r){let e="";try{e=(await Je("git",["diff","HEAD","--name-status","--no-renames"],{cwd:r,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let o of e.split(/\r?\n/).filter(Boolean)){let[n,...s]=o.split(" "),i=s.at(-1);if(!i)continue;let a="";try{a=(await Je("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:rn(n),ranges:tn(a)})}try{let o=await Je("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let n of o.stdout.split(/\r?\n/).filter(Boolean))t.some(s=>s.filePath===n)||t.push({filePath:n,status:"added",ranges:[]})}catch{}return t}var Ae=class{constructor(e){this.graph=e;this.mapper=new Ee(e),this.blast=new Pe(e)}graph;mapper;blast;async analyzeGitDiff(e,t,o={}){let n=await Nt(t),s=this.mapper.map(e,n),i=this.blast.analyze(e,s,o.maxDepth??4);return{mode:"git_diff",changes:n,...i}}analyzeFile(e,t,o={}){let n=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,n,o.maxDepth??4)}}};var V=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};import{createHash as on}from"node:crypto";import{readFile as nn}from"node:fs/promises";import{join as sn}from"node:path";function Ot(r){return on("sha256").update(r).digest("hex")}var Me=class{sanitizer=new O;async build(e,t,o,n={}){let s=n.maxLines??80,i=n.overlapLines??10,a=new Map;for(let d of o){let l=a.get(d.filePath)??[];l.push(d),a.set(d.filePath,l)}let c=[];for(let[d,l]of a){let u;try{u=await nn(sn(t,d),"utf8")}catch{continue}let p=u.split(/\r?\n/),f=l.filter(S=>S.type!=="file"&&typeof S.startLine=="number"&&typeof S.endLine=="number");if(f.length>0)for(let S of f)c.push(...this.chunkRange({projectId:e,filePath:d,lines:p,symbol:S,startLine:S.startLine,endLine:S.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:d,lines:p,startLine:1,endLine:Math.max(1,p.length),maxLines:s,overlapLines:i}))}return c}chunkRange(e){let{projectId:t,filePath:o,lines:n,symbol:s,maxLines:i}=e,a=Math.min(e.overlapLines,Math.max(0,i-1)),c=Math.max(1,e.startLine),d=Math.min(n.length,Math.max(c,e.endLine)),l=[],u=c,p=0;for(;u<=d;){let f=Math.min(d,u+i-1),S=n.slice(u-1,f).join(`
|
|
5
|
-
`).trim();if(S){let v=this.sanitizer.sanitize(S).text,A=Ot(v),M=[t,o,s?.id??"file",String(p),A].join(":");l.push({id:Ot(M).slice(0,32),projectId:t,filePath:o,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:u,endLine:f,content:v,contentHash:A})}if(f>=d)break;u=f-a+1,p++}return l}};var Re=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","chunks","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var Te=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var Ie=class{records=new Map;upsert(e){this.records.set(e.id,e)}get(e){return this.records.get(e)}has(e){return this.records.has(e)}remove(e){return this.records.delete(e)}clearProject(e){let t=0;for(let[o,n]of this.records)n.projectId===e&&(this.records.delete(o),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let o of e)!o?.id||!o?.projectId||!Array.isArray(o.vector)||(this.records.set(o.id,o),t++);return t}search(e,t,o=10){let n=[];for(let s of this.records.values()){if(s.projectId!==e)continue;let i=an(t,s.vector);n.push({id:s.id,score:i,metadata:s.metadata})}return n.sort((s,i)=>i.score-s.score).slice(0,o)}size(){return this.records.size}};function an(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,o=0,n=0;for(let s=0;s<r.length;s++){let i=r[s]??0,a=e[s]??0;t+=i*a,o+=i*i,n+=a*a}return o===0||n===0?0:t/(Math.sqrt(o)*Math.sqrt(n))}function Ft(r,e){let t=r.toLowerCase().replaceAll("\\","/"),o=e.toLowerCase(),n=/\b(test|tests|spec|fixture|mock)\b/.test(o);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!n?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var je=class{constructor(e){this.options=e}options;vectors=new Ie;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:o,embeddings:n,graph:s,model:i}=this.options,a=new Re(o),c=new Te(o),d=await new Me().build(e,t,s.allSymbols(e));this.chunks.clear();for(let w of d)this.chunks.set(w.id,w);let l=await a.load(e),u=!l||l.chunks.length!==d.length||l.chunks.some(w=>!this.chunks.has(w.id));u&&await a.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:d});let p=await c.load(e),f=0;p&&p.model===i&&(f=this.vectors.importRecords(p.records));let S=new Set(d.map(w=>w.id)),v=0;for(let w of this.vectors.exportProject(e))S.has(w.id)||this.vectors.remove(w.id)&&v++;let A=d.filter(w=>{let L=this.vectors.get(w.id);return L?L.metadata?.contentHash!==w.contentHash:!0}),M=0,ne=8,j=this.vectors.exportProject(e)[0]?.vector.length;for(let w=0;w<A.length;w+=ne){let L=A.slice(w,w+ne),to=L.map(P=>[`file: ${P.filePath}`,P.symbolName?`symbol: ${P.symbolName}`:"",P.symbolType?`type: ${P.symbolType}`:"",P.content].filter(Boolean).join(`
|
|
6
|
-
`)),ro=await n.embedMany(to);for(let P=0;P<L.length;P++){let T=L[P],N=ro[P];if(!(!T||!N||N.length===0)){if(j===void 0&&(j=N.length),N.length!==j){console.warn(`[code-semantic] skip dimension mismatch: ${N.length} != ${j}`);continue}this.vectors.upsert({id:T.id,projectId:e,vector:N,metadata:{contentHash:T.contentHash,filePath:T.filePath,symbolName:T.symbolName,symbolType:T.symbolType,startLine:T.startLine,endLine:T.endLine}}),M++}}}let ze=this.vectors.exportProject(e),lt=M>0||v>0||!p||p.model!==i;return lt&&await c.save({version:1,projectId:e,model:i,dimensions:ze[0]?.vector.length??j??0,updatedAt:new Date().toISOString(),records:ze}),{chunks:d.length,vectorsLoaded:f,vectorsIndexed:M,vectorsRemoved:v,totalVectors:ze.length,savedChunks:u,savedVectors:lt}}async search(e,t=8){let o=await this.options.embeddings.embed(e),n=this.vectors.search(this.options.projectId,o,Math.max(t*4,20)),s=new Set(F(e)),i=[];for(let a of n){let c=this.chunks.get(a.id);if(!c)continue;let d=new Set(F([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),l=0;for(let v of s)d.has(v)&&l++;let u=s.size===0?0:l/s.size,p=Math.max(0,a.score),f=Ft(c.filePath,e),S=(p*.75+u*.25)*f;i.push({chunk:c,score:S,vectorScore:p,lexicalScore:u})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}};import*as x from"typescript";import*as y from"typescript";var Fc=new Set([y.SyntaxKind.EqualsToken,y.SyntaxKind.PlusEqualsToken,y.SyntaxKind.MinusEqualsToken,y.SyntaxKind.AsteriskEqualsToken,y.SyntaxKind.SlashEqualsToken,y.SyntaxKind.PercentEqualsToken,y.SyntaxKind.QuestionQuestionEqualsToken,y.SyntaxKind.AmpersandAmpersandEqualsToken,y.SyntaxKind.BarBarEqualsToken]);function cn(r){return r.replaceAll("\\","/").toLowerCase()}var Y=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=[];for(let i of t){if(i.type!=="route"&&i.type!=="file")continue;let a=this.classify(i,o);a&&n.push({symbolId:i.id,filePath:i.filePath,name:i.name,kind:a.kind,score:a.score,reasons:a.reasons})}let s=new Map;for(let i of n){let a=i.kind==="route"?i.symbolId:i.filePath,c=s.get(a);(!c||i.score>c.score)&&s.set(a,i)}return[...s.values()].sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath))}classify(e,t){let o=cn(e.filePath),n=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let s=null,i=0;if(o.startsWith("bin/"))s="cli",i=100,n.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(o))s="cli",i=90,n.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(o))s="main",i=90,n.push("main/server file");else if(o.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(o))s="runtime",i=75,n.push("runtime bootstrap");else if(/(^|\/)index\.[^.]+$/.test(o)){let c=t.filter(l=>l.to===e.id&&l.type!=="DEFINES").length,d=t.filter(l=>l.from===e.id&&l.type!=="DEFINES").length;(o.startsWith("packages/")||c===0||d>0)&&(s="package",i=o.startsWith("packages/")?70:55,n.push("package/public index"))}return s?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(i+=10,n.push("no incoming dependency")),{kind:s,score:i,reasons:n}):null}};var _e=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Dt=new Set(["CALLS","CALL_REFERENCE"]),E=class{constructor(e){this.graph=e}graph;findSymbols(e,t){let o=t.trim().toLowerCase();return o?this.graph.allSymbols(e).filter(n=>n.name.toLowerCase().includes(o)||(n.qualifiedName?.toLowerCase().includes(o)??!1)||n.filePath.toLowerCase().includes(o)).sort((n,s)=>{let i=n.name.toLowerCase()===o,a=s.name.toLowerCase()===o;return i!==a?i?-1:1:n.filePath.localeCompare(s.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,Dt)}callees(e,t){return this.relatedOutgoing(e,t,Dt)}dependents(e,t){return this.relatedIncoming(e,t,_e)}dependencies(e,t){return this.relatedOutgoing(e,t,_e)}neighborhood(e,t,o=1){let n=this.graph.getSymbol(t);return!n||n.projectId!==e?null:{center:n,incoming:this.walk(e,t,"incoming",o),outgoing:this.walk(e,t,"outgoing",o)}}shortestPath(e,t,o,n=12){let s=this.graph.getSymbol(t),i=this.graph.getSymbol(o);if(!s||!i||s.projectId!==e||i.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===o)return{found:!0,distance:0,symbols:[s],edges:[]};let a=this.graph.allEdges(e).filter(p=>_e.has(p.type)),c=new Map;for(let p of a){let f=c.get(p.from)??[];f.push(p),c.set(p.from,f)}let d=[{id:t,depth:0}],l=new Set([t]),u=new Map;for(;d.length>0;){let p=d.shift();if(!(p.depth>=n)){for(let f of c.get(p.id)??[])if(!l.has(f.to)){if(l.add(f.to),u.set(f.to,{node:p.id,edge:f}),f.to===o)return this.buildPath(t,o,u);d.push({id:f.to,depth:p.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,o){let n=[t],s=[],i=t;for(;i!==e;){let c=o.get(i);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};s.push(c.edge),i=c.node,n.push(i)}n.reverse(),s.reverse();let a=n.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:s.length,symbols:a,edges:s}}walk(e,t,o,n){let s=this.graph.allEdges(e).filter(d=>_e.has(d.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let d=i.shift();if(!(d.depth>=n))for(let l of s){if(!(o==="incoming"?l.to===d.id:l.from===d.id))continue;let p=o==="incoming"?l.from:l.to;if(a.has(p))continue;let f=this.graph.getSymbol(p);f&&(a.add(p),c.push({symbol:f,depth:d.depth+1,via:l}),i.push({id:p,depth:d.depth+1}))}}return c}relatedIncoming(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.to===t&&o.has(s.type)).map(s=>s.from))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}relatedOutgoing(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.from===t&&o.has(s.type)).map(s=>s.to))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};var $t=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function Ze(r){return r.replaceAll("\\","/").toLowerCase()}function ln(r){let e=Ze(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function dn(r){let e=Ze(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var Q=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=new Set(new Y(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||ln(i.filePath)||n.has(i.id)||dn(i)||o.filter(f=>f.to===i.id&&$t.has(f.type)).length>0)continue;let c=o.filter(f=>f.from===i.id&&$t.has(f.type)),d=["no incoming usage edge"],l=50;(i.type==="function"||i.type==="method")&&(l+=20,d.push("callable symbol")),i.type==="property"&&(l-=15),c.length===0&&(l+=10,d.push("no outgoing dependency")),Ze(i.filePath).includes("/internal/")&&(l+=10,d.push("internal implementation")),i.name.startsWith("_")&&(l+=5);let p=l>=75?"high":l>=55?"medium":"low";s.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:p,score:l,reasons:d})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var mn=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),J=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e).filter(i=>mn.has(i.type)),n=new Map(t.map(i=>[i.id,i]));return[...new Set(t.map(i=>i.filePath))].sort().map(i=>{let a=new Set,c=new Set,d=0,l=0;for(let u of o){let p=n.get(u.from),f=n.get(u.to);!p||!f||p.filePath===f.filePath||(p.filePath===i&&(a.add(f.filePath),d++),f.filePath===i&&(c.add(p.filePath),l++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:d,incomingEdges:l}})}};import{homedir as Ln}from"node:os";import{join as Nn}from"node:path";import{DeleteObjectCommand as pn,GetObjectCommand as un,HeadObjectCommand as fn,ListObjectsV2Command as gn,PutObjectCommand as hn,S3Client as yn}from"@aws-sdk/client-s3";import{getSignedUrl as bn}from"@aws-sdk/s3-request-presigner";var Le=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new yn({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new hn({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await bn(this.client,new un({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new fn({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new pn({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new gn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as Kt,mkdir as Sn,readFile as vn,readdir as wn,rm as kn,stat as Gt,writeFile as xn}from"node:fs/promises";import{dirname as Cn,join as En,relative as Ut,resolve as Pn}from"node:path";var Z=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Pn(this.root,t)}async put(e,t){let o=this.path(e);await Sn(Cn(o),{recursive:!0}),await xn(o,t)}async get(e){try{return await vn(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await Kt(this.path(e)),!0}catch{return!1}}async delete(e){await kn(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await Kt(t)}catch{return o}let n=async i=>{let a=await wn(i,{withFileTypes:!0});for(let c of a){let d=En(i,c.name);if(c.isDirectory()){await n(d);continue}let l=await Gt(d);o.push({key:Ut(this.root,d),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await Gt(t);return s.isDirectory()?await n(t):o.push({key:Ut(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};import{DeleteObjectCommand as An,GetObjectCommand as Mn,HeadObjectCommand as Rn,ListObjectsV2Command as Tn,PutObjectCommand as In,S3Client as jn}from"@aws-sdk/client-s3";import{getSignedUrl as _n}from"@aws-sdk/s3-request-presigner";var X=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new jn({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new In({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await _n(this.client,new Mn({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Rn({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new An({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new Tn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function Xe(r,e){return console.warn(e),new Z(r)}function Bt(r){let e=r.localRoot??Nn(Ln(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new X({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Xe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new X({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Xe(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new Le({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Xe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new Z(e)}var Ne=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function On(r){return new Promise(e=>setTimeout(e,r))}async function zt(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,s;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(s=a,i>=t)break;let c=Math.min(n,o*2**(i-1)),d=Math.floor(Math.random()*Math.max(1,c*.2));await On(c+d)}throw s}var Fn=new Set(["put","get","getText","delete","list"]);function qt(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:Fn.has(o)?(...s)=>zt(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}function Ht(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Wt(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var Oe=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=Ht(n??o),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),o=t,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(o=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
|
|
7
|
-
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Wt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{McpServer as Fs}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Ds}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as Vt}from"zod";var Yt={query:Vt.string(),limit:Vt.number().int().min(1).max(20).optional()};async function Qt(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(o=>({id:o.memory.id,type:o.memory.type,content:o.memory.content,importance:o.memory.importance,score:o.score,tags:o.memory.tags}))}import{z as ee}from"zod";var Jt={type:ee.enum(["activity","decision","rule","todo","summary"]),content:ee.string().min(1),tags:ee.array(ee.string()).optional(),importance:ee.enum(["critical","high","normal","temporary"]).optional()};async function Zt(r,e){let t=r.memory.remember({projectId:r.project.id,type:e.type,content:e.content,tags:e.tags,importance:e.importance,source:"mcp"});return r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),t}import{z as Dn}from"zod";var Xt={id:Dn.string().min(1)};async function er(r,e){let t=r.memory.delete(e.id);return t&&r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),{deleted:t}}import{z as $n}from"zod";var tr={name:$n.string().min(1)};async function rr(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as Kn}from"zod";function R(r,e){let t=r.graph.getSymbol(e);if(t&&t.projectId===r.project.id)return t;let o=new E(r.graph),n=o.findSymbols(r.project.id,e).find(s=>s.name===e||s.qualifiedName===e);return n||(o.findSymbols(r.project.id,e)[0]??null)}function C(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var or={symbolId:Kn.string().min(1)};async function nr(r,e){let t=R(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let n=new E(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:C(t),count:n.length,callers:n.map(C)}}import{z as sr}from"zod";var ir={query:sr.string().min(1),limit:sr.number().int().min(1).max(50).optional()};async function ar(r,e){let t=e.query.toLowerCase(),o=e.limit??20;return r.graph.allSymbols(r.project.id).filter(n=>n.name.toLowerCase().includes(t)||n.qualifiedName?.toLowerCase().includes(t)||n.filePath.toLowerCase().includes(t)).slice(0,o)}import{z as cr}from"zod";var lr={query:cr.string().optional(),memoryLimit:cr.number().int().min(1).max(20).optional()};async function dr(r,e){let t=we(r.graph,r.project.id),o=r.memory.recent(r.project.id,5),n=e.query?r.retrieval.search(r.project.id,e.query,{topK:e.memoryLimit??5}):[];return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:t,recent:o,relevant:n.map(s=>s.memory)}}import{z as Un}from"zod";var Gn=["memories/current.json","vectors/current.json","graph/current.json","graph/manifest.json","graph/resolution/current.json","code/chunks/current.json","code/vectors/current.json","code/architecture/current.json","code/architecture/entry-points.json","code/architecture/hotspots.json","code/architecture/layers.json","code/architecture/clusters.json","code/analysis/current.json","code/analysis/dead-code.json","code/analysis/dependencies.json","code/visualization/graph.json"],I=class{constructor(e){this.storage=e}storage;projectPrefix(e){return`projects/${e}`}snapshotPrefix(e,t){return[this.projectPrefix(e),"snapshots",t].join("/")}async create(e,t="automatic",o){let n=new Date().toISOString(),s=n.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,s),c=[];for(let l of Gn){let u=`${i}/${l}`,p=await this.storage.get(u);p&&(await this.storage.put(`${a}/${l}`,p,"application/json"),c.push(l))}if(c.length===0)return null;let d={version:1,id:s,projectId:e,createdAt:n,reason:t,objects:c,metadata:o};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(d,null,2),"application/json"),d}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),n=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),s=[];for(let i of n){let a=await this.storage.getText(i.key);if(a)try{s.push(JSON.parse(a))}catch{}}return s.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.getText(`${o}/snapshot.json`);if(!n)throw new Error(`Snapshot not found: ${t}`);let s=JSON.parse(n);if(s.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of s.objects){let d=await this.storage.get(`${o}/${c}`);d&&(await this.storage.put(`${i}/${c}`,d,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.list(o);for(let s of n)await this.storage.delete(s.key);return n.length}async prune(e,t=10){let n=(await this.list(e)).slice(t),s=0;for(let i of n)await this.remove(e,i.id),s++;return s}};var mr={reason:Un.string().optional()};async function pr(r,e){if(!r.storage)throw new Error("Storage unavailable");return new I(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function ur(r){if(!r.storage)throw new Error("Storage unavailable");return new I(r.storage).list(r.project.id)}import{z as Bn}from"zod";var fr={snapshotId:Bn.string().min(1)};async function gr(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new I(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as et}from"zod";var hr={symbolId:et.string().min(1),direction:et.enum(["callers","callees"]).optional(),depth:et.number().int().min(1).max(10).optional()};async function yr(r,e){let t=new ke(r.graph),o=e.direction??"callees",n=e.depth??3,s=o==="callers"?t.callers(r.project.id,e.symbolId,n):t.callees(r.project.id,e.symbolId,n);return{direction:o,depth:n,results:s.map(i=>({id:i.symbol.id,name:i.symbol.name,qualifiedName:i.symbol.qualifiedName,type:i.symbol.type,filePath:i.symbol.filePath,depth:i.depth}))}}import{z as br}from"zod";var Sr={symbolId:br.string().min(1),depth:br.number().int().min(1).max(10).optional()};async function vr(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let n=new Ce(r.graph).analyze(r.project.id,t.id,e.depth??4);return{found:!0,target:{id:t.id,name:t.name,qualifiedName:t.qualifiedName,filePath:t.filePath,type:t.type},impacts:n.map(s=>({id:s.symbol.id,name:s.symbol.name,qualifiedName:s.symbol.qualifiedName,filePath:s.symbol.filePath,type:s.symbol.type,relation:s.relation,depth:s.depth}))}}async function wr(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:we(r.graph,r.project.id)}}import{z as kr}from"zod";var xr={filePath:kr.string().min(1),direction:kr.enum(["dependencies","dependents","both"]).optional()};async function Cr(r,e){let o=new J(r.graph).analyze(r.project.id).find(c=>c.filePath===e.filePath);if(!o)return{found:!1,filePath:e.filePath,dependencies:[],dependents:[]};let n=r.graph.allSymbols(r.project.id).filter(c=>c.type==="file"),s=new Map(n.map(c=>[c.filePath,c])),i=c=>({id:s.get(c)?.id??c,filePath:c}),a=e.direction??"both";return{found:!0,filePath:o.filePath,outgoingEdges:o.outgoingEdges,incomingEdges:o.incomingEdges,dependencies:a==="dependents"?[]:o.dependencies.map(i),dependents:a==="dependencies"?[]:o.dependents.map(i)}}import{z as Er}from"zod";var Pr={query:Er.string().min(1),limit:Er.number().int().min(1).max(20).optional()};async function Ar(r,e){return r.codeSemantic?{available:!0,results:(await r.codeSemantic.search(e.query,e.limit??8)).map(o=>({id:o.chunk.id,filePath:o.chunk.filePath,symbol:o.chunk.symbolName,symbolType:o.chunk.symbolType,startLine:o.chunk.startLine,endLine:o.chunk.endLine,score:o.score,vectorScore:o.vectorScore,lexicalScore:o.lexicalScore,content:o.chunk.content}))}:{available:!1,results:[]}}import{z as tt}from"zod";var Mr={mode:tt.enum(["git_diff","file"]).optional(),filePath:tt.string().optional(),depth:tt.number().int().min(1).max(10).optional()};async function Rr(r,e){let t=new Ae(r.graph);if((e.mode??(e.filePath?"file":"git_diff"))==="file"){if(!e.filePath)throw new Error("filePath is required when mode=file");return t.analyzeFile(r.project.id,e.filePath,{maxDepth:e.depth})}return t.analyzeGitDiff(r.project.id,r.project.rootPath,{maxDepth:e.depth})}import{z as zn}from"zod";var Tr={symbol:zn.string().min(1)};async function Ir(r,e){let t=R(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let n=new E(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:C(t),count:n.length,dependents:n.map(C)}}import{z as rt}from"zod";var jr={from:rt.string().min(1),to:rt.string().min(1),maxDepth:rt.number().int().min(1).max(30).optional()};async function _r(r,e){let t=R(r,e.from),o=R(r,e.to);if(!t||!o)return{found:!1,fromFound:!!t,toFound:!!o,path:[],edges:[]};let s=new E(r.graph).shortestPath(r.project.id,t.id,o.id,e.maxDepth??12);return{found:s.found,distance:s.distance,from:C(t),to:C(o),path:s.symbols.map(C),edges:s.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as ot}from"zod";var Lr={symbol:ot.string().min(1),depth:ot.number().int().min(1).max(5).optional(),limit:ot.number().int().min(1).max(200).optional()};async function Nr(r,e){let t=R(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let n=new E(r.graph).neighborhood(r.project.id,t.id,e.depth??1);if(!n)return{found:!1,query:e.symbol};let s=e.limit??50;return{found:!0,center:C(n.center),incomingCount:n.incoming.length,outgoingCount:n.outgoing.length,incoming:n.incoming.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)})),outgoing:n.outgoing.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:C(i.symbol)}))}}import{z as nt}from"zod";var Fr={confidence:nt.enum(["high","medium","low","all"]).optional(),filePath:nt.string().min(1).optional(),limit:nt.number().int().min(1).max(500).optional()},Or={high:3,medium:2,low:1};async function Dr(r,e){let o=new Q(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=Or[e.confidence];o=o.filter(a=>Or[a.confidence]>=i)}e.filePath&&(o=o.filter(i=>i.filePath===e.filePath));let n=o.length,s=e.limit??100;return{total:n,high:o.filter(i=>i.confidence==="high").length,medium:o.filter(i=>i.confidence==="medium").length,low:o.filter(i=>i.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:o.slice(0,s)}}import{z as Yr}from"zod";import{existsSync as es,readFileSync as ts}from"node:fs";import{join as rs}from"node:path";import{existsSync as qn,mkdirSync as ap,readFileSync as Hn,renameSync as cp,writeFileSync as lp}from"node:fs";import{dirname as mp,join as Wn}from"node:path";function Vn(r){return Wn(r.rootPath,".toolnet","work","current.json")}function st(r){let e=Vn(r);if(!qn(e))return null;try{let t=JSON.parse(Hn(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Yn,mkdirSync as fp,readFileSync as Qn,renameSync as gp,writeFileSync as hp}from"node:fs";import{dirname as bp,join as Jn}from"node:path";function Zn(r){return Jn(r.rootPath,".toolnet","context","session-origin.json")}function it(r){let e=Zn(r);if(!Yn(e))return null;try{let t=JSON.parse(Qn(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Xn(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Fe(r){let e=Xn(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),o=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&o?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}var os={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,progress:50,test:45,goal:35}},ns={handoff:18,"session-origin":14,"work-state":8};function ss(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function g(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function is(r){let e=rs(r.rootPath,".toolnet","work","handoff-latest.json");if(!es(e))return null;try{let o=JSON.parse(ts(e,"utf8")).continuity;return o?.schema!=="toolnet.handoff.v2"||o.project.id!==r.id?null:o}catch{return null}}function as(r){let e=is(r);if(!e)return[];let t=[];g(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.goal&&g(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&g(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&g(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&g(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&g(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let o of e.blockers)g(t,{kind:"blocker",value:o,source:"handoff"});for(let o of e.decisions)g(t,{kind:"decision",value:o,source:"handoff"});for(let o of e.completed.tasks)g(t,{kind:"completed",value:o,source:"handoff"});for(let o of e.remaining.todos)g(t,{kind:"todo",value:o,source:"handoff"});return g(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function cs(r){let e=it(r);if(!e)return[];let t=[];return g(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&g(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&g(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&g(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&g(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function ls(r){let e=st(r);if(!e)return[];let t=[];e.goal&&g(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let o=e.filesTouched.at(-1);o&&g(t,{kind:"file",value:o,source:"work-state"});for(let n of e.nextActions.slice(0,5))g(t,{kind:"next_action",value:n,source:"work-state"});for(let n of e.blockers.slice(-5))g(t,{kind:"blocker",value:n,source:"work-state"});for(let n of e.decisions.slice(-5))g(t,{kind:"decision",value:n,source:"work-state"});for(let n of e.tasks.filter(s=>s.status==="completed").slice(-8))g(t,{kind:"completed",value:n.title,source:"work-state"});for(let n of e.tasks.filter(s=>s.status!=="completed"&&s.status!=="cancelled").slice(0,8))g(t,{kind:"todo",value:n.title,source:"work-state"});for(let n of e.tests.slice(-5))g(t,{kind:"test",value:n,source:"work-state"});return g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function ds(r,e){let t=os[r];return e.map((o,n)=>({...o,score:(t[o.kind]??10)+ns[o.source]+Math.max(0,5-n*.01)}))}function ms(r){let e=new Map;for(let t of r){let o=`${t.kind}:${ss(t.value)}`,n=e.get(o);(!n||t.score>n.score)&&e.set(o,t)}return[...e.values()]}function $(r,e,t={}){let o=Fe(e),n=[...as(r),...cs(r),...ls(r)],s=ms(ds(o,n)).sort((l,u)=>u.score-l.score),i=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],d=0;for(let l of s){if(c.length>=i)break;let u=l.kind.length+l.value.length+l.source.length+16;c.length>0&&d+u>a||(c.push(l),d+=u)}return{intent:o,facts:c,context:{project:{id:r.id,name:r.name},intent:o,selectedFacts:c.map(l=>({kind:l.kind,value:l.value,source:l.source}))},stats:{candidates:n.length,selected:c.length,chars:d}}}var $r={previous_agent:"Agent tr\u01B0\u1EDBc",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},Kr=["previous_agent","phase","task","file","todo","next_action","blocker","decision","completed","test","progress","goal"],ps={previous_agent:["previous_agent"],current_task:["task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:Kr};function us(r){let e=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function fs(r){let e=r.filter(t=>t.source==="handoff");return e.length>0?e:r}function gs(r){let e=new Set,t=[];for(let o of r){let n=`${o.kind}:${o.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(n)||(e.add(n),t.push(o))}return t}function Gr(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function hs(r,e){let t=[];for(let o of e){let n=r.filter(s=>s.kind===o).slice(0,Gr(o));for(let s of n)t.push(`${$r[o]}: ${s.value}`)}return t.join(`
|
|
8
|
-
`)}function
|
|
9
|
-
`)}function
|
|
10
|
-
|
|
11
|
-
`)}]}}:{},contents:i,generationConfig:{temperature:e.temperature,maxOutputTokens:e.maxTokens}})}),d=c.candidates?.[0]?.content?.parts?.map(l=>l.text??"").join("").trim();if(!d)throw new Error("gemini: empty model response");return{text:d,provider:"gemini",model:n,usage:c.usageMetadata?{inputTokens:c.usageMetadata.promptTokenCount,outputTokens:c.usageMetadata.candidatesTokenCount,totalTokens:c.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let e=Date.now();try{return{ok:!0,provider:"gemini",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:"gemini",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};var
|
|
12
|
-
[truncated]`}function
|
|
1
|
+
var Bn=Object.defineProperty;var g=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(o){throw t=[o],o}};var ge=(r,e)=>{for(var t in e)Bn(r,t,{get:e[t],enumerable:!0})};var qn,ye,qt=g(()=>{"use strict";qn=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],ye=class{scan(e){let t=[];for(let o of qn){let n=new RegExp(o.regex.source,o.regex.flags);for(let s of e.matchAll(n))t.push({type:o.type,value:s[0]})}return t}hasSecrets(e){return this.scan(e).length>0}}});var D,Ze=g(()=>{"use strict";qt();D=class{scanner=new ye;sanitize(e){let t=e,o=this.scanner.scan(e),n=new Set;for(let s of o)n.add(s.type),t=t.split(s.value).join(`[REDACTED:${s.type}]`);return{text:t,redacted:o.length,secretTypes:[...n]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e)){let s=o.toLowerCase();s.includes("password")||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")?t[o]="[REDACTED]":t[o]=this.sanitizeValue(n)}return t}return e}}});function F(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var st=g(()=>{"use strict"});function O(r){let e=io.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function H(r){return io.some(e=>e.id===r)}var io,gt=g(()=>{"use strict";io=[{id:"openai-compatible",label:"OpenAI-compatible",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"alibaba",label:"Alibaba / DashScope",requiresApiKey:!0,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"openrouter",label:"OpenRouter",defaultBaseUrl:"https://openrouter.ai/api/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"groq",label:"Groq",defaultBaseUrl:"https://api.groq.com/openai/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"deepseek",label:"DeepSeek",defaultBaseUrl:"https://api.deepseek.com",defaultModel:"deepseek-v4-flash",requiresApiKey:!0,transport:"openai-compatible"},{id:"nvidia",label:"NVIDIA NIM",defaultBaseUrl:"https://integrate.api.nvidia.com/v1",defaultModel:"deepseek-ai/deepseek-v4-pro",requiresApiKey:!0,transport:"openai-compatible"},{id:"gemini",label:"Gemini",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta",requiresApiKey:!0,transport:"gemini"},{id:"huggingface",label:"Hugging Face",defaultBaseUrl:"https://router.huggingface.co/v1",requiresApiKey:!0,transport:"openai-compatible"},{id:"ollama",label:"Ollama / Local",defaultBaseUrl:"http://127.0.0.1:11434/v1",requiresApiKey:!1,transport:"openai-compatible"},{id:"custom",label:"Custom endpoint",requiresApiKey:!1,requiresBaseUrl:!0,transport:"openai-compatible"},{id:"cloudflare",label:"Cloudflare Workers AI",requiresApiKey:!0,requiresAccountId:!0,transport:"cloudflare"}]});function u(r){return process.env[r]?.trim()||void 0}function v(...r){return r.find(e=>!!e?.trim())}function ao(){if(u("GROQ_API_KEY"))return"groq";if(u("DEEPSEEK_API_KEY"))return"deepseek";if(u("NVIDIA_API_KEY")||u("NVIDIA_NIM_API_KEY"))return"nvidia";if(u("OPENROUTER_API_KEY"))return"openrouter";if(u("ALIBABA_API_KEY")||u("DASHSCOPE_API_KEY"))return"alibaba";if(u("GEMINI_API_KEY")||u("GOOGLE_API_KEY"))return"gemini";if(u("CLOUDFLARE_API_TOKEN")&&u("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(u("HF_TOKEN"))return"huggingface";if(u("OLLAMA_MODEL")||u("OLLAMA_BASE_URL"))return"ollama"}function co(){let r=u("TOOLNET_LLM_PROVIDER");return r&&H(r)?r:ao()??"openai-compatible"}function $e(r){let e=O(r);switch(r){case"alibaba":return{provider:r,apiKey:v(u("ALIBABA_API_KEY"),u("DASHSCOPE_API_KEY")),baseUrl:v(u("ALIBABA_BASE_URL"),u("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:v(u("ALIBABA_MODEL"),u("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:u("OPENROUTER_API_KEY"),baseUrl:v(u("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:u("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:u("GROQ_API_KEY"),baseUrl:v(u("GROQ_BASE_URL"),e.defaultBaseUrl),model:u("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:u("DEEPSEEK_API_KEY"),baseUrl:v(u("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:v(u("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:v(u("NVIDIA_API_KEY"),u("NVIDIA_NIM_API_KEY")),baseUrl:v(u("NVIDIA_BASE_URL"),u("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:v(u("NVIDIA_MODEL"),u("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:v(u("GEMINI_API_KEY"),u("GOOGLE_API_KEY")),baseUrl:v(u("GEMINI_BASE_URL"),e.defaultBaseUrl),model:u("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:u("HF_TOKEN"),baseUrl:v(u("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:v(u("HF_LLM_MODEL"),u("HF_MODEL"))};case"ollama":return{provider:r,apiKey:u("OLLAMA_API_KEY"),baseUrl:v(u("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:u("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:u("CLOUDFLARE_ACCOUNT_ID"),apiKey:u("CLOUDFLARE_API_TOKEN"),baseUrl:u("CLOUDFLARE_AI_BASE_URL"),model:u("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:u("CUSTOM_AI_API_KEY"),baseUrl:u("CUSTOM_AI_BASE_URL"),model:u("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:v(u("OPENAI_API_KEY"),u("MODEL_API_KEY")),baseUrl:v(u("OPENAI_BASE_URL"),u("MODEL_BASE_URL")),model:v(u("OPENAI_MODEL"),u("MODEL_NAME"))}}}function mi(){let r=u("TOOLNET_LLM_PROVIDER"),e=r&&H(r)?r:co(),t=O(e),o=$e(e);return{provider:e,apiKey:v(u("TOOLNET_LLM_API_KEY"),o.apiKey),baseUrl:v(u("TOOLNET_LLM_BASE_URL"),o.baseUrl,t.defaultBaseUrl),model:v(u("TOOLNET_LLM_MODEL"),o.model,t.defaultModel),accountId:v(u("TOOLNET_LLM_ACCOUNT_ID"),o.accountId)}}function pi(){let r=u("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&H(r)?r:u("HF_TOKEN")||u("HF_EMBEDDING_MODEL")?"huggingface":"local"}function fi(){let r=pi();if(r==="local")return{provider:"local",model:v(u("TOOLNET_EMBEDDING_MODEL"),u("LOCAL_EMBEDDING_MODEL"))};let e=O(r),t,o,n,s;switch(r){case"huggingface":t=u("HF_TOKEN"),o=u("HF_INFERENCE_BASE_URL"),n=u("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=u("OPENAI_API_KEY"),o=u("OPENAI_BASE_URL"),n=u("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=u("CLOUDFLARE_API_TOKEN"),o=u("CLOUDFLARE_AI_BASE_URL"),n=u("CLOUDFLARE_EMBEDDING_MODEL"),s=u("CLOUDFLARE_ACCOUNT_ID");break;default:t=$e(r).apiKey,o=$e(r).baseUrl,n=u(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let i=v(u("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),a=v(u("TOOLNET_EMBEDDING_BASE_URL"),o,e.defaultBaseUrl),c=r==="cloudflare"&&!a&&i?`https://api.cloudflare.com/client/v4/accounts/${i}/ai/v1`:a;return{provider:r,apiKey:v(u("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:v(u("TOOLNET_EMBEDDING_MODEL"),n),accountId:i}}function Y(){let r=mi(),e=fi();return{llm:r,embedding:e,legacy:{llm:!u("TOOLNET_LLM_PROVIDER")&&!!ao(),embedding:!u("TOOLNET_EMBEDDING_PROVIDER")&&!!(u("HF_TOKEN")||u("HF_EMBEDDING_MODEL"))}}}function lo(r=co()){let e=Y().llm;if(r===e.provider)return{id:r,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId};let t=$e(r);return{id:r,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}function J(r,e){return u(`TOOLNET_LLM_FALLBACK_${r}_${e}`)}function uo(){let r=[];for(let e of[1,2]){let t=J(e,"PROVIDER");if(!t||!H(t))continue;let o=O(t);r.push({slot:e,config:{provider:t,apiKey:J(e,"API_KEY"),baseUrl:v(J(e,"BASE_URL"),o.defaultBaseUrl),model:v(J(e,"MODEL"),o.defaultModel),accountId:J(e,"ACCOUNT_ID")}})}return r}function mo(){let r=u("TOOLNET_LLM_FALLBACK_COOLDOWN_MS"),e=u("TOOLNET_LLM_MAX_RETRIES"),t=Number(r??6e4),o=Number(e??1);return{cooldownMs:Number.isFinite(t)&&t>=0?t:6e4,maxRetries:Number.isFinite(o)&&o>=0?Math.floor(o):1}}var Ge=g(()=>{"use strict";gt()});import{existsSync as ca,readFileSync as la}from"node:fs";import{homedir as da}from"node:os";import{join as ua}from"node:path";function ma(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
|
|
2
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function pa(){let r=process.env.TOOLNET_GLOBAL_ENV??ua(da(),".config","toolnet-memory",".env");if(!ca(r))return;let e=la(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=ma(o.slice(n+1)))}}var rn=g(()=>{"use strict";pa()});var on={};ge(on,{loadConfig:()=>fa});function se(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function ie(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function fa(){return{memory:{autoCapture:se(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:se(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:se(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:se(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:ie(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:ie(process.env.MEMORY_RERANK_TOP,10),finalContext:ie(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:ie(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:se(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:ie(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var nn=g(()=>{"use strict";rn()});var sn=g(()=>{"use strict"});import{DeleteObjectCommand as ga,GetObjectCommand as ya,HeadObjectCommand as ha,ListObjectsV2Command as va,PutObjectCommand as wa,S3Client as ba}from"@aws-sdk/client-s3";import{getSignedUrl as ka}from"@aws-sdk/s3-request-presigner";var ae,bt=g(()=>{"use strict";ae=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ba({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new wa({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await ka(this.client,new ya({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new ha({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new ga({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new va({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}}});import{access as an,mkdir as Sa,readFile as xa,readdir as Ca,rm as Aa,stat as cn,writeFile as Pa}from"node:fs/promises";import{dirname as Ea,join as Ma,relative as ln,resolve as ja}from"node:path";var U,kt=g(()=>{"use strict";U=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ja(this.root,t)}async put(e,t){let o=this.path(e);await Sa(Ea(o),{recursive:!0}),await Pa(o,t)}async get(e){try{return await xa(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await an(this.path(e)),!0}catch{return!1}}async delete(e){await Aa(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await an(t)}catch{return o}let n=async i=>{let a=await Ca(i,{withFileTypes:!0});for(let c of a){let d=Ma(i,c.name);if(c.isDirectory()){await n(d);continue}let l=await cn(d);o.push({key:ln(this.root,d),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await cn(t);return s.isDirectory()?await n(t):o.push({key:ln(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}}});import{DeleteObjectCommand as Ra,GetObjectCommand as Ia,HeadObjectCommand as Ta,ListObjectsV2Command as _a,PutObjectCommand as Oa,S3Client as La}from"@aws-sdk/client-s3";import{getSignedUrl as Na}from"@aws-sdk/s3-request-presigner";var W,St=g(()=>{"use strict";W=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new La({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Oa({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Na(this.client,new Ia({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Ta({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Ra({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new _a({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}}});import{homedir as Ka}from"node:os";import{join as Da}from"node:path";function xt(r,e){return console.warn(e),new U(r)}function Fa(r){let e=r.localRoot??Da(Ka(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new W({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):xt(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new W({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):xt(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new ae({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):xt(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new U(e)}var dn=g(()=>{"use strict";bt();kt();St()});var Ct,un=g(()=>{"use strict";Ct=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}}});var mn=g(()=>{"use strict";kt()});var pn=g(()=>{"use strict";bt()});var fn=g(()=>{"use strict";St()});var At,gn=g(()=>{"use strict";At=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return null;let o=JSON.parse(t);if(o.version!==1||o.projectId!==e||!Array.isArray(o.records))throw new Error("Invalid vector snapshot");return o}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Pt,yn=g(()=>{"use strict";Pt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Et,hn=g(()=>{"use strict";Et=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","manifest.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var ce,Mt=g(()=>{"use strict";ce=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","chunks","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var le,jt=g(()=>{"use strict";le=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});function $a(r){return new Promise(e=>setTimeout(e,r))}async function vn(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,s;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(s=a,i>=t)break;let c=Math.min(n,o*2**(i-1)),d=Math.floor(Math.random()*Math.max(1,c*.2));await $a(c+d)}throw s}var wn=g(()=>{"use strict"});function Ua(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:Ga.has(o)?(...s)=>vn(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}var Ga,bn=g(()=>{"use strict";wn();Ga=new Set(["put","get","getText","delete","list"])});function Rt(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}var It=g(()=>{"use strict"});function Tt(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var _t=g(()=>{"use strict"});var Ot,kn=g(()=>{"use strict";It();_t();Ot=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=Rt(n??o),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),o=t,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(o=i.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
|
|
3
|
+
`,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Tt(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}}});var Sn=g(()=>{"use strict";It();kn();_t()});var Lt,xn=g(()=>{"use strict";Lt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","resolution","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}}});var Nt,Cn=g(()=>{"use strict";Nt=class{constructor(e){this.storage=e}storage;base(e){return["projects",e,"code","architecture"].join("/")}async load(e){let t=await this.storage.getText(`${this.base(e)}/current.json`);return t?JSON.parse(t):null}async save(e){let t=this.base(e.projectId),o=n=>JSON.stringify({version:e.version,projectId:e.projectId,updatedAt:e.updatedAt,data:n},null,2);await Promise.all([this.storage.put(`${t}/current.json`,JSON.stringify(e,null,2),"application/json"),this.storage.put(`${t}/entry-points.json`,o(e.entryPoints),"application/json"),this.storage.put(`${t}/hotspots.json`,o(e.hotspots),"application/json"),this.storage.put(`${t}/layers.json`,o(e.layers),"application/json"),this.storage.put(`${t}/clusters.json`,o(e.clusters),"application/json")])}}});var Kt,An=g(()=>{"use strict";Kt=class{constructor(e){this.storage=e}storage;base(e){return["projects",e,"code","analysis"].join("/")}async load(e){let t=await this.storage.getText(`${this.base(e)}/current.json`);return t?JSON.parse(t):null}async save(e){let t=this.base(e.projectId),o=n=>JSON.stringify({version:e.version,projectId:e.projectId,updatedAt:e.updatedAt,data:n},null,2);await Promise.all([this.storage.put(`${t}/current.json`,JSON.stringify(e,null,2),"application/json"),this.storage.put(`${t}/dead-code.json`,o(e.deadCode),"application/json"),this.storage.put(`${t}/dependencies.json`,o(e.dependencies),"application/json")])}}});var Dt,Pn=g(()=>{"use strict";Dt=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"code","visualization","graph.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e,null,2),"application/json")}}});var En={};ge(En,{HuggingFaceStorageProvider:()=>ae,LocalStorageProvider:()=>U,MemoryStore:()=>Ct,PersistentArchitectureStore:()=>Nt,PersistentCodeAnalysisStore:()=>Kt,PersistentCodeChunkStore:()=>ce,PersistentCodeGraphStore:()=>Pt,PersistentCodeManifestStore:()=>Et,PersistentCodeVectorStore:()=>le,PersistentTypeResolutionStore:()=>Lt,PersistentVectorStore:()=>At,PersistentVisualizationStore:()=>Dt,ProjectScopedStorageProvider:()=>Ot,S3StorageProvider:()=>W,createStorageProvider:()=>Fa,mapProjectStoragePath:()=>Tt,sanitizeProjectFolder:()=>Rt,withStorageRetry:()=>Ua});var Mn=g(()=>{"use strict";sn();dn();un();mn();pn();fn();gn();yn();hn();Mt();jt();bn();Sn();xn();Cn();An();Pn()});import{createHash as Wa}from"node:crypto";import{readFile as za}from"node:fs/promises";import{join as Ba}from"node:path";function jn(r){return Wa("sha256").update(r).digest("hex")}var qe,Rn=g(()=>{"use strict";Ze();qe=class{sanitizer=new D;async build(e,t,o,n={}){let s=n.maxLines??80,i=n.overlapLines??10,a=new Map;for(let d of o){let l=a.get(d.filePath)??[];l.push(d),a.set(d.filePath,l)}let c=[];for(let[d,l]of a){let m;try{m=await za(Ba(t,d),"utf8")}catch{continue}let p=m.split(/\r?\n/),f=l.filter(y=>y.type!=="file"&&typeof y.startLine=="number"&&typeof y.endLine=="number");if(f.length>0)for(let y of f)c.push(...this.chunkRange({projectId:e,filePath:d,lines:p,symbol:y,startLine:y.startLine,endLine:y.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:d,lines:p,startLine:1,endLine:Math.max(1,p.length),maxLines:s,overlapLines:i}))}return c}chunkRange(e){let{projectId:t,filePath:o,lines:n,symbol:s,maxLines:i}=e,a=Math.min(e.overlapLines,Math.max(0,i-1)),c=Math.max(1,e.startLine),d=Math.min(n.length,Math.max(c,e.endLine)),l=[],m=c,p=0;for(;m<=d;){let f=Math.min(d,m+i-1),y=n.slice(m-1,f).join(`
|
|
4
|
+
`).trim();if(y){let b=this.sanitizer.sanitize(y).text,P=jn(b),E=[t,o,s?.id??"file",String(p),P].join(":");l.push({id:jn(E).slice(0,32),projectId:t,filePath:o,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:m,endLine:f,content:b,contentHash:P})}if(f>=d)break;m=f-a+1,p++}return l}}});function Va(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,o=0,n=0;for(let s=0;s<r.length;s++){let i=r[s]??0,a=e[s]??0;t+=i*a,o+=i*i,n+=a*a}return o===0||n===0?0:t/(Math.sqrt(o)*Math.sqrt(n))}var He,In=g(()=>{"use strict";He=class{records=new Map;upsert(e){this.records.set(e.id,e)}get(e){return this.records.get(e)}has(e){return this.records.has(e)}remove(e){return this.records.delete(e)}clearProject(e){let t=0;for(let[o,n]of this.records)n.projectId===e&&(this.records.delete(o),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let o of e)!o?.id||!o?.projectId||!Array.isArray(o.vector)||(this.records.set(o.id,o),t++);return t}search(e,t,o=10){let n=[];for(let s of this.records.values()){if(s.projectId!==e)continue;let i=Va(t,s.vector);n.push({id:s.id,score:i,metadata:s.metadata})}return n.sort((s,i)=>i.score-s.score).slice(0,o)}size(){return this.records.size}}});function Tn(r,e){let t=r.toLowerCase().replaceAll("\\","/"),o=e.toLowerCase(),n=/\b(test|tests|spec|fixture|mock)\b/.test(o);return(t.startsWith("tests/")||t.includes("/tests/")||t.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(t))&&!n?.35:t.includes("/generated/")||t.includes(".generated.")?.25:1}var _n=g(()=>{"use strict"});var On={};ge(On,{SemanticCodeEngine:()=>Ft});var Ft,Ln=g(()=>{"use strict";Mt();jt();Rn();In();st();_n();Ft=class{constructor(e){this.options=e}options;vectors=new He;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:o,embeddings:n,graph:s,model:i}=this.options,a=new ce(o),c=new le(o),d=await new qe().build(e,t,s.allSymbols(e));this.chunks.clear();for(let S of d)this.chunks.set(S.id,S);let l=await a.load(e),m=!l||l.chunks.length!==d.length||l.chunks.some(S=>!this.chunks.has(S.id));m&&await a.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:d});let p=await c.load(e),f=0;p&&p.model===i&&(f=this.vectors.importRecords(p.records));let y=new Set(d.map(S=>S.id)),b=0;for(let S of this.vectors.exportProject(e))y.has(S.id)||this.vectors.remove(S.id)&&b++;let P=d.filter(S=>{let N=this.vectors.get(S.id);return N?N.metadata?.contentHash!==S.contentHash:!0}),E=0,fe=8,_=this.vectors.exportProject(e)[0]?.vector.length;for(let S=0;S<P.length;S+=fe){let N=P.slice(S,S+fe),Wn=N.map(A=>[`file: ${A.filePath}`,A.symbolName?`symbol: ${A.symbolName}`:"",A.symbolType?`type: ${A.symbolType}`:"",A.content].filter(Boolean).join(`
|
|
5
|
+
`)),zn=await n.embedMany(Wn);for(let A=0;A<N.length;A++){let I=N[A],K=zn[A];if(!(!I||!K||K.length===0)){if(_===void 0&&(_=K.length),K.length!==_){console.warn(`[code-semantic] skip dimension mismatch: ${K.length} != ${_}`);continue}this.vectors.upsert({id:I.id,projectId:e,vector:K,metadata:{contentHash:I.contentHash,filePath:I.filePath,symbolName:I.symbolName,symbolType:I.symbolType,startLine:I.startLine,endLine:I.endLine}}),E++}}}let Xe=this.vectors.exportProject(e),zt=E>0||b>0||!p||p.model!==i;return zt&&await c.save({version:1,projectId:e,model:i,dimensions:Xe[0]?.vector.length??_??0,updatedAt:new Date().toISOString(),records:Xe}),{chunks:d.length,vectorsLoaded:f,vectorsIndexed:E,vectorsRemoved:b,totalVectors:Xe.length,savedChunks:m,savedVectors:zt}}async search(e,t=8){let o=await this.options.embeddings.embed(e),n=this.vectors.search(this.options.projectId,o,Math.max(t*4,20)),s=new Set(F(e)),i=[];for(let a of n){let c=this.chunks.get(a.id);if(!c)continue;let d=new Set(F([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),l=0;for(let b of s)d.has(b)&&l++;let m=s.size===0?0:l/s.size,p=Math.max(0,a.score),f=Tn(c.filePath,e),y=(p*.75+m*.25)*f;i.push({chunk:c,score:y,vectorScore:p,lexicalScore:m})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}}});var Nn=g(()=>{"use strict"});var de,$t=g(()=>{"use strict";de=class{constructor(e){this.options=e}options;name="gemini";async embed(e){let t=this.options.model.replace(/^models\//,""),n=`${this.options.baseUrl?.replace(/\/+$/,"")||"https://generativelanguage.googleapis.com/v1beta"}/models/${encodeURIComponent(t)}:embedContent?key=${encodeURIComponent(this.options.apiKey)}`,s=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!s.ok)throw new Error(`Gemini embedding failed: ${s.status} ${await s.text()}`);let a=(await s.json()).embedding?.values;if(!Array.isArray(a)||a.length===0)throw new Error("Gemini embedding returned invalid response");return a}async embedMany(e){let t=[];for(let o of e)t.push(await this.embed(o));return t}}});import{createHash as qa}from"node:crypto";function Ha(r){let e=Math.sqrt(r.reduce((t,o)=>t+o*o,0));return e===0?r:r.map(t=>t/e)}var ue,Gt=g(()=>{"use strict";ue=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),o=e.toLowerCase().split(/\s+/).filter(Boolean);for(let n of o){let i=qa("sha256").update(n).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Ha(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}}});var me,Ut=g(()=>{"use strict";me=class{constructor(e){this.options=e;this.dimensions=e.dimensions}options;name="openai-compatible";dimensions;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=this.options.baseUrl.replace(/\/+$/,""),o=await fetch(`${t}/embeddings`,{method:"POST",headers:{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{}},body:JSON.stringify({model:this.options.model,input:e})});if(!o.ok)throw new Error(`Embedding failed: ${o.status} ${await o.text()}`);let s=(await o.json()).data?.sort((i,a)=>(i.index??0)-(a.index??0)).map(i=>i.embedding);if(!s||s.length!==e.length||s.some(i=>!Array.isArray(i)))throw new Error("Embedding provider returned invalid response");return s}}});function Ja(r){if(!Array.isArray(r))throw new Error("Invalid embedding");if(r.length>0&&typeof r[0]=="number")return r;if(r.length>0&&Array.isArray(r[0])){let e=r;if(e.length===0)return[];let t=e[0].length,o=new Array(t).fill(0);for(let n of e)for(let s=0;s<t;s++)o[s]+=n[s]??0;for(let n=0;n<t;n++)o[n]/=e.length;return o}throw new Error("Unsupported embedding shape")}var pe,Wt=g(()=>{"use strict";pe=class{constructor(e){this.options=e}options;name="huggingface";dimensions=384;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,o=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:e,options:{wait_for_model:!0}})});if(!o.ok)throw new Error(`HF embedding failed: ${o.status} ${await o.text()}`);let n=await o.json();if(!Array.isArray(n))throw new Error("HF embedding returned invalid response");return n.map(s=>Ja(s))}}});function Ya(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Qa(){let r=Y().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new pe({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new de({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=Ya(r.accountId)),e&&r.model?new me({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Xa(){return new Je(Qa())}var Je,Kn=g(()=>{"use strict";Ge();$t();Gt();Ut();Wt();Je=class{constructor(e,t=new ue){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}}});var Dn={};ge(Dn,{GeminiEmbeddingProvider:()=>de,HashEmbeddingProvider:()=>ue,HuggingFaceEmbeddingProvider:()=>pe,OpenAiCompatibleEmbeddingProvider:()=>me,ResilientEmbeddingProvider:()=>Je,createEmbeddingProvider:()=>Xa});var Fn=g(()=>{"use strict";Nn();Kn();Wt();Gt();Ut();$t()});import"dotenv/config";import{randomUUID as as}from"node:crypto";var Vn={critical:100,high:75,normal:50,temporary:20};function Bt(r){return Vn[r]}function Vt(r,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c")||t.includes("must not")||t.includes("critical")?"critical":r==="rule"||r==="decision"?"high":r==="todo"?"normal":r==="activity"||r==="summary"?"temporary":"normal"}Ze();var Hn=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Jn=new Set(["d\xF9ng","s\u1EED","d\u1EE5ng","use","using","the","a","an","cho","v\xE0","l\xE0","c\u1EE7a","to","for","with","quy\u1EBFt","\u0111\u1ECBnh"]);function Ht(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Jn.has(e)))}function Yn(r,e){let t=Ht(r),o=Ht(e);if(t.size===0||o.size===0)return 0;let n=0;for(let i of t)o.has(i)&&n++;let s=new Set([...t,...o]).size;return n/s}function Jt(r){return new Set(r.tags.filter(e=>!Hn.has(e.toLowerCase())))}var he=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let o=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,n=Jt(e);return t.filter(s=>{if(s.id===e.id||s.projectId!==e.projectId||s.type!==e.type||s.metadata?.supersededBy)return!1;let i=typeof s.metadata?.topic=="string"?s.metadata.topic:void 0;if(o&&i&&o===i)return!0;let a=Jt(s);for(let c of n)if(a.has(c))return!0;return Yn(e.content,s.content)>=.6})}};var Qn=new Set(["code","decision","rule","todo","summary"]);function Xn(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function Yt(r){return r.tags.includes("class:permanent")?4:r.tags.includes("class:task")?3:r.tags.includes("class:session")?2:r.tags.includes("class:transient")?1:0}function Zn(r,e){let t=Yt(e)-Yt(r);if(t!==0)return t;let o=e.importanceScore-r.importanceScore;if(o!==0)return o;let n=e.updatedAt.localeCompare(r.updatedAt);if(n!==0)return n;let s=e.createdAt.localeCompare(r.createdAt);return s!==0?s:r.id.localeCompare(e.id)}function Qt(r){let e=new Set,t=[];for(let o of r){let n=o.trim();if(!n)continue;let s=n.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(n))}return t}function Xt(r){let e=new Map;for(let n of r){if(!Qn.has(n.type)||n.metadata?.supersededBy)continue;let s=Xn(n.content);if(!s)continue;let i=[n.projectId,n.type,s].join("\0"),a=e.get(i)??[];a.push(n),e.set(i,a)}let t=[],o=0;for(let n of e.values()){if(n.length<2)continue;let s=[...n].sort(Zn),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:Qt(s.flatMap(c=>c.tags)),mergedSources:Qt(s.map(c=>c.source))}),o+=a.length}return{groups:t,duplicates:o}}function et(r){if(r.tags.includes("class:permanent"))return"permanent";if(r.tags.includes("class:task"))return"task";if(r.tags.includes("class:session"))return"session";if(r.tags.includes("class:transient"))return"transient"}function es(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function ts(r){let e=et(r);if(e==="permanent")return 730;if(e==="task")return 180;if(e==="session")return 45;if(e==="transient")return 7;switch(r.type){case"rule":return 730;case"decision":return 365;case"code":return 180;case"todo":return 120;case"summary":return 45;case"activity":return 14}}function rs(r){return et(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function os(r){let e=r.normalize("NFKC").toLowerCase().trim();return e.length<8?!0:[/^ok(?:ay)?[.!]?$/u,/^done[.!]?$/u,/^thanks?[.!]?$/u,/^test(?:ing)?[.!]?$/u,/^npm notice\b/u,/^changed \d+ packages?/u,/^packages? are looking for funding/u].some(t=>t.test(e))}function Zt(r,e=Date.now()){let t=50,o=[],n=et(r);switch(n==="permanent"?(t+=25,o.push("permanent project knowledge")):n==="task"?(t+=15,o.push("active task knowledge")):n==="session"?(t+=2,o.push("session-scoped knowledge")):n==="transient"&&(t-=25,o.push("transient knowledge")),r.importance){case"critical":t+=25,o.push("critical importance");break;case"high":t+=15,o.push("high importance");break;case"normal":break;case"temporary":t-=15,o.push("temporary importance");break}(r.type==="rule"||r.type==="decision")&&(t+=10,o.push("durable knowledge type"));let s=r.content.trim().length;s<12?(t-=30,o.push("very short content")):s<30?(t-=10,o.push("limited context")):s<=1200?(t+=8,o.push("useful context density")):s>5e3&&(t-=15,o.push("excessively large memory")),os(r.content)&&(t-=35,o.push("matches transient/noise pattern"));let i=r.metadata?.consolidation;i&&typeof i=="object"&&Array.isArray(i.sources)&&i.sources.length>1&&(t+=10,o.push("confirmed across multiple sources"));let a=es(r,e)>=ts(r);a&&(t-=15,o.push("stale for lifecycle class"));let c=rs(r);t=Math.max(0,Math.min(100,Math.round(t)));let d;t>=80?d="trusted":t>=55?d="useful":t>=30?d="weak":d="noise";let l=r.importance==="temporary"||r.type==="activity"||n==="transient";return{score:t,tier:d,stale:a,protected:c,pruneEligible:!c&&(d==="noise"&&l||a&&(d==="noise"||d==="weak")),reasons:o}}var ns={critical:100,high:75,normal:50,temporary:20},ss={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function er(r,e,t=new Date){let o;if(e==="temporary"&&(o=30),r==="activity"&&(o=Math.min(o??14,14)),r==="summary"&&(o=Math.min(o??30,30)),!!o)return new Date(t.getTime()+o*864e5).toISOString()}function tt(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function is(r){return!!r.metadata?.supersededBy}function rt(r,e=Date.now()){return!tt(r,e)&&!is(r)}function z(r,e=Date.now()){if(!rt(r,e))return 0;let t=ns[r.importance];if(r.importance==="critical")return t;let o=ss[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/o);return t*i}var ve=class{memories=new Map;sanitizer=new D;conflicts=new he;remember(e){let t=new Date().toISOString(),o=this.sanitizer.sanitize(e.content.trim()).text,n=e.importance??Vt(e.type,o),s={id:as(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:Bt(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??er(e.type,n,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},i=this.conflicts.findSuperseded(s,this.list(e.projectId));if(i.length){s.metadata={...s.metadata??{},supersedes:i.map(a=>a.id)};for(let a of i)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:s.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(s.id,s),s}importRecords(e){let t=0;for(let o of e)o?.id&&(this.memories.set(o.id,o),t++);return t}exportProject(e){return this.listAll(e)}get(e){return this.memories.get(e)}delete(e){return this.memories.delete(e)}listAll(e){return[...this.memories.values()].filter(t=>t.projectId===e).sort((t,o)=>o.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>rt(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(o=>o.type===t)}search(e){let t=e.query.trim().toLowerCase(),o=e.limit??10,n=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(s=>{if(e.types&&!e.types.includes(s.type))return!1;let i=z(s);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>s.tags.includes(c)))}).map(s=>{let i=s.content.toLowerCase(),a=n.filter(l=>i.includes(l)).length,c=n.length===0?0:a/n.length,d=z(s)/500;return{memory:s,score:c+d,source:"memory"}}).filter(s=>t.length===0||s.score>0).sort((s,i)=>i.score-s.score).slice(0,o)}consolidate(e,t=Date.now()){let o=Xt(this.list(e)),n=[],s=0;for(let i of o.groups){let a=this.memories.get(i.canonicalId);if(a){a.tags=i.mergedTags,a.metadata={...a.metadata??{},consolidation:{version:1,consolidatedAt:new Date(t).toISOString(),mergedIds:i.duplicateIds,sources:i.mergedSources}},this.memories.set(a.id,a),n.push(a.id);for(let c of i.duplicateIds)this.memories.delete(c)&&(s+=1)}}return{groupsConsolidated:n.length,duplicatesRemoved:s,canonicalIds:n}}reviewLifecycle(e,t=Date.now()){let o={reviewed:0,trusted:0,useful:0,weak:0,noise:0,stale:0,protected:0,pruned:0};for(let n of this.list(e)){let s=Zt(n,t);o.reviewed+=1,o[s.tier]+=1,s.stale&&(o.stale+=1),s.protected&&(o.protected+=1),n.metadata={...n.metadata??{},lifecycle:{version:1,reviewedAt:new Date(t).toISOString(),qualityScore:s.score,tier:s.tier,stale:s.stale,protected:s.protected,reasons:s.reasons}},this.memories.set(n.id,n),s.pruneEligible&&this.memories.delete(n.id)&&(o.pruned+=1)}return o}pruneExpired(e,t=Date.now()){let o=0;for(let[n,s]of this.memories)s.projectId===e&&tt(s,t)&&(this.memories.delete(n),o++);return o}pruneSuperseded(e,t=30,o=Date.now()){let n=0,s=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;o-new Date(c).getTime()>=s&&(this.memories.delete(i),n++)}return n}clearProject(e){let t=0;for(let[o,n]of this.memories)n.projectId===e&&(this.memories.delete(o),t++);return t}};import{createHash as cs}from"node:crypto";import{existsSync as ot,mkdirSync as ls,readFileSync as ds,renameSync as us,writeFileSync as ms}from"node:fs";import{basename as ps,dirname as we,join as ke,parse as or,resolve as B}from"node:path";var nr=".toolnet",fs="project.json";function gs(r){return cs("sha256").update(r).digest("hex").slice(0,16)}function nt(r){return ke(r,nr,fs)}function ys(r){return ot(nt(r))}function hs(r,e){let t=B(r),o=or(t).root;for(;;){if(ys(t))return t;if(t===o||e&&t===B(e))break;let n=we(t);if(n===t)break;t=n}return null}function vs(r){let e=B(r),t=or(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>ot(ke(e,s))))return e;if(e===t)break;let n=we(e);if(n===e)break;e=n}return B(r)}function ws(r){let e;try{e=JSON.parse(ds(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:we(we(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function tr(r,e){let t=ke(r,nr);ls(t,{recursive:!0});let o=nt(r),n=`${o}.tmp-${process.pid}`;ms(n,JSON.stringify(e,null,2)+`
|
|
6
|
+
`,{encoding:"utf8",mode:384}),us(n,o)}function rr(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var be=class{detect(e=process.cwd()){let t=B(e),o=vs(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>ot(ke(o,l))),i=hs(t,s?o:void 0);if(i){let l=nt(i),m=ws(l);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),tr(i,m)),rr(m,i)}let a=new Date().toISOString(),c=ps(o),d={version:1,id:gs(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return tr(o,d),rr(d,o)}};st();var Se=class{score(e,t){let o=F(e),n=F([t.content,...t.tags??[],t.type].join(" "));if(o.length===0||n.length===0)return 0;let s=new Map;for(let a of n)s.set(a,(s.get(a)??0)+1);let i=0;for(let a of o){let c=s.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/o.length}};function sr(r,e=Date.now()){let t=r.updatedAt??r.createdAt,o=new Date(t).getTime();if(!Number.isFinite(o))return 0;let n=Math.max(0,e-o)/864e5;return Math.exp(-Math.LN2*n/30)}function ir(r){return z(r)/100}var bs={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function ar(r){return bs[r]??.4}var xe=class{analyze(e){let t=e.toLowerCase(),o=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&o.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&o.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&o.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&o.push("summary"),{query:e,preferredTypes:o}}};var Ce=class{bm25=new Se;analyzer=new xe;search(e,t,o={}){let n=o.topK??8,s=o.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(o.types?.length&&!o.types.includes(c.type))continue;let d=this.bm25.score(e,c),l=sr(c),m=ir(c),p=ar(c.type);i.preferredTypes.includes(c.type)&&(p=Math.min(1,p+.25));let f=d*.55+m*.2+l*.15+p*.1;d<=0||f<s||a.push({memory:c,score:f,scores:{keyword:d,recency:l,importance:m,type:p}})}return a.sort((c,d)=>d.score-c.score).slice(0,n)}};var Ae=class{build(e,t=6e3){let o=[],n=0;for(let s of e){let i=s.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(n+a.length>t)break;o.push(a),n+=a.length}return o.join(`
|
|
7
|
+
`)}};var Pe=class{constructor(e){this.memory=e}memory;searcher=new Ce;contextBuilder=new Ae;search(e,t,o={}){return this.searcher.search(t,this.memory.list(e),o)}context(e,t,o={}){let n=this.search(e,t,o);return this.contextBuilder.build(n)}};var Ee=class{symbols=new Map;edges=new Map;addSymbol(e){this.symbols.set(e.id,e)}addEdge(e){this.edges.set(e.id,e)}getSymbol(e){return this.symbols.get(e)}findByName(e,t){return[...this.symbols.values()].filter(o=>o.projectId===e&&(o.name===t||o.qualifiedName===t))}allSymbols(e){return[...this.symbols.values()].filter(t=>t.projectId===e)}allEdges(e){return[...this.edges.values()].filter(t=>t.projectId===e)}import(e,t){for(let o of e)this.addSymbol(o);for(let o of t)this.addEdge(o)}clearProject(e){for(let[t,o]of this.symbols)o.projectId===e&&this.symbols.delete(t);for(let[t,o]of this.edges)o.projectId===e&&this.edges.delete(t)}};var Me=class{constructor(e){this.graph=e}graph;findSymbol(e,t){return this.graph.findByName(e,t)}findCallers(e,t){return this.graph.allEdges(e).filter(n=>n.type==="CALLS"&&n.to===t).map(n=>n.from).map(n=>this.graph.getSymbol(n)).filter(n=>!!n)}};import{McpServer as na}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as sa}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as cr}from"zod";var lr={query:cr.string(),limit:cr.number().int().min(1).max(20).optional()};async function dr(r,e){return r.retrieval.search(r.project.id,e.query,{topK:e.limit??8}).map(o=>({id:o.memory.id,type:o.memory.type,content:o.memory.content,importance:o.memory.importance,score:o.score,tags:o.memory.tags}))}import{z as V}from"zod";var ur={type:V.enum(["activity","decision","rule","todo","summary"]),content:V.string().min(1),tags:V.array(V.string()).optional(),importance:V.enum(["critical","high","normal","temporary"]).optional()};async function mr(r,e){let t=r.memory.remember({projectId:r.project.id,type:e.type,content:e.content,tags:e.tags,importance:e.importance,source:"mcp"});return r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),t}import{z as ks}from"zod";var pr={id:ks.string().min(1)};async function fr(r,e){let t=r.memory.delete(e.id);return t&&r.memoryStore&&await r.memoryStore.save(r.project.id,r.memory.exportProject(r.project.id)),{deleted:t}}import{z as Ss}from"zod";var gr={name:Ss.string().min(1)};async function yr(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as xs}from"zod";var je=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),hr=new Set(["CALLS","CALL_REFERENCE"]),C=class{constructor(e){this.graph=e}graph;findSymbols(e,t){let o=t.trim().toLowerCase();return o?this.graph.allSymbols(e).filter(n=>n.name.toLowerCase().includes(o)||(n.qualifiedName?.toLowerCase().includes(o)??!1)||n.filePath.toLowerCase().includes(o)).sort((n,s)=>{let i=n.name.toLowerCase()===o,a=s.name.toLowerCase()===o;return i!==a?i?-1:1:n.filePath.localeCompare(s.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,hr)}callees(e,t){return this.relatedOutgoing(e,t,hr)}dependents(e,t){return this.relatedIncoming(e,t,je)}dependencies(e,t){return this.relatedOutgoing(e,t,je)}neighborhood(e,t,o=1){let n=this.graph.getSymbol(t);return!n||n.projectId!==e?null:{center:n,incoming:this.walk(e,t,"incoming",o),outgoing:this.walk(e,t,"outgoing",o)}}shortestPath(e,t,o,n=12){let s=this.graph.getSymbol(t),i=this.graph.getSymbol(o);if(!s||!i||s.projectId!==e||i.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===o)return{found:!0,distance:0,symbols:[s],edges:[]};let a=this.graph.allEdges(e).filter(p=>je.has(p.type)),c=new Map;for(let p of a){let f=c.get(p.from)??[];f.push(p),c.set(p.from,f)}let d=[{id:t,depth:0}],l=new Set([t]),m=new Map;for(;d.length>0;){let p=d.shift();if(!(p.depth>=n)){for(let f of c.get(p.id)??[])if(!l.has(f.to)){if(l.add(f.to),m.set(f.to,{node:p.id,edge:f}),f.to===o)return this.buildPath(t,o,m);d.push({id:f.to,depth:p.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,o){let n=[t],s=[],i=t;for(;i!==e;){let c=o.get(i);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};s.push(c.edge),i=c.node,n.push(i)}n.reverse(),s.reverse();let a=n.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:s.length,symbols:a,edges:s}}walk(e,t,o,n){let s=this.graph.allEdges(e).filter(d=>je.has(d.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let d=i.shift();if(!(d.depth>=n))for(let l of s){if(!(o==="incoming"?l.to===d.id:l.from===d.id))continue;let p=o==="incoming"?l.from:l.to;if(a.has(p))continue;let f=this.graph.getSymbol(p);f&&(a.add(p),c.push({symbol:f,depth:d.depth+1,via:l}),i.push({id:p,depth:d.depth+1}))}}return c}relatedIncoming(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.to===t&&o.has(s.type)).map(s=>s.from))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}relatedOutgoing(e,t,o){return[...new Set(this.graph.allEdges(e).filter(s=>s.from===t&&o.has(s.type)).map(s=>s.to))].map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};function M(r,e){let t=r.graph.getSymbol(e);if(t&&t.projectId===r.project.id)return t;let o=new C(r.graph),n=o.findSymbols(r.project.id,e).find(s=>s.name===e||s.qualifiedName===e);return n||(o.findSymbols(r.project.id,e)[0]??null)}function x(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var vr={symbolId:xs.string().min(1)};async function wr(r,e){let t=M(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let n=new C(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:x(t),count:n.length,callers:n.map(x)}}import{z as br}from"zod";var kr={query:br.string().min(1),limit:br.number().int().min(1).max(50).optional()};async function Sr(r,e){let t=e.query.toLowerCase(),o=e.limit??20;return r.graph.allSymbols(r.project.id).filter(n=>n.name.toLowerCase().includes(t)||n.qualifiedName?.toLowerCase().includes(t)||n.filePath.toLowerCase().includes(t)).slice(0,o)}import{z as xr}from"zod";function Re(r,e){let t=r.allSymbols(e),o=r.allEdges(e),n=i=>t.filter(a=>a.type===i).length,s=i=>o.filter(a=>a.type===i).length;return{files:n("file"),classes:n("class"),interfaces:n("interface"),functions:n("function"),methods:n("method"),properties:n("property"),routes:n("route"),symbols:t.length,edges:o.length,calls:s("CALLS"),callReferences:s("CALL_REFERENCE"),imports:s("IMPORTS"),inherits:s("INHERITS"),implements:s("IMPLEMENTS"),usesType:s("USES_TYPE"),tests:s("TESTS"),routeEdges:s("ROUTE"),writes:s("WRITES")}}var Cr={query:xr.string().optional(),memoryLimit:xr.number().int().min(1).max(20).optional()};async function Ar(r,e){let t=Re(r.graph,r.project.id),o=r.memory.recent(r.project.id,5),n=e.query?r.retrieval.search(r.project.id,e.query,{topK:e.memoryLimit??5}):[];return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:t,recent:o,relevant:n.map(s=>s.memory)}}import{z as As}from"zod";var Cs=["memories/current.json","vectors/current.json","graph/current.json","graph/manifest.json","graph/resolution/current.json","code/chunks/current.json","code/vectors/current.json","code/architecture/current.json","code/architecture/entry-points.json","code/architecture/hotspots.json","code/architecture/layers.json","code/architecture/clusters.json","code/analysis/current.json","code/analysis/dead-code.json","code/analysis/dependencies.json","code/visualization/graph.json"],T=class{constructor(e){this.storage=e}storage;projectPrefix(e){return`projects/${e}`}snapshotPrefix(e,t){return[this.projectPrefix(e),"snapshots",t].join("/")}async create(e,t="automatic",o){let n=new Date().toISOString(),s=n.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,s),c=[];for(let l of Cs){let m=`${i}/${l}`,p=await this.storage.get(m);p&&(await this.storage.put(`${a}/${l}`,p,"application/json"),c.push(l))}if(c.length===0)return null;let d={version:1,id:s,projectId:e,createdAt:n,reason:t,objects:c,metadata:o};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(d,null,2),"application/json"),d}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),n=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),s=[];for(let i of n){let a=await this.storage.getText(i.key);if(a)try{s.push(JSON.parse(a))}catch{}}return s.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.getText(`${o}/snapshot.json`);if(!n)throw new Error(`Snapshot not found: ${t}`);let s=JSON.parse(n);if(s.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of s.objects){let d=await this.storage.get(`${o}/${c}`);d&&(await this.storage.put(`${i}/${c}`,d,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.list(o);for(let s of n)await this.storage.delete(s.key);return n.length}async prune(e,t=10){let n=(await this.list(e)).slice(t),s=0;for(let i of n)await this.remove(e,i.id),s++;return s}};var Pr={reason:As.string().optional()};async function Er(r,e){if(!r.storage)throw new Error("Storage unavailable");return new T(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function Mr(r){if(!r.storage)throw new Error("Storage unavailable");return new T(r.storage).list(r.project.id)}import{z as Ps}from"zod";var jr={snapshotId:Ps.string().min(1)};async function Rr(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new T(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as it}from"zod";var Ie=class{constructor(e){this.graph=e}graph;callees(e,t,o=3){return this.walk(e,t,"out",o)}callers(e,t,o=3){return this.walk(e,t,"in",o)}walk(e,t,o,n){let s=[],i=new Set([t]),a=[{id:t,depth:0}],c=this.graph.allEdges(e).filter(d=>d.type==="CALLS"||d.type==="CALL_REFERENCE");for(;a.length;){let d=a.shift();if(d.depth>=n)continue;let l=o==="out"?c.filter(m=>m.from===d.id):c.filter(m=>m.to===d.id);for(let m of l){let p=o==="out"?m.to:m.from;if(i.has(p))continue;i.add(p);let f=this.graph.getSymbol(p);if(!f)continue;let y=d.depth+1;s.push({symbol:f,depth:y}),a.push({id:p,depth:y})}}return s}};var Ir={symbolId:it.string().min(1),direction:it.enum(["callers","callees"]).optional(),depth:it.number().int().min(1).max(10).optional()};async function Tr(r,e){let t=new Ie(r.graph),o=e.direction??"callees",n=e.depth??3,s=o==="callers"?t.callers(r.project.id,e.symbolId,n):t.callees(r.project.id,e.symbolId,n);return{direction:o,depth:n,results:s.map(i=>({id:i.symbol.id,name:i.symbol.name,qualifiedName:i.symbol.qualifiedName,type:i.symbol.type,filePath:i.symbol.filePath,depth:i.depth}))}}import{z as _r}from"zod";var Te=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Set([t]),i=[{id:t,depth:0}],a=[];for(;i.length;){let c=i.shift();if(c.depth>=o)continue;let d=n.filter(l=>l.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(l.type));for(let l of d){if(s.has(l.from))continue;s.add(l.from);let m=this.graph.getSymbol(l.from);if(!m)continue;let p=c.depth+1;a.push({symbol:m,depth:p,relation:l.type}),i.push({id:l.from,depth:p})}}return a}};var Or={symbolId:_r.string().min(1),depth:_r.number().int().min(1).max(10).optional()};async function Lr(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let n=new Te(r.graph).analyze(r.project.id,t.id,e.depth??4);return{found:!0,target:{id:t.id,name:t.name,qualifiedName:t.qualifiedName,filePath:t.filePath,type:t.type},impacts:n.map(s=>({id:s.symbol.id,name:s.symbol.name,qualifiedName:s.symbol.qualifiedName,filePath:s.symbol.filePath,type:s.symbol.type,relation:s.relation,depth:s.depth}))}}async function Nr(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:Re(r.graph,r.project.id)}}import{z as Kr}from"zod";var Es=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),_e=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e).filter(i=>Es.has(i.type)),n=new Map(t.map(i=>[i.id,i]));return[...new Set(t.map(i=>i.filePath))].sort().map(i=>{let a=new Set,c=new Set,d=0,l=0;for(let m of o){let p=n.get(m.from),f=n.get(m.to);!p||!f||p.filePath===f.filePath||(p.filePath===i&&(a.add(f.filePath),d++),f.filePath===i&&(c.add(p.filePath),l++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:d,incomingEdges:l}})}};var Dr={filePath:Kr.string().min(1),direction:Kr.enum(["dependencies","dependents","both"]).optional()};async function Fr(r,e){let o=new _e(r.graph).analyze(r.project.id).find(c=>c.filePath===e.filePath);if(!o)return{found:!1,filePath:e.filePath,dependencies:[],dependents:[]};let n=r.graph.allSymbols(r.project.id).filter(c=>c.type==="file"),s=new Map(n.map(c=>[c.filePath,c])),i=c=>({id:s.get(c)?.id??c,filePath:c}),a=e.direction??"both";return{found:!0,filePath:o.filePath,outgoingEdges:o.outgoingEdges,incomingEdges:o.incomingEdges,dependencies:a==="dependents"?[]:o.dependencies.map(i),dependents:a==="dependencies"?[]:o.dependents.map(i)}}import{z as $r}from"zod";var Gr={query:$r.string().min(1),limit:$r.number().int().min(1).max(20).optional()};async function Ur(r,e){return r.codeSemantic?{available:!0,results:(await r.codeSemantic.search(e.query,e.limit??8)).map(o=>({id:o.chunk.id,filePath:o.chunk.filePath,symbol:o.chunk.symbolName,symbolType:o.chunk.symbolType,startLine:o.chunk.startLine,endLine:o.chunk.endLine,score:o.score,vectorScore:o.vectorScore,lexicalScore:o.lexicalScore,content:o.chunk.content}))}:{available:!1,results:[]}}import{z as ct}from"zod";import{execFile as Ms}from"node:child_process";import{promisify as js}from"node:util";var at=js(Ms);function Rs(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let o of r.matchAll(t)){let n=Number(o[1]),s=Number(o[2]??1);e.push({startLine:n,endLine:Math.max(n,n+s-1)})}return e}function Is(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function Wr(r){let e="";try{e=(await at("git",["diff","HEAD","--name-status","--no-renames"],{cwd:r,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let o of e.split(/\r?\n/).filter(Boolean)){let[n,...s]=o.split(" "),i=s.at(-1);if(!i)continue;let a="";try{a=(await at("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:Is(n),ranges:Rs(a)})}try{let o=await at("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let n of o.stdout.split(/\r?\n/).filter(Boolean))t.some(s=>s.filePath===n)||t.push({filePath:n,status:"added",ranges:[]})}catch{}return t}function Ts(r,e){return e.ranges.length===0?!0:typeof r.startLine!="number"||typeof r.endLine!="number"?!1:e.ranges.some(t=>r.startLine<=t.endLine&&r.endLine>=t.startLine)}var Oe=class{constructor(e){this.graph=e}graph;map(e,t){let o=this.graph.allSymbols(e),n=[];for(let s of t){let i=o.filter(d=>d.filePath===s.filePath),c=i.filter(d=>d.type!=="file").filter(d=>Ts(d,s));if(c.length===0){let d=i.find(l=>l.type==="file");d&&n.push({symbol:d,fileStatus:s.status,direct:!0});continue}for(let d of c)n.push({symbol:d,fileStatus:s.status,direct:!0})}return n}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var _s={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Os(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function zr(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Le=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),s=new Map,i=0;for(let l of t){l.fileStatus==="deleted"?i+=8:l.fileStatus==="renamed"?i+=5:i+=2,l.symbol.type==="interface"&&(i+=5),l.symbol.type==="class"&&(i+=3);let m=new Set([l.symbol.id]),p=[{id:l.symbol.id,depth:0}];for(;p.length;){let f=p.shift();if(f.depth>=o)continue;let y=n.filter(b=>b.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(b.type));for(let b of y){if(m.has(b.from))continue;m.add(b.from);let P=this.graph.getSymbol(b.from);if(!P)continue;let E=f.depth+1,fe=`${l.symbol.id}:${P.id}`;s.set(fe,{symbol:P,relation:b.type,depth:E,sourceSymbolId:l.symbol.id});let _=_s[b.type]??1;i+=Math.max(1,_-(E-1)),p.push({id:P.id,depth:E})}}}let a=[...s.values()].sort((l,m)=>l.depth-m.depth),c=[...new Set(a.map(l=>l.symbol.filePath))],d=c.filter(zr);return d.length===0&&d.push(...c.filter(l=>!zr(l)).slice(0,10)),{risk:Os(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:d}}};var Ne=class{constructor(e){this.graph=e;this.mapper=new Oe(e),this.blast=new Le(e)}graph;mapper;blast;async analyzeGitDiff(e,t,o={}){let n=await Wr(t),s=this.mapper.map(e,n),i=this.blast.analyze(e,s,o.maxDepth??4);return{mode:"git_diff",changes:n,...i}}analyzeFile(e,t,o={}){let n=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,n,o.maxDepth??4)}}};var Br={mode:ct.enum(["git_diff","file"]).optional(),filePath:ct.string().optional(),depth:ct.number().int().min(1).max(10).optional()};async function Vr(r,e){let t=new Ne(r.graph);if((e.mode??(e.filePath?"file":"git_diff"))==="file"){if(!e.filePath)throw new Error("filePath is required when mode=file");return t.analyzeFile(r.project.id,e.filePath,{maxDepth:e.depth})}return t.analyzeGitDiff(r.project.id,r.project.rootPath,{maxDepth:e.depth})}import{z as Ls}from"zod";var qr={symbol:Ls.string().min(1)};async function Hr(r,e){let t=M(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let n=new C(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:x(t),count:n.length,dependents:n.map(x)}}import{z as lt}from"zod";var Jr={from:lt.string().min(1),to:lt.string().min(1),maxDepth:lt.number().int().min(1).max(30).optional()};async function Yr(r,e){let t=M(r,e.from),o=M(r,e.to);if(!t||!o)return{found:!1,fromFound:!!t,toFound:!!o,path:[],edges:[]};let s=new C(r.graph).shortestPath(r.project.id,t.id,o.id,e.maxDepth??12);return{found:s.found,distance:s.distance,from:x(t),to:x(o),path:s.symbols.map(x),edges:s.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as dt}from"zod";var Qr={symbol:dt.string().min(1),depth:dt.number().int().min(1).max(5).optional(),limit:dt.number().int().min(1).max(200).optional()};async function Xr(r,e){let t=M(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let n=new C(r.graph).neighborhood(r.project.id,t.id,e.depth??1);if(!n)return{found:!1,query:e.symbol};let s=e.limit??50;return{found:!0,center:x(n.center),incomingCount:n.incoming.length,outgoingCount:n.outgoing.length,incoming:n.incoming.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:x(i.symbol)})),outgoing:n.outgoing.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:x(i.symbol)}))}}import{z as mt}from"zod";function Ns(r){return r.replaceAll("\\","/").toLowerCase()}var Ke=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=[];for(let i of t){if(i.type!=="route"&&i.type!=="file")continue;let a=this.classify(i,o);a&&n.push({symbolId:i.id,filePath:i.filePath,name:i.name,kind:a.kind,score:a.score,reasons:a.reasons})}let s=new Map;for(let i of n){let a=i.kind==="route"?i.symbolId:i.filePath,c=s.get(a);(!c||i.score>c.score)&&s.set(a,i)}return[...s.values()].sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath))}classify(e,t){let o=Ns(e.filePath),n=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let s=null,i=0;if(o.startsWith("bin/"))s="cli",i=100,n.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(o))s="cli",i=90,n.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(o))s="main",i=90,n.push("main/server file");else if(o.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(o))s="runtime",i=75,n.push("runtime bootstrap");else if(/(^|\/)index\.[^.]+$/.test(o)){let c=t.filter(l=>l.to===e.id&&l.type!=="DEFINES").length,d=t.filter(l=>l.from===e.id&&l.type!=="DEFINES").length;(o.startsWith("packages/")||c===0||d>0)&&(s="package",i=o.startsWith("packages/")?70:55,n.push("package/public index"))}return s?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(i+=10,n.push("no incoming dependency")),{kind:s,score:i,reasons:n}):null}};var Zr=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function ut(r){return r.replaceAll("\\","/").toLowerCase()}function Ks(r){let e=ut(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function Ds(r){let e=ut(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var De=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=new Set(new Ke(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||Ks(i.filePath)||n.has(i.id)||Ds(i)||o.filter(f=>f.to===i.id&&Zr.has(f.type)).length>0)continue;let c=o.filter(f=>f.from===i.id&&Zr.has(f.type)),d=["no incoming usage edge"],l=50;(i.type==="function"||i.type==="method")&&(l+=20,d.push("callable symbol")),i.type==="property"&&(l-=15),c.length===0&&(l+=10,d.push("no outgoing dependency")),ut(i.filePath).includes("/internal/")&&(l+=10,d.push("internal implementation")),i.name.startsWith("_")&&(l+=5);let p=l>=75?"high":l>=55?"medium":"low";s.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:p,score:l,reasons:d})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var to={confidence:mt.enum(["high","medium","low","all"]).optional(),filePath:mt.string().min(1).optional(),limit:mt.number().int().min(1).max(500).optional()},eo={high:3,medium:2,low:1};async function ro(r,e){let o=new De(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=eo[e.confidence];o=o.filter(a=>eo[a.confidence]>=i)}e.filePath&&(o=o.filter(i=>i.filePath===e.filePath));let n=o.length,s=e.limit??100;return{total:n,high:o.filter(i=>i.confidence==="high").length,medium:o.filter(i=>i.confidence==="medium").length,low:o.filter(i=>i.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:o.slice(0,s)}}import{z as bo}from"zod";import{existsSync as Hs,readFileSync as Js}from"node:fs";import{join as Ys}from"node:path";import{existsSync as Fs,mkdirSync as bd,readFileSync as $s,renameSync as kd,writeFileSync as Sd}from"node:fs";import{dirname as Cd,join as Gs}from"node:path";function Us(r){return Gs(r.rootPath,".toolnet","work","current.json")}function pt(r){let e=Us(r);if(!Fs(e))return null;try{let t=JSON.parse($s(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Ws,mkdirSync as Ed,readFileSync as zs,renameSync as Md,writeFileSync as jd}from"node:fs";import{dirname as Id,join as Bs}from"node:path";function Vs(r){return Bs(r.rootPath,".toolnet","context","session-origin.json")}function ft(r){let e=Vs(r);if(!Ws(e))return null;try{let t=JSON.parse(zs(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function qs(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Fe(r){let e=qs(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),o=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&o?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}var Qs={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,progress:50,test:45,goal:35}},Xs={handoff:18,"session-origin":14,"work-state":8};function Zs(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function h(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function ei(r){let e=Ys(r.rootPath,".toolnet","work","handoff-latest.json");if(!Hs(e))return null;try{let o=JSON.parse(Js(e,"utf8")).continuity;return o?.schema!=="toolnet.handoff.v2"||o.project.id!==r.id?null:o}catch{return null}}function ti(r){let e=ei(r);if(!e)return[];let t=[];h(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.goal&&h(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&h(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&h(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&h(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&h(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let o of e.blockers)h(t,{kind:"blocker",value:o,source:"handoff"});for(let o of e.decisions)h(t,{kind:"decision",value:o,source:"handoff"});for(let o of e.completed.tasks)h(t,{kind:"completed",value:o,source:"handoff"});for(let o of e.remaining.todos)h(t,{kind:"todo",value:o,source:"handoff"});return h(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),h(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function ri(r){let e=ft(r);if(!e)return[];let t=[];return h(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&h(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&h(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&h(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&h(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&h(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&h(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function oi(r){let e=pt(r);if(!e)return[];let t=[];e.goal&&h(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&h(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&h(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let o=e.filesTouched.at(-1);o&&h(t,{kind:"file",value:o,source:"work-state"});for(let n of e.nextActions.slice(0,5))h(t,{kind:"next_action",value:n,source:"work-state"});for(let n of e.blockers.slice(-5))h(t,{kind:"blocker",value:n,source:"work-state"});for(let n of e.decisions.slice(-5))h(t,{kind:"decision",value:n,source:"work-state"});for(let n of e.tasks.filter(s=>s.status==="completed").slice(-8))h(t,{kind:"completed",value:n.title,source:"work-state"});for(let n of e.tasks.filter(s=>s.status!=="completed"&&s.status!=="cancelled").slice(0,8))h(t,{kind:"todo",value:n.title,source:"work-state"});for(let n of e.tests.slice(-5))h(t,{kind:"test",value:n,source:"work-state"});return h(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function ni(r,e){let t=Qs[r];return e.map((o,n)=>({...o,score:(t[o.kind]??10)+Xs[o.source]+Math.max(0,5-n*.01)}))}function si(r){let e=new Map;for(let t of r){let o=`${t.kind}:${Zs(t.value)}`,n=e.get(o);(!n||t.score>n.score)&&e.set(o,t)}return[...e.values()]}function $(r,e,t={}){let o=Fe(e),n=[...ti(r),...ri(r),...oi(r)],s=si(ni(o,n)).sort((l,m)=>m.score-l.score),i=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],d=0;for(let l of s){if(c.length>=i)break;let m=l.kind.length+l.value.length+l.source.length+16;c.length>0&&d+m>a||(c.push(l),d+=m)}return{intent:o,facts:c,context:{project:{id:r.id,name:r.name},intent:o,selectedFacts:c.map(l=>({kind:l.kind,value:l.value,source:l.source}))},stats:{candidates:n.length,selected:c.length,chars:d}}}var oo={previous_agent:"Agent tr\u01B0\u1EDBc",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},no=["previous_agent","phase","task","file","todo","next_action","blocker","decision","completed","test","progress","goal"],ii={previous_agent:["previous_agent"],current_task:["task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:no};function ai(r){let e=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function ci(r){let e=r.filter(t=>t.source==="handoff");return e.length>0?e:r}function li(r){let e=new Set,t=[];for(let o of r){let n=`${o.kind}:${o.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(n)||(e.add(n),t.push(o))}return t}function so(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function di(r,e){let t=[];for(let o of e){let n=r.filter(s=>s.kind===o).slice(0,so(o));for(let s of n)t.push(`${oo[o]}: ${s.value}`)}return t.join(`
|
|
8
|
+
`)}function ui(r,e){let t=ii[e]??no,o=[];for(let n of t){let s=r.filter(i=>i.kind===n).slice(0,so(n));for(let i of s)o.push(`${oo[n]}: ${i.value}`)}return o.join(`
|
|
9
|
+
`)}function q(r,e){let t=$(r,e,{maxFacts:32,maxChars:6400}),o=li(ci(t.facts)),n=ai(e)?di(o,["todo","task","next_action","file"]):ui(o,String(t.intent));return n?{intent:String(t.intent),answer:n,source:o[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}Ge();var Q=class extends Error{status;constructor(e,t){super(e),this.name="AiHttpError",this.status=t}};async function G(r,e,t=3e4){let o=new AbortController,n=setTimeout(()=>o.abort(),t);n.unref?.();try{let s=await fetch(r,{...e,signal:o.signal}),i=await s.text();if(!s.ok){let a=i;try{let c=JSON.parse(i);a=c.error?.message??c.message??i}catch{}throw new Q(a||`HTTP ${s.status}`,s.status)}return i.trim()?JSON.parse(i):{}}finally{clearTimeout(n)}}function Ue(r,e){return`${r.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}Ge();gt();var We=class{constructor(e){this.config=e}config;id="cloudflare";model(){let e=this.config.model?.trim();if(!e)throw new Error("cloudflare: MODEL is not configured");return e}async generate(e){let t=this.config.accountId?.trim(),o=this.config.apiKey?.trim();if(!t)throw new Error("cloudflare: ACCOUNT ID is not configured");if(!o)throw new Error("cloudflare: API TOKEN is not configured");let n=this.model(),i=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${t}/ai/run`).replace(/\/+$/,"")}/${n}`,a=await G(i,{method:"POST",headers:{authorization:`Bearer ${o}`,"content-type":"application/json",...this.config.headers},body:JSON.stringify({messages:e.messages,temperature:e.temperature,max_tokens:e.maxTokens})}),c=a.result?.response?.trim();if(!c)throw new Error(a.errors?.[0]?.message??"cloudflare: empty model response");return{text:c,provider:"cloudflare",model:n}}async healthCheck(){let e=Date.now();try{return{ok:!0,provider:"cloudflare",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:"cloudflare",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};var ze=class{constructor(e){this.config=e}config;id="gemini";model(){let e=this.config.model?.trim();if(!e)throw new Error("gemini: MODEL is not configured");return e.replace(/^models\//,"")}async generate(e){let t=this.config.apiKey?.trim();if(!t)throw new Error("gemini: API KEY is not configured");let o=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",n=this.model(),s=e.messages.filter(l=>l.role==="system"),i=e.messages.filter(l=>l.role!=="system").map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]})),a=`${Ue(o,`models/${encodeURIComponent(n)}:generateContent`)}?key=${encodeURIComponent(t)}`,c=await G(a,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...s.length?{systemInstruction:{parts:[{text:s.map(l=>l.content).join(`
|
|
10
|
+
|
|
11
|
+
`)}]}}:{},contents:i,generationConfig:{temperature:e.temperature,maxOutputTokens:e.maxTokens}})}),d=c.candidates?.[0]?.content?.parts?.map(l=>l.text??"").join("").trim();if(!d)throw new Error("gemini: empty model response");return{text:d,provider:"gemini",model:n,usage:c.usageMetadata?{inputTokens:c.usageMetadata.promptTokenCount,outputTokens:c.usageMetadata.candidatesTokenCount,totalTokens:c.usageMetadata.totalTokenCount}:void 0}}async healthCheck(){let e=Date.now();try{return{ok:!0,provider:"gemini",model:(await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8})).model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:"gemini",model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};var Be=class{constructor(e){this.config=e;this.id=e.id}config;id;baseUrl(){let e=this.config.baseUrl?.trim();if(!e)throw new Error(`${this.id}: BASE URL is not configured`);return e}model(){let e=this.config.model?.trim();if(!e)throw new Error(`${this.id}: MODEL is not configured`);return e}headers(){let e={"content-type":"application/json",...this.config.headers};return this.config.apiKey&&(e.authorization=`Bearer ${this.config.apiKey}`),e}async generate(e){let t=this.model(),o=await G(Ue(this.baseUrl(),"chat/completions"),{method:"POST",headers:this.headers(),body:JSON.stringify({model:t,messages:e.messages,temperature:e.temperature,max_tokens:e.maxTokens,...this.id==="alibaba"?{enable_thinking:!1}:{}})}),n=o.choices?.[0]?.message?.content?.trim();if(!n)throw new Error(`${this.id}: empty model response`);return{text:n,provider:this.id,model:t,usage:o.usage?{inputTokens:o.usage.prompt_tokens,outputTokens:o.usage.completion_tokens,totalTokens:o.usage.total_tokens}:void 0}}async healthCheck(){let e=Date.now();try{let t=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:this.id,model:t.model,message:"Provider reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:this.id,model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}};function po(r=lo()){switch(O(r.id).transport){case"gemini":return new ze(r);case"cloudflare":return new We(r);default:return new Be(r)}}function gi(r){return new Promise(e=>{setTimeout(e,r)})}function yi(r){if(r instanceof Q){let t=r.status;return t===void 0||t===408||t===409||t===425||t===429?!0:t>=500}if(!(r instanceof Error))return!0;let e=r.message.toLowerCase();return e.includes("401")||e.includes("403")||e.includes("400")||e.includes("invalid api key")||e.includes("unauthorized")||e.includes("forbidden")?!1:e.includes("timeout")||e.includes("timed out")||e.includes("abort")||e.includes("network")||e.includes("fetch failed")||e.includes("econnreset")||e.includes("econnrefused")||e.includes("429")||e.includes("rate limit")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("504")}var Ve=class{id;config;providers;states=new Map;cooldownMs;maxRetries;constructor(e,t=[],o={}){this.id=e.config.id,this.config=e.config,this.cooldownMs=o.cooldownMs??6e4,this.maxRetries=Math.max(0,o.maxRetries??1),this.providers=[e,...t].map(n=>({provider:po(n.config),label:n.label}))}key(e){let t=this.providers[e];return`${e}:${t.provider.id}:${t.provider.config.model??""}`}state(e){let t=this.key(e),o=this.states.get(t);return o||(o={failures:0,cooldownUntil:0},this.states.set(t,o)),o}available(e){return this.state(e).cooldownUntil<=Date.now()}success(e){let t=this.state(e);t.failures=0,t.cooldownUntil=0,t.lastError=void 0}fail(e,t){let o=this.state(e);o.failures+=1,o.lastError=t instanceof Error?t.message:String(t),o.cooldownUntil=Date.now()+this.cooldownMs}async generate(e){let t=[];for(let o=0;o<this.providers.length;o+=1){if(!this.available(o)){t.push(`${this.providers[o].label}: cooldown`);continue}let n=this.providers[o];for(let s=0;s<=this.maxRetries;s+=1)try{let i=await n.provider.generate(e);return this.success(o),i}catch(i){let a=i instanceof Error?i.message:String(i),c=yi(i);if(t.push(`${n.label}: ${a}`),!c)throw i;if(s<this.maxRetries){await gi(Math.min(250*2**s,2e3));continue}this.fail(o,i)}}throw new Error(`All ToolNet LLM providers failed: ${t.join(" | ")}`)}async healthCheck(){let e=Date.now();try{let t=await this.generate({messages:[{role:"user",content:"Reply exactly: OK"}],temperature:0,maxTokens:8});return{ok:!0,provider:t.provider,model:t.model,message:"Fallback chain reachable",latencyMs:Date.now()-e}}catch(t){return{ok:!1,provider:this.id,model:this.config.model,message:t instanceof Error?t.message:String(t),latencyMs:Date.now()-e}}}status(){return this.providers.map((e,t)=>{let o=this.state(t);return{position:t,provider:e.provider.id,model:e.provider.config.model,cooldown:o.cooldownUntil>Date.now(),cooldownUntil:o.cooldownUntil||void 0,failures:o.failures,lastError:o.lastError}})}};function fo(){let r=Y(),e=uo();return new Ve({label:`Primary (${r.llm.provider})`,config:{id:r.llm.provider,apiKey:r.llm.apiKey,baseUrl:r.llm.baseUrl,model:r.llm.model,accountId:r.llm.accountId}},e.map(t=>({label:`Fallback ${t.slot} (${t.config.provider})`,config:{id:t.config.provider,apiKey:t.config.apiKey,baseUrl:t.config.baseUrl,model:t.config.model,accountId:t.config.accountId}})),mo())}var yt=class{constructor(e=fo()){this.provider=e}provider;get activeProvider(){return this.provider}setProvider(e){this.provider=e}generate(e){return this.provider.generate(e)}};function go(){return new yt(fo())}function hi(r,e){let t=JSON.stringify(r,null,2);return t.length<=e?t:t.slice(0,e)+`
|
|
12
|
+
[truncated]`}function vi(r,e){let t=q(r,e),o=$(r,e,{maxFacts:12,maxChars:3200});return hi({project:o.context.project,intent:o.intent,directAnswer:t.answer,selectedMemory:o.context.selectedFacts,retrievalStats:o.stats},4200)}async function yo(r,e,t={}){let o=q(r,e),n=vi(r,e),s=t.router??go();try{let i=await s.generate({temperature:.1,maxTokens:450,messages:[{role:"system",content:`
|
|
13
13
|
You are ToolNet Memory Agent.
|
|
14
14
|
|
|
15
15
|
You are NOT the coding agent.
|
|
@@ -46,7 +46,9 @@ ToolNet selected memory:
|
|
|
46
46
|
${n}
|
|
47
47
|
|
|
48
48
|
Answer the coding agent directly.
|
|
49
|
-
`.trim()}]}),a=i.text.trim();return a?{answer:a,provider:i.provider,model:i.model,usedAi:!0}:{answer:o.answer,usedAi:!1}}catch{return{answer:o.answer,usedAi:!1}}}import{existsSync as
|
|
50
|
-
`,{encoding:"utf8",mode:384}),
|
|
51
|
-
`)}function
|
|
52
|
-
`):e.trim(),c=Fe(e),l=$(r,a,{maxFacts:8,maxChars:1800}).facts.map(p=>({kind:p.kind,value:p.value,source:p.source})),
|
|
49
|
+
`.trim()}]}),a=i.text.trim();return a?{answer:a,provider:i.provider,model:i.model,usedAi:!0}:{answer:o.answer,usedAi:!1}}catch{return{answer:o.answer,usedAi:!1}}}import{existsSync as wi,mkdirSync as bi,readFileSync as ki,renameSync as Si,rmSync as xi,writeFileSync as Ci}from"node:fs";import{join as ho}from"node:path";var Ai=720*60*1e3;function vo(r){return ho(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function X(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function Pi(r){let e=X(r);return[/\btiếp tục\b/u,/\btiếp tục task\b/u,/\blúc nãy\b/u,/\btrước đó\b/u,/\btask trước\b/u,/\bprevious (?:task|session|work)\b/u,/\bcontinue\b/u,/\bresume\b/u,/\bcurrent task\b/u,/\bđang làm gì\b/u].some(t=>t.test(e))}function Ei(r){if(Pi(r))return!1;let e=X(r),t=e.split(/\s+/u).filter(Boolean);return[/^(?:tại sao|vì sao|sao vậy)\b/u,/^(?:why|why so|why that)\b/u,/^(?:còn|thế|vậy|rồi sao|sau đó)\b/u,/^(?:what about|and what|then what)\b/u,/^(?:cái đó|việc đó|nó|phần đó)\b/u].some(o=>o.test(e))?!0:t.length<=5&&/\b(?:nó|đó|vậy|thế|that|it|this)\b/u.test(e)}function Mi(r,e,t){let o=vo(r);if(!wi(o))return null;try{let n=JSON.parse(ki(o,"utf8"));if(n.schema!=="toolnet.memory-conversation.v1"||n.version!==1||n.projectId!==r.id||!Array.isArray(n.focus))return null;let s=Date.parse(n.updatedAt);return!Number.isFinite(s)||e-s>t?null:n}catch{return null}}function ji(r,e=8){let t=new Set,o=[];for(let n of r){let s=n.value.replace(/\s+/gu," ").trim();if(!s)continue;let i=[n.kind,X(s)].join(":");if(!t.has(i)&&(t.add(i),o.push({...n,value:s}),o.length>=e))break}return o}function Ri(r,e){let t=vo(r),o=ho(r.rootPath,".toolnet","context");bi(o,{recursive:!0,mode:448});let n=`${t}.${process.pid}.tmp`;try{Ci(n,JSON.stringify(e,null,2)+`
|
|
50
|
+
`,{encoding:"utf8",mode:384}),Si(n,t)}finally{xi(n,{force:!0})}}function Ii(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
|
|
51
|
+
`)}function Ti(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function ht(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=X(r.originalQuestion),t=/^(?:tại sao|vì sao|sao vậy|why|why so|why that)\b/u.test(e),o=/^(?:rồi sao|sau đó|tiếp thì sao|thế tiếp theo|then what|what next)\b/u.test(e),n=t?["decision","blocker","next_action","task","file"]:o?["next_action","todo","task","blocker","file","decision"]:["task","next_action","file","decision","blocker"],s={task:"Task li\xEAn quan",next_action:"Vi\u1EC7c ti\u1EBFp theo",file:"File li\xEAn quan",decision:"Quy\u1EBFt \u0111\u1ECBnh li\xEAn quan",blocker:"Blocker",todo:"TODO"},i=[];for(let a of n){let c=Ti(r,a);if(c&&(i.push(`${s[a]??a}: ${c}.`),t&&i.length>=2||!t&&i.length>=3))break}return i.length===0?null:{answer:i.join(" "),intent:"summary",source:"conversation-focus"}}function _i(r){let e=X(r);return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(e)}function wo(r,e,t={}){let o=t.now??Date.now(),n=t.maxAgeMs??Ai,s=Mi(r,o,n),i=!!(s&&s.focus.length>0&&Ei(e)&&!_i(e)),a=i&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",Ii(s),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
|
|
52
|
+
`):e.trim(),c=Fe(e),l=$(r,a,{maxFacts:8,maxChars:1800}).facts.map(p=>({kind:p.kind,value:p.value,source:p.source})),m=ji(i&&s?[...l,...s.focus]:l);return Ri(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(o).toISOString(),lastIntent:c,focus:m}),{question:a,originalQuestion:e,usedPriorFocus:i,previousIntent:s?.lastIntent,currentIntent:c,priorFocus:s?.focus??[],focusCount:m.length}}var ko={question:bo.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:bo.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only.")};async function So(r,e){let t=wo(r.project,e.question);if(e.mode==="local"){let n=ht(t);if(n)return{answer:n.answer,mode:"local",usedAi:!1,source:n.source,intent:n.intent};let s=q(r.project,t.originalQuestion);return{answer:s.answer,mode:"local",usedAi:!1,source:s.source,intent:s.intent}}let o=await yo(r.project,t.question);if(!o.usedAi){let n=ht(t);if(n)return{answer:n.answer,mode:"ai",usedAi:!1,provider:o.provider,model:o.model}}return{answer:o.answer,mode:"ai",usedAi:o.usedAi,provider:o.provider,model:o.model}}import{z as jo}from"zod";import{chmodSync as Eu,existsSync as xo,mkdirSync as Mu,readFileSync as Co,renameSync as ju,writeFileSync as Ru}from"node:fs";import{dirname as Tu,join as Z}from"node:path";var Ao="toolnet.context-offload.v1",Oi="toolnet.context-offload-asset.v1";function Po(r){return Z(r,".toolnet","offload")}function Eo(r){return Z(Po(r),"assets")}function Li(r){return Z(Po(r),"graph.json")}function vt(){return{schema:Ao,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Ni(r){let e=Li(r);if(!xo(e))return vt();try{let t=JSON.parse(Co(e,"utf8"));return t.schema!==Ao||t.version!==1||!Array.isArray(t.nodes)?vt():t}catch{return vt()}}function Ki(r,e){let t=e.trim().toLowerCase();if(!/^[a-f0-9]{8,64}$/u.test(t))throw new Error("Invalid context offload asset reference.");if(t.length===64&&xo(Z(Eo(r),`${t}.json`)))return t;let o=Ni(r).nodes.map(n=>n.id).filter(n=>n.startsWith(t));if(o.length===0)throw new Error(`Context offload asset not found: ${e}`);if(o.length>1)throw new Error(`Ambiguous context offload asset reference: ${e}`);return o[0]}function Mo(r,e,t=6e3){let o=Ki(r,e),n=Co(Z(Eo(r),`${o}.json`),"utf8"),s=JSON.parse(n);if(s.schema!==Oi||s.version!==1||s.assetId!==o)throw new Error(`Invalid context offload asset: ${e}`);let i=Math.max(200,Math.min(2e4,Math.floor(t)));return{assetId:o,kind:s.event.type,bytes:Buffer.byteLength(n,"utf8"),truncated:n.length>i,content:n.length>i?`${n.slice(0,i)}
|
|
53
|
+
[truncated]`:n}}var Ro={assetId:jo.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:jo.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function Io(r,e){return Mo(r.project.rootPath,e.assetId,e.maxChars??6e3)}import{z as Oo}from"zod";import{chmodSync as Du,existsSync as Di,mkdirSync as Fu,readFileSync as Fi,readdirSync as $i,renameSync as $u,statSync as Gi,writeFileSync as Gu}from"node:fs";import{join as To}from"node:path";var Ui="toolnet.skill-memory.v1";function Wi(r,e=Number.MAX_SAFE_INTEGER){let t=new Set,o=[];for(let n of r){let s=n.replace(/\s+/gu," ").trim();if(!s)continue;let i=s.normalize("NFKC").toLowerCase();if(!t.has(i)&&(t.add(i),o.push(s),o.length>=e))break}return o}function zi(r){return To(r.rootPath,".toolnet","memory","skills")}function Bi(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Ui&&t.version===1&&t.projectId===e&&typeof t.id=="string"&&typeof t.task=="string"&&Array.isArray(t.steps)&&Array.isArray(t.verification)&&Array.isArray(t.files)}function Vi(r){let e=zi(r);if(!Di(e))return[];if(!Gi(e).isDirectory())return[];let t=[];for(let o of $i(e)){if(!o.endsWith(".json"))continue;let n=To(e,o);try{let s=JSON.parse(Fi(n,"utf8"));Bi(s,r.id)&&t.push(s)}catch{}}return t.sort((o,n)=>{let s=n.createdAt.localeCompare(o.createdAt);return s!==0?s:o.id.localeCompare(n.id)})}function qi(r){return Wi(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function Hi(r,e){let t=e.normalize("NFKC").toLowerCase().trim();if(!t)return 0;if(r.id.toLowerCase()===t||r.fingerprint.toLowerCase()===t)return 1e3;let o=[r.title,r.task,r.summary,...r.steps,...r.verification,...r.files].join(`
|
|
54
|
+
`).normalize("NFKC").toLowerCase(),n=0;r.task.normalize("NFKC").toLowerCase().includes(t)&&(n+=40),r.title.normalize("NFKC").toLowerCase().includes(t)&&(n+=30);for(let s of qi(t))o.includes(s)&&(n+=5),r.task.normalize("NFKC").toLowerCase().includes(s)&&(n+=4),r.files.some(i=>i.toLowerCase().includes(s))&&(n+=3);return n}function _o(r,e,t=5){let o=Math.max(1,Math.min(10,Math.floor(t)));return Vi(r).map(n=>({...n,score:Hi(n,e)})).filter(n=>n.score>0).sort((n,s)=>s.score!==n.score?s.score-n.score:s.createdAt.localeCompare(n.createdAt)).slice(0,o)}var Lo={query:Oo.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:Oo.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function No(r,e){let t=_o(r.project,e.query,e.limit??5);return{schema:"toolnet.skill-memory-search.v1",query:e.query,count:t.length,matches:t}}import{z as Ho}from"zod";var Ko="wiki/state.v1.json";function Ji(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Yi(r,e){let t=JSON.parse(r);if(t.schema!=="toolnet.wiki.v1"||t.version!==1||t.projectId!==e.id||!Array.isArray(t.pages)||!Array.isArray(t.revisions))throw new Error("Invalid ToolNet Wiki state");return t}var j=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(Ko);if(!e){let t=Ji(this.project);return await this.save(t),t}return Yi(e,this.project)}async save(e){await this.storage.put(Ko,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as $o}from"node:crypto";var k=class extends Error{constructor(t,o){super(t);this.statusCode=o}statusCode};function ee(r){let e=new Set,t=[];for(let o of r){let n=o.replace(/\s+/gu," ").trim();if(!n)continue;let s=n.normalize("NFKC").toLowerCase();e.has(s)||(e.add(s),t.push(n))}return t}function te(r){let e=r.normalize("NFKD").replace(/[\u0300-\u036f]/gu,"").toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,120);if(!e)throw new k("Invalid Wiki slug",400);return e}function Do(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let o=t[1]?.trim();o&&e.push(te(o))}return ee(e)}function Qi(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function Fo(r){return{id:`revision-${$o()}`,pageId:r.id,slug:r.slug,revision:r.revision,title:r.title,...r.summary?{summary:r.summary}:{},content:r.content,tags:[...r.tags],links:[...r.links],createdAt:r.updatedAt}}function L(r){return structuredClone(r)}var R=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}async mutate(e){let t,o=this.queue.then(async()=>{let n=await this.ensureState();t=e(n),n.updatedAt=new Date().toISOString(),await this.store.save(n)});return this.queue=o.then(()=>{},()=>{}),await o,t}async summary(){let e=await this.ensureState(),t=new Set(e.pages.flatMap(o=>o.links));return{schema:"toolnet.wiki-summary.v1",projectId:e.projectId,pages:e.pages.length,revisions:e.revisions.length,tags:ee(e.pages.flatMap(o=>o.tags)).sort((o,n)=>o.localeCompare(n)),links:e.pages.reduce((o,n)=>o+n.links.length,0),orphanPages:e.pages.filter(o=>o.links.length===0&&!t.has(o.slug)).length,automatedPages:e.pages.filter(o=>o.tags.some(n=>n.startsWith("toolnet-auto-"))).length,updatedAt:e.updatedAt}}async listPages(){let e=await this.ensureState();return L([...e.pages].sort((t,o)=>t.title.localeCompare(o.title)))}async getPage(e){let t=await this.ensureState(),o=te(e),n=t.pages.find(s=>s.slug===o||s.id===e);if(!n)throw new k(`Wiki page not found: ${e}`,404);return L(n)}async createPage(e){return this.mutate(t=>{let o=e.title.trim(),n=e.content.trim();if(!o)throw new k("Wiki title is required",400);let s=te(e.slug??o);if(t.pages.some(c=>c.slug===s))throw new k(`Wiki page already exists: ${s}`,409);let i=new Date().toISOString(),a={id:`wiki-${$o()}`,slug:s,title:o,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:n,tags:ee(e.tags??[]),links:Do(n),revision:1,createdAt:i,updatedAt:i};return t.pages.push(a),t.revisions.push(Fo(a)),L(a)})}async updatePage(e,t){return this.mutate(o=>{let n=te(e),s=o.pages.find(i=>i.slug===n||i.id===e);if(!s)throw new k(`Wiki page not found: ${e}`,404);if(t.title!==void 0){let i=t.title.trim();if(!i)throw new k("Wiki title is required",400);s.title=i}if(t.summary!==void 0){let i=t.summary.trim();i?s.summary=i:delete s.summary}return t.content!==void 0&&(s.content=t.content.trim(),s.links=Do(s.content)),t.tags!==void 0&&(s.tags=ee(t.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),o.revisions.push(Fo(s)),L(s)})}async history(e){let t=await this.getPage(e),o=await this.ensureState();return L(o.revisions.filter(n=>n.pageId===t.id).sort((n,s)=>s.revision-n.revision))}async backlinks(e){let t=await this.getPage(e),o=await this.ensureState();return L(o.pages.filter(n=>n.links.includes(t.slug)).sort((n,s)=>n.title.localeCompare(s.title)))}async search(e,t=10){let o=await this.ensureState(),n=ee(Qi(e));if(n.length===0)return[];let s=Math.max(1,Math.min(20,Math.floor(t))),i=[];for(let a of o.pages){let c=a.title.toLowerCase(),d=a.slug.toLowerCase(),l=a.summary?.toLowerCase()??"",m=a.content.toLowerCase(),p=a.tags.map(y=>y.toLowerCase()),f=0;for(let y of n)d===y&&(f+=12),c===y&&(f+=10),c.includes(y)&&(f+=6),d.includes(y)&&(f+=5),p.some(b=>b===y)?f+=5:p.some(b=>b.includes(y))&&(f+=3),l.includes(y)&&(f+=2),m.includes(y)&&(f+=1);f>0&&i.push({page:L(a),score:f})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};import{createHash as Xi,randomUUID as Go}from"node:crypto";var Uo="wiki/governance.v1.json",Vo="toolnet.knowledge-governance.v1",Wo=500,re={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Zi(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function wt(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function zo(r){return Xi("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function ea(r){let e=[r.title,r.summary??"",r.content.slice(0,2e3),...r.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function ta(r){let e=r.sourceType==="skill"?.96:r.sourceType==="memory"?.94:.88,t=r.tags.map(o=>o.toLowerCase());return(t.includes("permanent")||t.includes("task"))&&(e+=.03),r.content.length>=200&&(e+=.02),r.content.length<80&&(e-=.05),r.title.length<4&&(e-=.05),Zi(e)}function Bo(r){let e=new Date().toISOString();return{schema:Vo,version:1,projectId:r,policy:{...re},reviews:[],audit:[],createdAt:e,updatedAt:e}}function qo(r){let e=r.autoApproveThreshold??re.autoApproveThreshold,t=r.criticalApproveThreshold??re.criticalApproveThreshold,o=r.staleAfterDays??re.staleAfterDays;if(!Number.isFinite(e)||e<.5||e>1)throw new k("Invalid autoApproveThreshold",400);if(!Number.isFinite(t)||t<.5||t>1)throw new k("Invalid criticalApproveThreshold",400);if(!Number.isInteger(o)||o<1||o>3650)throw new k("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:t,staleAfterDays:o}}var oe=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(Uo);if(!e){let t=Bo(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==Vo||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:qo(t.policy??re)}}catch{let t=Bo(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(Uo,JSON.stringify(e,null,2),"application/json")}},ne=class{constructor(e){this.store=e}store;state;queue=Promise.resolve();async initialize(){await this.ensureState()}async ensureState(){return this.state||(this.state=await this.store.load()),this.state}audit(e,t,o,n={}){e.audit.push({id:Go(),action:t,principal:o,...n.reviewId?{reviewId:n.reviewId}:{},...n.sourceKey?{sourceKey:n.sourceKey}:{},timestamp:new Date().toISOString(),...n.metadata?{metadata:n.metadata}:{}}),e.audit.length>Wo&&(e.audit=e.audit.slice(-Wo))}async mutate(e){let t,o=this.queue.then(async()=>{let n=await this.ensureState();t=await e(n),n.updatedAt=new Date().toISOString(),await this.store.save(n)});return this.queue=o.then(()=>{},()=>{}),await o,t}async policy(){return{...(await this.ensureState()).policy}}async setPolicy(e,t){return this.mutate(o=>(o.policy=qo({...o.policy,...e}),this.audit(o,"policy:update",t,{metadata:{...o.policy}}),{...o.policy}))}async summary(){let e=await this.ensureState(),t=o=>e.reviews.filter(n=>n.status===o).length;return{schema:"toolnet.knowledge-governance-summary.v1",projectId:e.projectId,pending:t("pending"),approved:t("approved"),rejected:t("rejected"),superseded:t("superseded"),criticalPending:e.reviews.filter(o=>o.status==="pending"&&o.risk==="critical").length,conflictPending:e.reviews.filter(o=>o.status==="pending"&&o.risk==="conflict").length,auditEvents:e.audit.length,policy:{...e.policy},updatedAt:e.updatedAt}}async listReviews(e){let t=await this.ensureState();return structuredClone(t.reviews.filter(o=>!e||o.status===e).sort((o,n)=>n.updatedAt.localeCompare(o.updatedAt)))}async auditLog(e=100){let t=await this.ensureState(),o=Math.max(1,Math.min(500,Math.floor(e)));return structuredClone(t.audit.slice(-o).reverse())}async assess(e,t){let o=await this.ensureState(),n=ta(e),s=wt(e.title),i=t.filter(l=>l.slug!==e.slug&&wt(l.title)===s&&zo(l.content)!==zo(e.content)).map(l=>l.slug),a=ea(e),c=[];n<o.policy.autoApproveThreshold&&c.push(`confidence:${n.toFixed(2)}`),a&&n<o.policy.criticalApproveThreshold&&c.push("critical-knowledge"),i.length>0&&c.push("conflicting-knowledge");let d=i.length>0?"conflict":a?"critical":"normal";return{confidence:n,risk:d,requiresReview:i.length>0||n<o.policy.autoApproveThreshold||a&&n<o.policy.criticalApproveThreshold,reasons:c,conflicts:i}}async gate(e,t){let o=await this.assess(e,t);return this.mutate(n=>{let s=n.reviews.find(c=>c.sourceKey===e.sourceKey&&c.digest===e.digest);if(s?.status==="approved")return{allowed:!0,mode:"review-approved",assessment:o,review:structuredClone(s)};if(s?.status==="rejected")return{allowed:!1,mode:"rejected",assessment:o,review:structuredClone(s)};if(!o.requiresReview)return this.audit(n,"knowledge:auto-approved","system",{sourceKey:e.sourceKey,metadata:{confidence:o.confidence,risk:o.risk}}),{allowed:!0,mode:"auto-approved",assessment:o};if(s?.status==="pending")return{allowed:!1,mode:"pending-review",assessment:o,review:structuredClone(s)};let i=new Date().toISOString(),a={id:Go(),sourceKey:e.sourceKey,sourceType:e.sourceType,slug:e.slug,marker:e.marker,digest:e.digest,title:e.title,...e.summary?{summary:e.summary}:{},content:e.content,tags:[...new Set([...e.tags,e.marker])],confidence:o.confidence,risk:o.risk,reasons:[...o.reasons],conflicts:[...o.conflicts],status:"pending",createdAt:i,updatedAt:i};return n.reviews.push(a),this.audit(n,"knowledge:review-requested","system",{reviewId:a.id,sourceKey:a.sourceKey,metadata:{confidence:a.confidence,risk:a.risk}}),{allowed:!1,mode:"pending-review",assessment:o,review:structuredClone(a)}})}async markApplied(e,t){await this.mutate(o=>{let n=o.reviews.find(s=>s.sourceKey===e&&s.digest===t&&s.status==="approved");n&&(n.appliedAt=new Date().toISOString(),n.updatedAt=n.appliedAt,this.audit(o,"knowledge:applied",n.reviewedBy??"system",{reviewId:n.id,sourceKey:e}))})}async decide(e,t,o){return this.mutate(async n=>{let s=n.reviews.find(d=>d.id===e);if(!s)throw new k(`Governance review not found: ${e}`,404);if(s.status!=="pending")throw new k("Governance review is already resolved",409);let i=new Date().toISOString();if(s.reviewedAt=i,s.reviewedBy=t.principal,s.updatedAt=i,t.note?.trim()&&(s.reviewNote=t.note.trim()),t.action==="reject")return s.status="rejected",this.audit(n,"knowledge:rejected",t.principal,{reviewId:e,sourceKey:s.sourceKey}),structuredClone(s);if(t.action==="supersede")return s.status="superseded",t.targetReviewId&&(s.supersededBy=t.targetReviewId),this.audit(n,"knowledge:superseded",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:t.targetReviewId}}),structuredClone(s);if(t.action==="merge"){if(!t.targetReviewId)throw new k("targetReviewId is required for merge",400);let d=n.reviews.find(l=>l.id===t.targetReviewId);if(!d)throw new k("Merge target review not found",404);return s.status="superseded",s.mergedInto=d.id,this.audit(n,"knowledge:merged",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:d.id}}),structuredClone(s)}s.status="approved";let c=(await o.listPages()).find(d=>d.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new k(`Wiki page '${s.slug}' is manually managed`,409);return c?await o.updatePage(s.slug,{title:s.title,summary:s.summary??"",content:s.content,tags:s.tags}):await o.createPage({slug:s.slug,title:s.title,...s.summary?{summary:s.summary}:{},content:s.content,tags:s.tags}),s.appliedAt=i,this.audit(n,"knowledge:approved",t.principal,{reviewId:e,sourceKey:s.sourceKey}),structuredClone(s)})}async quality(e){let t=await this.ensureState(),o=await e.listPages(),n=Date.now(),s=t.policy.staleAfterDays*864e5,i=o.map(l=>{let m=n-Date.parse(l.updatedAt);return{slug:l.slug,title:l.title,updatedAt:l.updatedAt,ageDays:Math.max(0,Math.floor(m/864e5)),stale:Number.isFinite(m)&&m>s}}).filter(l=>l.stale).map(({stale:l,...m})=>m),a=new Map;for(let l of o){let m=wt(l.title),p=a.get(m)??[];p.push(l),a.set(m,p)}let c=[...a.entries()].filter(([,l])=>l.length>1).map(([l,m])=>({title:l,pages:m.map(p=>p.slug)})),d=t.reviews.filter(l=>l.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:o.length,automatedPages:o.filter(l=>l.tags.some(m=>m.startsWith("toolnet-auto-"))).length,manualPages:o.filter(l=>!l.tags.some(m=>m.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:d.length,lowConfidenceReviews:d.filter(l=>l.confidence<t.policy.autoApproveThreshold).length,conflicts:d.filter(l=>l.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var Jo={query:Ho.string().min(2).max(500).describe("Knowledge topic or project concept to search in ToolNet Wiki."),limit:Ho.number().int().min(1).max(10).optional().describe("Maximum Wiki matches. Default 5.")};async function Yo(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let o=new R(new j(t,r.project));await o.initialize();let n=await o.search(e.query,e.limit??5);return{schema:"toolnet.wiki-search.v1",query:e.query,count:n.length,results:n.map(({page:s,score:i})=>({id:s.id,slug:s.slug,title:s.title,summary:s.summary,tags:s.tags,links:s.links,revision:s.revision,updatedAt:s.updatedAt,score:i}))}}import{z as ra}from"zod";var Qo={page:ra.string().min(1).max(200).describe("Wiki page slug or page id.")};async function Xo(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let o=new R(new j(t,r.project));await o.initialize();let n=await o.getPage(e.page),s=await o.backlinks(n.slug);return{schema:"toolnet.wiki-read.v1",page:n,backlinks:s.map(i=>({slug:i.slug,title:i.title}))}}import{z as oa}from"zod";var Zo={includePending:oa.boolean().optional().describe("Include compact pending-review metadata. Default false.")};async function en(r,e){let t=r.storage;if(!t)throw new Error("Knowledge Governance storage unavailable");let o=new ne(new oe(t,r.project));await o.initialize();let n=new R(new j(t,r.project));await n.initialize();let s=await o.summary(),i=await o.quality(n),a=e.includePending?(await o.listReviews("pending")).slice(0,10).map(c=>({id:c.id,sourceType:c.sourceType,title:c.title,confidence:c.confidence,risk:c.risk,reasons:c.reasons})):void 0;return{schema:"toolnet.knowledge-governance-status.v1",summary:s,quality:{stalePages:i.stalePages.length,duplicateTitles:i.duplicateTitles.length,pendingReviews:i.pendingReviews,conflicts:i.conflicts},...a?{pending:a}:{}}}function w(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var ia=["# ToolNet Memory \u2014 Persistent Project Continuity","","ToolNet Memory provides persistent work continuity across coding agents and sessions.","","CONTINUITY RULES:","","1. When the user asks to continue, resume, finish, pick up, or return to previous work,"," call memory_agent_ask BEFORE reconstructing previous work from git, files, or session history.","",'2. Use memory_agent_ask with mode="local" for direct continuity facts such as:'," - current task"," - completed work"," - current/last file"," - TODOs"," - blockers"," - next action","",'3. Use mode="ai" only when the continuity question is ambiguous or requires synthesis.',"","4. NEVER reconstruct previous work by reading or searching raw agent/session history, including:"," - .toolnet/sessions/**"," - state.json"," - events.jsonl"," - raw transcripts"," - ~/.gemini/antigravity-cli/brain/**"," - another coding agent's internal session history","","5. Do not search the filesystem for the implementation or JSON schema of memory_agent_ask."," Invoke the MCP tool directly.","","6. After ToolNet resolves continuity, inspect the current repository only to verify current truth."," Current repository evidence overrides stale memory.","","7. Do not ask the user to repeat project context already available through ToolNet Memory.","","8. Do not call memory_agent_ask for unrelated coding questions when current context is sufficient.","","9. Large tool/file payloads may be stored outside prompt context."," If the compact graph references a needed asset, call context_offload_read.","","10. Never bulk-load offloaded assets. Read only the minimum asset required."].join("\\n");function aa(r){let e=new na({name:"toolnet-memory",version:"0.1.0"},{instructions:ia});return e.tool("memory_search","Search relevant long-term memory for the current project.",lr,async t=>w(await dr(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",ur,async t=>w(await mr(r,t))),e.tool("memory_forget","Delete a memory by id.",pr,async t=>w(await fr(r,t))),e.tool("find_symbol","Find code symbols by exact name.",gr,async t=>w(await yr(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",vr,async t=>w(await wr(r,t))),e.tool("code_search","Search indexed code symbols and files.",kr,async t=>w(await Sr(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Cr,async t=>w(await Ar(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",Ir,async t=>w(await Tr(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Or,async t=>w(await Lr(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>w(await Nr(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",Dr,async t=>w(await Fr(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",Gr,async t=>w(await Ur(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Pr,async t=>w(await Er(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>w(await Mr(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",jr,async t=>w(await Rr(r,t))),e.tool("impact_guard","Analyze blast radius before or after code changes. Maps changed files/lines to symbols, follows reverse dependencies, assigns risk and suggests verification targets.",Br,async t=>w(await Vr(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",qr,async t=>w(await Hr(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",Jr,async t=>w(await Yr(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Qr,async t=>w(await Xr(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",to,async t=>w(await ro(r,t))),e.tool("memory_agent_ask",["Ask ToolNet Memory Agent about previous project work.","CALL THIS TOOL before guessing when the user asks to continue/resume previous work,","mentions a previous agent/session, asks what was unfinished, what file was last touched,","which TODOs are complete, blockers, decisions, or what should happen next.","Use mode=local for direct state facts and mode=ai for composite or ambiguous continuity questions.","Do not use it for unrelated coding questions when current repository context is already sufficient.","Returns concise selected memory instead of raw transcripts or full memory dumps.","Short conversational follow-ups are supported using compact ToolNet Memory focus; raw transcripts are never replayed."].join(" "),ko,async t=>w(await So(r,t))),e.tool("context_offload_read",["Read one external ToolNet tool/file asset referenced by the compact context graph.","Use only when needed for the current task.","Never bulk-load all offloaded assets."].join(" "),Ro,async t=>w(await Io(r,t))),e.tool("skill_memory_search",["Search successful ToolNet project work promoted into reusable Skill Memory SOPs.","Call this before repeating a task that may have been solved successfully before.","Returns compact procedure steps, files and verification evidence.","Raw transcripts are never returned."].join(" "),Lo,async t=>w(await No(r,t))),e.tool("wiki_search",["Search the ToolNet project Wiki for durable project knowledge.","Use Wiki before rereading broad project history when a maintained knowledge page may exist.","Returns compact metadata; call wiki_read only for the page needed."].join(" "),Jo,async t=>w(await Yo(r,t))),e.tool("wiki_read",["Read one ToolNet Wiki page by slug or id.","Returns the maintained page plus compact backlinks.","Do not bulk-read unrelated Wiki pages."].join(" "),Qo,async t=>w(await Xo(r,t))),e.tool("knowledge_governance_status",["Inspect ToolNet Knowledge Governance health.","Returns review counts, confidence, conflicts, stale knowledge, and optional compact pending reviews.","Use this before trusting or changing important durable project knowledge."].join(" "),Zo,async t=>w(await en(r,t))),e}async function tn(r){let e=aa(r),t=new sa;await e.connect(t)}function Ye(r){return r instanceof Error?r.message:String(r)}async function $n(r){let e={memory:"failed",graph:"failed",semantic:"failed",errors:[]};try{let[{loadConfig:t},o]=await Promise.all([Promise.resolve().then(()=>(nn(),on)),Promise.resolve().then(()=>(Mn(),En))]),n=t(),s=o.createStorageProvider({provider:n.storage.provider,r2:n.storage.r2,s3:n.storage.s3,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),i=o.withStorageRetry(s,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),a=new o.ProjectScopedStorageProvider(i,r.project.id,r.project.name,r.project.remote??r.project.name),c=new o.MemoryStore(a);r.storage=a,r.memoryStore=c;let[d,l]=await Promise.allSettled([c.load(r.project.id),new o.PersistentCodeGraphStore(a).load(r.project.id)]);d.status==="fulfilled"?(r.memory.importRecords(d.value),e.memory="ready"):e.errors.push(`memory: ${Ye(d.reason)}`),l.status==="fulfilled"?(l.value&&r.graph.import(l.value.symbols,l.value.edges),e.graph="ready"):e.errors.push(`graph: ${Ye(l.reason)}`);try{let[{SemanticCodeEngine:m},{createEmbeddingProvider:p}]=await Promise.all([Promise.resolve().then(()=>(Ln(),On)),Promise.resolve().then(()=>(Fn(),Dn))]),f=new m({projectId:r.project.id,rootPath:r.project.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:a,embeddings:p(),graph:r.graph});await f.initialize(),r.codeSemantic=f,e.semantic="ready"}catch(m){e.errors.push(`semantic: ${Ye(m)}`)}}catch(t){e.errors.push(`storage: ${Ye(t)}`)}return e}import{closeSync as Za,mkdirSync as ec,openSync as tc,readFileSync as rc,unlinkSync as Gn,writeFileSync as oc}from"node:fs";import{tmpdir as nc}from"node:os";import{join as Un}from"node:path";function sc(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var Qe=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=Un(nc(),"toolnet-memory-locks");ec(t,{recursive:!0});let o=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=Un(t,`${o}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=tc(this.path,"wx");oc(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Za(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let o=!0;try{let n=JSON.parse(rc(this.path,"utf8"));Number.isInteger(n.pid)&&sc(n.pid)&&(o=!1)}catch{o=!0}if(!o)throw new Error("ToolNet Memory is already running for this project");try{Gn(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{Gn(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function ic(){let r=new be().detect(),e=new Qe(r.id);await e.acquire();let t=()=>{e.release().finally(()=>process.exit(0))};process.once("SIGINT",t),process.once("SIGTERM",t);let o=new ve,n=new Pe(o),s=new Ee,i=new Me(s),a={project:r,memory:o,retrieval:n,graph:s,references:i};await tn(a),$n(a).then(c=>{c.errors.length>0&&console.error(`[toolnet-memory] MCP background hydration degraded: ${c.errors.join(" | ")}`)}).catch(c=>{console.error(`[toolnet-memory] MCP background hydration failed: ${c instanceof Error?c.message:String(c)}`)})}ic().catch(r=>{console.error(r),process.exit(1)});
|