toolnet-memory 0.2.20 → 0.2.21

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/bundle/mcp.js CHANGED
@@ -1,16 +1,15 @@
1
- import"dotenv/config";import{existsSync as Gr,readFileSync as Ur}from"node:fs";import{homedir as Br}from"node:os";import{join as zr}from"node:path";function qr(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 Wr(){let r=process.env.TOOLNET_GLOBAL_ENV??zr(Br(),".config","toolnet-memory",".env");if(!Gr(r))return;let e=Ur(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 i=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=qr(o.slice(n+1)))}}Wr();function F(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function K(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function nt(){return{memory:{autoCapture:F(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:F(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:F(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:F(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:K(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:K(process.env.MEMORY_RERANK_TOP,10),finalContext:K(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:K(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:F(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:K(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Hr={critical:100,high:75,normal:50,temporary:20};function st(r){return Hr[r]}function it(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 Vr}from"node:crypto";import{existsSync as Be,mkdirSync as Yr,readFileSync as Jr,renameSync as Qr,writeFileSync as Zr}from"node:fs";import{basename as Xr,dirname as re,join as ne,parse as lt,resolve as G}from"node:path";var dt=".toolnet",eo="project.json";function to(r){return Vr("sha256").update(r).digest("hex").slice(0,16)}function ze(r){return ne(r,dt,eo)}function ro(r){return Be(ze(r))}function oo(r,e){let t=G(r),o=lt(t).root;for(;;){if(ro(t))return t;if(t===o||e&&t===G(e))break;let n=re(t);if(n===t)break;t=n}return null}function no(r){let e=G(r),t=lt(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(i=>Be(ne(e,i))))return e;if(e===t)break;let n=re(e);if(n===e)break;e=n}return G(r)}function so(r){let e;try{e=JSON.parse(Jr(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:re(re(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 at(r,e){let t=ne(r,dt);Yr(t,{recursive:!0});let o=ze(r),n=`${o}.tmp-${process.pid}`;Zr(n,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),Qr(n,o)}function ct(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 oe=class{detect(e=process.cwd()){let t=G(e),o=no(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>Be(ne(o,l))),s=oo(t,i?o:void 0);if(s){let l=ze(s),u=so(l);return u.rootPath!==s&&(u.rootPath=s,u.updatedAt=new Date().toISOString(),at(s,u)),ct(u,s)}let a=new Date().toISOString(),c=Xr(o),d={version:1,id:to(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return at(o,d),ct(d,o)}};import{randomUUID as fo}from"node:crypto";var io=[{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}],se=class{scan(e){let t=[];for(let o of io){let n=new RegExp(o.regex.source,o.regex.flags);for(let i of e.matchAll(n))t.push({type:o.type,value:i[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var N=class{scanner=new se;sanitize(e){let t=e,o=this.scanner.scan(e),n=new Set;for(let i of o)n.add(i.type),t=t.split(i.value).join(`[REDACTED:${i.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 i=o.toLowerCase();i.includes("password")||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")?t[o]="[REDACTED]":t[o]=this.sanitizeValue(n)}return t}return e}};var ao=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),co=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 pt(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!co.has(e)))}function lo(r,e){let t=pt(r),o=pt(e);if(t.size===0||o.size===0)return 0;let n=0;for(let s of t)o.has(s)&&n++;let i=new Set([...t,...o]).size;return n/i}function mt(r){return new Set(r.tags.filter(e=>!ao.has(e.toLowerCase())))}var ie=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=mt(e);return t.filter(i=>{if(i.id===e.id||i.projectId!==e.projectId||i.type!==e.type||i.metadata?.supersededBy)return!1;let s=typeof i.metadata?.topic=="string"?i.metadata.topic:void 0;if(o&&s&&o===s)return!0;let a=mt(i);for(let c of n)if(a.has(c))return!0;return lo(e.content,i.content)>=.6})}};var po={critical:100,high:75,normal:50,temporary:20},mo={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function ut(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 qe(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function uo(r){return!!r.metadata?.supersededBy}function We(r,e=Date.now()){return!qe(r,e)&&!uo(r)}function U(r,e=Date.now()){if(!We(r,e))return 0;let t=po[r.importance];if(r.importance==="critical")return t;let o=mo[r.type]??180,i=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,s=Math.pow(.5,i/o);return t*s}var ae=class{memories=new Map;sanitizer=new N;conflicts=new ie;remember(e){let t=new Date().toISOString(),o=this.sanitizer.sanitize(e.content.trim()).text,n=e.importance??it(e.type,o),i={id:fo(),projectId:e.projectId,type:e.type,content:o,importance:n,importanceScore:st(n),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??ut(e.type,n,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},s=this.conflicts.findSuperseded(i,this.list(e.projectId));if(s.length){i.metadata={...i.metadata??{},supersedes:s.map(a=>a.id)};for(let a of s)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:i.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(i.id,i),i}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=>We(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(i=>{if(e.types&&!e.types.includes(i.type))return!1;let s=U(i);return!(e.minImportanceScore&&s<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>i.tags.includes(c)))}).map(i=>{let s=i.content.toLowerCase(),a=n.filter(l=>s.includes(l)).length,c=n.length===0?0:a/n.length,d=U(i)/500;return{memory:i,score:c+d,source:"memory"}}).filter(i=>t.length===0||i.score>0).sort((i,s)=>s.score-i.score).slice(0,o)}pruneExpired(e,t=Date.now()){let o=0;for(let[n,i]of this.memories)i.projectId===e&&qe(i,t)&&(this.memories.delete(n),o++);return o}pruneSuperseded(e,t=30,o=Date.now()){let n=0,i=t*864e5;for(let[s,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;o-new Date(c).getTime()>=i&&(this.memories.delete(s),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 O(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var ce=class{score(e,t){let o=O(e),n=O([t.content,...t.tags??[],t.type].join(" "));if(o.length===0||n.length===0)return 0;let i=new Map;for(let a of n)i.set(a,(i.get(a)??0)+1);let s=0;for(let a of o){let c=i.get(a)??0;c!==0&&(s+=1+Math.log(1+c))}return s/o.length}};function ft(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 gt(r){return U(r)/100}var go={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function ht(r){return go[r]??.4}var le=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 de=class{bm25=new ce;analyzer=new le;search(e,t,o={}){let n=o.topK??8,i=o.minScore??.05,s=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=ft(c),u=gt(c),m=ht(c.type);s.preferredTypes.includes(c.type)&&(m=Math.min(1,m+.25));let f=d*.55+u*.2+l*.15+m*.1;d<=0||f<i||a.push({memory:c,score:f,scores:{keyword:d,recency:l,importance:u,type:m}})}return a.sort((c,d)=>d.score-c.score).slice(0,n)}};var pe=class{build(e,t=6e3){let o=[],n=0;for(let i of e){let s=i.memory,a=[`[${s.type.toUpperCase()}]`,s.content].join(" ");if(n+a.length>t)break;o.push(a),n+=a.length}return o.join(`
4
- `)}};var me=class{constructor(e){this.memory=e}memory;searcher=new de;contextBuilder=new pe;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 yt=[{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 I(r){let e=yt.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function B(r){return yt.some(e=>e.id===r)}function p(r){return process.env[r]?.trim()||void 0}function g(...r){return r.find(e=>!!e?.trim())}function bt(){if(p("GROQ_API_KEY"))return"groq";if(p("DEEPSEEK_API_KEY"))return"deepseek";if(p("NVIDIA_API_KEY")||p("NVIDIA_NIM_API_KEY"))return"nvidia";if(p("OPENROUTER_API_KEY"))return"openrouter";if(p("ALIBABA_API_KEY")||p("DASHSCOPE_API_KEY"))return"alibaba";if(p("GEMINI_API_KEY")||p("GOOGLE_API_KEY"))return"gemini";if(p("CLOUDFLARE_API_TOKEN")&&p("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(p("HF_TOKEN"))return"huggingface";if(p("OLLAMA_MODEL")||p("OLLAMA_BASE_URL"))return"ollama"}function St(){let r=p("TOOLNET_LLM_PROVIDER");return r&&B(r)?r:bt()??"openai-compatible"}function ue(r){let e=I(r);switch(r){case"alibaba":return{provider:r,apiKey:g(p("ALIBABA_API_KEY"),p("DASHSCOPE_API_KEY")),baseUrl:g(p("ALIBABA_BASE_URL"),p("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:g(p("ALIBABA_MODEL"),p("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:p("OPENROUTER_API_KEY"),baseUrl:g(p("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:p("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:p("GROQ_API_KEY"),baseUrl:g(p("GROQ_BASE_URL"),e.defaultBaseUrl),model:p("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:p("DEEPSEEK_API_KEY"),baseUrl:g(p("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:g(p("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:g(p("NVIDIA_API_KEY"),p("NVIDIA_NIM_API_KEY")),baseUrl:g(p("NVIDIA_BASE_URL"),p("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:g(p("NVIDIA_MODEL"),p("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:g(p("GEMINI_API_KEY"),p("GOOGLE_API_KEY")),baseUrl:g(p("GEMINI_BASE_URL"),e.defaultBaseUrl),model:p("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:p("HF_TOKEN"),baseUrl:g(p("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:g(p("HF_LLM_MODEL"),p("HF_MODEL"))};case"ollama":return{provider:r,apiKey:p("OLLAMA_API_KEY"),baseUrl:g(p("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:p("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:p("CLOUDFLARE_ACCOUNT_ID"),apiKey:p("CLOUDFLARE_API_TOKEN"),baseUrl:p("CLOUDFLARE_AI_BASE_URL"),model:p("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:p("CUSTOM_AI_API_KEY"),baseUrl:p("CUSTOM_AI_BASE_URL"),model:p("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:g(p("OPENAI_API_KEY"),p("MODEL_API_KEY")),baseUrl:g(p("OPENAI_BASE_URL"),p("MODEL_BASE_URL")),model:g(p("OPENAI_MODEL"),p("MODEL_NAME"))}}}function ho(){let r=p("TOOLNET_LLM_PROVIDER"),e=r&&B(r)?r:St(),t=I(e),o=ue(e);return{provider:e,apiKey:g(p("TOOLNET_LLM_API_KEY"),o.apiKey),baseUrl:g(p("TOOLNET_LLM_BASE_URL"),o.baseUrl,t.defaultBaseUrl),model:g(p("TOOLNET_LLM_MODEL"),o.model,t.defaultModel),accountId:g(p("TOOLNET_LLM_ACCOUNT_ID"),o.accountId)}}function yo(){let r=p("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&B(r)?r:p("HF_TOKEN")||p("HF_EMBEDDING_MODEL")?"huggingface":"local"}function bo(){let r=yo();if(r==="local")return{provider:"local",model:g(p("TOOLNET_EMBEDDING_MODEL"),p("LOCAL_EMBEDDING_MODEL"))};let e=I(r),t,o,n,i;switch(r){case"huggingface":t=p("HF_TOKEN"),o=p("HF_INFERENCE_BASE_URL"),n=p("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=p("OPENAI_API_KEY"),o=p("OPENAI_BASE_URL"),n=p("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=p("CLOUDFLARE_API_TOKEN"),o=p("CLOUDFLARE_AI_BASE_URL"),n=p("CLOUDFLARE_EMBEDDING_MODEL"),i=p("CLOUDFLARE_ACCOUNT_ID");break;default:t=ue(r).apiKey,o=ue(r).baseUrl,n=p(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let s=g(p("TOOLNET_EMBEDDING_ACCOUNT_ID"),i),a=g(p("TOOLNET_EMBEDDING_BASE_URL"),o,e.defaultBaseUrl),c=r==="cloudflare"&&!a&&s?`https://api.cloudflare.com/client/v4/accounts/${s}/ai/v1`:a;return{provider:r,apiKey:g(p("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:g(p("TOOLNET_EMBEDDING_MODEL"),n),accountId:s}}function q(){let r=ho(),e=bo();return{llm:r,embedding:e,legacy:{llm:!p("TOOLNET_LLM_PROVIDER")&&!!bt(),embedding:!p("TOOLNET_EMBEDDING_PROVIDER")&&!!(p("HF_TOKEN")||p("HF_EMBEDDING_MODEL"))}}}function vt(r=St()){let e=q().llm;if(r===e.provider)return{id:r,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId};let t=ue(r);return{id:r,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}function z(r,e){return p(`TOOLNET_LLM_FALLBACK_${r}_${e}`)}function wt(){let r=[];for(let e of[1,2]){let t=z(e,"PROVIDER");if(!t||!B(t))continue;let o=I(t);r.push({slot:e,config:{provider:t,apiKey:z(e,"API_KEY"),baseUrl:g(z(e,"BASE_URL"),o.defaultBaseUrl),model:g(z(e,"MODEL"),o.defaultModel),accountId:z(e,"ACCOUNT_ID")}})}return r}function xt(){let r=p("TOOLNET_LLM_FALLBACK_COOLDOWN_MS"),e=p("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 fe=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)}`,i=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({model:`models/${t}`,content:{parts:[{text:e}]}})});if(!i.ok)throw new Error(`Gemini embedding failed: ${i.status} ${await i.text()}`);let a=(await i.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 So}from"node:crypto";var ge=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 s=So("sha256").update(n).digest().readUInt32BE(0)%this.dimensions;t[s]+=1}return vo(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function vo(r){let e=Math.sqrt(r.reduce((t,o)=>t+o*o,0));return e===0?r:r.map(t=>t/e)}var he=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 i=(await o.json()).data?.sort((s,a)=>(s.index??0)-(a.index??0)).map(s=>s.embedding);if(!i||i.length!==e.length||i.some(s=>!Array.isArray(s)))throw new Error("Embedding provider returned invalid response");return i}};var ye=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(i=>wo(i))}};function wo(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 i=0;i<t;i++)o[i]+=n[i]??0;for(let n=0;n<t;n++)o[n]/=e.length;return o}throw new Error("Unsupported embedding shape")}var He=class{constructor(e,t=new ge){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 xo(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Eo(){let r=q().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new ye({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new fe({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=xo(r.accountId)),e&&r.model?new he({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Et(){return new He(Eo())}import*as w 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 be(r,e){let t=r.allSymbols(e),o=r.allEdges(e),n=s=>t.filter(a=>a.type===s).length,i=s=>o.filter(a=>a.type===s).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:i("CALLS"),callReferences:i("CALL_REFERENCE"),imports:i("IMPORTS"),inherits:i("INHERITS"),implements:i("IMPLEMENTS"),usesType:i("USES_TYPE"),tests:i("TESTS"),routeEdges:i("ROUTE"),writes:i("WRITES")}}var Se=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 i=[],s=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 m=o==="out"?u.to:u.from;if(s.has(m))continue;s.add(m);let f=this.graph.getSymbol(m);if(!f)continue;let b=d.depth+1;i.push({symbol:f,depth:b}),a.push({id:m,depth:b})}}return i}};var ve=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 we=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),i=new Set([t]),s=[{id:t,depth:0}],a=[];for(;s.length;){let c=s.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(i.has(l.from))continue;i.add(l.from);let u=this.graph.getSymbol(l.from);if(!u)continue;let m=c.depth+1;a.push({symbol:u,depth:m,relation:l.type}),s.push({id:l.from,depth:m})}}return a}};function Ao(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 xe=class{constructor(e){this.graph=e}graph;map(e,t){let o=this.graph.allSymbols(e),n=[];for(let i of t){let s=o.filter(d=>d.filePath===i.filePath),c=s.filter(d=>d.type!=="file").filter(d=>Ao(d,i));if(c.length===0){let d=s.find(l=>l.type==="file");d&&n.push({symbol:d,fileStatus:i.status,direct:!0});continue}for(let d of c)n.push({symbol:d,fileStatus:i.status,direct:!0})}return n}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var To={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Ro(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function Ct(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Ee=class{constructor(e){this.graph=e}graph;analyze(e,t,o=4){let n=this.graph.allEdges(e),i=new Map,s=0;for(let l of t){l.fileStatus==="deleted"?s+=8:l.fileStatus==="renamed"?s+=5:s+=2,l.symbol.type==="interface"&&(s+=5),l.symbol.type==="class"&&(s+=3);let u=new Set([l.symbol.id]),m=[{id:l.symbol.id,depth:0}];for(;m.length;){let f=m.shift();if(f.depth>=o)continue;let b=n.filter(S=>S.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(S.type));for(let S of b){if(u.has(S.from))continue;u.add(S.from);let k=this.graph.getSymbol(S.from);if(!k)continue;let A=f.depth+1,te=`${l.symbol.id}:${k.id}`;i.set(te,{symbol:k,relation:S.type,depth:A,sourceSymbolId:l.symbol.id});let j=To[S.type]??1;s+=Math.max(1,j-(A-1)),m.push({id:k.id,depth:A})}}}let a=[...i.values()].sort((l,u)=>l.depth-u.depth),c=[...new Set(a.map(l=>l.symbol.filePath))],d=c.filter(Ct);return d.length===0&&d.push(...c.filter(l=>!Ct(l)).slice(0,10)),{risk:Ro(s),riskScore:s,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:d}}};import{execFile as Mo}from"node:child_process";import{promisify as jo}from"node:util";var Ve=jo(Mo);function Io(r){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let o of r.matchAll(t)){let n=Number(o[1]),i=Number(o[2]??1);e.push({startLine:n,endLine:Math.max(n,n+i-1)})}return e}function Lo(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function Pt(r){let e="";try{e=(await Ve("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,...i]=o.split(" "),s=i.at(-1);if(!s)continue;let a="";try{a=(await Ve("git",["diff","HEAD","--unified=0","--",s],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:s,status:Lo(n),ranges:Io(a)})}try{let o=await Ve("git",["ls-files","--others","--exclude-standard"],{cwd:r});for(let n of o.stdout.split(/\r?\n/).filter(Boolean))t.some(i=>i.filePath===n)||t.push({filePath:n,status:"added",ranges:[]})}catch{}return t}var Ce=class{constructor(e){this.graph=e;this.mapper=new xe(e),this.blast=new Ee(e)}graph;mapper;blast;async analyzeGitDiff(e,t,o={}){let n=await Pt(t),i=this.mapper.map(e,n),s=this.blast.analyze(e,i,o.maxDepth??4);return{mode:"git_diff",changes:n,...s}}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 W=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 _o}from"node:crypto";import{readFile as No}from"node:fs/promises";import{join as Oo}from"node:path";function kt(r){return _o("sha256").update(r).digest("hex")}var Pe=class{sanitizer=new N;async build(e,t,o,n={}){let i=n.maxLines??80,s=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 No(Oo(t,d),"utf8")}catch{continue}let m=u.split(/\r?\n/),f=l.filter(b=>b.type!=="file"&&typeof b.startLine=="number"&&typeof b.endLine=="number");if(f.length>0)for(let b of f)c.push(...this.chunkRange({projectId:e,filePath:d,lines:m,symbol:b,startLine:b.startLine,endLine:b.endLine,maxLines:i,overlapLines:s}));else c.push(...this.chunkRange({projectId:e,filePath:d,lines:m,startLine:1,endLine:Math.max(1,m.length),maxLines:i,overlapLines:s}))}return c}chunkRange(e){let{projectId:t,filePath:o,lines:n,symbol:i,maxLines:s}=e,a=Math.min(e.overlapLines,Math.max(0,s-1)),c=Math.max(1,e.startLine),d=Math.min(n.length,Math.max(c,e.endLine)),l=[],u=c,m=0;for(;u<=d;){let f=Math.min(d,u+s-1),b=n.slice(u-1,f).join(`
5
- `).trim();if(b){let S=this.sanitizer.sanitize(b).text,k=kt(S),A=[t,o,i?.id??"file",String(m),k].join(":");l.push({id:kt(A).slice(0,32),projectId:t,filePath:o,symbolId:i?.id,symbolName:i?.qualifiedName??i?.name,symbolType:i?.type,startLine:u,endLine:f,content:S,contentHash:k})}if(f>=d)break;u=f-a+1,m++}return l}};var ke=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 Ae=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 Te=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 i of this.records.values()){if(i.projectId!==e)continue;let s=Do(t,i.vector);n.push({id:i.id,score:s,metadata:i.metadata})}return n.sort((i,s)=>s.score-i.score).slice(0,o)}size(){return this.records.size}};function Do(r,e){if(r.length===0||e.length===0||r.length!==e.length)return 0;let t=0,o=0,n=0;for(let i=0;i<r.length;i++){let s=r[i]??0,a=e[i]??0;t+=s*a,o+=s*s,n+=a*a}return o===0||n===0?0:t/(Math.sqrt(o)*Math.sqrt(n))}function At(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 Re=class{constructor(e){this.options=e}options;vectors=new Te;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:o,embeddings:n,graph:i,model:s}=this.options,a=new ke(o),c=new Ae(o),d=await new Pe().build(e,t,i.allSymbols(e));this.chunks.clear();for(let v of d)this.chunks.set(v.id,v);let l=await a.load(e),u=!l||l.chunks.length!==d.length||l.chunks.some(v=>!this.chunks.has(v.id));u&&await a.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:d});let m=await c.load(e),f=0;m&&m.model===s&&(f=this.vectors.importRecords(m.records));let b=new Set(d.map(v=>v.id)),S=0;for(let v of this.vectors.exportProject(e))b.has(v.id)||this.vectors.remove(v.id)&&S++;let k=d.filter(v=>{let L=this.vectors.get(v.id);return L?L.metadata?.contentHash!==v.contentHash:!0}),A=0,te=8,j=this.vectors.exportProject(e)[0]?.vector.length;for(let v=0;v<k.length;v+=te){let L=k.slice(v,v+te),Fr=L.map(P=>[`file: ${P.filePath}`,P.symbolName?`symbol: ${P.symbolName}`:"",P.symbolType?`type: ${P.symbolType}`:"",P.content].filter(Boolean).join(`
6
- `)),Kr=await n.embedMany(Fr);for(let P=0;P<L.length;P++){let R=L[P],_=Kr[P];if(!(!R||!_||_.length===0)){if(j===void 0&&(j=_.length),_.length!==j){console.warn(`[code-semantic] skip dimension mismatch: ${_.length} != ${j}`);continue}this.vectors.upsert({id:R.id,projectId:e,vector:_,metadata:{contentHash:R.contentHash,filePath:R.filePath,symbolName:R.symbolName,symbolType:R.symbolType,startLine:R.startLine,endLine:R.endLine}}),A++}}}let Ue=this.vectors.exportProject(e),ot=A>0||S>0||!m||m.model!==s;return ot&&await c.save({version:1,projectId:e,model:s,dimensions:Ue[0]?.vector.length??j??0,updatedAt:new Date().toISOString(),records:Ue}),{chunks:d.length,vectorsLoaded:f,vectorsIndexed:A,vectorsRemoved:S,totalVectors:Ue.length,savedChunks:u,savedVectors:ot}}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)),i=new Set(O(e)),s=[];for(let a of n){let c=this.chunks.get(a.id);if(!c)continue;let d=new Set(O([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),l=0;for(let S of i)d.has(S)&&l++;let u=i.size===0?0:l/i.size,m=Math.max(0,a.score),f=At(c.filePath,e),b=(m*.75+u*.25)*f;s.push({chunk:c,score:b,vectorScore:m,lexicalScore:u})}return s.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}};import*as x from"typescript";import*as h from"typescript";var Da=new Set([h.SyntaxKind.EqualsToken,h.SyntaxKind.PlusEqualsToken,h.SyntaxKind.MinusEqualsToken,h.SyntaxKind.AsteriskEqualsToken,h.SyntaxKind.SlashEqualsToken,h.SyntaxKind.PercentEqualsToken,h.SyntaxKind.QuestionQuestionEqualsToken,h.SyntaxKind.AmpersandAmpersandEqualsToken,h.SyntaxKind.BarBarEqualsToken]);function $o(r){return r.replaceAll("\\","/").toLowerCase()}var H=class{constructor(e){this.graph=e}graph;detect(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=[];for(let s of t){if(s.type!=="route"&&s.type!=="file")continue;let a=this.classify(s,o);a&&n.push({symbolId:s.id,filePath:s.filePath,name:s.name,kind:a.kind,score:a.score,reasons:a.reasons})}let i=new Map;for(let s of n){let a=s.kind==="route"?s.symbolId:s.filePath,c=i.get(a);(!c||s.score>c.score)&&i.set(a,s)}return[...i.values()].sort((s,a)=>a.score-s.score||s.filePath.localeCompare(a.filePath))}classify(e,t){let o=$o(e.filePath),n=[];if(e.type==="route")return{kind:"route",score:100,reasons:["HTTP route"]};let i=null,s=0;if(o.startsWith("bin/"))i="cli",s=100,n.push("bin executable");else if(/(^|\/)(cli)\.[^.]+$/.test(o))i="cli",s=90,n.push("CLI entry file");else if(/(^|\/)(main|server)\.[^.]+$/.test(o))i="main",s=90,n.push("main/server file");else if(o.includes("/runtime/")&&/(^|\/)(bootstrap|index)\.[^.]+$/.test(o))i="runtime",s=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)&&(i="package",s=o.startsWith("packages/")?70:55,n.push("package/public index"))}return i?(t.filter(c=>c.to===e.id&&c.type!=="DEFINES").length===0&&(s+=10,n.push("no incoming dependency")),{kind:i,score:s,reasons:n}):null}};var Me=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Tt=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,i)=>{let s=n.name.toLowerCase()===o,a=i.name.toLowerCase()===o;return s!==a?s?-1:1:n.filePath.localeCompare(i.filePath)}):[]}callers(e,t){return this.relatedIncoming(e,t,Tt)}callees(e,t){return this.relatedOutgoing(e,t,Tt)}dependents(e,t){return this.relatedIncoming(e,t,Me)}dependencies(e,t){return this.relatedOutgoing(e,t,Me)}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 i=this.graph.getSymbol(t),s=this.graph.getSymbol(o);if(!i||!s||i.projectId!==e||s.projectId!==e)return{found:!1,distance:-1,symbols:[],edges:[]};if(t===o)return{found:!0,distance:0,symbols:[i],edges:[]};let a=this.graph.allEdges(e).filter(m=>Me.has(m.type)),c=new Map;for(let m of a){let f=c.get(m.from)??[];f.push(m),c.set(m.from,f)}let d=[{id:t,depth:0}],l=new Set([t]),u=new Map;for(;d.length>0;){let m=d.shift();if(!(m.depth>=n)){for(let f of c.get(m.id)??[])if(!l.has(f.to)){if(l.add(f.to),u.set(f.to,{node:m.id,edge:f}),f.to===o)return this.buildPath(t,o,u);d.push({id:f.to,depth:m.depth+1})}}}return{found:!1,distance:-1,symbols:[],edges:[]}}buildPath(e,t,o){let n=[t],i=[],s=t;for(;s!==e;){let c=o.get(s);if(!c)return{found:!1,distance:-1,symbols:[],edges:[]};i.push(c.edge),s=c.node,n.push(s)}n.reverse(),i.reverse();let a=n.map(c=>this.graph.getSymbol(c)).filter(c=>!!c);return{found:!0,distance:i.length,symbols:a,edges:i}}walk(e,t,o,n){let i=this.graph.allEdges(e).filter(d=>Me.has(d.type)),s=[{id:t,depth:0}],a=new Set([t]),c=[];for(;s.length>0;){let d=s.shift();if(!(d.depth>=n))for(let l of i){if(!(o==="incoming"?l.to===d.id:l.from===d.id))continue;let m=o==="incoming"?l.from:l.to;if(a.has(m))continue;let f=this.graph.getSymbol(m);f&&(a.add(m),c.push({symbol:f,depth:d.depth+1,via:l}),s.push({id:m,depth:d.depth+1}))}}return c}relatedIncoming(e,t,o){return[...new Set(this.graph.allEdges(e).filter(i=>i.to===t&&o.has(i.type)).map(i=>i.from))].map(i=>this.graph.getSymbol(i)).filter(i=>!!i)}relatedOutgoing(e,t,o){return[...new Set(this.graph.allEdges(e).filter(i=>i.from===t&&o.has(i.type)).map(i=>i.to))].map(i=>this.graph.getSymbol(i)).filter(i=>!!i)}};var Rt=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function Ye(r){return r.replaceAll("\\","/").toLowerCase()}function Fo(r){let e=Ye(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function Ko(r){let e=Ye(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var V=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e),n=new Set(new H(this.graph).detect(e).map(s=>s.symbolId)),i=[];for(let s of t){if(!["function","method","class","interface","property"].includes(s.type)||Fo(s.filePath)||n.has(s.id)||Ko(s)||o.filter(f=>f.to===s.id&&Rt.has(f.type)).length>0)continue;let c=o.filter(f=>f.from===s.id&&Rt.has(f.type)),d=["no incoming usage edge"],l=50;(s.type==="function"||s.type==="method")&&(l+=20,d.push("callable symbol")),s.type==="property"&&(l-=15),c.length===0&&(l+=10,d.push("no outgoing dependency")),Ye(s.filePath).includes("/internal/")&&(l+=10,d.push("internal implementation")),s.name.startsWith("_")&&(l+=5);let m=l>=75?"high":l>=55?"medium":"low";i.push({symbolId:s.id,name:s.name,qualifiedName:s.qualifiedName,type:s.type,filePath:s.filePath,startLine:s.startLine,confidence:m,score:l,reasons:d})}return i.sort((s,a)=>a.score-s.score||s.filePath.localeCompare(a.filePath)||s.name.localeCompare(a.name))}};var Go=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Y=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),o=this.graph.allEdges(e).filter(s=>Go.has(s.type)),n=new Map(t.map(s=>[s.id,s]));return[...new Set(t.map(s=>s.filePath))].sort().map(s=>{let a=new Set,c=new Set,d=0,l=0;for(let u of o){let m=n.get(u.from),f=n.get(u.to);!m||!f||m.filePath===f.filePath||(m.filePath===s&&(a.add(f.filePath),d++),f.filePath===s&&(c.add(m.filePath),l++))}return{filePath:s,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:d,incomingEdges:l}})}};import{homedir as pn}from"node:os";import{join as mn}from"node:path";import{DeleteObjectCommand as Uo,GetObjectCommand as Bo,HeadObjectCommand as zo,ListObjectsV2Command as qo,PutObjectCommand as Wo,S3Client as Ho}from"@aws-sdk/client-s3";import{getSignedUrl as Vo}from"@aws-sdk/s3-request-presigner";var je=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ho({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 Wo({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await Vo(this.client,new Bo({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 zo({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 Uo({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new qo({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as Mt,mkdir as Yo,readFile as Jo,readdir as Qo,rm as Zo,stat as jt,writeFile as Xo}from"node:fs/promises";import{dirname as en,join as tn,relative as It,resolve as rn}from"node:path";var J=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return rn(this.root,t)}async put(e,t){let o=this.path(e);await Yo(en(o),{recursive:!0}),await Xo(o,t)}async get(e){try{return await Jo(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 Mt(this.path(e)),!0}catch{return!1}}async delete(e){await Zo(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await Mt(t)}catch{return o}let n=async s=>{let a=await Qo(s,{withFileTypes:!0});for(let c of a){let d=tn(s,c.name);if(c.isDirectory()){await n(d);continue}let l=await jt(d);o.push({key:It(this.root,d),size:l.size,updatedAt:l.mtime.toISOString()})}},i=await jt(t);return i.isDirectory()?await n(t):o.push({key:It(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),o}};import{DeleteObjectCommand as on,GetObjectCommand as nn,HeadObjectCommand as sn,ListObjectsV2Command as an,PutObjectCommand as cn,S3Client as ln}from"@aws-sdk/client-s3";import{getSignedUrl as dn}from"@aws-sdk/s3-request-presigner";var Q=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ln({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 cn({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await dn(this.client,new nn({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 sn({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 on({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new an({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function Je(r,e){return console.warn(e),new J(r)}function Lt(r){let e=r.localRoot??mn(pn(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new Q({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Je(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 Q({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Je(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 je({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Je(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new J(e)}var Ie=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 un(r){return new Promise(e=>setTimeout(e,r))}async function _t(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,i;for(let s=1;s<=t;s++)try{return await r()}catch(a){if(i=a,s>=t)break;let c=Math.min(n,o*2**(s-1)),d=Math.floor(Math.random()*Math.max(1,c*.2));await un(c+d)}throw i}var fn=new Set(["put","get","getText","delete","list"]);function Nt(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:fn.has(o)?(...i)=>_t(()=>Promise.resolve(n.apply(t,i)),e):n.bind(t)}})}function Ot(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 Dt(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 Le=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=Ot(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 s;try{s=JSON.parse(n)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof s.id=="string"&&s.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${s.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof s.createdAt=="string"&&(o=s.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
7
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Dt(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 Gn}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Un}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as $t}from"zod";var Ft={query:$t.string(),limit:$t.number().int().min(1).max(20).optional()};async function Kt(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 Z}from"zod";var Gt={type:Z.enum(["activity","decision","rule","todo","summary"]),content:Z.string().min(1),tags:Z.array(Z.string()).optional(),importance:Z.enum(["critical","high","normal","temporary"]).optional()};async function Ut(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 gn}from"zod";var Bt={id:gn.string().min(1)};async function zt(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 hn}from"zod";var qt={name:hn.string().min(1)};async function Wt(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as yn}from"zod";function T(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(i=>i.name===e||i.qualifiedName===e);return n||(o.findSymbols(r.project.id,e)[0]??null)}function E(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var Ht={symbolId:yn.string().min(1)};async function Vt(r,e){let t=T(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:E(t),count:n.length,callers:n.map(E)}}import{z as Yt}from"zod";var Jt={query:Yt.string().min(1),limit:Yt.number().int().min(1).max(50).optional()};async function Qt(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 Zt}from"zod";var Xt={query:Zt.string().optional(),memoryLimit:Zt.number().int().min(1).max(20).optional()};async function er(r,e){let t=be(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(i=>i.memory)}}import{z as Sn}from"zod";var bn=["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"],M=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(),i=n.replace(/[:.]/g,"-"),s=this.projectPrefix(e),a=this.snapshotPrefix(e,i),c=[];for(let l of bn){let u=`${s}/${l}`,m=await this.storage.get(u);m&&(await this.storage.put(`${a}/${l}`,m,"application/json"),c.push(l))}if(c.length===0)return null;let d={version:1,id:i,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(s=>s.key.endsWith("/snapshot.json")),i=[];for(let s of n){let a=await this.storage.getText(s.key);if(a)try{i.push(JSON.parse(a))}catch{}}return i.sort((s,a)=>a.createdAt.localeCompare(s.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 i=JSON.parse(n);if(i.projectId!==e)throw new Error("Snapshot project mismatch");let s=this.projectPrefix(e),a=[];for(let c of i.objects){let d=await this.storage.get(`${o}/${c}`);d&&(await this.storage.put(`${s}/${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 i of n)await this.storage.delete(i.key);return n.length}async prune(e,t=10){let n=(await this.list(e)).slice(t),i=0;for(let s of n)await this.remove(e,s.id),i++;return i}};var tr={reason:Sn.string().optional()};async function rr(r,e){if(!r.storage)throw new Error("Storage unavailable");return new M(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function or(r){if(!r.storage)throw new Error("Storage unavailable");return new M(r.storage).list(r.project.id)}import{z as vn}from"zod";var nr={snapshotId:vn.string().min(1)};async function sr(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new M(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as Qe}from"zod";var ir={symbolId:Qe.string().min(1),direction:Qe.enum(["callers","callees"]).optional(),depth:Qe.number().int().min(1).max(10).optional()};async function ar(r,e){let t=new Se(r.graph),o=e.direction??"callees",n=e.depth??3,i=o==="callers"?t.callers(r.project.id,e.symbolId,n):t.callees(r.project.id,e.symbolId,n);return{direction:o,depth:n,results:i.map(s=>({id:s.symbol.id,name:s.symbol.name,qualifiedName:s.symbol.qualifiedName,type:s.symbol.type,filePath:s.symbol.filePath,depth:s.depth}))}}import{z as cr}from"zod";var lr={symbolId:cr.string().min(1),depth:cr.number().int().min(1).max(10).optional()};async function dr(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let n=new we(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(i=>({id:i.symbol.id,name:i.symbol.name,qualifiedName:i.symbol.qualifiedName,filePath:i.symbol.filePath,type:i.symbol.type,relation:i.relation,depth:i.depth}))}}async function pr(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:be(r.graph,r.project.id)}}import{z as mr}from"zod";var ur={filePath:mr.string().min(1),direction:mr.enum(["dependencies","dependents","both"]).optional()};async function fr(r,e){let o=new Y(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"),i=new Map(n.map(c=>[c.filePath,c])),s=c=>({id:i.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(s),dependents:a==="dependencies"?[]:o.dependents.map(s)}}import{z as gr}from"zod";var hr={query:gr.string().min(1),limit:gr.number().int().min(1).max(20).optional()};async function yr(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 Ze}from"zod";var br={mode:Ze.enum(["git_diff","file"]).optional(),filePath:Ze.string().optional(),depth:Ze.number().int().min(1).max(10).optional()};async function Sr(r,e){let t=new Ce(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 wn}from"zod";var vr={symbol:wn.string().min(1)};async function wr(r,e){let t=T(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:E(t),count:n.length,dependents:n.map(E)}}import{z as Xe}from"zod";var xr={from:Xe.string().min(1),to:Xe.string().min(1),maxDepth:Xe.number().int().min(1).max(30).optional()};async function Er(r,e){let t=T(r,e.from),o=T(r,e.to);if(!t||!o)return{found:!1,fromFound:!!t,toFound:!!o,path:[],edges:[]};let i=new C(r.graph).shortestPath(r.project.id,t.id,o.id,e.maxDepth??12);return{found:i.found,distance:i.distance,from:E(t),to:E(o),path:i.symbols.map(E),edges:i.edges.map(s=>({id:s.id,type:s.type,from:s.from,to:s.to,metadata:s.metadata}))}}import{z as et}from"zod";var Cr={symbol:et.string().min(1),depth:et.number().int().min(1).max(5).optional(),limit:et.number().int().min(1).max(200).optional()};async function Pr(r,e){let t=T(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 i=e.limit??50;return{found:!0,center:E(n.center),incomingCount:n.incoming.length,outgoingCount:n.outgoing.length,incoming:n.incoming.slice(0,i).map(s=>({depth:s.depth,via:s.via?.type,symbol:E(s.symbol)})),outgoing:n.outgoing.slice(0,i).map(s=>({depth:s.depth,via:s.via?.type,symbol:E(s.symbol)}))}}import{z as tt}from"zod";var Ar={confidence:tt.enum(["high","medium","low","all"]).optional(),filePath:tt.string().min(1).optional(),limit:tt.number().int().min(1).max(500).optional()},kr={high:3,medium:2,low:1};async function Tr(r,e){let o=new V(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let s=kr[e.confidence];o=o.filter(a=>kr[a.confidence]>=s)}e.filePath&&(o=o.filter(s=>s.filePath===e.filePath));let n=o.length,i=e.limit??100;return{total:n,high:o.filter(s=>s.confidence==="high").length,medium:o.filter(s=>s.confidence==="medium").length,low:o.filter(s=>s.confidence==="low").length,warning:"Dead-code results are candidates only. Verify before deleting code.",candidates:o.slice(0,i)}}import{z as Lr}from"zod";import{existsSync as Mn,readFileSync as jn}from"node:fs";import{join as In}from"node:path";import{existsSync as xn,mkdirSync as ap,readFileSync as En,renameSync as cp,writeFileSync as lp}from"node:fs";import{dirname as pp,join as Cn}from"node:path";function Pn(r){return Cn(r.rootPath,".toolnet","work","current.json")}function _e(r){let e=Pn(r);if(!xn(e))return null;try{let t=JSON.parse(En(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as kn,mkdirSync as fp,readFileSync as An,renameSync as gp,writeFileSync as hp}from"node:fs";import{dirname as bp,join as Tn}from"node:path";function Rn(r){return Tn(r.rootPath,".toolnet","context","session-origin.json")}function Ne(r){let e=Rn(r);if(!kn(e))return null;try{let t=JSON.parse(An(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Ln(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function _n(r){let e=Ln(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"}function Nn(r){let e=In(r.rootPath,".toolnet","context","handoff.md");if(!Mn(e))return null;try{let t=jn(e,"utf8").trim();return t||null}catch{return null}}function On(r,e=5){return r.slice(0,e).map(t=>`- ${t}`).join(`
8
- `)}function X(r,e){let t=_n(e),o=Ne(r),n=_e(r);switch(t){case"previous_agent":{if(o)return{intent:t,answer:`Agent tr\u01B0\u1EDBc l\xE0 ${o.agent}. Session: ${o.nativeSessionId}.`,source:"session-origin"};break}case"current_task":{if(o?.currentTask){let s=[`Task hi\u1EC7n t\u1EA1i: ${o.currentTask}.`];return o.lastTouchedFile&&s.push(`File g\u1EA7n nh\u1EA5t: ${o.lastTouchedFile}.`),o.latestNextAction&&s.push(`Ti\u1EBFp theo: ${o.latestNextAction}.`),{intent:t,answer:s.join(" "),source:"session-origin"}}if(n?.currentTask)return{intent:t,answer:`Task hi\u1EC7n t\u1EA1i: ${n.currentTask.title} (${n.currentTask.status}).`,source:"work-state"};break}case"next_action":{let s=o?.latestNextAction??n?.nextActions?.[0];if(s)return{intent:t,answer:`Vi\u1EC7c n\xEAn l\xE0m ti\u1EBFp: ${s}.`,source:o?.latestNextAction?"session-origin":"work-state"};break}case"last_file":{let s=o?.lastTouchedFile??n?.filesTouched?.at(-1);if(s)return{intent:t,answer:`File g\u1EA7n nh\u1EA5t \u0111\u01B0\u1EE3c nh\u1EAFc ho\u1EB7c s\u1EEDa: ${s}.`,source:o?.lastTouchedFile?"session-origin":"work-state"};break}case"blocker":{let s=o?.latestBlocker??n?.blockers?.at(-1);return s?{intent:t,answer:`Blocker hi\u1EC7n t\u1EA1i: ${s}.`,source:o?.latestBlocker?"session-origin":"work-state"}:{intent:t,answer:"Hi\u1EC7n ToolNet ch\u01B0a ghi nh\u1EADn blocker n\xE0o.",source:n?"work-state":"none"}}case"decision":{let s=o?.latestDecision??n?.decisions?.at(-1);if(s)return{intent:t,answer:`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${s}.`,source:o?.latestDecision?"session-origin":"work-state"};break}case"completed":{let s=n?.tasks?.filter(a=>a.status==="completed").map(a=>a.title)??[];if(s.length)return{intent:t,answer:`C\xE1c task \u0111\xE3 ho\xE0n th\xE0nh:
9
- ${On(s,8)}`,source:"work-state"};break}case"status":{if(n){let s=[`Progress: ${n.progress.tasksCompleted}/${n.progress.tasksTotal} task ho\xE0n th\xE0nh.`];return n.currentTask&&s.push(`\u0110ang l\xE0m: ${n.currentTask.title}.`),n.progress.blocked>0&&s.push(`Blocked: ${n.progress.blocked}.`),{intent:t,answer:s.join(" "),source:"work-state"}}break}case"summary":{if(o||n){let s=[];o&&s.push(`Agent tr\u01B0\u1EDBc: ${o.agent}.`);let a=o?.currentTask??n?.currentTask?.title;a&&s.push(`Task hi\u1EC7n t\u1EA1i: ${a}.`);let c=o?.lastTouchedFile??n?.filesTouched?.at(-1);c&&s.push(`File g\u1EA7n nh\u1EA5t: ${c}.`);let d=o?.latestNextAction??n?.nextActions?.[0];d&&s.push(`Ti\u1EBFp theo: ${d}.`);let l=o?.latestBlocker??n?.blockers?.at(-1);l&&s.push(`Blocker: ${l}.`);let u=o?.latestDecision??n?.decisions?.at(-1);return u&&s.push(`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${u}.`),{intent:t,answer:s.join(" "),source:o?"session-origin":"work-state"}}break}}let i=Nn(r);if(i){let s=i.length>900?`${i.slice(0,900)}
10
- [truncated]`:i;return{intent:t,answer:s,source:"handoff"}}return{intent:t,answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}var ee=class extends Error{status;constructor(e,t){super(e),this.name="AiHttpError",this.status=t}};async function $(r,e,t=3e4){let o=new AbortController,n=setTimeout(()=>o.abort(),t);n.unref?.();try{let i=await fetch(r,{...e,signal:o.signal}),s=await i.text();if(!i.ok){let a=s;try{let c=JSON.parse(s);a=c.error?.message??c.message??s}catch{}throw new ee(a||`HTTP ${i.status}`,i.status)}return s.trim()?JSON.parse(s):{}}finally{clearTimeout(n)}}function Oe(r,e){return`${r.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}var De=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(),s=`${(this.config.baseUrl?.trim()||`https://api.cloudflare.com/client/v4/accounts/${t}/ai/run`).replace(/\/+$/,"")}/${n}`,a=await $(s,{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 $e=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(),i=e.messages.filter(l=>l.role==="system"),s=e.messages.filter(l=>l.role!=="system").map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]})),a=`${Oe(o,`models/${encodeURIComponent(n)}:generateContent`)}?key=${encodeURIComponent(t)}`,c=await $(a,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...i.length?{systemInstruction:{parts:[{text:i.map(l=>l.content).join(`
11
-
12
- `)}]}}:{},contents:s,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 Fe=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 $(Oe(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 Rr(r=vt()){switch(I(r.id).transport){case"gemini":return new $e(r);case"cloudflare":return new De(r);default:return new Fe(r)}}function Dn(r){return new Promise(e=>{setTimeout(e,r)})}function $n(r){if(r instanceof ee){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 Ke=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:Rr(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 i=0;i<=this.maxRetries;i+=1)try{let s=await n.provider.generate(e);return this.success(o),s}catch(s){let a=s instanceof Error?s.message:String(s),c=$n(s);if(t.push(`${n.label}: ${a}`),!c)throw s;if(i<this.maxRetries){await Dn(Math.min(250*2**i,2e3));continue}this.fail(o,s)}}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 Mr(){let r=q(),e=wt();return new Ke({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}})),xt())}var rt=class{constructor(e=Mr()){this.provider=e}provider;get activeProvider(){return this.provider}setProvider(e){this.provider=e}generate(e){return this.provider.generate(e)}};function jr(){return new rt(Mr())}function Fn(r,e){let t=JSON.stringify(r,null,2);return t.length<=e?t:t.slice(0,e)+`
13
- [truncated]`}function Kn(r,e){let t=X(r,e),o=Ne(r),n=_e(r),i={project:{id:r.id,name:r.name},directAnswer:t.answer,previousSession:o,workState:n?{goal:n.goal,plan:n.plan,currentPhase:n.currentPhase,currentTask:n.currentTask,tasks:n.tasks,blockers:n.blockers,decisions:n.decisions,nextActions:n.nextActions,filesTouched:n.filesTouched,tests:n.tests,progress:n.progress,lastSession:n.lastSession}:null};return Fn(i,7e3)}async function Ir(r,e){let t=X(r,e),o=Kn(r,e),n=jr();try{let i=await n.generate({temperature:.1,maxTokens:450,messages:[{role:"system",content:`
1
+ import"dotenv/config";import{existsSync as oo,readFileSync as no}from"node:fs";import{homedir as so}from"node:os";import{join as io}from"node:path";function ao(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 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 ys(r,e){let t=ps[e]??Kr,o=[];for(let n of t){let s=r.filter(i=>i.kind===n).slice(0,Gr(n));for(let i of s)o.push(`${$r[n]}: ${i.value}`)}return o.join(`
9
+ `)}function te(r,e){let t=$(r,e,{maxFacts:32,maxChars:6400}),o=gs(fs(t.facts)),n=us(e)?hs(o,["todo","task","next_action","file"]):ys(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"}}var re=class extends Error{status;constructor(e,t){super(e),this.name="AiHttpError",this.status=t}};async function K(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 re(a||`HTTP ${s.status}`,s.status)}return i.trim()?JSON.parse(i):{}}finally{clearTimeout(n)}}function De(r,e){return`${r.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}var $e=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 K(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 Ke=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=`${De(o,`models/${encodeURIComponent(n)}:generateContent`)}?key=${encodeURIComponent(t)}`,c=await K(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 Ge=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 K(De(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 Ur(r=Tt()){switch(_(r.id).transport){case"gemini":return new Ke(r);case"cloudflare":return new $e(r);default:return new Ge(r)}}function bs(r){return new Promise(e=>{setTimeout(e,r)})}function Ss(r){if(r instanceof re){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 Ue=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:Ur(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=Ss(i);if(t.push(`${n.label}: ${a}`),!c)throw i;if(s<this.maxRetries){await bs(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 Br(){let r=W(),e=It();return new Ue({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}})),jt())}var at=class{constructor(e=Br()){this.provider=e}provider;get activeProvider(){return this.provider}setProvider(e){this.provider=e}generate(e){return this.provider.generate(e)}};function zr(){return new at(Br())}function vs(r,e){let t=JSON.stringify(r,null,2);return t.length<=e?t:t.slice(0,e)+`
12
+ [truncated]`}function ws(r,e){let t=te(r,e),o=$(r,e,{maxFacts:12,maxChars:3200});return vs({project:o.context.project,intent:o.intent,directAnswer:t.answer,selectedMemory:o.context.selectedFacts,retrievalStats:o.stats},4200)}async function qr(r,e,t={}){let o=te(r,e),n=ws(r,e),s=t.router??zr();try{let i=await s.generate({temperature:.1,maxTokens:450,messages:[{role:"system",content:`
14
13
  You are ToolNet Memory Agent.
15
14
 
16
15
  You are NOT the coding agent.
@@ -44,7 +43,10 @@ ${e}
44
43
 
45
44
  ToolNet selected memory:
46
45
 
47
- ${o}
46
+ ${n}
48
47
 
49
48
  Answer the coding agent directly.
50
- `.trim()}]}),s=i.text.trim();return s?{answer:s,provider:i.provider,model:i.model,usedAi:!0}:{answer:t.answer,usedAi:!1}}catch{return{answer:t.answer,usedAi:!1}}}var _r={question:Lr.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Lr.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only.")};async function Nr(r,e){if(e.mode==="local"){let o=X(r.project,e.question);return{answer:o.answer,mode:"local",usedAi:!1,source:o.source,intent:o.intent}}let t=await Ir(r.project,e.question);return{answer:t.answer,mode:"ai",usedAi:t.usedAi,provider:t.provider,model:t.model}}function y(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var Bn=["# 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."].join("\\n");function zn(r){let e=new Gn({name:"toolnet-memory",version:"0.1.0"},{instructions:Bn});return e.tool("memory_search","Search relevant long-term memory for the current project.",Ft,async t=>y(await Kt(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",Gt,async t=>y(await Ut(r,t))),e.tool("memory_forget","Delete a memory by id.",Bt,async t=>y(await zt(r,t))),e.tool("find_symbol","Find code symbols by exact name.",qt,async t=>y(await Wt(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",Ht,async t=>y(await Vt(r,t))),e.tool("code_search","Search indexed code symbols and files.",Jt,async t=>y(await Qt(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Xt,async t=>y(await er(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",ir,async t=>y(await ar(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",lr,async t=>y(await dr(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>y(await pr(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",ur,async t=>y(await fr(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",hr,async t=>y(await yr(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",tr,async t=>y(await rr(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>y(await or(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",nr,async t=>y(await sr(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=>y(await Sr(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",vr,async t=>y(await wr(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",xr,async t=>y(await Er(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Cr,async t=>y(await Pr(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Ar,async t=>y(await Tr(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."].join(" "),_r,async t=>y(await Nr(r,t))),e}async function Or(r){let e=zn(r),t=new Un;await e.connect(t)}import{closeSync as qn,mkdirSync as Wn,openSync as Hn,readFileSync as Vn,unlinkSync as Dr,writeFileSync as Yn}from"node:fs";import{tmpdir as Jn}from"node:os";import{join as $r}from"node:path";function Qn(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var Ge=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=$r(Jn(),"toolnet-memory-locks");Wn(t,{recursive:!0});let o=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=$r(t,`${o}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Hn(this.path,"wx");Yn(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),qn(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(Vn(this.path,"utf8"));Number.isInteger(n.pid)&&Qn(n.pid)&&(o=!1)}catch{o=!0}if(!o)throw new Error("ToolNet Memory is already running for this project");try{Dr(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{Dr(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function Zn(){let r=nt(),e=new oe().detect(),t=Lt({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),o=Nt(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),n=new Le(o,e.id,e.name,e.remote??e.name),i=new Ge(e.id);await i.acquire();let s=()=>{i.release().finally(()=>process.exit(0))};process.once("SIGINT",s),process.once("SIGTERM",s);let a=new ae,c=new Ie(n);a.importRecords(await c.load(e.id));let d=new me(a),l=new D,u=await new W(n).load(e.id);u&&l.import(u.symbols,u.edges);let m=new ve(l),f=new Re({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:n,embeddings:Et(),graph:l});await f.initialize(),await Or({project:e,memory:a,retrieval:d,graph:l,references:m,codeSemantic:f,memoryStore:c,storage:n})}Zn().catch(r=>{console.error(r),process.exit(1)});
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 ks,mkdirSync as xs,readFileSync as Cs,renameSync as Es,rmSync as Ps,writeFileSync as As}from"node:fs";import{join as Hr}from"node:path";var Ms=720*60*1e3;function Wr(r){return Hr(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function oe(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function Rs(r){let e=oe(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 Ts(r){if(Rs(r))return!1;let e=oe(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 Is(r,e,t){let o=Wr(r);if(!ks(o))return null;try{let n=JSON.parse(Cs(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 js(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,oe(s)].join(":");if(!t.has(i)&&(t.add(i),o.push({...n,value:s}),o.length>=e))break}return o}function _s(r,e){let t=Wr(r),o=Hr(r.rootPath,".toolnet","context");xs(o,{recursive:!0,mode:448});let n=`${t}.${process.pid}.tmp`;try{As(n,JSON.stringify(e,null,2)+`
50
+ `,{encoding:"utf8",mode:384}),Es(n,t)}finally{Ps(n,{force:!0})}}function Ls(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
51
+ `)}function Ns(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function ct(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=oe(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=Ns(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 Os(r){let e=oe(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 Vr(r,e,t={}){let o=t.now??Date.now(),n=t.maxAgeMs??Ms,s=Is(r,o,n),i=!!(s&&s.focus.length>0&&Ts(e)&&!Os(e)),a=i&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",Ls(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})),u=js(i&&s?[...l,...s.focus]:l);return _s(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(o).toISOString(),lastIntent:c,focus:u}),{question:a,originalQuestion:e,usedPriorFocus:i,previousIntent:s?.lastIntent,currentIntent:c,priorFocus:s?.focus??[],focusCount:u.length}}var Qr={question:Yr.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Yr.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only.")};async function Jr(r,e){let t=Vr(r.project,e.question);if(e.mode==="local"){let n=ct(t);if(n)return{answer:n.answer,mode:"local",usedAi:!1,source:n.source,intent:n.intent};let s=te(r.project,t.originalQuestion);return{answer:s.answer,mode:"local",usedAi:!1,source:s.source,intent:s.intent}}let o=await qr(r.project,t.question);if(!o.usedAi){let n=ct(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}}function b(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var $s=["# 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."].join("\\n");function Ks(r){let e=new Fs({name:"toolnet-memory",version:"0.1.0"},{instructions:$s});return e.tool("memory_search","Search relevant long-term memory for the current project.",Yt,async t=>b(await Qt(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",Jt,async t=>b(await Zt(r,t))),e.tool("memory_forget","Delete a memory by id.",Xt,async t=>b(await er(r,t))),e.tool("find_symbol","Find code symbols by exact name.",tr,async t=>b(await rr(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",or,async t=>b(await nr(r,t))),e.tool("code_search","Search indexed code symbols and files.",ir,async t=>b(await ar(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",lr,async t=>b(await dr(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",hr,async t=>b(await yr(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Sr,async t=>b(await vr(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>b(await wr(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",xr,async t=>b(await Cr(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",Pr,async t=>b(await Ar(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",mr,async t=>b(await pr(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>b(await ur(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",fr,async t=>b(await gr(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.",Mr,async t=>b(await Rr(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",Tr,async t=>b(await Ir(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",jr,async t=>b(await _r(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Lr,async t=>b(await Nr(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Fr,async t=>b(await Dr(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(" "),Qr,async t=>b(await Jr(r,t))),e}async function Zr(r){let e=Ks(r),t=new Ds;await e.connect(t)}import{closeSync as Gs,mkdirSync as Us,openSync as Bs,readFileSync as zs,unlinkSync as Xr,writeFileSync as qs}from"node:fs";import{tmpdir as Hs}from"node:os";import{join as eo}from"node:path";function Ws(r){try{return process.kill(r,0),!0}catch(e){return e?.code==="EPERM"}}var Be=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=eo(Hs(),"toolnet-memory-locks");Us(t,{recursive:!0});let o=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=eo(t,`${o}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Bs(this.path,"wx");qs(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),Gs(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(zs(this.path,"utf8"));Number.isInteger(n.pid)&&Ws(n.pid)&&(o=!1)}catch{o=!0}if(!o)throw new Error("ToolNet Memory is already running for this project");try{Xr(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{Xr(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};async function Vs(){let r=dt(),e=new ie().detect(),t=Bt({provider:r.storage.provider,huggingface:r.storage.huggingface,localRoot:r.storage.localRoot}),o=qt(t,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),n=new Oe(o,e.id,e.name,e.remote??e.name),s=new Be(e.id);await s.acquire();let i=()=>{s.release().finally(()=>process.exit(0))};process.once("SIGINT",i),process.once("SIGTERM",i);let a=new de,c=new Ne(n);a.importRecords(await c.load(e.id));let d=new ge(a),l=new D,u=await new V(n).load(e.id);u&&l.import(u.symbols,u.edges);let p=new xe(l),f=new je({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:n,embeddings:_t(),graph:l});await f.initialize(),await Zr({project:e,memory:a,retrieval:d,graph:l,references:p,codeSemantic:f,memoryStore:c,storage:n})}Vs().catch(r=>{console.error(r),process.exit(1)});