toolnet-memory 0.3.2 → 0.3.3

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