toolnet-memory 0.3.12 → 0.3.13

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,59 +1,18 @@
1
- var Cs=Object.defineProperty;var y=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(n){throw t=[n],n}};var we=(r,e)=>{for(var t in e)Cs(r,t,{get:e[t],enumerable:!0})};var Ms,Ce,lr=y(()=>{"use strict";Ms=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],Ce=class{scan(e){let t=[];for(let n of Ms){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 _,xe=y(()=>{"use strict";lr();_=class{scanner=new Ce;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.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")?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 bt=y(()=>{"use strict"});import{existsSync as Ii,readFileSync as ji}from"node:fs";import{homedir as _i}from"node:os";import{join as Oi}from"node:path";function Ni(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 Li(){let r=process.env.TOOLNET_GLOBAL_ENV??Oi(_i(),".config","toolnet-memory",".env");if(!Ii(r))return;let e=ji(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]=Ni(n.slice(o+1)))}}var Cn=y(()=>{"use strict";Li()});var Mn={};we(Mn,{loadConfig:()=>xn});function te(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function re(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function xn(){return{memory:{autoCapture:te(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:te(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:te(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:te(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:re(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:re(process.env.MEMORY_RERANK_TOP,10),finalContext:re(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:re(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:te(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:re(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Et=y(()=>{"use strict";Cn()});function L(r){let e=In.find(t=>t.id===r);if(!e)throw new Error(`Unsupported AI provider: ${r}`);return e}function ne(r){return In.some(e=>e.id===r)}var In,Rt=y(()=>{"use strict";In=[{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 d(r){return process.env[r]?.trim()||void 0}function b(...r){return r.find(e=>!!e?.trim())}function jn(){if(d("GROQ_API_KEY"))return"groq";if(d("DEEPSEEK_API_KEY"))return"deepseek";if(d("NVIDIA_API_KEY")||d("NVIDIA_NIM_API_KEY"))return"nvidia";if(d("OPENROUTER_API_KEY"))return"openrouter";if(d("ALIBABA_API_KEY")||d("DASHSCOPE_API_KEY"))return"alibaba";if(d("GEMINI_API_KEY")||d("GOOGLE_API_KEY"))return"gemini";if(d("CLOUDFLARE_API_TOKEN")&&d("CLOUDFLARE_ACCOUNT_ID"))return"cloudflare";if(d("HF_TOKEN"))return"huggingface";if(d("OLLAMA_MODEL")||d("OLLAMA_BASE_URL"))return"ollama"}function _n(){let r=d("TOOLNET_LLM_PROVIDER");return r&&ne(r)?r:jn()??"openai-compatible"}function Je(r){let e=L(r);switch(r){case"alibaba":return{provider:r,apiKey:b(d("ALIBABA_API_KEY"),d("DASHSCOPE_API_KEY")),baseUrl:b(d("ALIBABA_BASE_URL"),d("DASHSCOPE_BASE_URL"),e.defaultBaseUrl),model:b(d("ALIBABA_MODEL"),d("DASHSCOPE_MODEL"))};case"openrouter":return{provider:r,apiKey:d("OPENROUTER_API_KEY"),baseUrl:b(d("OPENROUTER_BASE_URL"),e.defaultBaseUrl),model:d("OPENROUTER_MODEL")};case"groq":return{provider:r,apiKey:d("GROQ_API_KEY"),baseUrl:b(d("GROQ_BASE_URL"),e.defaultBaseUrl),model:d("GROQ_MODEL")};case"deepseek":return{provider:r,apiKey:d("DEEPSEEK_API_KEY"),baseUrl:b(d("DEEPSEEK_BASE_URL"),e.defaultBaseUrl),model:b(d("DEEPSEEK_MODEL"),e.defaultModel)};case"nvidia":return{provider:r,apiKey:b(d("NVIDIA_API_KEY"),d("NVIDIA_NIM_API_KEY")),baseUrl:b(d("NVIDIA_BASE_URL"),d("NVIDIA_NIM_BASE_URL"),e.defaultBaseUrl),model:b(d("NVIDIA_MODEL"),d("NVIDIA_NIM_MODEL"),e.defaultModel)};case"gemini":return{provider:r,apiKey:b(d("GEMINI_API_KEY"),d("GOOGLE_API_KEY")),baseUrl:b(d("GEMINI_BASE_URL"),e.defaultBaseUrl),model:d("GEMINI_MODEL")};case"huggingface":return{provider:r,apiKey:d("HF_TOKEN"),baseUrl:b(d("HF_INFERENCE_BASE_URL"),e.defaultBaseUrl),model:b(d("HF_LLM_MODEL"),d("HF_MODEL"))};case"ollama":return{provider:r,apiKey:d("OLLAMA_API_KEY"),baseUrl:b(d("OLLAMA_BASE_URL"),e.defaultBaseUrl),model:d("OLLAMA_MODEL")};case"cloudflare":return{provider:r,accountId:d("CLOUDFLARE_ACCOUNT_ID"),apiKey:d("CLOUDFLARE_API_TOKEN"),baseUrl:d("CLOUDFLARE_AI_BASE_URL"),model:d("CLOUDFLARE_MODEL")};case"custom":return{provider:r,apiKey:d("CUSTOM_AI_API_KEY"),baseUrl:d("CUSTOM_AI_BASE_URL"),model:d("CUSTOM_AI_MODEL")};default:return{provider:"openai-compatible",apiKey:b(d("OPENAI_API_KEY"),d("MODEL_API_KEY")),baseUrl:b(d("OPENAI_BASE_URL"),d("MODEL_BASE_URL")),model:b(d("OPENAI_MODEL"),d("MODEL_NAME"))}}}function aa(){let r=d("TOOLNET_LLM_PROVIDER"),e=r&&ne(r)?r:_n(),t=L(e),n=Je(e);return{provider:e,apiKey:b(d("TOOLNET_LLM_API_KEY"),n.apiKey),baseUrl:b(d("TOOLNET_LLM_BASE_URL"),n.baseUrl,t.defaultBaseUrl),model:b(d("TOOLNET_LLM_MODEL"),n.model,t.defaultModel),accountId:b(d("TOOLNET_LLM_ACCOUNT_ID"),n.accountId)}}function ca(){let r=d("TOOLNET_EMBEDDING_PROVIDER");return r==="local"?"local":r&&ne(r)?r:d("HF_TOKEN")||d("HF_EMBEDDING_MODEL")?"huggingface":"local"}function la(){let r=ca();if(r==="local")return{provider:"local",model:b(d("TOOLNET_EMBEDDING_MODEL"),d("LOCAL_EMBEDDING_MODEL"))};let e=L(r),t,n,o,s;switch(r){case"huggingface":t=d("HF_TOKEN"),n=d("HF_INFERENCE_BASE_URL"),o=d("HF_EMBEDDING_MODEL");break;case"openai-compatible":t=d("OPENAI_API_KEY"),n=d("OPENAI_BASE_URL"),o=d("OPENAI_EMBEDDING_MODEL");break;case"cloudflare":t=d("CLOUDFLARE_API_TOKEN"),n=d("CLOUDFLARE_AI_BASE_URL"),o=d("CLOUDFLARE_EMBEDDING_MODEL"),s=d("CLOUDFLARE_ACCOUNT_ID");break;default:t=Je(r).apiKey,n=Je(r).baseUrl,o=d(`${r.toUpperCase().replace(/-/g,"_")}_EMBEDDING_MODEL`)}let i=b(d("TOOLNET_EMBEDDING_ACCOUNT_ID"),s),a=b(d("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:b(d("TOOLNET_EMBEDDING_API_KEY"),t),baseUrl:c,model:b(d("TOOLNET_EMBEDDING_MODEL"),o),accountId:i}}function se(){let r=aa(),e=la();return{llm:r,embedding:e,legacy:{llm:!d("TOOLNET_LLM_PROVIDER")&&!!jn(),embedding:!d("TOOLNET_EMBEDDING_PROVIDER")&&!!(d("HF_TOKEN")||d("HF_EMBEDDING_MODEL"))}}}function On(r=_n()){let e=se().llm;if(r===e.provider)return{id:r,apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,accountId:e.accountId};let t=Je(r);return{id:r,apiKey:t.apiKey,baseUrl:t.baseUrl,model:t.model,accountId:t.accountId}}function oe(r,e){return d(`TOOLNET_LLM_FALLBACK_${r}_${e}`)}function Nn(){let r=[];for(let e of[1,2]){let t=oe(e,"PROVIDER");if(!t||!ne(t))continue;let n=L(t);r.push({slot:e,config:{provider:t,apiKey:oe(e,"API_KEY"),baseUrl:b(oe(e,"BASE_URL"),n.defaultBaseUrl),model:b(oe(e,"MODEL"),n.defaultModel),accountId:oe(e,"ACCOUNT_ID")}})}return r}function Ln(){let r=d("TOOLNET_LLM_FALLBACK_COOLDOWN_MS"),e=d("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 Ye=y(()=>{"use strict";Rt()});var Ko=y(()=>{"use strict"});import{DeleteObjectCommand as fc,GetObjectCommand as gc,HeadObjectCommand as yc,ListObjectsV2Command as hc,PutObjectCommand as bc,S3Client as kc}from"@aws-sdk/client-s3";import{getSignedUrl as vc}from"@aws-sdk/s3-request-presigner";var ge,Nt=y(()=>{"use strict";ge=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new kc({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 bc({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await vc(this.client,new gc({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 yc({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 fc({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new hc({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 Fo,mkdir as Sc,readFile as wc,readdir as Cc,rm as xc,stat as $o,writeFile as Mc}from"node:fs/promises";import{dirname as Ac,join as Pc,relative as Go,resolve as Ec}from"node:path";var H,Lt=y(()=>{"use strict";H=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ec(this.root,t)}async put(e,t){let n=this.path(e);await Sc(Ac(n),{recursive:!0}),await Mc(n,t)}async get(e){try{return await wc(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 Fo(this.path(e)),!0}catch{return!1}}async delete(e){await xc(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await Fo(t)}catch{return n}let o=async i=>{let a=await Cc(i,{withFileTypes:!0});for(let c of a){let l=Pc(i,c.name);if(c.isDirectory()){await o(l);continue}let u=await $o(l);n.push({key:Go(this.root,l),size:u.size,updatedAt:u.mtime.toISOString()})}},s=await $o(t);return s.isDirectory()?await o(t):n.push({key:Go(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),n}}});import{DeleteObjectCommand as Rc,GetObjectCommand as Tc,HeadObjectCommand as Ic,ListObjectsV2Command as jc,PutObjectCommand as _c,S3Client as Oc}from"@aws-sdk/client-s3";import{getSignedUrl as Nc}from"@aws-sdk/s3-request-presigner";var V,Dt=y(()=>{"use strict";V=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Oc({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 _c({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Nc(this.client,new Tc({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 Ic({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 Rc({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new jc({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 Lc}from"node:os";import{join as Dc}from"node:path";function Kt(r,e){return console.warn(e),new H(r)}function Kc(r){let e=r.localRoot??Dc(Lc(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new V({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Kt(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 V({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Kt(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 ge({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Kt(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new H(e)}var zo=y(()=>{"use strict";Nt();Lt();Dt()});var Ft,Uo=y(()=>{"use strict";Ft=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 Wo=y(()=>{"use strict";Lt()});var Bo=y(()=>{"use strict";Nt()});var qo=y(()=>{"use strict";Dt()});var $t,Ho=y(()=>{"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 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 Gt,Vo=y(()=>{"use strict";Gt=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 zt,Jo=y(()=>{"use strict";zt=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 ye,Ut=y(()=>{"use strict";ye=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 he,Wt=y(()=>{"use strict";he=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 Fc(r){return new Promise(e=>setTimeout(e,r))}async function Yo(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)),l=Math.floor(Math.random()*Math.max(1,c*.2));await Fc(c+l)}throw s}var Qo=y(()=>{"use strict"});function Gc(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:$c.has(n)?(...s)=>Yo(()=>Promise.resolve(o.apply(t,s)),e):o.bind(t)}})}var $c,Xo=y(()=>{"use strict";Qo();$c=new Set(["put","get","getText","delete","list"])});function Bt(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 qt=y(()=>{"use strict"});function Ht(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 Vt=y(()=>{"use strict"});var Jt,Zo=y(()=>{"use strict";qt();Vt();Jt=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Bt(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=Ht(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 es=y(()=>{"use strict";qt();Zo();Vt()});var Yt,ts=y(()=>{"use strict";Yt=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 Qt,rs=y(()=>{"use strict";Qt=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 Xt,ns=y(()=>{"use strict";Xt=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 Zt,os=y(()=>{"use strict";Zt=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 ss={};we(ss,{HuggingFaceStorageProvider:()=>ge,LocalStorageProvider:()=>H,MemoryStore:()=>Ft,PersistentArchitectureStore:()=>Qt,PersistentCodeAnalysisStore:()=>Xt,PersistentCodeChunkStore:()=>ye,PersistentCodeGraphStore:()=>Gt,PersistentCodeManifestStore:()=>zt,PersistentCodeVectorStore:()=>he,PersistentTypeResolutionStore:()=>Yt,PersistentVectorStore:()=>$t,PersistentVisualizationStore:()=>Zt,ProjectScopedStorageProvider:()=>Jt,S3StorageProvider:()=>V,createStorageProvider:()=>Kc,mapProjectStoragePath:()=>Ht,sanitizeProjectFolder:()=>Bt,withStorageRetry:()=>Gc});var is=y(()=>{"use strict";Ko();zo();Uo();Wo();Bo();qo();Ho();Vo();Jo();Ut();Wt();Xo();es();ts();rs();ns();os()});import{createHash as zc}from"node:crypto";import{readFile as Uc}from"node:fs/promises";import{join as Wc}from"node:path";function as(r){return zc("sha256").update(r).digest("hex")}var ct,cs=y(()=>{"use strict";xe();ct=class{sanitizer=new _;async build(e,t,n,o={}){let s=o.maxLines??80,i=o.overlapLines??10,a=new Map;for(let l of n){let u=a.get(l.filePath)??[];u.push(l),a.set(l.filePath,u)}let c=[];for(let[l,u]of a){let m;try{m=await Uc(Wc(t,l),"utf8")}catch{continue}let f=m.split(/\r?\n/),p=u.filter(h=>h.type!=="file"&&typeof h.startLine=="number"&&typeof h.endLine=="number");if(p.length>0)for(let h of p)c.push(...this.chunkRange({projectId:e,filePath:l,lines:f,symbol:h,startLine:h.startLine,endLine:h.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:l,lines:f,startLine:1,endLine:Math.max(1,f.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),l=Math.min(o.length,Math.max(c,e.endLine)),u=[],m=c,f=0;for(;m<=l;){let p=Math.min(l,m+i-1),h=o.slice(m-1,p).join(`
4
- `).trim();if(h){let v=this.sanitizer.sanitize(h).text,M=as(v),P=[t,n,s?.id??"file",String(f),M].join(":");u.push({id:as(P).slice(0,32),projectId:t,filePath:n,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:m,endLine:p,content:v,contentHash:M})}if(p>=l)break;m=p-a+1,f++}return u}}});function Bc(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 lt,ls=y(()=>{"use strict";lt=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=Bc(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 us(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 ds=y(()=>{"use strict"});var ms={};we(ms,{SemanticCodeEngine:()=>er});var er,ps=y(()=>{"use strict";Ut();Wt();cs();ls();bt();ds();er=class{constructor(e){this.options=e}options;vectors=new lt;chunks=new Map;async initialize(e){let{projectId:t,rootPath:n,storage:o,embeddings:s,graph:i,model:a}=this.options,c=new ye(o),l=new he(o),u=await new ct().build(t,n,i.allSymbols(t));this.chunks.clear();for(let w of u)this.chunks.set(w.id,w);let m=await c.load(t),f=!m||m.chunks.length!==u.length||m.chunks.some(w=>!this.chunks.has(w.id));f&&await c.save({version:1,projectId:t,updatedAt:new Date().toISOString(),chunks:u});let p=await l.load(t),h=0;p&&p.model===a&&(h=this.vectors.importRecords(p.records));let v=new Set(u.map(w=>w.id)),M=0;for(let w of this.vectors.exportProject(t))v.has(w.id)||this.vectors.remove(w.id)&&M++;let P=u.filter(w=>{let K=this.vectors.get(w.id);return K?K.metadata?.contentHash!==w.contentHash:!0}),J=0,Y=8,Q=this.vectors.exportProject(t)[0]?.vector.length,dt=Math.ceil(P.length/Y),sr=0;for(let w=0;w<P.length;w+=Y){let K=P.slice(w,w+Y),Ss=K.map(A=>[`file: ${A.filePath}`,A.symbolName?`symbol: ${A.symbolName}`:"",A.symbolType?`type: ${A.symbolType}`:"",A.content].filter(Boolean).join(`
5
- `)),ws=await s.embedMany(Ss);for(let A=0;A<K.length;A++){let j=K[A],F=ws[A];if(!(!j||!F||F.length===0)){if(Q===void 0&&(Q=F.length),F.length!==Q){console.warn(`[code-semantic] skip dimension mismatch: ${F.length} != ${Q}`);continue}this.vectors.upsert({id:j.id,projectId:t,vector:F,metadata:{contentHash:j.contentHash,filePath:j.filePath,symbolName:j.symbolName,symbolType:j.symbolType,startLine:j.startLine,endLine:j.endLine}}),J++}}sr++,e?.({current:sr,total:dt,phase:"embedding"})}let mt=this.vectors.exportProject(t),ir=J>0||M>0||!p||p.model!==a;return ir&&(e?.({current:dt,total:dt,phase:"saving"}),await l.save({version:1,projectId:t,model:a,dimensions:mt[0]?.vector.length??Q??0,updatedAt:new Date().toISOString(),records:mt})),{chunks:u.length,vectorsLoaded:h,vectorsIndexed:J,vectorsRemoved:M,totalVectors:mt.length,savedChunks:f,savedVectors:ir}}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 l=new Set($([c.filePath,c.symbolName??"",c.symbolType??"",c.content].join(" "))),u=0;for(let v of s)l.has(v)&&u++;let m=s.size===0?0:u/s.size,f=Math.max(0,a.score),p=us(c.filePath,e),h=(f*.75+m*.25)*p;i.push({chunk:c,score:h,vectorScore:f,lexicalScore:m})}return i.sort((a,c)=>c.score-a.score).slice(0,t)}size(){return this.chunks.size}}});var fs=y(()=>{"use strict"});var be,tr=y(()=>{"use strict";be=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 qc}from"node:crypto";function Hc(r){let e=Math.sqrt(r.reduce((t,n)=>t+n*n,0));return e===0?r:r.map(t=>t/e)}var ke,rr=y(()=>{"use strict";ke=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=qc("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Hc(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}}});var ve,nr=y(()=>{"use strict";ve=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 Vc(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 Se,or=y(()=>{"use strict";Se=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=>Vc(s))}}});function Jc(r){return`https://api.cloudflare.com/client/v4/accounts/${r}/ai/v1`}function Yc(){let r=se().embedding;if(r.provider==="local")return null;if(r.provider==="huggingface")return!r.apiKey||!r.model?null:new Se({token:r.apiKey,model:r.model});if(r.provider==="gemini")return!r.apiKey||!r.model?null:new be({apiKey:r.apiKey,model:r.model,baseUrl:r.baseUrl});let e=r.baseUrl;return r.provider==="cloudflare"&&!e&&r.accountId&&(e=Jc(r.accountId)),e&&r.model?new ve({apiKey:r.apiKey,baseUrl:e,model:r.model}):null}function Qc(){return new ut(Yc())}var ut,gs=y(()=>{"use strict";Ye();tr();rr();nr();or();ut=class{constructor(e,t=new ke){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 ys={};we(ys,{GeminiEmbeddingProvider:()=>be,HashEmbeddingProvider:()=>ke,HuggingFaceEmbeddingProvider:()=>Se,OpenAiCompatibleEmbeddingProvider:()=>ve,ResilientEmbeddingProvider:()=>ut,createEmbeddingProvider:()=>Qc});var hs=y(()=>{"use strict";fs();gs();or();rr();nr();tr()});import"dotenv/config";import{randomUUID as Fs}from"node:crypto";var xs={critical:100,high:75,normal:50,temporary:20};function ar(r){return xs[r]}function cr(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"}xe();var As=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Ps=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 ur(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Ps.has(e)))}function Es(r,e){let t=ur(r),n=ur(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 dr(r){return new Set(r.tags.filter(e=>!As.has(e.toLowerCase())))}var Me=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=dr(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=dr(s);for(let c of o)if(a.has(c))return!0;return Es(e.content,s.content)>=.6})}};var Rs=new Set(["code","decision","rule","todo","summary"]);function Ts(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function mr(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 Is(r,e){let t=mr(e)-mr(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 pr(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 fr(r){let e=new Map;for(let o of r){if(!Rs.has(o.type)||o.metadata?.supersededBy)continue;let s=Ts(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(Is),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:pr(s.flatMap(c=>c.tags)),mergedSources:pr(s.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function pt(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 js(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function _s(r){let e=pt(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 Os(r){return pt(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function Ns(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 gr(r,e=Date.now()){let t=50,n=[],o=pt(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")),Ns(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=js(r,e)>=_s(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Os(r);t=Math.max(0,Math.min(100,Math.round(t)));let l;t>=80?l="trusted":t>=55?l="useful":t>=30?l="weak":l="noise";let u=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:l,stale:a,protected:c,pruneEligible:!c&&(l==="noise"&&u||a&&(l==="noise"||l==="weak")),reasons:n}}var Ls={critical:100,high:75,normal:50,temporary:20},Ds={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function yr(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 ft(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Ks(r){return!!r.metadata?.supersededBy}function gt(r,e=Date.now()){return!ft(r,e)&&!Ks(r)}function X(r,e=Date.now()){if(!gt(r,e))return 0;let t=Ls[r.importance];if(r.importance==="critical")return t;let n=Ds[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/n);return t*i}var Ae=class{memories=new Map;sanitizer=new _;conflicts=new Me;remember(e){let t=new Date().toISOString(),n=this.sanitizer.sanitize(e.content.trim()).text,o=e.importance??cr(e.type,n),s={id:Fs(),projectId:e.projectId,type:e.type,content:n,importance:o,importanceScore:ar(o),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??yr(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=>gt(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=X(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(u=>i.includes(u)).length,c=o.length===0?0:a/o.length,l=X(s)/500;return{memory:s,score:c+l,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=fr(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=gr(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&&ft(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 $s}from"node:crypto";import{existsSync as yt,mkdirSync as Gs,readFileSync as zs,renameSync as Us,writeFileSync as Ws}from"node:fs";import{basename as Bs,dirname as Pe,join as Re,parse as kr,resolve as Z}from"node:path";var vr=".toolnet",qs="project.json";function Hs(r){return $s("sha256").update(r).digest("hex").slice(0,16)}function ht(r){return Re(r,vr,qs)}function Vs(r){return yt(ht(r))}function Js(r,e){let t=Z(r),n=kr(t).root;for(;;){if(Vs(t))return t;if(t===n||e&&t===Z(e))break;let o=Pe(t);if(o===t)break;t=o}return null}function Ys(r){let e=Z(r),t=kr(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(s=>yt(Re(e,s))))return e;if(e===t)break;let o=Pe(e);if(o===e)break;e=o}return Z(r)}function Qs(r){let e;try{e=JSON.parse(zs(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:Pe(Pe(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 hr(r,e){let t=Re(r,vr);Gs(t,{recursive:!0});let n=ht(r),o=`${n}.tmp-${process.pid}`;Ws(o,JSON.stringify(e,null,2)+`
6
- `,{encoding:"utf8",mode:384}),Us(o,n)}function br(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 Ee=class{detect(e=process.cwd()){let t=Z(e),n=Ys(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(u=>yt(Re(n,u))),i=Js(t,s?n:void 0);if(i){let u=ht(i),m=Qs(u);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),hr(i,m)),br(m,i)}let a=new Date().toISOString(),c=Bs(n),l={version:1,id:Hs(n),name:c,remote:c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return hr(n,l),br(l,n)}};bt();var Te=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 Sr(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 wr(r){return X(r)/100}var Xs={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function Cr(r){return Xs[r]??.4}var Ie=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 je=class{bm25=new Te;analyzer=new Ie;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 l=this.bm25.score(e,c),u=Sr(c),m=wr(c),f=Cr(c.type);i.preferredTypes.includes(c.type)&&(f=Math.min(1,f+.25));let p=l*.55+m*.2+u*.15+f*.1;l<=0||p<s||a.push({memory:c,score:p,scores:{keyword:l,recency:u,importance:m,type:f}})}return a.sort((c,l)=>l.score-c.score).slice(0,o)}};var _e=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 Oe=class{constructor(e){this.memory=e}memory;searcher=new je;contextBuilder=new _e;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 Ne=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 Le=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 uc}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as dc}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as xr}from"zod";var Mr={query:xr.string(),limit:xr.number().int().min(1).max(20).optional()};async function Ar(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 ee}from"zod";import{createConnection as ti}from"node:net";import{homedir as Zs}from"node:os";import{join as ei}from"node:path";function Pr(){return process.env.TOOLNET_SERVICE_SOCKET??ei(Zs(),".toolnet","run","service.sock")}function Er(r,e={}){let t=e.socketPath??Pr(),n=e.timeoutMs??1e3;return new Promise((o,s)=>{let i=ti({path:t}),a="",c=!1,l=m=>{c||(c=!0,clearTimeout(u),i.destroy(),m())},u=setTimeout(()=>{l(()=>{s(new Error(`ToolNet service timeout after ${n}ms`))})},n);i.setEncoding("utf8"),i.once("connect",()=>{i.write(`${JSON.stringify(r)}
8
- `)}),i.on("data",m=>{a+=m;let f=a.indexOf(`
9
- `);if(f===-1)return;let p=a.slice(0,f).trim();l(()=>{try{o(JSON.parse(p))}catch(h){s(h instanceof Error?h:new Error(String(h)))}})}),i.once("error",m=>{l(()=>{s(m)})}),i.once("end",()=>{c||l(()=>{s(new Error("ToolNet service closed without response"))})})})}async function ri(r,e={}){let t=await Er({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 Rr(r,e={}){try{return await ri(r,e)}catch{return null}}async function De(r,e={}){try{let t=await Er({type:"invalidate",project:r},{timeoutMs:250,...e});return t.ok&&t.type==="invalidate"}catch{return!1}}var Tr={type:ee.enum(["activity","decision","rule","todo","summary"]),content:ee.string().min(1),tags:ee.array(ee.string()).optional(),importance:ee.enum(["critical","high","normal","temporary"]).optional()};async function Ir(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)),De(r.project),t}import{z as ni}from"zod";var jr={id:ni.string().min(1)};async function _r(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&&De(r.project),{deleted:t}}import{z as oi}from"zod";var Or={name:oi.string().min(1)};async function Nr(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as si}from"zod";var Ke=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Lr=new Set(["CALLS","CALL_REFERENCE"]),x=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,Lr)}callees(e,t){return this.relatedOutgoing(e,t,Lr)}dependents(e,t){return this.relatedIncoming(e,t,Ke)}dependencies(e,t){return this.relatedOutgoing(e,t,Ke)}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(f=>Ke.has(f.type)),c=new Map;for(let f of a){let p=c.get(f.from)??[];p.push(f),c.set(f.from,p)}let l=[{id:t,depth:0}],u=new Set([t]),m=new Map;for(;l.length>0;){let f=l.shift();if(!(f.depth>=o)){for(let p of c.get(f.id)??[])if(!u.has(p.to)){if(u.add(p.to),m.set(p.to,{node:f.id,edge:p}),p.to===n)return this.buildPath(t,n,m);l.push({id:p.to,depth:f.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(l=>Ke.has(l.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let l=i.shift();if(!(l.depth>=o))for(let u of s){if(!(n==="incoming"?u.to===l.id:u.from===l.id))continue;let f=n==="incoming"?u.from:u.to;if(a.has(f))continue;let p=this.graph.getSymbol(f);p&&(a.add(f),c.push({symbol:p,depth:l.depth+1,via:u}),i.push({id:f,depth:l.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 x(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 Dr={symbolId:si.string().min(1)};async function Kr(r,e){let t=E(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let o=new x(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:C(t),count:o.length,callers:o.map(C)}}import{z as Fr}from"zod";var $r={query:Fr.string().min(1),limit:Fr.number().int().min(1).max(50).optional()};async function Gr(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 zr}from"zod";function Fe(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 Ur={query:zr.string().optional(),memoryLimit:zr.number().int().min(1).max(20).optional()};async function Wr(r,e){let t=Fe(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 ai}from"zod";var ii=["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"],O=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 u of ii){let m=`${i}/${u}`,f=await this.storage.get(m);f&&(await this.storage.put(`${a}/${u}`,f,"application/json"),c.push(u))}if(c.length===0)return null;let l={version:1,id:s,projectId:e,createdAt:o,reason:t,objects:c,metadata:n};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(l,null,2),"application/json"),l}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 l=await this.storage.get(`${n}/${c}`);l&&(await this.storage.put(`${i}/${c}`,l,"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 Br={reason:ai.string().optional()};async function qr(r,e){if(!r.storage)throw new Error("Storage unavailable");return new O(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function Hr(r){if(!r.storage)throw new Error("Storage unavailable");return new O(r.storage).list(r.project.id)}import{z as ci}from"zod";var Vr={snapshotId:ci.string().min(1)};async function Jr(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new O(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as kt}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(l=>l.type==="CALLS"||l.type==="CALL_REFERENCE");for(;a.length;){let l=a.shift();if(l.depth>=o)continue;let u=n==="out"?c.filter(m=>m.from===l.id):c.filter(m=>m.to===l.id);for(let m of u){let f=n==="out"?m.to:m.from;if(i.has(f))continue;i.add(f);let p=this.graph.getSymbol(f);if(!p)continue;let h=l.depth+1;s.push({symbol:p,depth:h}),a.push({id:f,depth:h})}}return s}};var Yr={symbolId:kt.string().min(1),direction:kt.enum(["callers","callees"]).optional(),depth:kt.number().int().min(1).max(10).optional()};async function Qr(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 Xr}from"zod";var Ge=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 l=o.filter(u=>u.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(u.type));for(let u of l){if(s.has(u.from))continue;s.add(u.from);let m=this.graph.getSymbol(u.from);if(!m)continue;let f=c.depth+1;a.push({symbol:m,depth:f,relation:u.type}),i.push({id:u.from,depth:f})}}return a}};var Zr={symbolId:Xr.string().min(1),depth:Xr.number().int().min(1).max(10).optional()};async function en(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let o=new Ge(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 tn(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:Fe(r.graph,r.project.id)}}import{z as rn}from"zod";var li=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),ze=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e).filter(i=>li.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,l=0,u=0;for(let m of n){let f=o.get(m.from),p=o.get(m.to);!f||!p||f.filePath===p.filePath||(f.filePath===i&&(a.add(p.filePath),l++),p.filePath===i&&(c.add(f.filePath),u++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:l,incomingEdges:u}})}};var nn={filePath:rn.string().min(1),direction:rn.enum(["dependencies","dependents","both"]).optional()};async function on(r,e){let n=new ze(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 sn}from"zod";var an={query:sn.string().min(1),limit:sn.number().int().min(1).max(20).optional()};async function cn(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 St}from"zod";import{execFile as ui}from"node:child_process";import{promisify as di}from"node:util";var vt=di(ui);function mi(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 pi(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function ln(r){let e="";try{e=(await vt("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 vt("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:pi(o),ranges:mi(a)})}try{let n=await vt("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 fi(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 Ue=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(l=>l.filePath===s.filePath),c=i.filter(l=>l.type!=="file").filter(l=>fi(l,s));if(c.length===0){let l=i.find(u=>u.type==="file");l&&o.push({symbol:l,fileStatus:s.status,direct:!0});continue}for(let l of c)o.push({symbol:l,fileStatus:s.status,direct:!0})}return o}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var gi={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function yi(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function un(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var We=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 u of t){u.fileStatus==="deleted"?i+=8:u.fileStatus==="renamed"?i+=5:i+=2,u.symbol.type==="interface"&&(i+=5),u.symbol.type==="class"&&(i+=3);let m=new Set([u.symbol.id]),f=[{id:u.symbol.id,depth:0}];for(;f.length;){let p=f.shift();if(p.depth>=n)continue;let h=o.filter(v=>v.to===p.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(v.type));for(let v of h){if(m.has(v.from))continue;m.add(v.from);let M=this.graph.getSymbol(v.from);if(!M)continue;let P=p.depth+1,J=`${u.symbol.id}:${M.id}`;s.set(J,{symbol:M,relation:v.type,depth:P,sourceSymbolId:u.symbol.id});let Y=gi[v.type]??1;i+=Math.max(1,Y-(P-1)),f.push({id:M.id,depth:P})}}}let a=[...s.values()].sort((u,m)=>u.depth-m.depth),c=[...new Set(a.map(u=>u.symbol.filePath))],l=c.filter(un);return l.length===0&&l.push(...c.filter(u=>!un(u)).slice(0,10)),{risk:yi(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};var Be=class{constructor(e){this.graph=e;this.mapper=new Ue(e),this.blast=new We(e)}graph;mapper;blast;async analyzeGitDiff(e,t,n={}){let o=await ln(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 dn={mode:St.enum(["git_diff","file"]).optional(),filePath:St.string().optional(),depth:St.number().int().min(1).max(10).optional()};async function mn(r,e){let t=new Be(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 hi}from"zod";var pn={symbol:hi.string().min(1)};async function fn(r,e){let t=E(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let o=new x(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:C(t),count:o.length,dependents:o.map(C)}}import{z as wt}from"zod";var gn={from:wt.string().min(1),to:wt.string().min(1),maxDepth:wt.number().int().min(1).max(30).optional()};async function yn(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 x(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 Ct}from"zod";var hn={symbol:Ct.string().min(1),depth:Ct.number().int().min(1).max(5).optional(),limit:Ct.number().int().min(1).max(200).optional()};async function bn(r,e){let t=E(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let o=new x(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 Mt}from"zod";function bi(r){return r.replaceAll("\\","/").toLowerCase()}var qe=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=bi(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(u=>u.to===e.id&&u.type!=="DEFINES").length,l=t.filter(u=>u.from===e.id&&u.type!=="DEFINES").length;(n.startsWith("packages/")||c===0||l>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 kn=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function xt(r){return r.replaceAll("\\","/").toLowerCase()}function ki(r){let e=xt(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function vi(r){let e=xt(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var He=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e),o=new Set(new qe(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||ki(i.filePath)||o.has(i.id)||vi(i)||n.filter(p=>p.to===i.id&&kn.has(p.type)).length>0)continue;let c=n.filter(p=>p.from===i.id&&kn.has(p.type)),l=["no incoming usage edge"],u=50;(i.type==="function"||i.type==="method")&&(u+=20,l.push("callable symbol")),i.type==="property"&&(u-=15),c.length===0&&(u+=10,l.push("no outgoing dependency")),xt(i.filePath).includes("/internal/")&&(u+=10,l.push("internal implementation")),i.name.startsWith("_")&&(u+=5);let f=u>=75?"high":u>=55?"medium":"low";s.push({symbolId:i.id,name:i.name,qualifiedName:i.qualifiedName,type:i.type,filePath:i.filePath,startLine:i.startLine,confidence:f,score:u,reasons:l})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var Sn={confidence:Mt.enum(["high","medium","low","all"]).optional(),filePath:Mt.string().min(1).optional(),limit:Mt.number().int().min(1).max(500).optional()},vn={high:3,medium:2,low:1};async function wn(r,e){let n=new He(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=vn[e.confidence];n=n.filter(a=>vn[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 jt}from"zod";import{existsSync as zi,readFileSync as Ui}from"node:fs";import{join as Wi}from"node:path";import{existsSync as Si,mkdirSync as wd,readFileSync as wi,renameSync as Cd,writeFileSync as xd}from"node:fs";import{dirname as Ad,join as Ci}from"node:path";function xi(r){return Ci(r.rootPath,".toolnet","work","current.json")}function At(r){let e=xi(r);if(!Si(e))return null;try{let t=JSON.parse(wi(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Mi,mkdirSync as Rd,readFileSync as Ai,renameSync as Td,writeFileSync as Id}from"node:fs";import{dirname as _d,join as Pi}from"node:path";function Ei(r){return Pi(r.rootPath,".toolnet","context","session-origin.json")}function Pt(r){let e=Ei(r);if(!Mi(e))return null;try{let t=JSON.parse(Ai(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Ri(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Ve(r){let e=Ri(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"}import{existsSync as Di,mkdirSync as km,readFileSync as Ki}from"node:fs";import{join as An}from"node:path";xe();Et();var am=new _;function Fi(r){return An(r.rootPath,".toolnet","memory","checkpoints")}function $i(r){return An(Fi(r),"latest.json")}function Gi(r){let e=$i(r);if(!Di(e))return null;try{let t=JSON.parse(Ki(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function Pn(r){return Gi(r)}var Bi={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,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,rule:85,architecture:80,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,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},qi={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Hi(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function g(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function Vi(r){let e=Wi(r.rootPath,".toolnet","work","handoff-latest.json");if(!zi(e))return null;try{let n=JSON.parse(Ui(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function Ji(r){let e=Pn(r);if(!e)return[];let t=[];e.request&&g(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&g(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&g(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&g(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let n=e.files.active.at(-1);n&&g(t,{kind:"file",value:n,source:"checkpoint"});for(let o of e.nextActions)g(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)g(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)g(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)g(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)g(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function Yi(r){let e=Vi(r);if(!e)return[];let t=[];g(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&g(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&g(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&g(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&g(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&g(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&g(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&g(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let n of e.blockers)g(t,{kind:"blocker",value:n,source:"handoff"});for(let n of e.decisions)g(t,{kind:"decision",value:n,source:"handoff"});for(let n of e.completed.tasks)g(t,{kind:"completed",value:n,source:"handoff"});for(let n of e.remaining.todos)g(t,{kind:"todo",value:n,source:"handoff"});return g(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function Qi(r){let e=Pt(r);if(!e)return[];let t=[];return g(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&g(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&g(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&g(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&g(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function Xi(r){let e=At(r);if(!e)return[];let t=[];e.currentRequest&&g(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&g(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&g(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&g(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&g(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let n=e.activeFiles?.at(-1)??e.filesTouched.at(-1);n&&g(t,{kind:"file",value:n,source:"work-state"});for(let o of e.nextActions.slice(0,5))g(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))g(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))g(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(s=>s.status==="completed").slice(-8))g(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))g(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))g(t,{kind:"test",value:o,source:"work-state"});return g(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function Zi(r,e){let t=Bi[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+qi[n.source]+Math.max(0,5-o*.01)}))}function ea(r){let e=new Map;for(let t of r){let n=`${t.kind}:${Hi(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=Ve(e),o=[...Ji(r),...Yi(r),...Qi(r),...Xi(r)],s=ea(Zi(n,o)).sort((u,m)=>m.score-u.score),i=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],l=0;for(let u of s){if(c.length>=i)break;let m=u.kind.length+u.value.length+u.source.length+16;c.length>0&&l+m>a||(c.push(u),l+=m)}return{intent:n,facts:c,context:{project:{id:r.id,name:r.name},intent:n,selectedFacts:c.map(u=>({kind:u.kind,value:u.value,source:u.source}))},stats:{candidates:o.length,selected:c.length,chars:l}}}var En={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",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",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},Rn=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],ta={previous_agent:["previous_agent"],current_task:["request","activity","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:Rn};function ra(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 na(r){let e=r.filter(n=>n.source==="handoff");if(e.length===0)return r;let t=r.filter(n=>n.source==="checkpoint"&&["rule","architecture","fix"].includes(n.kind));return[...e,...t]}function oa(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 Tn(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function sa(r,e){let t=[];for(let n of e){let o=r.filter(s=>s.kind===n).slice(0,Tn(n));for(let s of o)t.push(`${En[n]}: ${s.value}`)}return t.join(`
10
- `)}function ia(r,e){let t=ta[e]??Rn,n=[];for(let o of t){let s=r.filter(i=>i.kind===o).slice(0,Tn(o));for(let i of s)n.push(`${En[o]}: ${i.value}`)}return n.join(`
11
- `)}function z(r,e){let t=G(r,e,{maxFacts:32,maxChars:6400}),n=oa(na(t.facts)),o=ra(e)?sa(n,["todo","task","next_action","file"]):ia(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"}}Ye();var ie=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 ie(a||`HTTP ${s.status}`,s.status)}return i.trim()?JSON.parse(i):{}}finally{clearTimeout(o)}}function Qe(r,e){return`${r.replace(/\/+$/,"")}/${e.replace(/^\/+/,"")}`}Ye();Rt();var Xe=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 Ze=class{constructor(e){this.config=e}config;id="gemini";model(){let e=this.config.model?.trim();if(!e)throw new Error("gemini: MODEL is not configured");return e.replace(/^models\//,"")}async generate(e){let t=this.config.apiKey?.trim();if(!t)throw new Error("gemini: API KEY is not configured");let n=this.config.baseUrl?.trim()||"https://generativelanguage.googleapis.com/v1beta",o=this.model(),s=e.messages.filter(u=>u.role==="system"),i=e.messages.filter(u=>u.role!=="system").map(u=>({role:u.role==="assistant"?"model":"user",parts:[{text:u.content}]})),a=`${Qe(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(u=>u.content).join(`
12
-
13
- `)}]}}:{},contents:i,generationConfig:{temperature:e.temperature,maxOutputTokens:e.maxTokens}})}),l=c.candidates?.[0]?.content?.parts?.map(u=>u.text??"").join("").trim();if(!l)throw new Error("gemini: empty model response");return{text:l,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 et=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(Qe(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 Dn(r=On()){switch(L(r.id).transport){case"gemini":return new Ze(r);case"cloudflare":return new Xe(r);default:return new et(r)}}function ua(r){return new Promise(e=>{setTimeout(e,r)})}function da(r){if(r instanceof ie){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 tt=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:Dn(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=da(i);if(t.push(`${o.label}: ${a}`),!c)throw i;if(s<this.maxRetries){await ua(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=se(),e=Nn();return new tt({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}})),Ln())}var Tt=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 Fn(){return new Tt(Kn())}function ma(r,e){let t=JSON.stringify(r,null,2);return t.length<=e?t:t.slice(0,e)+`
14
- [truncated]`}function pa(r,e){let t=z(r,e),n=G(r,e,{maxFacts:12,maxChars:3200});return ma({project:n.context.project,intent:n.intent,directAnswer:t.answer,selectedMemory:n.context.selectedFacts,retrievalStats:n.stats},4200)}async function $n(r,e,t={}){let n=z(r,e),o=pa(r,e),s=t.router??Fn();try{let i=await s.generate({temperature:.1,maxTokens:450,messages:[{role:"system",content:`
15
- You are ToolNet Memory Agent.
16
-
17
- You are NOT the coding agent.
18
-
19
- Your job is to help another coding AI continue work from previous sessions.
20
-
21
- Rules:
22
-
23
- 1. Answer only from the supplied ToolNet project memory.
24
- 2. Never invent completed work, files, blockers, decisions, or test results.
25
- 3. Prefer the latest session/work state over old information.
26
- 4. Be concise.
27
- 5. Do not dump raw JSON or full memory files.
28
- 6. Tell the coding agent exactly:
29
- - what the previous agent was doing,
30
- - what is already completed,
31
- - what remains unfinished,
32
- - what file was last touched,
33
- - what should be done next,
34
- when those facts are available.
35
- 7. If information is missing, say it is not recorded.
36
- 8. Do not explain ToolNet internals unless asked.
37
- 9. Do not repeat irrelevant history.
38
- 10. Respond in the same language as the question.
39
-
40
- Think of yourself as the project's memory coworker talking directly to another AI.
41
- `.trim()},{role:"user",content:`
42
- Question from coding agent:
43
-
44
- ${e}
45
-
46
- ToolNet selected memory:
47
-
48
- ${o}
49
-
50
- Answer the coding agent directly.
51
- `.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 fa,mkdirSync as ga,readFileSync as ya,renameSync as ha,rmSync as ba,writeFileSync as ka}from"node:fs";import{join as Gn}from"node:path";var va=720*60*1e3;function zn(r){return Gn(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function ae(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function Sa(r){let e=ae(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 wa(r){if(Sa(r))return!1;let e=ae(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 Ca(r,e,t){let n=zn(r);if(!fa(n))return null;try{let o=JSON.parse(ya(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 xa(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,ae(s)].join(":");if(!t.has(i)&&(t.add(i),n.push({...o,value:s}),n.length>=e))break}return n}function Ma(r,e){let t=zn(r),n=Gn(r.rootPath,".toolnet","context");ga(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{ka(o,JSON.stringify(e,null,2)+`
52
- `,{encoding:"utf8",mode:384}),ha(o,t)}finally{ba(o,{force:!0})}}function Aa(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
53
- `)}function Pa(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function It(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=ae(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=Pa(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 Ea(r){let e=ae(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 Un(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??va,s=Ca(r,n,o),i=!!(s&&s.focus.length>0&&wa(e)&&!Ea(e)),a=i&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",Aa(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=Ve(e),u=G(r,a,{maxFacts:8,maxChars:1800}).facts.map(f=>({kind:f.kind,value:f.value,source:f.source})),m=xa(i&&s?[...u,...s.focus]:u);return Ma(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}}import{existsSync as Ra,readFileSync as Ta}from"node:fs";import{join as Ia}from"node:path";function N(r){return!!r?.trim()}function Wn(r){let e=[],t=[],n=100;N(r.goal)||N(r.request)||(e.push("goal_or_request"),n-=20),N(r.activity)||N(r.current.task?.title)||N(r.current.phase?.title)||(e.push("current_work"),n-=25),N(r.nextAction)||N(r.remaining.todos[0])||(e.push("next_action"),n-=25),r.tests.status!=="unknown"||r.tests.recent.length>0||(r.tests.checks?.length??0)>0||(r.evidence?.commands.length??0)>0||(r.evidence?.references.length??0)>0||(e.push("evidence"),n-=20),N(r.files.current)||r.files.recent.length>0||(r.files.active?.length??0)>0||(r.files.modified?.length??0)>0||(r.files.created?.length??0)>0||(e.push("files"),n-=10),r.tests.status==="failing"&&t.push("tests_failing"),r.blockers.length>0&&t.push("active_blockers"),n=Math.max(0,Math.min(100,n));let l=e.includes("current_work")||e.includes("next_action"),u;return n>=80&&!l?u="high":n>=50?u="medium":u="low",{confidence:u,score:n,missingContext:e,warnings:t}}var Bn={compact:{completed:3,evidence:3,files:5,blockers:2,maxChars:1800},normal:{completed:10,evidence:10,files:15,blockers:5,maxChars:4200},benchmark:{completed:30,evidence:30,files:40,blockers:10,maxChars:1e4}};function W(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 B(r){return r.length>0?r.map(e=>`- ${e}`).join(`
55
- `):"- none"}function ja(r,e){return r.length<=e?r:[r.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
56
- `)}function qn(r,e){if(e)return e;let t=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/\bbenchmark\b/u.test(t)||/\bdeep handoff\b/u.test(t)||/\bfull handoff\b/u.test(t)||/\btakeover\b/u.test(t)||/\btake over\b/u.test(t)||/tiếp quản/u.test(t)||/bằng chứng đầy đủ/u.test(t)||/evidence.*(?:file|test|command)/u.test(t)?"benchmark":/\bcompact\b/u.test(t)||/\bbrief\b/u.test(t)||/ngắn gọn/u.test(t)||/tóm tắt ngắn/u.test(t)?"compact":"normal"}function _a(r,e="normal"){let t=Bn[e],n=W([`Source agent: ${r.source.agent}`,`Captured: ${r.capturedAt}`,r.goal?`Goal: ${r.goal}`:void 0,r.request?`Request: ${r.request}`:void 0,r.activity?`Activity: ${r.activity}`:void 0,r.current.phase?`Phase: ${r.current.phase.title} [${r.current.phase.status}]`:void 0,r.current.task?`Task: ${r.current.task.title} [${r.current.task.status}]`:void 0,r.current.file?`Current file: ${r.current.file}`:void 0,`Progress: ${JSON.stringify(r.progress)}`]),o=W([...r.completed.phases.map(l=>`Phase: ${l}`),...r.completed.tasks.map(l=>`Task: ${l}`)]).slice(0,t.completed),s=W([`Tests status: ${r.tests.status}`,...r.tests.recent.map(l=>`Test: ${l}`),...(r.tests.checks??[]).map(l=>`Check [${l.status}] ${l.kind}: ${l.command}`),...(r.evidence?.commands??[]).map(l=>`Command: ${l}`),...(r.evidence?.references??[]).map(l=>`Reference: ${l}`),...r.decisions.map(l=>`Decision: ${l}`),...r.attention.map(l=>`Attention: ${l}`)]).slice(0,t.evidence),i=W([r.files.current,...(r.files.active??[]).map(l=>`Active: ${l}`),...(r.files.modified??[]).map(l=>`Modified: ${l}`),...(r.files.created??[]).map(l=>`Created: ${l}`),...(r.files.deleted??[]).map(l=>`Deleted: ${l}`),...r.files.recent.map(l=>`Recent: ${l}`)]).slice(0,t.files),a=W(r.blockers).slice(0,t.blockers),c=W([r.nextAction,r.nextAction?void 0:r.remaining.todos[0]]).slice(0,1);return{currentState:n,completed:o,evidence:s,filesTouched:i,blockers:a,nextAction:c}}function Oa(r,e,t){return[`HANDOFF_DETAIL: ${e}`,`CONTINUITY_CONFIDENCE: ${t.confidence}`,`QUALITY_SCORE: ${t.score}`,`MISSING_CONTEXT: ${t.missingContext.length>0?t.missingContext.join(", "):"none"}`,`QUALITY_WARNINGS: ${t.warnings.length>0?t.warnings.join(", "):"none"}`,"","CURRENT_STATE",B(r.currentState),"","COMPLETED",B(r.completed),"","EVIDENCE",B(r.evidence),"","FILES_TOUCHED",B(r.filesTouched),"","BLOCKERS",B(r.blockers),"","NEXT_ACTION",B(r.nextAction)].join(`
57
- `)}function Hn(r,e="normal"){let t=Ia(r.rootPath,".toolnet","work","handoff-latest.json");if(!Ra(t))return null;try{let o=JSON.parse(Ta(t,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let s=_a(o,e),i=Wn(o),a=ja(Oa(s,e,i),Bn[e].maxChars);return{detail:e,data:s,quality:i,text:a}}catch{return null}}function Na(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var La=[/\bhandoff\b/u,/\bcontinuity\b/u,/\bcontinue\b/u,/\bresume\b/u,/\btakeover\b/u,/\btake over\b/u,/tiếp tục/u,/tiếp quản/u,/bàn giao/u,/dừng ở đâu/u,/đang làm gì/u],Da=[/\bcurrent state\b/u,/\bcurrent task\b/u,/\bevidence\b/u,/\breport locations?\b/u,/\bfiles?\b/u,/\burls?\b/u,/\bassets?\b/u,/\btests?\b/u,/\bcommands?\b/u,/\bblockers?\b/u,/\bnext actions?\b/u,/trạng thái hiện tại/u,/task hiện tại/u,/bằng chứng/u,/vị trí báo cáo/u,/file/u,/url/u,/blocker/u,/việc tiếp theo/u,/bước tiếp theo/u],Ka=[/\bsummarize\b/u,/\bsummary\b/u,/\bfull state\b/u,/\bfull context\b/u,/tóm tắt/u,/đầy đủ/u,/toàn bộ trạng thái/u];function Fa(r){let e=0;for(let t of Da)t.test(r)&&(e+=1);return e}function Vn(r,e){let t=Na(r);if(/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(t)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(t)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(t))return!1;if(e==="summary"||e==="status")return!0;if(!t)return!1;let o=La.some(a=>a.test(t)),s=Ka.some(a=>a.test(t)),i=Fa(t);return!!(o&&i>=1||s&&i>=2||i>=4)}var Jn={question:jt.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:jt.enum(["ai","local"]).optional().describe("ai uses ToolNet Memory Agent with configured LLM fallback chain. local returns deterministic local memory only."),detail:jt.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function rt(r,e,t,n,o){if(!Vn(e,t))return{answer:n};let s=qn(e,o),i=Hn(r.project,s);return i?{answer:i.text,handoff:i.data,detail:i.detail,confidence:i.quality.confidence,missingContext:i.quality.missingContext,quality:i.quality}:{answer:n}}async function Yn(r,e){let t=Un(r.project,e.question);if(e.mode==="local"){let i=It(t);if(i)return{...rt(r,t.originalQuestion,String(i.intent),i.answer,e.detail),mode:"local",usedAi:!1,source:i.source,intent:i.intent};let a=z(r.project,t.originalQuestion);return{...rt(r,t.originalQuestion,String(a.intent),a.answer,e.detail),mode:"local",usedAi:!1,source:a.source,intent:a.intent}}let n=z(r.project,t.originalQuestion),o=rt(r,t.originalQuestion,String(n.intent),n.answer,e.detail);if("handoff"in o)return{...o,mode:"ai",usedAi:!1,source:n.source,intent:n.intent,routing:"deterministic-handoff"};let s=await $n(r.project,t.question);if(!s.usedAi){let i=It(t);if(i)return{...rt(r,t.originalQuestion,String(i.intent),i.answer,e.detail),mode:"ai",usedAi:!1,provider:s.provider,model:s.model}}return{answer:s.answer,mode:"ai",usedAi:s.usedAi,provider:s.provider,model:s.model}}import{z as no}from"zod";import{chmodSync as xp,existsSync as Qn,mkdirSync as Mp,readFileSync as Xn,renameSync as Ap,writeFileSync as Pp}from"node:fs";import{dirname as Rp,join as ce}from"node:path";var Zn="toolnet.context-offload.v1",$a="toolnet.context-offload-asset.v1";function eo(r){return ce(r,".toolnet","offload")}function to(r){return ce(eo(r),"assets")}function Ga(r){return ce(eo(r),"graph.json")}function _t(){return{schema:Zn,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function za(r){let e=Ga(r);if(!Qn(e))return _t();try{let t=JSON.parse(Xn(e,"utf8"));return t.schema!==Zn||t.version!==1||!Array.isArray(t.nodes)?_t():t}catch{return _t()}}function Ua(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&&Qn(ce(to(r),`${t}.json`)))return t;let n=za(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 ro(r,e,t=6e3){let n=Ua(r,e),o=Xn(ce(to(r),`${n}.json`),"utf8"),s=JSON.parse(o);if(s.schema!==$a||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)}
58
- [truncated]`:o}}var oo={assetId:no.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:no.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function so(r,e){return ro(r.project.rootPath,e.assetId,e.maxChars??6e3)}import{z as co}from"zod";import{chmodSync as Np,existsSync as Wa,mkdirSync as Lp,readFileSync as Ba,readdirSync as qa,renameSync as Dp,statSync as Ha,writeFileSync as Kp}from"node:fs";import{join as io}from"node:path";var Va="toolnet.skill-memory.v1";function Ja(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 Ya(r){return io(r.rootPath,".toolnet","memory","skills")}function Qa(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Va&&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 Xa(r){let e=Ya(r);if(!Wa(e))return[];if(!Ha(e).isDirectory())return[];let t=[];for(let n of qa(e)){if(!n.endsWith(".json"))continue;let o=io(e,n);try{let s=JSON.parse(Ba(o,"utf8"));Qa(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 Za(r){return Ja(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function ec(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(`
59
- `).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 Za(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 ao(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return Xa(r).map(o=>({...o,score:ec(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 lo={query:co.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:co.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function uo(r,e){let t=ao(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 Co}from"zod";var mo="wiki/state.v1.json";function tc(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function rc(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(mo);if(!e){let t=tc(this.project);return await this.save(t),t}return rc(e,this.project)}async save(e){await this.storage.put(mo,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as go}from"node:crypto";var S=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function le(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 ue(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 po(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(ue(n))}return le(e)}function nc(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function fo(r){return{id:`revision-${go()}`,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 D(r){return structuredClone(r)}var T=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:le(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 D([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=ue(e),o=t.pages.find(s=>s.slug===n||s.id===e);if(!o)throw new S(`Wiki page not found: ${e}`,404);return D(o)}async createPage(e){return this.mutate(t=>{let n=e.title.trim(),o=e.content.trim();if(!n)throw new S("Wiki title is required",400);let s=ue(e.slug??n);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-${go()}`,slug:s,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:le(e.tags??[]),links:po(o),revision:1,createdAt:i,updatedAt:i};return t.pages.push(a),t.revisions.push(fo(a)),D(a)})}async updatePage(e,t){return this.mutate(n=>{let o=ue(e),s=n.pages.find(i=>i.slug===o||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=po(s.content)),t.tags!==void 0&&(s.tags=le(t.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),n.revisions.push(fo(s)),D(s)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return D(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 D(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=le(nc(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(),l=a.slug.toLowerCase(),u=a.summary?.toLowerCase()??"",m=a.content.toLowerCase(),f=a.tags.map(h=>h.toLowerCase()),p=0;for(let h of o)l===h&&(p+=12),c===h&&(p+=10),c.includes(h)&&(p+=6),l.includes(h)&&(p+=5),f.some(v=>v===h)?p+=5:f.some(v=>v.includes(h))&&(p+=3),u.includes(h)&&(p+=2),m.includes(h)&&(p+=1);p>0&&i.push({page:D(a),score:p})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};import{createHash as oc,randomUUID as yo}from"node:crypto";var ho="wiki/governance.v1.json",So="toolnet.knowledge-governance.v1",bo=500,de={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function sc(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function Ot(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function ko(r){return oc("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function ic(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 ac(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),sc(e)}function vo(r){let e=new Date().toISOString();return{schema:So,version:1,projectId:r,policy:{...de},reviews:[],audit:[],createdAt:e,updatedAt:e}}function wo(r){let e=r.autoApproveThreshold??de.autoApproveThreshold,t=r.criticalApproveThreshold??de.criticalApproveThreshold,n=r.staleAfterDays??de.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(n)||n<1||n>3650)throw new S("Invalid staleAfterDays",400);return{autoApproveThreshold:e,criticalApproveThreshold:t,staleAfterDays:n}}var me=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=vo(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==So||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:wo(t.policy??de)}}catch{let t=vo(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(ho,JSON.stringify(e,null,2),"application/json")}},pe=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:yo(),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>bo&&(e.audit=e.audit.slice(-bo))}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=wo({...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=ac(e),s=Ot(e.title),i=t.filter(u=>u.slug!==e.slug&&Ot(u.title)===s&&ko(u.content)!==ko(e.content)).map(u=>u.slug),a=ic(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 l=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:l,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:yo(),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(l=>l.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(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 S("targetReviewId is required for merge",400);let l=o.reviews.find(u=>u.id===t.targetReviewId);if(!l)throw new S("Merge target review not found",404);return s.status="superseded",s.mergedInto=l.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:l.id}}),structuredClone(s)}s.status="approved";let c=(await n.listPages()).find(l=>l.slug===s.slug);if(c&&!c.tags.includes(s.marker))throw new S(`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(u=>{let m=o-Date.parse(u.updatedAt);return{slug:u.slug,title:u.title,updatedAt:u.updatedAt,ageDays:Math.max(0,Math.floor(m/864e5)),stale:Number.isFinite(m)&&m>s}}).filter(u=>u.stale).map(({stale:u,...m})=>m),a=new Map;for(let u of n){let m=Ot(u.title),f=a.get(m)??[];f.push(u),a.set(m,f)}let c=[...a.entries()].filter(([,u])=>u.length>1).map(([u,m])=>({title:u,pages:m.map(f=>f.slug)})),l=t.reviews.filter(u=>u.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(u=>u.tags.some(m=>m.startsWith("toolnet-auto-"))).length,manualPages:n.filter(u=>!u.tags.some(m=>m.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:l.length,lowConfidenceReviews:l.filter(u=>u.confidence<t.policy.autoApproveThreshold).length,conflicts:l.filter(u=>u.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var xo={query:Co.string().min(2).max(500).describe("Knowledge topic or project concept to search in ToolNet Wiki."),limit:Co.number().int().min(1).max(10).optional().describe("Maximum Wiki matches. Default 5.")};async function Mo(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new T(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 cc}from"zod";var Ao={page:cc.string().min(1).max(200).describe("Wiki page slug or page id.")};async function Po(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new T(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 lc}from"zod";var Eo={includePending:lc.boolean().optional().describe("Include compact pending-review metadata. Default false.")};async function Ro(r,e){let t=r.storage;if(!t)throw new Error("Knowledge Governance storage unavailable");let n=new pe(new me(t,r.project));await n.initialize();let o=new T(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 To={};function Io(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 k(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var mc=["# 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 pc(r){let e=new uc({name:"toolnet-memory",version:"0.1.0"},{instructions:mc});return e.tool("memory_search","Search relevant long-term memory for the current project.",Mr,async t=>k(await Ar(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",Tr,async t=>k(await Ir(r,t))),e.tool("memory_forget","Delete a memory by id.",jr,async t=>k(await _r(r,t))),e.tool("find_symbol","Find code symbols by exact name.",Or,async t=>k(await Nr(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",Dr,async t=>k(await Kr(r,t))),e.tool("code_search","Search indexed code symbols and files.",$r,async t=>k(await Gr(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",Ur,async t=>k(await Wr(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",Yr,async t=>k(await Qr(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",Zr,async t=>k(await en(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>k(await tn(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",nn,async t=>k(await on(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",an,async t=>k(await cn(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",Br,async t=>k(await qr(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>k(await Hr(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",Vr,async t=>k(await Jr(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.",dn,async t=>k(await mn(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",pn,async t=>k(await fn(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",gn,async t=>k(await yn(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",hn,async t=>k(await bn(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Sn,async t=>k(await wn(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(" "),Jn,async t=>k(await Yn(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(" "),oo,async t=>k(await so(r,t))),e.tool("skill_memory_search",["Search successful ToolNet project work promoted into reusable Skill Memory SOPs.","Call this before repeating a task that may have been solved successfully before.","Returns compact procedure steps, files and verification evidence.","Raw transcripts are never returned."].join(" "),lo,async t=>k(await uo(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(" "),xo,async t=>k(await Mo(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(" "),Ao,async t=>k(await Po(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(" "),To,async()=>k(Io(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(" "),Eo,async t=>k(await Ro(r,t))),e}async function jo(r){let e=pc(r),t=new dc;await e.connect(t)}function _o(){return new Date().toISOString()}function I(r){r.lastUpdatedAt=_o()}function nt(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:_o()}}function Oo(r,e=Date.now()){r.metrics.mcpConnectedAtMs=e,r.metrics.startupMs=e-r.metrics.processStartedAtMs,r.phase="hydrating",I(r)}function No(r,e=Date.now()){r.phase="hydrating",r.metrics.hydrationStartedAtMs=e,r.metrics.hydrationRuns+=1,I(r)}function ot(r,e){r.dependencies[e].state!=="ready"&&(r.dependencies[e].state="loading",r.dependencies[e].lastError=void 0,I(r))}function st(r,e){r.dependencies[e].attempts+=1,I(r)}function it(r){r.metrics.retryCount+=1,I(r)}function q(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 fe(r,e,t){let n=r.dependencies[e];n.state="failed",n.lastError=t instanceof Error?t.message:String(t),I(r)}function Lo(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 Do(r,e){r.phase="failed",r.errors=[e instanceof Error?e.message:String(e)],I(r)}async function at(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 bs(r,e){let t=Number(r);return!Number.isFinite(t)||t<1?e:Math.floor(t)}function Xc(r,e){let t=Number(r);return!Number.isFinite(t)||t<0?e:Math.floor(t)}function Zc(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 ks(r){let e=r.runtime??nt(Date.now());r.runtime=e,No(e);let t=bs(process.env.TOOLNET_MCP_HYDRATION_RETRIES,3),n=Xc(process.env.TOOLNET_MCP_HYDRATION_RETRY_DELAY_MS,500);if(e.dependencies.memory.state!=="ready"||e.dependencies.graph.state!=="ready"){let o=await Rr(r.project,{timeoutMs:bs(process.env.TOOLNET_SERVICE_REQUEST_TIMEOUT_MS,1e3)});o&&(e.dataSource="daemon",e.dependencies.memory.state!=="ready"&&(r.memory.importRecords(o.memory),q(e,"memory")),e.dependencies.graph.state!=="ready"&&(o.graph&&r.graph.import(o.graph.symbols,o.graph.edges),q(e,"graph")))}try{let[{loadConfig:o},s]=await Promise.all([Promise.resolve().then(()=>(Et(),Mn)),Promise.resolve().then(()=>(is(),ss))]),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)}),l=new s.ProjectScopedStorageProvider(c,r.project.id,r.project.name,r.project.remote??r.project.name),u=new s.MemoryStore(l);r.storage=l,r.memoryStore=u;let m=e.dependencies.memory.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",ot(e,"memory");try{let p=await at(()=>u.load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{st(e,"memory")},onRetry:()=>{it(e)}});r.memory.importRecords(p),q(e,"memory")}catch(p){fe(e,"memory",p)}})(),f=e.dependencies.graph.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",ot(e,"graph");try{let p=await at(()=>new s.PersistentCodeGraphStore(l).load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{st(e,"graph")},onRetry:()=>{it(e)}});p&&r.graph.import(p.symbols,p.edges),q(e,"graph")}catch(p){fe(e,"graph",p)}})();if(await Promise.all([m,f]),e.dependencies.semantic.state!=="ready"){ot(e,"semantic");try{let[{SemanticCodeEngine:p},{createEmbeddingProvider:h}]=await Promise.all([Promise.resolve().then(()=>(ps(),ms)),Promise.resolve().then(()=>(hs(),ys))]),v=new p({projectId:r.project.id,rootPath:r.project.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:l,embeddings:h(),graph:r.graph});await at(()=>v.initialize(),{attempts:t,delayMs:n,onAttempt:()=>{st(e,"semantic")},onRetry:()=>{it(e)}}),r.codeSemantic=v,q(e,"semantic")}catch(p){fe(e,"semantic",p)}}}catch(o){for(let s of["memory","graph","semantic"])e.dependencies[s].state!=="ready"&&fe(e,s,o)}return Lo(e),Zc(r)}function vs(){let r=Number(process.env.TOOLNET_MCP_DEGRADED_RETRY_MS??3e4);return Number.isFinite(r)&&r>=1e3?Math.floor(r):3e4}async function el(){let r=Date.now(),e=new Ee().detect(),t=new Ae,n=new Oe(t),o=new Ne,s=new Le(o),i=nt(r),a={project:e,memory:t,retrieval:n,graph:o,references:s,runtime:i};await jo(a),Oo(i);let c=async()=>{try{await ks(a),i.phase==="degraded"&&setTimeout(()=>{c()},vs()).unref()}catch(l){Do(i,l),setTimeout(()=>{i.phase="degraded",c()},vs()).unref()}};c()}el().catch(r=>{console.error(r),process.exit(1)});
1
+ var xo=Object.defineProperty;var y=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(n){throw t=[n],n}};var Ie=(r,e)=>{for(var t in e)xo(r,t,{get:e[t],enumerable:!0})};var Po,X,bt=y(()=>{"use strict";Po=[{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}],X=class{scan(e){let t=[];for(let n of Po){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 P,Z=y(()=>{"use strict";bt();P=class{scanner=new X;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.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")?t[n]="[REDACTED]":t[n]=this.sanitizeValue(o)}return t}return e}}});import{existsSync as Is,readFileSync as Ns}from"node:fs";import{homedir as _s}from"node:os";import{join as Os}from"node:path";function Fs(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 Ls(){let r=process.env.TOOLNET_GLOBAL_ENV??Os(_s(),".config","toolnet-memory",".env");if(!Is(r))return;let e=Ns(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]=Fs(n.slice(o+1)))}}var Nr=y(()=>{"use strict";Ls()});var Or={};Ie(Or,{loadConfig:()=>_r});function $(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function z(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function _r(){return{memory:{autoCapture:$(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:$(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:$(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:$(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(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:$(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:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}var Ue=y(()=>{"use strict";Nr()});var zn=y(()=>{"use strict"});import{DeleteObjectCommand as ca,GetObjectCommand as ua,HeadObjectCommand as la,ListObjectsV2Command as da,PutObjectCommand as ma,S3Client as pa}from"@aws-sdk/client-s3";import{getSignedUrl as fa}from"@aws-sdk/s3-request-presigner";var Q,Xe=y(()=>{"use strict";Q=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new pa({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 ma({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await fa(this.client,new ua({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 la({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 ca({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new da({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 Wn,mkdir as ga,readFile as ya,readdir as ha,rm as ka,stat as Gn,writeFile as Sa}from"node:fs/promises";import{dirname as ba,join as wa,relative as qn,resolve as va}from"node:path";var _,Ze=y(()=>{"use strict";_=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return va(this.root,t)}async put(e,t){let n=this.path(e);await ga(ba(n),{recursive:!0}),await Sa(n,t)}async get(e){try{return await ya(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 Wn(this.path(e)),!0}catch{return!1}}async delete(e){await ka(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await Wn(t)}catch{return n}let o=async i=>{let a=await ha(i,{withFileTypes:!0});for(let c of a){let u=wa(i,c.name);if(c.isDirectory()){await o(u);continue}let l=await Gn(u);n.push({key:qn(this.root,u),size:l.size,updatedAt:l.mtime.toISOString()})}},s=await Gn(t);return s.isDirectory()?await o(t):n.push({key:qn(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),n}}});import{DeleteObjectCommand as Ca,GetObjectCommand as xa,HeadObjectCommand as Ma,ListObjectsV2Command as Pa,PutObjectCommand as Aa,S3Client as ja}from"@aws-sdk/client-s3";import{getSignedUrl as Ta}from"@aws-sdk/s3-request-presigner";var O,et=y(()=>{"use strict";O=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 Aa({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Ta(this.client,new xa({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 Ma({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 Ca({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Pa({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 Ra}from"node:os";import{join as Ea}from"node:path";function tt(r,e){return console.warn(e),new _(r)}function Ia(r){let e=r.localRoot??Ea(Ra(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new O({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 O({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 Q({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):tt(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new _(e)}var Hn=y(()=>{"use strict";Xe();Ze();et()});var rt,Vn=y(()=>{"use strict";rt=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 Bn=y(()=>{"use strict";Ze()});var Un=y(()=>{"use strict";Xe()});var Jn=y(()=>{"use strict";et()});var nt,Qn=y(()=>{"use strict";nt=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 ot,Yn=y(()=>{"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 st,Xn=y(()=>{"use strict";st=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 Y,it=y(()=>{"use strict";Y=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 at,Zn=y(()=>{"use strict";at=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 Na(r){return new Promise(e=>setTimeout(e,r))}async function eo(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)),u=Math.floor(Math.random()*Math.max(1,c*.2));await Na(c+u)}throw s}var to=y(()=>{"use strict"});function Oa(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:_a.has(n)?(...s)=>eo(()=>Promise.resolve(o.apply(t,s)),e):o.bind(t)}})}var _a,ro=y(()=>{"use strict";to();_a=new Set(["put","get","getText","delete","list"])});function ct(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 ut=y(()=>{"use strict"});function lt(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 dt=y(()=>{"use strict"});var mt,no=y(()=>{"use strict";ut();dt();mt=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=ct(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=lt(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 oo=y(()=>{"use strict";ut();no();dt()});var pt,so=y(()=>{"use strict";pt=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 ft,io=y(()=>{"use strict";ft=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 gt,ao=y(()=>{"use strict";gt=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 yt,co=y(()=>{"use strict";yt=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 uo={};Ie(uo,{HuggingFaceStorageProvider:()=>Q,LocalStorageProvider:()=>_,MemoryStore:()=>rt,PersistentArchitectureStore:()=>ft,PersistentCodeAnalysisStore:()=>gt,PersistentCodeChunkStore:()=>Y,PersistentCodeGraphStore:()=>ot,PersistentCodeManifestStore:()=>st,PersistentCodeVectorStore:()=>at,PersistentTypeResolutionStore:()=>pt,PersistentVectorStore:()=>nt,PersistentVisualizationStore:()=>yt,ProjectScopedStorageProvider:()=>mt,S3StorageProvider:()=>O,createStorageProvider:()=>Ia,mapProjectStoragePath:()=>lt,sanitizeProjectFolder:()=>ct,withStorageRetry:()=>Oa});var lo=y(()=>{"use strict";zn();Hn();Vn();Bn();Un();Jn();Qn();Yn();Xn();it();Zn();ro();oo();so();io();ao();co()});import{createHash as Fa}from"node:crypto";import{readFile as La}from"node:fs/promises";import{join as Ka}from"node:path";function mo(r){return Fa("sha256").update(r).digest("hex")}var Re,po=y(()=>{"use strict";Z();Re=class{sanitizer=new P;async build(e,t,n,o={}){let s=o.maxLines??80,i=o.overlapLines??10,a=new Map;for(let u of n){let l=a.get(u.filePath)??[];l.push(u),a.set(u.filePath,l)}let c=[];for(let[u,l]of a){let d;try{d=await La(Ka(t,u),"utf8")}catch{continue}let m=d.split(/\r?\n/),p=l.filter(g=>g.type!=="file"&&typeof g.startLine=="number"&&typeof g.endLine=="number");if(p.length>0)for(let g of p)c.push(...this.chunkRange({projectId:e,filePath:u,lines:m,symbol:g,startLine:g.startLine,endLine:g.endLine,maxLines:s,overlapLines:i}));else c.push(...this.chunkRange({projectId:e,filePath:u,lines:m,startLine:1,endLine:Math.max(1,m.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),u=Math.min(o.length,Math.max(c,e.endLine)),l=[],d=c,m=0;for(;d<=u;){let p=Math.min(u,d+i-1),g=o.slice(d-1,p).join(`
4
+ `).trim();if(g){let S=this.sanitizer.sanitize(g).text,T=mo(S),F=[t,n,s?.id??"file",String(m),T].join(":");l.push({id:mo(F).slice(0,32),projectId:t,filePath:n,symbolId:s?.id,symbolName:s?.qualifiedName??s?.name,symbolType:s?.type,startLine:d,endLine:p,content:S,contentHash:T})}if(p>=u)break;d=p-a+1,m++}return l}}});import{DatabaseSync as Da}from"node:sqlite";var Ee,fo=y(()=>{"use strict";Ee=class{constructor(e){this.projectId=e;this.db.exec("CREATE VIRTUAL TABLE code_fts USING fts5(id UNINDEXED, projectId UNINDEXED, filePath, symbol, content, tokenize='unicode61')")}projectId;db=new Da(":memory:");chunks=new Map;get size(){return this.chunks.size}build(e){if(e.length===0)return 0;this.db.exec("DELETE FROM code_fts"),this.chunks.clear();let t=this.db.prepare("INSERT INTO code_fts (id, projectId, filePath, symbol, content) VALUES (?, ?, ?, ?, ?)");this.db.exec("BEGIN");try{for(let n of e)this.chunks.set(n.id,n),t.run(n.id,this.projectId,n.filePath,n.symbolName??"",n.content);this.db.exec("COMMIT")}catch(n){throw this.db.exec("ROLLBACK"),n}return e.length}search(e,t=8){let n=this.toMatchQuery(e);if(!n)return[];let o=this.db.prepare("SELECT id, bm25(code_fts) AS rank FROM code_fts WHERE code_fts MATCH ? ORDER BY rank LIMIT ?").all(n,Math.max(t*4,20)),s=[];for(let i of o){let a=this.chunks.get(i.id);if(!a)continue;let c=1/(1+Math.abs(i.rank));s.push({chunk:a,score:c})}return s.slice(0,t)}toMatchQuery(e){let t=e.toLowerCase().normalize("NFKC").split(/[^\p{L}\p{N}]+/u).map(n=>n.trim()).filter(n=>n.length>0);return t.length===0?null:t.length===1?`"${t[0]}"`:`(${t.map(n=>`"${n}"`).join(" OR ")})`}close(){this.db.close()}}});function go(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 yo=y(()=>{"use strict"});var ho={};Ie(ho,{SemanticCodeEngine:()=>ht});var ht,ko=y(()=>{"use strict";it();po();fo();yo();ht=class{constructor(e){this.options=e;this.fts=new Ee(e.projectId)}options;fts;async initialize(e){let{projectId:t,rootPath:n,storage:o,graph:s}=this.options,i=new Y(o),a=await new Re().build(t,n,s.allSymbols(t)),c=await i.load(t),u=!c||c.chunks.length!==a.length||c.chunks.some(d=>!a.some(m=>m.id===d.id));u&&await i.save({version:1,projectId:t,updatedAt:new Date().toISOString(),chunks:a}),e?.({current:a.length,total:a.length,phase:"index"});let l=this.fts.build(a);return{chunks:a.length,vectorsLoaded:0,vectorsIndexed:l,vectorsRemoved:0,totalVectors:this.fts.size,savedChunks:u,savedVectors:u}}async search(e,t=8){let n=this.fts.search(e,t),o=[];for(let s of n){let i=s.chunk,a=go(i.filePath,e),c=s.score,u=0,l=c*a;o.push({chunk:i,score:l,vectorScore:u,lexicalScore:c})}return o}size(){return this.fts.size}}});import"dotenv/config";import{randomUUID as $o}from"node:crypto";var Mo={critical:100,high:75,normal:50,temporary:20};function kt(r){return Mo[r]}function St(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"}Z();var Ao=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),jo=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 wt(r){return new Set(r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!jo.has(e)))}function To(r,e){let t=wt(r),n=wt(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 vt(r){return new Set(r.tags.filter(e=>!Ao.has(e.toLowerCase())))}var ee=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=vt(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=vt(s);for(let c of o)if(a.has(c))return!0;return To(e.content,s.content)>=.6})}};var Ro=new Set(["code","decision","rule","todo","summary"]);function Eo(r){return r.normalize("NFKC").toLowerCase().replace(/[“”"'`]/gu,"").replace(/[.!?]+$/gu,"").replace(/\s+/gu," ").trim()}function Ct(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 Io(r,e){let t=Ct(e)-Ct(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 xt(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 Mt(r){let e=new Map;for(let o of r){if(!Ro.has(o.type)||o.metadata?.supersededBy)continue;let s=Eo(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(Io),i=s[0];if(!i)continue;let a=s.slice(1);t.push({canonicalId:i.id,duplicateIds:a.map(c=>c.id),mergedTags:xt(s.flatMap(c=>c.tags)),mergedSources:xt(s.map(c=>c.source))}),n+=a.length}return{groups:t,duplicates:n}}function Ne(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 No(r,e){let t=new Date(r.updatedAt).getTime();return Number.isFinite(t)?Math.max(0,(e-t)/864e5):0}function _o(r){let e=Ne(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 Oo(r){return Ne(r)==="permanent"||r.type==="rule"||r.type==="decision"||r.importance==="critical"}function Fo(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 Pt(r,e=Date.now()){let t=50,n=[],o=Ne(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")),Fo(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=No(r,e)>=_o(r);a&&(t-=15,n.push("stale for lifecycle class"));let c=Oo(r);t=Math.max(0,Math.min(100,Math.round(t)));let u;t>=80?u="trusted":t>=55?u="useful":t>=30?u="weak":u="noise";let l=r.importance==="temporary"||r.type==="activity"||o==="transient";return{score:t,tier:u,stale:a,protected:c,pruneEligible:!c&&(u==="noise"&&l||a&&(u==="noise"||u==="weak")),reasons:n}}var Lo={critical:100,high:75,normal:50,temporary:20},Ko={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function At(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 _e(r,e=Date.now()){return r.expiresAt?new Date(r.expiresAt).getTime()<=e:!1}function Do(r){return!!r.metadata?.supersededBy}function Oe(r,e=Date.now()){return!_e(r,e)&&!Do(r)}function L(r,e=Date.now()){if(!Oe(r,e))return 0;let t=Lo[r.importance];if(r.importance==="critical")return t;let n=Ko[r.type]??180,s=Math.max(0,e-new Date(r.updatedAt).getTime())/864e5,i=Math.pow(.5,s/n);return t*i}var te=class{memories=new Map;sanitizer=new P;conflicts=new ee;remember(e){let t=new Date().toISOString(),n=this.sanitizer.sanitize(e.content.trim()).text,o=e.importance??St(e.type,n),s={id:$o(),projectId:e.projectId,type:e.type,content:n,importance:o,importanceScore:kt(o),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??At(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=>Oe(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=L(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,u=L(s)/500;return{memory:s,score:c+u,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=Mt(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=Pt(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&&_e(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 zo}from"node:crypto";import{existsSync as Fe,mkdirSync as Wo,readFileSync as Go,renameSync as qo,writeFileSync as Ho}from"node:fs";import{basename as Vo,dirname as re,join as oe,parse as Rt,resolve as K}from"node:path";var Et=".toolnet",Bo="project.json";function Uo(r){return zo("sha256").update(r).digest("hex").slice(0,16)}function Le(r){return oe(r,Et,Bo)}function Jo(r){return Fe(Le(r))}function Qo(r,e){let t=K(r),n=Rt(t).root;for(;;){if(Jo(t))return t;if(t===n||e&&t===K(e))break;let o=re(t);if(o===t)break;t=o}return null}function Yo(r){let e=K(r),t=Rt(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(s=>Fe(oe(e,s))))return e;if(e===t)break;let o=re(e);if(o===e)break;e=o}return K(r)}function Xo(r){let e;try{e=JSON.parse(Go(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:re(re(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 jt(r,e){let t=oe(r,Et);Wo(t,{recursive:!0});let n=Le(r),o=`${n}.tmp-${process.pid}`;Ho(o,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),qo(o,n)}function Tt(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 ne=class{detect(e=process.cwd()){let t=K(e),n=Yo(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>Fe(oe(n,l))),i=Qo(t,s?n:void 0);if(i){let l=Le(i),d=Xo(l);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),jt(i,d)),Tt(d,i)}let a=new Date().toISOString(),c=Vo(n),u={version:1,id:Uo(n),name:c,remote:c,rootPath:n,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return jt(n,u),Tt(u,n)}};function Ke(r){return r.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var se=class{score(e,t){let n=Ke(e),o=Ke([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 It(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 Nt(r){return L(r)/100}var Zo={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function _t(r){return Zo[r]??.4}var ie=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 ae=class{bm25=new se;analyzer=new ie;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 u=this.bm25.score(e,c),l=It(c),d=Nt(c),m=_t(c.type);i.preferredTypes.includes(c.type)&&(m=Math.min(1,m+.25));let p=u*.55+d*.2+l*.15+m*.1;u<=0||p<s||a.push({memory:c,score:p,scores:{keyword:u,recency:l,importance:d,type:m}})}return a.sort((c,u)=>u.score-c.score).slice(0,o)}};var ce=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(`
6
+ `)}};var ue=class{constructor(e){this.memory=e}memory;searcher=new ae;contextBuilder=new ce;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 le=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 de=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 oa}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as sa}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as Ot}from"zod";var Ft={query:Ot.string(),limit:Ot.number().int().min(1).max(20).optional()};async function Lt(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 D}from"zod";import{createConnection as rs}from"node:net";import{homedir as es}from"node:os";import{join as ts}from"node:path";function Kt(){return process.env.TOOLNET_SERVICE_SOCKET??ts(es(),".toolnet","run","service.sock")}function Dt(r,e={}){let t=e.socketPath??Kt(),n=e.timeoutMs??1e3;return new Promise((o,s)=>{let i=rs({path:t}),a="",c=!1,u=d=>{c||(c=!0,clearTimeout(l),i.destroy(),d())},l=setTimeout(()=>{u(()=>{s(new Error(`ToolNet service timeout after ${n}ms`))})},n);i.setEncoding("utf8"),i.once("connect",()=>{i.write(`${JSON.stringify(r)}
7
+ `)}),i.on("data",d=>{a+=d;let m=a.indexOf(`
8
+ `);if(m===-1)return;let p=a.slice(0,m).trim();u(()=>{try{o(JSON.parse(p))}catch(g){s(g instanceof Error?g:new Error(String(g)))}})}),i.once("error",d=>{u(()=>{s(d)})}),i.once("end",()=>{c||u(()=>{s(new Error("ToolNet service closed without response"))})})})}async function ns(r,e={}){let t=await Dt({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 $t(r,e={}){try{return await ns(r,e)}catch{return null}}async function me(r,e={}){try{let t=await Dt({type:"invalidate",project:r},{timeoutMs:250,...e});return t.ok&&t.type==="invalidate"}catch{return!1}}var zt={type:D.enum(["activity","decision","rule","todo","summary"]),content:D.string().min(1),tags:D.array(D.string()).optional(),importance:D.enum(["critical","high","normal","temporary"]).optional()};async function Wt(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)),me(r.project),t}import{z as os}from"zod";var Gt={id:os.string().min(1)};async function qt(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&&me(r.project),{deleted:t}}import{z as ss}from"zod";var Ht={name:ss.string().min(1)};async function Vt(r,e){return r.graph.findByName(r.project.id,e.name)}import{z as is}from"zod";var pe=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),Bt=new Set(["CALLS","CALL_REFERENCE"]),w=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,Bt)}callees(e,t){return this.relatedOutgoing(e,t,Bt)}dependents(e,t){return this.relatedIncoming(e,t,pe)}dependencies(e,t){return this.relatedOutgoing(e,t,pe)}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(m=>pe.has(m.type)),c=new Map;for(let m of a){let p=c.get(m.from)??[];p.push(m),c.set(m.from,p)}let u=[{id:t,depth:0}],l=new Set([t]),d=new Map;for(;u.length>0;){let m=u.shift();if(!(m.depth>=o)){for(let p of c.get(m.id)??[])if(!l.has(p.to)){if(l.add(p.to),d.set(p.to,{node:m.id,edge:p}),p.to===n)return this.buildPath(t,n,d);u.push({id:p.to,depth:m.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(u=>pe.has(u.type)),i=[{id:t,depth:0}],a=new Set([t]),c=[];for(;i.length>0;){let u=i.shift();if(!(u.depth>=o))for(let l of s){if(!(n==="incoming"?l.to===u.id:l.from===u.id))continue;let m=n==="incoming"?l.from:l.to;if(a.has(m))continue;let p=this.graph.getSymbol(m);p&&(a.add(m),c.push({symbol:p,depth:u.depth+1,via:l}),i.push({id:m,depth:u.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 v(r,e){let t=r.graph.getSymbol(e);if(t&&t.projectId===r.project.id)return t;let n=new w(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 b(r){return{id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,startLine:r.startLine,endLine:r.endLine}}var Ut={symbolId:is.string().min(1)};async function Jt(r,e){let t=v(r,e.symbolId);if(!t)return{found:!1,query:e.symbolId,callers:[]};let o=new w(r.graph).callers(r.project.id,t.id);return{found:!0,symbol:b(t),count:o.length,callers:o.map(b)}}import{z as Qt}from"zod";var Yt={query:Qt.string().min(1),limit:Qt.number().int().min(1).max(50).optional()};async function Xt(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 Zt}from"zod";function fe(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 er={query:Zt.string().optional(),memoryLimit:Zt.number().int().min(1).max(20).optional()};async function tr(r,e){let t=fe(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 cs}from"zod";var as=["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"],A=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 as){let d=`${i}/${l}`,m=await this.storage.get(d);m&&(await this.storage.put(`${a}/${l}`,m,"application/json"),c.push(l))}if(c.length===0)return null;let u={version:1,id:s,projectId:e,createdAt:o,reason:t,objects:c,metadata:n};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(u,null,2),"application/json"),u}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 u=await this.storage.get(`${n}/${c}`);u&&(await this.storage.put(`${i}/${c}`,u,"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 rr={reason:cs.string().optional()};async function nr(r,e){if(!r.storage)throw new Error("Storage unavailable");return new A(r.storage).create(r.project.id,e.reason??"manual-mcp")}async function or(r){if(!r.storage)throw new Error("Storage unavailable");return new A(r.storage).list(r.project.id)}import{z as us}from"zod";var sr={snapshotId:us.string().min(1)};async function ir(r,e){if(!r.storage)throw new Error("Storage unavailable");let t=new A(r.storage);return await t.create(r.project.id,"before-rollback"),t.restore(r.project.id,e.snapshotId)}import{z as De}from"zod";var ge=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(u=>u.type==="CALLS"||u.type==="CALL_REFERENCE");for(;a.length;){let u=a.shift();if(u.depth>=o)continue;let l=n==="out"?c.filter(d=>d.from===u.id):c.filter(d=>d.to===u.id);for(let d of l){let m=n==="out"?d.to:d.from;if(i.has(m))continue;i.add(m);let p=this.graph.getSymbol(m);if(!p)continue;let g=u.depth+1;s.push({symbol:p,depth:g}),a.push({id:m,depth:g})}}return s}};var ar={symbolId:De.string().min(1),direction:De.enum(["callers","callees"]).optional(),depth:De.number().int().min(1).max(10).optional()};async function cr(r,e){let t=new ge(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 ur}from"zod";var ye=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 u=o.filter(l=>l.to===c.id&&["CALLS","IMPORTS","INHERITS","IMPLEMENTS"].includes(l.type));for(let l of u){if(s.has(l.from))continue;s.add(l.from);let d=this.graph.getSymbol(l.from);if(!d)continue;let m=c.depth+1;a.push({symbol:d,depth:m,relation:l.type}),i.push({id:l.from,depth:m})}}return a}};var lr={symbolId:ur.string().min(1),depth:ur.number().int().min(1).max(10).optional()};async function dr(r,e){let t=r.graph.getSymbol(e.symbolId);if(!t)return{found:!1,impacts:[]};let o=new ye(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 mr(r){return{project:{id:r.project.id,name:r.project.name,rootPath:r.project.rootPath},architecture:fe(r.graph,r.project.id)}}import{z as pr}from"zod";var ls=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE"]),he=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e).filter(i=>ls.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,u=0,l=0;for(let d of n){let m=o.get(d.from),p=o.get(d.to);!m||!p||m.filePath===p.filePath||(m.filePath===i&&(a.add(p.filePath),u++),p.filePath===i&&(c.add(m.filePath),l++))}return{filePath:i,dependencies:[...a].sort(),dependents:[...c].sort(),outgoingEdges:u,incomingEdges:l}})}};var fr={filePath:pr.string().min(1),direction:pr.enum(["dependencies","dependents","both"]).optional()};async function gr(r,e){let n=new he(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 yr}from"zod";var hr={query:yr.string().min(1),limit:yr.number().int().min(1).max(20).optional()};async function kr(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 ze}from"zod";import{execFile as ds}from"node:child_process";import{promisify as ms}from"node:util";var $e=ms(ds);function ps(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 fs(r){return r.startsWith("A")?"added":r.startsWith("D")?"deleted":r.startsWith("R")?"renamed":"modified"}async function Sr(r){let e="";try{e=(await $e("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 $e("git",["diff","HEAD","--unified=0","--",i],{cwd:r,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:fs(o),ranges:ps(a)})}try{let n=await $e("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 gs(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 n=this.graph.allSymbols(e),o=[];for(let s of t){let i=n.filter(u=>u.filePath===s.filePath),c=i.filter(u=>u.type!=="file").filter(u=>gs(u,s));if(c.length===0){let u=i.find(l=>l.type==="file");u&&o.push({symbol:u,fileStatus:s.status,direct:!0});continue}for(let u of c)o.push({symbol:u,fileStatus:s.status,direct:!0})}return o}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var ys={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function hs(r){return r>=30?"CRITICAL":r>=16?"HIGH":r>=6?"MEDIUM":"LOW"}function br(r){let e=r.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Se=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 d=new Set([l.symbol.id]),m=[{id:l.symbol.id,depth:0}];for(;m.length;){let p=m.shift();if(p.depth>=n)continue;let g=o.filter(S=>S.to===p.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(S.type));for(let S of g){if(d.has(S.from))continue;d.add(S.from);let T=this.graph.getSymbol(S.from);if(!T)continue;let F=p.depth+1,vo=`${l.symbol.id}:${T.id}`;s.set(vo,{symbol:T,relation:S.type,depth:F,sourceSymbolId:l.symbol.id});let Co=ys[S.type]??1;i+=Math.max(1,Co-(F-1)),m.push({id:T.id,depth:F})}}}let a=[...s.values()].sort((l,d)=>l.depth-d.depth),c=[...new Set(a.map(l=>l.symbol.filePath))],u=c.filter(br);return u.length===0&&u.push(...c.filter(l=>!br(l)).slice(0,10)),{risk:hs(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:u}}};var be=class{constructor(e){this.graph=e;this.mapper=new ke(e),this.blast=new Se(e)}graph;mapper;blast;async analyzeGitDiff(e,t,n={}){let o=await Sr(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 wr={mode:ze.enum(["git_diff","file"]).optional(),filePath:ze.string().optional(),depth:ze.number().int().min(1).max(10).optional()};async function vr(r,e){let t=new be(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 ks}from"zod";var Cr={symbol:ks.string().min(1)};async function xr(r,e){let t=v(r,e.symbol);if(!t)return{found:!1,query:e.symbol,dependents:[]};let o=new w(r.graph).dependents(r.project.id,t.id);return{found:!0,symbol:b(t),count:o.length,dependents:o.map(b)}}import{z as We}from"zod";var Mr={from:We.string().min(1),to:We.string().min(1),maxDepth:We.number().int().min(1).max(30).optional()};async function Pr(r,e){let t=v(r,e.from),n=v(r,e.to);if(!t||!n)return{found:!1,fromFound:!!t,toFound:!!n,path:[],edges:[]};let s=new w(r.graph).shortestPath(r.project.id,t.id,n.id,e.maxDepth??12);return{found:s.found,distance:s.distance,from:b(t),to:b(n),path:s.symbols.map(b),edges:s.edges.map(i=>({id:i.id,type:i.type,from:i.from,to:i.to,metadata:i.metadata}))}}import{z as Ge}from"zod";var Ar={symbol:Ge.string().min(1),depth:Ge.number().int().min(1).max(5).optional(),limit:Ge.number().int().min(1).max(200).optional()};async function jr(r,e){let t=v(r,e.symbol);if(!t)return{found:!1,query:e.symbol};let o=new w(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:b(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:b(i.symbol)})),outgoing:o.outgoing.slice(0,s).map(i=>({depth:i.depth,via:i.via?.type,symbol:b(i.symbol)}))}}import{z as He}from"zod";function Ss(r){return r.replaceAll("\\","/").toLowerCase()}var we=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=Ss(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,u=t.filter(l=>l.from===e.id&&l.type!=="DEFINES").length;(n.startsWith("packages/")||c===0||u>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 Tr=new Set(["CALLS","CALL_REFERENCE","IMPORTS","USES_TYPE","WRITES","INHERITS","IMPLEMENTS","ROUTE","TESTS"]);function qe(r){return r.replaceAll("\\","/").toLowerCase()}function bs(r){let e=qe(r);return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}function ws(r){let e=qe(r.filePath);return e.startsWith("bin/")||/(^|\/)index\.[^.]+$/.test(e)||/(^|\/)(main|server|cli)\.[^.]+$/.test(e)}var ve=class{constructor(e){this.graph=e}graph;analyze(e){let t=this.graph.allSymbols(e),n=this.graph.allEdges(e),o=new Set(new we(this.graph).detect(e).map(i=>i.symbolId)),s=[];for(let i of t){if(!["function","method","class","interface","property"].includes(i.type)||bs(i.filePath)||o.has(i.id)||ws(i)||n.filter(p=>p.to===i.id&&Tr.has(p.type)).length>0)continue;let c=n.filter(p=>p.from===i.id&&Tr.has(p.type)),u=["no incoming usage edge"],l=50;(i.type==="function"||i.type==="method")&&(l+=20,u.push("callable symbol")),i.type==="property"&&(l-=15),c.length===0&&(l+=10,u.push("no outgoing dependency")),qe(i.filePath).includes("/internal/")&&(l+=10,u.push("internal implementation")),i.name.startsWith("_")&&(l+=5);let m=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:m,score:l,reasons:u})}return s.sort((i,a)=>a.score-i.score||i.filePath.localeCompare(a.filePath)||i.name.localeCompare(a.name))}};var Er={confidence:He.enum(["high","medium","low","all"]).optional(),filePath:He.string().min(1).optional(),limit:He.number().int().min(1).max(500).optional()},Rr={high:3,medium:2,low:1};async function Ir(r,e){let n=new ve(r.graph).analyze(r.project.id);if(e.confidence&&e.confidence!=="all"){let i=Rr[e.confidence];n=n.filter(a=>Rr[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 Je}from"zod";import{existsSync as Gs,readFileSync as qs}from"node:fs";import{join as Hs}from"node:path";import{existsSync as vs,mkdirSync as ll,readFileSync as Cs,renameSync as dl,writeFileSync as ml}from"node:fs";import{dirname as fl,join as xs}from"node:path";function Ms(r){return xs(r.rootPath,".toolnet","work","current.json")}function Ve(r){let e=Ms(r);if(!vs(e))return null;try{let t=JSON.parse(Cs(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as Ps,mkdirSync as hl,readFileSync as As,renameSync as kl,writeFileSync as Sl}from"node:fs";import{dirname as wl,join as js}from"node:path";function Ts(r){return js(r.rootPath,".toolnet","context","session-origin.json")}function Be(r){let e=Ts(r);if(!Ps(e))return null;try{let t=JSON.parse(As(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function Rs(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function Ce(r){let e=Rs(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"}import{existsSync as Ks,mkdirSync as ad,readFileSync as Ds}from"node:fs";import{join as Fr}from"node:path";Z();Ue();var Jl=new P;function $s(r){return Fr(r.rootPath,".toolnet","memory","checkpoints")}function zs(r){return Fr($s(r),"latest.json")}function Ws(r){let e=zs(r);if(!Ks(e))return null;try{let t=JSON.parse(Ds(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==r.id?null:t}catch{return null}}function Lr(r){return Ws(r)}var Vs={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,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,rule:85,architecture:80,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,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},Bs={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Us(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function f(r,e){let t=e.value.replace(/\s+/g," ").trim();t&&r.push({...e,value:t,score:0})}function Js(r){let e=Hs(r.rootPath,".toolnet","work","handoff-latest.json");if(!Gs(e))return null;try{let n=JSON.parse(qs(e,"utf8")).continuity;return n?.schema!=="toolnet.handoff.v2"||n.project.id!==r.id?null:n}catch{return null}}function Qs(r){let e=Lr(r);if(!e)return[];let t=[];e.request&&f(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&f(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&f(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&f(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let n=e.files.active.at(-1);n&&f(t,{kind:"file",value:n,source:"checkpoint"});for(let o of e.nextActions)f(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)f(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)f(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)f(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)f(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function Ys(r){let e=Js(r);if(!e)return[];let t=[];f(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&f(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&f(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&f(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&f(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&f(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&f(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&f(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let n of e.blockers)f(t,{kind:"blocker",value:n,source:"handoff"});for(let n of e.decisions)f(t,{kind:"decision",value:n,source:"handoff"});for(let n of e.completed.tasks)f(t,{kind:"completed",value:n,source:"handoff"});for(let n of e.remaining.todos)f(t,{kind:"todo",value:n,source:"handoff"});return f(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),f(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function Xs(r){let e=Be(r);if(!e)return[];let t=[];return f(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&f(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&f(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&f(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&f(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&f(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&f(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function Zs(r){let e=Ve(r);if(!e)return[];let t=[];e.currentRequest&&f(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&f(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&f(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&f(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&f(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let n=e.activeFiles?.at(-1)??e.filesTouched.at(-1);n&&f(t,{kind:"file",value:n,source:"work-state"});for(let o of e.nextActions.slice(0,5))f(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))f(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))f(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(s=>s.status==="completed").slice(-8))f(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))f(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))f(t,{kind:"test",value:o,source:"work-state"});return f(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=Vs[r];return e.map((n,o)=>({...n,score:(t[n.kind]??10)+Bs[n.source]+Math.max(0,5-o*.01)}))}function ti(r){let e=new Map;for(let t of r){let n=`${t.kind}:${Us(t.value)}`,o=e.get(n);(!o||t.score>o.score)&&e.set(n,t)}return[...e.values()]}function xe(r,e,t={}){let n=Ce(e),o=[...Qs(r),...Ys(r),...Xs(r),...Zs(r)],s=ti(ei(n,o)).sort((l,d)=>d.score-l.score),i=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),c=[],u=0;for(let l of s){if(c.length>=i)break;let d=l.kind.length+l.value.length+l.source.length+16;c.length>0&&u+d>a||(c.push(l),u+=d)}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:u}}}var Kr={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",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",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},Dr=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],ri={previous_agent:["previous_agent"],current_task:["request","activity","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:Dr};function ni(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 oi(r){let e=r.filter(n=>n.source==="handoff");if(e.length===0)return r;let t=r.filter(n=>n.source==="checkpoint"&&["rule","architecture","fix"].includes(n.kind));return[...e,...t]}function si(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 $r(r){switch(r){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function ii(r,e){let t=[];for(let n of e){let o=r.filter(s=>s.kind===n).slice(0,$r(n));for(let s of o)t.push(`${Kr[n]}: ${s.value}`)}return t.join(`
9
+ `)}function ai(r,e){let t=ri[e]??Dr,n=[];for(let o of t){let s=r.filter(i=>i.kind===o).slice(0,$r(o));for(let i of s)n.push(`${Kr[o]}: ${i.value}`)}return n.join(`
10
+ `)}function zr(r,e){let t=xe(r,e,{maxFacts:32,maxChars:6400}),n=si(oi(t.facts)),o=ni(e)?ii(n,["todo","task","next_action","file"]):ai(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"}}import{existsSync as ci,mkdirSync as ui,readFileSync as li,renameSync as di,rmSync as mi,writeFileSync as pi}from"node:fs";import{join as Wr}from"node:path";var fi=720*60*1e3;function Gr(r){return Wr(r.rootPath,".toolnet","context","memory-agent-conversation.json")}function W(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}function gi(r){let e=W(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 yi(r){if(gi(r))return!1;let e=W(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 hi(r,e,t){let n=Gr(r);if(!ci(n))return null;try{let o=JSON.parse(li(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 ki(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,W(s)].join(":");if(!t.has(i)&&(t.add(i),n.push({...o,value:s}),n.length>=e))break}return n}function Si(r,e){let t=Gr(r),n=Wr(r.rootPath,".toolnet","context");ui(n,{recursive:!0,mode:448});let o=`${t}.${process.pid}.tmp`;try{pi(o,JSON.stringify(e,null,2)+`
11
+ `,{encoding:"utf8",mode:384}),di(o,t)}finally{mi(o,{force:!0})}}function bi(r){return r.focus.slice(0,8).map(e=>`- ${e.kind}: ${e.value}`).join(`
12
+ `)}function wi(r,e){return r.priorFocus.find(t=>t.kind===e)?.value}function qr(r){if(!r.usedPriorFocus||r.currentIntent!=="summary"||r.priorFocus.length===0)return null;let e=W(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=wi(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 vi(r){let e=W(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 Hr(r,e,t={}){let n=t.now??Date.now(),o=t.maxAgeMs??fi,s=hi(r,n,o),i=!!(s&&s.focus.length>0&&yi(e)&&!vi(e)),a=i&&s?[e.trim(),"","Previous ToolNet Memory conversation focus:",bi(s),"","Use the compact focus only to resolve the current follow-up question.","Do not reconstruct or request raw session transcripts."].join(`
13
+ `):e.trim(),c=Ce(e),l=xe(r,a,{maxFacts:8,maxChars:1800}).facts.map(m=>({kind:m.kind,value:m.value,source:m.source})),d=ki(i&&s?[...l,...s.focus]:l);return Si(r,{schema:"toolnet.memory-conversation.v1",version:1,projectId:r.id,updatedAt:new Date(n).toISOString(),lastIntent:c,focus:d}),{question:a,originalQuestion:e,usedPriorFocus:i,previousIntent:s?.lastIntent,currentIntent:c,priorFocus:s?.focus??[],focusCount:d.length}}import{existsSync as Ci,readFileSync as xi}from"node:fs";import{join as Mi}from"node:path";function j(r){return!!r?.trim()}function Vr(r){let e=[],t=[],n=100;j(r.goal)||j(r.request)||(e.push("goal_or_request"),n-=20),j(r.activity)||j(r.current.task?.title)||j(r.current.phase?.title)||(e.push("current_work"),n-=25),j(r.nextAction)||j(r.remaining.todos[0])||(e.push("next_action"),n-=25),r.tests.status!=="unknown"||r.tests.recent.length>0||(r.tests.checks?.length??0)>0||(r.evidence?.commands.length??0)>0||(r.evidence?.references.length??0)>0||(e.push("evidence"),n-=20),j(r.files.current)||r.files.recent.length>0||(r.files.active?.length??0)>0||(r.files.modified?.length??0)>0||(r.files.created?.length??0)>0||(e.push("files"),n-=10),r.tests.status==="failing"&&t.push("tests_failing"),r.blockers.length>0&&t.push("active_blockers"),n=Math.max(0,Math.min(100,n));let u=e.includes("current_work")||e.includes("next_action"),l;return n>=80&&!u?l="high":n>=50?l="medium":l="low",{confidence:l,score:n,missingContext:e,warnings:t}}var Br={compact:{completed:3,evidence:3,files:5,blockers:2,maxChars:1800},normal:{completed:10,evidence:10,files:15,blockers:5,maxChars:4200},benchmark:{completed:30,evidence:30,files:40,blockers:10,maxChars:1e4}};function E(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 I(r){return r.length>0?r.map(e=>`- ${e}`).join(`
14
+ `):"- none"}function Pi(r,e){return r.length<=e?r:[r.slice(0,e).trimEnd(),"","[Structured handoff truncated]"].join(`
15
+ `)}function Ur(r,e){if(e)return e;let t=r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/\bbenchmark\b/u.test(t)||/\bdeep handoff\b/u.test(t)||/\bfull handoff\b/u.test(t)||/\btakeover\b/u.test(t)||/\btake over\b/u.test(t)||/tiếp quản/u.test(t)||/bằng chứng đầy đủ/u.test(t)||/evidence.*(?:file|test|command)/u.test(t)?"benchmark":/\bcompact\b/u.test(t)||/\bbrief\b/u.test(t)||/ngắn gọn/u.test(t)||/tóm tắt ngắn/u.test(t)?"compact":"normal"}function Ai(r,e="normal"){let t=Br[e],n=E([`Source agent: ${r.source.agent}`,`Captured: ${r.capturedAt}`,r.goal?`Goal: ${r.goal}`:void 0,r.request?`Request: ${r.request}`:void 0,r.activity?`Activity: ${r.activity}`:void 0,r.current.phase?`Phase: ${r.current.phase.title} [${r.current.phase.status}]`:void 0,r.current.task?`Task: ${r.current.task.title} [${r.current.task.status}]`:void 0,r.current.file?`Current file: ${r.current.file}`:void 0,`Progress: ${JSON.stringify(r.progress)}`]),o=E([...r.completed.phases.map(u=>`Phase: ${u}`),...r.completed.tasks.map(u=>`Task: ${u}`)]).slice(0,t.completed),s=E([`Tests status: ${r.tests.status}`,...r.tests.recent.map(u=>`Test: ${u}`),...(r.tests.checks??[]).map(u=>`Check [${u.status}] ${u.kind}: ${u.command}`),...(r.evidence?.commands??[]).map(u=>`Command: ${u}`),...(r.evidence?.references??[]).map(u=>`Reference: ${u}`),...r.decisions.map(u=>`Decision: ${u}`),...r.attention.map(u=>`Attention: ${u}`)]).slice(0,t.evidence),i=E([r.files.current,...(r.files.active??[]).map(u=>`Active: ${u}`),...(r.files.modified??[]).map(u=>`Modified: ${u}`),...(r.files.created??[]).map(u=>`Created: ${u}`),...(r.files.deleted??[]).map(u=>`Deleted: ${u}`),...r.files.recent.map(u=>`Recent: ${u}`)]).slice(0,t.files),a=E(r.blockers).slice(0,t.blockers),c=E([r.nextAction,r.nextAction?void 0:r.remaining.todos[0]]).slice(0,1);return{currentState:n,completed:o,evidence:s,filesTouched:i,blockers:a,nextAction:c}}function ji(r,e,t){return[`HANDOFF_DETAIL: ${e}`,`CONTINUITY_CONFIDENCE: ${t.confidence}`,`QUALITY_SCORE: ${t.score}`,`MISSING_CONTEXT: ${t.missingContext.length>0?t.missingContext.join(", "):"none"}`,`QUALITY_WARNINGS: ${t.warnings.length>0?t.warnings.join(", "):"none"}`,"","CURRENT_STATE",I(r.currentState),"","COMPLETED",I(r.completed),"","EVIDENCE",I(r.evidence),"","FILES_TOUCHED",I(r.filesTouched),"","BLOCKERS",I(r.blockers),"","NEXT_ACTION",I(r.nextAction)].join(`
16
+ `)}function Jr(r,e="normal"){let t=Mi(r.rootPath,".toolnet","work","handoff-latest.json");if(!Ci(t))return null;try{let o=JSON.parse(xi(t,"utf8")).continuity;if(!o||o.schema!=="toolnet.handoff.v2"||o.version!==2)return null;let s=Ai(o,e),i=Vr(o),a=Pi(ji(s,e,i),Br[e].maxChars);return{detail:e,data:s,quality:i,text:a}}catch{return null}}function Ti(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}var Ri=[/\bhandoff\b/u,/\bcontinuity\b/u,/\bcontinue\b/u,/\bresume\b/u,/\btakeover\b/u,/\btake over\b/u,/tiếp tục/u,/tiếp quản/u,/bàn giao/u,/dừng ở đâu/u,/đang làm gì/u],Ei=[/\bcurrent state\b/u,/\bcurrent task\b/u,/\bevidence\b/u,/\breport locations?\b/u,/\bfiles?\b/u,/\burls?\b/u,/\bassets?\b/u,/\btests?\b/u,/\bcommands?\b/u,/\bblockers?\b/u,/\bnext actions?\b/u,/trạng thái hiện tại/u,/task hiện tại/u,/bằng chứng/u,/vị trí báo cáo/u,/file/u,/url/u,/blocker/u,/việc tiếp theo/u,/bước tiếp theo/u],Ii=[/\bsummarize\b/u,/\bsummary\b/u,/\bfull state\b/u,/\bfull context\b/u,/tóm tắt/u,/đầy đủ/u,/toàn bộ trạng thái/u];function Ni(r){let e=0;for(let t of Ei)t.test(r)&&(e+=1);return e}function Qr(r,e){let t=Ti(r);if(/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(t)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(t)||/(?:còn|các)\s+(?:todo|việc)\b/u.test(t))return!1;if(e==="summary"||e==="status")return!0;if(!t)return!1;let o=Ri.some(a=>a.test(t)),s=Ii.some(a=>a.test(t)),i=Ni(t);return!!(o&&i>=1||s&&i>=2||i>=4)}var Xr={question:Je.string().min(2).max(4e3).describe("Question about previous project work, unfinished tasks, handoff, blockers, decisions, files or next actions."),mode:Je.enum(["local"]).optional().describe("Returns deterministic local memory only. No external AI is used."),detail:Je.enum(["compact","normal","benchmark"]).optional().describe("Handoff detail level. compact=minimal, normal=standard, benchmark=deep evidence/files/tests for agent takeover.")};function Yr(r,e,t,n,o){if(!Qr(e,t))return{answer:n};let s=Ur(e,o),i=Jr(r.project,s);return i?{answer:i.text,handoff:i.data,detail:i.detail,confidence:i.quality.confidence,missingContext:i.quality.missingContext,quality:i.quality}:{answer:n}}async function Zr(r,e){let t=Hr(r.project,e.question),n=qr(t);if(n)return{...Yr(r,t.originalQuestion,String(n.intent),n.answer,e.detail),mode:"local",usedAi:!1,source:n.source,intent:n.intent};let o=zr(r.project,t.originalQuestion),s=Yr(r,t.originalQuestion,String(o.intent),o.answer,e.detail);return"handoff"in s?{...s,mode:"local",usedAi:!1,source:o.source,intent:o.intent,routing:"deterministic-handoff"}:{...s,mode:"local",usedAi:!1,source:o.source,intent:o.intent}}import{z as an}from"zod";import{chmodSync as Dd,existsSync as en,mkdirSync as $d,readFileSync as tn,renameSync as zd,writeFileSync as Wd}from"node:fs";import{dirname as qd,join as G}from"node:path";var rn="toolnet.context-offload.v1",_i="toolnet.context-offload-asset.v1";function nn(r){return G(r,".toolnet","offload")}function on(r){return G(nn(r),"assets")}function Oi(r){return G(nn(r),"graph.json")}function Qe(){return{schema:rn,version:1,updatedAt:new Date(0).toISOString(),nodes:[]}}function Fi(r){let e=Oi(r);if(!en(e))return Qe();try{let t=JSON.parse(tn(e,"utf8"));return t.schema!==rn||t.version!==1||!Array.isArray(t.nodes)?Qe():t}catch{return Qe()}}function Li(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&&en(G(on(r),`${t}.json`)))return t;let n=Fi(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 sn(r,e,t=6e3){let n=Li(r,e),o=tn(G(on(r),`${n}.json`),"utf8"),s=JSON.parse(o);if(s.schema!==_i||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)}
17
+ [truncated]`:o}}var cn={assetId:an.string().regex(/^[a-f0-9]{8,64}$/iu).describe("Asset reference from the ToolNet Context Offload Graph."),maxChars:an.number().int().min(200).max(2e4).optional().describe("Maximum asset characters to return. Defaults to 6000.")};async function un(r,e){return sn(r.project.rootPath,e.assetId,e.maxChars??6e3)}import{z as mn}from"zod";import{chmodSync as Qd,existsSync as Ki,mkdirSync as Yd,readFileSync as Di,readdirSync as $i,renameSync as Xd,statSync as zi,writeFileSync as Zd}from"node:fs";import{join as ln}from"node:path";var Wi="toolnet.skill-memory.v1";function Gi(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 qi(r){return ln(r.rootPath,".toolnet","memory","skills")}function Hi(r,e){if(!r||typeof r!="object")return!1;let t=r;return t.schema===Wi&&t.version===1&&t.projectId===e&&typeof t.id=="string"&&typeof t.task=="string"&&Array.isArray(t.steps)&&Array.isArray(t.verification)&&Array.isArray(t.files)}function Vi(r){let e=qi(r);if(!Ki(e))return[];if(!zi(e).isDirectory())return[];let t=[];for(let n of $i(e)){if(!n.endsWith(".json"))continue;let o=ln(e,n);try{let s=JSON.parse(Di(o,"utf8"));Hi(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 Bi(r){return Gi(r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_./-]+/gu).filter(e=>e.length>=2),32)}function Ui(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(`
18
+ `).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 Bi(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 dn(r,e,t=5){let n=Math.max(1,Math.min(10,Math.floor(t)));return Vi(r).map(o=>({...o,score:Ui(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 pn={query:mn.string().min(2).max(500).describe("Task, problem, file, command or workflow to match against successful reusable Skill Memory SOPs."),limit:mn.number().int().min(1).max(10).optional().describe("Maximum matching reusable SOPs to return. Default 5.")};async function fn(r,e){let t=dn(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 Pn}from"zod";var gn="wiki/state.v1.json";function Ji(r){let e=new Date().toISOString();return{schema:"toolnet.wiki.v1",version:1,projectId:r.id,pages:[],revisions:[],createdAt:e,updatedAt:e}}function Qi(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 C=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(gn);if(!e){let t=Ji(this.project);return await this.save(t),t}return Qi(e,this.project)}async save(e){await this.storage.put(gn,JSON.stringify(e,null,2),"application/json")}};import{randomUUID as kn}from"node:crypto";var k=class extends Error{constructor(t,n){super(t);this.statusCode=n}statusCode};function q(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 H(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 yn(r){let e=[];for(let t of r.matchAll(/\[\[([^\[\]]+)\]\]/gu)){let n=t[1]?.trim();n&&e.push(H(n))}return q(e)}function Yi(r){return r.normalize("NFKC").toLowerCase().split(/[^\p{L}\p{N}_-]+/u).map(e=>e.trim()).filter(e=>e.length>=2)}function hn(r){return{id:`revision-${kn()}`,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 R(r){return structuredClone(r)}var x=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:q(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 R([...e.pages].sort((t,n)=>t.title.localeCompare(n.title)))}async getPage(e){let t=await this.ensureState(),n=H(e),o=t.pages.find(s=>s.slug===n||s.id===e);if(!o)throw new k(`Wiki page not found: ${e}`,404);return R(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=H(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-${kn()}`,slug:s,title:n,...e.summary?.trim()?{summary:e.summary.trim()}:{},content:o,tags:q(e.tags??[]),links:yn(o),revision:1,createdAt:i,updatedAt:i};return t.pages.push(a),t.revisions.push(hn(a)),R(a)})}async updatePage(e,t){return this.mutate(n=>{let o=H(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=yn(s.content)),t.tags!==void 0&&(s.tags=q(t.tags)),s.revision+=1,s.updatedAt=new Date().toISOString(),n.revisions.push(hn(s)),R(s)})}async history(e){let t=await this.getPage(e),n=await this.ensureState();return R(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 R(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=q(Yi(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(),u=a.slug.toLowerCase(),l=a.summary?.toLowerCase()??"",d=a.content.toLowerCase(),m=a.tags.map(g=>g.toLowerCase()),p=0;for(let g of o)u===g&&(p+=12),c===g&&(p+=10),c.includes(g)&&(p+=6),u.includes(g)&&(p+=5),m.some(S=>S===g)?p+=5:m.some(S=>S.includes(g))&&(p+=3),l.includes(g)&&(p+=2),d.includes(g)&&(p+=1);p>0&&i.push({page:R(a),score:p})}return i.sort((a,c)=>c.score-a.score||c.page.updatedAt.localeCompare(a.page.updatedAt)).slice(0,s)}};import{createHash as Xi,randomUUID as Sn}from"node:crypto";var bn="wiki/governance.v1.json",xn="toolnet.knowledge-governance.v1",wn=500,V={autoApproveThreshold:.86,criticalApproveThreshold:.94,staleAfterDays:90};function Zi(r,e=0,t=1){return Math.max(e,Math.min(t,r))}function Ye(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/gu," ").trim()}function vn(r){return Xi("sha256").update(r.normalize("NFKC").replace(/\s+/gu," ").trim()).digest("hex")}function ea(r){let e=[r.title,r.summary??"",r.content.slice(0,2e3),...r.tags].join(" ").toLowerCase();return/\b(?:architecture|security|authentication|authorization|auth|database|production|deploy|deployment|payment|billing|permission|permissions|acl|credential|secret|migration)\b/u.test(e)}function ta(r){let e=r.sourceType==="skill"?.96:r.sourceType==="memory"?.94:.88,t=r.tags.map(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),Zi(e)}function Cn(r){let e=new Date().toISOString();return{schema:xn,version:1,projectId:r,policy:{...V},reviews:[],audit:[],createdAt:e,updatedAt:e}}function Mn(r){let e=r.autoApproveThreshold??V.autoApproveThreshold,t=r.criticalApproveThreshold??V.criticalApproveThreshold,n=r.staleAfterDays??V.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 B=class{constructor(e,t){this.storage=e;this.project=t}storage;project;async load(){let e=await this.storage.getText(bn);if(!e){let t=Cn(this.project.id);return await this.save(t),t}try{let t=JSON.parse(e);if(t.schema!==xn||t.version!==1||t.projectId!==this.project.id||!Array.isArray(t.reviews)||!Array.isArray(t.audit))throw new Error("invalid");return{...t,policy:Mn(t.policy??V)}}catch{let t=Cn(this.project.id);return await this.save(t),t}}async save(e){await this.storage.put(bn,JSON.stringify(e,null,2),"application/json")}},U=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:Sn(),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>wn&&(e.audit=e.audit.slice(-wn))}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=Mn({...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=ta(e),s=Ye(e.title),i=t.filter(l=>l.slug!==e.slug&&Ye(l.title)===s&&vn(l.content)!==vn(e.content)).map(l=>l.slug),a=ea(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 u=i.length>0?"conflict":a?"critical":"normal";return{confidence:o,risk:u,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:Sn(),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(u=>u.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 u=o.reviews.find(l=>l.id===t.targetReviewId);if(!u)throw new k("Merge target review not found",404);return s.status="superseded",s.mergedInto=u.id,this.audit(o,"knowledge:merged",t.principal,{reviewId:e,sourceKey:s.sourceKey,metadata:{targetReviewId:u.id}}),structuredClone(s)}s.status="approved";let c=(await n.listPages()).find(u=>u.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 d=o-Date.parse(l.updatedAt);return{slug:l.slug,title:l.title,updatedAt:l.updatedAt,ageDays:Math.max(0,Math.floor(d/864e5)),stale:Number.isFinite(d)&&d>s}}).filter(l=>l.stale).map(({stale:l,...d})=>d),a=new Map;for(let l of n){let d=Ye(l.title),m=a.get(d)??[];m.push(l),a.set(d,m)}let c=[...a.entries()].filter(([,l])=>l.length>1).map(([l,d])=>({title:l,pages:d.map(m=>m.slug)})),u=t.reviews.filter(l=>l.status==="pending");return{schema:"toolnet.knowledge-quality.v1",totalPages:n.length,automatedPages:n.filter(l=>l.tags.some(d=>d.startsWith("toolnet-auto-"))).length,manualPages:n.filter(l=>!l.tags.some(d=>d.startsWith("toolnet-auto-"))).length,stalePages:i,duplicateTitles:c,pendingReviews:u.length,lowConfidenceReviews:u.filter(l=>l.confidence<t.policy.autoApproveThreshold).length,conflicts:u.filter(l=>l.risk==="conflict").length,generatedAt:new Date().toISOString()}}};var An={query:Pn.string().min(2).max(500).describe("Knowledge topic or project concept to search in ToolNet Wiki."),limit:Pn.number().int().min(1).max(10).optional().describe("Maximum Wiki matches. Default 5.")};async function jn(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new x(new C(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 ra}from"zod";var Tn={page:ra.string().min(1).max(200).describe("Wiki page slug or page id.")};async function Rn(r,e){let t=r.storage;if(!t)throw new Error("Wiki storage unavailable");let n=new x(new C(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 na}from"zod";var En={includePending:na.boolean().optional().describe("Include compact pending-review metadata. Default false.")};async function In(r,e){let t=r.storage;if(!t)throw new Error("Knowledge Governance storage unavailable");let n=new U(new B(t,r.project));await n.initialize();let o=new x(new C(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 Nn={};function _n(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 h(r){return{content:[{type:"text",text:JSON.stringify(r,null,2)}]}}var ia=["# ToolNet Memory \u2014 Persistent Project Continuity","","ToolNet Memory provides persistent work continuity across coding agents and sessions.","","CONTINUITY RULES:","","1. When the user asks to continue, resume, finish, pick up, or return to previous work,"," call memory_agent_ask BEFORE reconstructing previous work from git, files, or session history.","",'2. Use memory_agent_ask with mode="local" for direct continuity facts such as:'," - current task"," - completed work"," - current/last file"," - TODOs"," - blockers"," - next action","",'3. Use mode="ai" only when the continuity question is ambiguous or requires synthesis.',"","4. NEVER reconstruct previous work by reading or searching raw agent/session history, including:"," - .toolnet/sessions/**"," - state.json"," - events.jsonl"," - raw transcripts"," - ~/.gemini/antigravity-cli/brain/**"," - another coding agent's internal session history","","5. Do not search the filesystem for the implementation or JSON schema of memory_agent_ask."," Invoke the MCP tool directly.","","6. After ToolNet resolves continuity, inspect the current repository only to verify current truth."," Current repository evidence overrides stale memory.","","7. Do not ask the user to repeat project context already available through ToolNet Memory.","","8. Do not call memory_agent_ask for unrelated coding questions when current context is sufficient.","","9. Large tool/file payloads may be stored outside prompt context."," If the compact graph references a needed asset, call context_offload_read.","","10. Never bulk-load offloaded assets. Read only the minimum asset required."].join("\\n");function aa(r){let e=new oa({name:"toolnet-memory",version:"0.1.0"},{instructions:ia});return e.tool("memory_search","Search relevant long-term memory for the current project.",Ft,async t=>h(await Lt(r,t))),e.tool("memory_save","Save an important memory, decision, rule, TODO or summary.",zt,async t=>h(await Wt(r,t))),e.tool("memory_forget","Delete a memory by id.",Gt,async t=>h(await qt(r,t))),e.tool("find_symbol","Find code symbols by exact name.",Ht,async t=>h(await Vt(r,t))),e.tool("find_callers","Find functions or methods calling a symbol.",Ut,async t=>h(await Jt(r,t))),e.tool("code_search","Search indexed code symbols and files.",Yt,async t=>h(await Xt(r,t))),e.tool("project_context","Get compact project architecture, recent memory and relevant context.",er,async t=>h(await tr(r,t))),e.tool("trace_calls","Trace callers or callees through the code call graph.",ar,async t=>h(await cr(r,t))),e.tool("analyze_impact","Analyze what code can be affected if a symbol changes.",lr,async t=>h(await dr(r,t))),e.tool("get_architecture","Get compact architecture statistics for the indexed project.",{},async()=>h(await mr(r))),e.tool("find_dependencies","Find direct file dependencies and reverse dependents.",fr,async t=>h(await gr(r,t))),e.tool("semantic_code_search","Search source code by semantic meaning, not only exact symbol names.",hr,async t=>h(await kr(r,t))),e.tool("snapshot_create","Create a safe versioned snapshot of project memory, vectors and graph.",rr,async t=>h(await nr(r,t))),e.tool("snapshot_list","List available ToolNet Memory snapshots.",{},async()=>h(await or(r))),e.tool("snapshot_restore","Restore a previous ToolNet Memory snapshot. A safety snapshot is created first.",sr,async t=>h(await ir(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.",wr,async t=>h(await vr(r,t))),e.tool("graph_dependents","Find code symbols that depend on a symbol through calls, imports, type usage, writes, inheritance or implementation relationships.",Cr,async t=>h(await xr(r,t))),e.tool("graph_path","Find the shortest dependency path between two code symbols.",Mr,async t=>h(await Pr(r,t))),e.tool("graph_neighborhood","Explore incoming and outgoing dependency relationships around a code symbol.",Ar,async t=>h(await jr(r,t))),e.tool("dead_code","Find likely unused code. Results are candidates and must be verified before deletion.",Er,async t=>h(await Ir(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(" "),Xr,async t=>h(await Zr(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(" "),cn,async t=>h(await un(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(" "),pn,async t=>h(await fn(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=>h(await jn(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(" "),Tn,async t=>h(await Rn(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(" "),Nn,async()=>h(_n(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(" "),En,async t=>h(await In(r,t))),e}async function On(r){let e=aa(r),t=new sa;await e.connect(t)}function Fn(){return new Date().toISOString()}function M(r){r.lastUpdatedAt=Fn()}function Me(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:Fn()}}function Ln(r,e=Date.now()){r.metrics.mcpConnectedAtMs=e,r.metrics.startupMs=e-r.metrics.processStartedAtMs,r.phase="hydrating",M(r)}function Kn(r,e=Date.now()){r.phase="hydrating",r.metrics.hydrationStartedAtMs=e,r.metrics.hydrationRuns+=1,M(r)}function Pe(r,e){r.dependencies[e].state!=="ready"&&(r.dependencies[e].state="loading",r.dependencies[e].lastError=void 0,M(r))}function Ae(r,e){r.dependencies[e].attempts+=1,M(r)}function je(r){r.metrics.retryCount+=1,M(r)}function N(r,e,t=Date.now()){let n=r.dependencies[e];n.state="ready",n.lastError=void 0,n.readyAfterMs=t-r.metrics.processStartedAtMs,M(r)}function J(r,e,t){let n=r.dependencies[e];n.state="failed",n.lastError=t instanceof Error?t.message:String(t),M(r)}function Dn(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",M(r)}function $n(r,e){r.phase="failed",r.errors=[e instanceof Error?e.message:String(e)],M(r)}async function Te(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 So(r,e){let t=Number(r);return!Number.isFinite(t)||t<1?e:Math.floor(t)}function $a(r,e){let t=Number(r);return!Number.isFinite(t)||t<0?e:Math.floor(t)}function za(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 bo(r){let e=r.runtime??Me(Date.now());r.runtime=e,Kn(e);let t=So(process.env.TOOLNET_MCP_HYDRATION_RETRIES,3),n=$a(process.env.TOOLNET_MCP_HYDRATION_RETRY_DELAY_MS,500);if(e.dependencies.memory.state!=="ready"||e.dependencies.graph.state!=="ready"){let o=await $t(r.project,{timeoutMs:So(process.env.TOOLNET_SERVICE_REQUEST_TIMEOUT_MS,1e3)});o&&(e.dataSource="daemon",e.dependencies.memory.state!=="ready"&&(r.memory.importRecords(o.memory),N(e,"memory")),e.dependencies.graph.state!=="ready"&&(o.graph&&r.graph.import(o.graph.symbols,o.graph.edges),N(e,"graph")))}try{let[{loadConfig:o},s]=await Promise.all([Promise.resolve().then(()=>(Ue(),Or)),Promise.resolve().then(()=>(lo(),uo))]),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)}),u=new s.ProjectScopedStorageProvider(c,r.project.id,r.project.name,r.project.remote??r.project.name),l=new s.MemoryStore(u);r.storage=u,r.memoryStore=l;let d=e.dependencies.memory.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",Pe(e,"memory");try{let p=await Te(()=>l.load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{Ae(e,"memory")},onRetry:()=>{je(e)}});r.memory.importRecords(p),N(e,"memory")}catch(p){J(e,"memory",p)}})(),m=e.dependencies.graph.state==="ready"?Promise.resolve():(async()=>{e.dataSource="embedded",Pe(e,"graph");try{let p=await Te(()=>new s.PersistentCodeGraphStore(u).load(r.project.id),{attempts:t,delayMs:n,onAttempt:()=>{Ae(e,"graph")},onRetry:()=>{je(e)}});p&&r.graph.import(p.symbols,p.edges),N(e,"graph")}catch(p){J(e,"graph",p)}})();if(await Promise.all([d,m]),e.dependencies.semantic.state!=="ready"){Pe(e,"semantic");try{let{SemanticCodeEngine:p}=await Promise.resolve().then(()=>(ko(),ho)),g=new p({projectId:r.project.id,rootPath:r.project.rootPath,storage:u,graph:r.graph});await Te(()=>g.initialize(),{attempts:t,delayMs:n,onAttempt:()=>{Ae(e,"semantic")},onRetry:()=>{je(e)}}),r.codeSemantic=g,N(e,"semantic")}catch(p){J(e,"semantic",p)}}}catch(o){for(let s of["memory","graph","semantic"])e.dependencies[s].state!=="ready"&&J(e,s,o)}return Dn(e),za(r)}function wo(){let r=Number(process.env.TOOLNET_MCP_DEGRADED_RETRY_MS??3e4);return Number.isFinite(r)&&r>=1e3?Math.floor(r):3e4}async function Wa(){let r=Date.now(),e=new ne().detect(),t=new te,n=new ue(t),o=new le,s=new de(o),i=Me(r),a={project:e,memory:t,retrieval:n,graph:o,references:s,runtime:i};await On(a),Ln(i);let c=async()=>{try{await bo(a),i.phase==="degraded"&&setTimeout(()=>{c()},wo()).unref()}catch(u){$n(i,u),setTimeout(()=>{i.phase="degraded",c()},wo()).unref()}};c()}Wa().catch(r=>{console.error(r),process.exit(1)});