toolnet-memory 0.2.3 → 0.2.4

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.
@@ -13,6 +13,12 @@ ROOT="$(cd -P "$(dirname "$SOURCE")/.." >/dev/null 2>&1 && pwd)"
13
13
  NODE="${NODE_BINARY:-node}"
14
14
  TSX="$ROOT/node_modules/.bin/tsx"
15
15
 
16
+
17
+ if [ "${1:-}" = "--version" ] || [ "${1:-}" = "-v" ]; then
18
+ node -e 'console.log("v" + require(process.argv[1]).version)' "$ROOT/package.json"
19
+ exit 0
20
+ fi
21
+
16
22
  COMMAND="${1:-help}"
17
23
 
18
24
  run() {
@@ -35,6 +41,16 @@ run() {
35
41
  }
36
42
 
37
43
  case "$COMMAND" in
44
+ update)
45
+ shift
46
+ run bundle/update.js src/production/update.ts "$@"
47
+ ;;
48
+
49
+ config)
50
+ shift
51
+ run bundle/config.js src/production/config-cli.ts "$@"
52
+ ;;
53
+
38
54
  setup)
39
55
  if [ -f "$ROOT/bundle/setup.js" ]; then
40
56
  exec node "$ROOT/bundle/setup.js" "$@"
@@ -48,11 +64,12 @@ case "$COMMAND" in
48
64
 
49
65
 
50
66
  doctor)
51
- run bundle/doctor.js src/production/doctor.ts
67
+ shift
68
+ run bundle/doctor.js src/production/doctor.ts "$@"
52
69
  ;;
53
70
 
54
71
  run)
55
- run dist/index.js src/index.ts
72
+ run bundle/runtime.js src/index.ts
56
73
  ;;
57
74
 
58
75
  mcp)
@@ -64,21 +81,21 @@ case "$COMMAND" in
64
81
  ;;
65
82
 
66
83
  index:graph)
67
- run dist/src/code-intelligence/test-index.js src/code-intelligence/test-index.ts
84
+ run bundle/graph-index.js src/code-intelligence/test-index.ts
68
85
  ;;
69
86
 
70
87
  incremental)
71
- run dist/src/code-intelligence/test-incremental.js src/code-intelligence/test-incremental.ts
88
+ run bundle/incremental.js src/code-intelligence/test-incremental.ts
72
89
  ;;
73
90
 
74
91
  semantic)
75
92
  shift
76
- run dist/src/code-intelligence/test-semantic.js src/code-intelligence/test-semantic.ts "$@"
93
+ run bundle/semantic.js src/code-intelligence/test-semantic.ts "$@"
77
94
  ;;
78
95
 
79
96
  impact)
80
97
  shift
81
- run dist/src/code-intelligence/test-impact.js src/code-intelligence/test-impact.ts "$@"
98
+ run bundle/impact.js src/code-intelligence/test-impact.ts "$@"
82
99
  ;;
83
100
 
84
101
  snapshot:list)
@@ -386,8 +403,13 @@ case "$COMMAND" in
386
403
  ToolNet Memory
387
404
 
388
405
  Commands:
406
+ toolnet-memory --version
389
407
  toolnet-memory doctor
390
408
  toolnet-memory setup
409
+ toolnet-memory update
410
+ toolnet-memory config get KEY
411
+ toolnet-memory config set KEY VALUE
412
+ toolnet-memory config open
391
413
  toolnet-memory index
392
414
  toolnet-memory index:graph
393
415
  toolnet-memory incremental
@@ -0,0 +1,15 @@
1
+ import i from"node:fs";import d from"node:os";import u from"node:path";import{spawnSync as p}from"node:child_process";var l=u.join(d.homedir(),".config","toolnet-memory"),s=u.join(l,".env"),E=/(SECRET|TOKEN|PASSWORD|ACCESS_KEY|API_KEY|PRIVATE_KEY)/i;function f(){i.mkdirSync(l,{recursive:!0,mode:448}),i.existsSync(s)||i.writeFileSync(s,"",{encoding:"utf8",mode:384}),i.chmodSync(l,448),i.chmodSync(s,384)}function a(){return f(),i.readFileSync(s,"utf8").split(/\r?\n/)}function m(){let o=new Map;for(let t of a()){let e=t.trim();if(!e||e.startsWith("#"))continue;let n=e.indexOf("=");n<1||o.set(e.slice(0,n).trim(),e.slice(n+1).trim())}return o}function y(o){return/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)}function g(o,t){return E.test(o)?t?t.length<=8?"********":t.slice(0,4)+"\u2026"+t.slice(-4):"":t}function h(o,t){if(!y(o))throw new Error(`Invalid config key: ${o}`);let e=a(),n=!1,r=e.map(c=>c.trim().startsWith(`${o}=`)?(n=!0,`${o}=${t}`):c);n||(r.length&&r[r.length-1]!==""&&r.push(""),r.push(`${o}=${t}`)),i.writeFileSync(s,r.join(`
2
+ `),{encoding:"utf8",mode:384}),i.chmodSync(s,384)}function S(){console.log(`ToolNet Memory Config
3
+
4
+ Commands:
5
+ toolnet-memory config path
6
+ toolnet-memory config list
7
+ toolnet-memory config get KEY
8
+ toolnet-memory config get KEY --reveal
9
+ toolnet-memory config set KEY VALUE
10
+ toolnet-memory config open
11
+
12
+ Examples:
13
+ toolnet-memory config get HF_NAMESPACE
14
+ toolnet-memory config set HF_BUCKET toolnet-memory
15
+ toolnet-memory config open`)}function v(){let[o="help",...t]=process.argv.slice(2);if(o==="path"){f(),console.log(s);return}if(o==="list"){let e=m();for(let[n,r]of e)console.log(`${n}=${g(n,r)}`);return}if(o==="get"){let e=t[0];e||(console.error("Usage: toolnet-memory config get KEY"),process.exit(1));let n=m();n.has(e)||(console.error(`Config key not found: ${e}`),process.exit(1));let r=n.get(e)??"",c=t.includes("--reveal");console.log(c?r:g(e,r));return}if(o==="set"){let e=t[0],n=t[1];(!e||n===void 0)&&(console.error("Usage: toolnet-memory config set KEY VALUE"),process.exit(1)),h(e,n),console.log(`\u2713 ${e} updated`);return}if(o==="open"){if(f(),!process.stdin.isTTY){console.log(s);return}let e=process.env.VISUAL||process.env.EDITOR||"vi",n=p(e,[s],{stdio:"inherit",shell:!0});process.exitCode=n.status??0;return}S()}try{v()}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exit(1)}
package/bundle/doctor.js CHANGED
@@ -1,3 +1,3 @@
1
- import"dotenv/config";import{existsSync as U,readFileSync as Y}from"node:fs";import{homedir as G}from"node:os";import{join as W}from"node:path";function Z(o){let e=o.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 Q(){let o=process.env.TOOLNET_GLOBAL_ENV??W(G(),".config","toolnet-memory",".env");if(!U(o))return;let e=Y(o,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let n=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=Z(r.slice(s+1)))}}Q();function f(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function g(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function _(){return{memory:{autoCapture:f(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:f(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:f(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:f(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:g(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:g(process.env.MEMORY_RERANK_TOP,10),finalContext:g(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:g(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:g(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as X}from"node:crypto";import{existsSync as M,mkdirSync as q,readFileSync as ee,renameSync as te,writeFileSync as re}from"node:fs";import{basename as oe,dirname as h,join as v,parse as N,resolve as u}from"node:path";var D=".toolnet",se="project.json";function ne(o){return X("sha256").update(o).digest("hex").slice(0,16)}function T(o){return v(o,D,se)}function ie(o){return M(T(o))}function ae(o,e){let t=u(o),r=N(t).root;for(;;){if(ie(t))return t;if(t===r||e&&t===u(e))break;let s=h(t);if(s===t)break;t=s}return null}function ce(o){let e=u(o),t=N(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>M(v(e,n))))return e;if(e===t)break;let s=h(e);if(s===e)break;e=s}return u(o)}function pe(o){let e;try{e=JSON.parse(ee(o,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${o}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${o}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${o}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${o}`);let r=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:h(h(o)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 I(o,e){let t=v(o,D);q(t,{recursive:!0});let r=T(o),s=`${r}.tmp-${process.pid}`;re(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),te(s,r)}function $(o,e){return{id:o.id,name:o.name,remote:o.remote,rootPath:e,createdAt:o.createdAt,updatedAt:o.updatedAt,graphVersion:o.graphVersion,memoryVersion:o.memoryVersion,metadata:o.metadata}}var y=class{detect(e=process.cwd()){let t=u(e),r=ce(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>M(v(r,m))),i=ae(t,n?r:void 0);if(i){let m=T(i),d=pe(m);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),I(i,d)),$(d,i)}let a=new Date().toISOString(),c=oe(r),p={version:1,id:ne(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return I(r,p),$(p,r)}};import{homedir as ke}from"node:os";import{join as Ee}from"node:path";import{DeleteObjectCommand as me,GetObjectCommand as de,HeadObjectCommand as ge,ListObjectsV2Command as ue,PutObjectCommand as le,S3Client as fe}from"@aws-sdk/client-s3";import{getSignedUrl as he}from"@aws-sdk/s3-request-presigner";var j=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new fe({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,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new le({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await he(this.client,new de({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 ge({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 me({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new ue({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of s.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as z,mkdir as ye,readFile as ve,readdir as je,rm as we,stat as V,writeFile as Se}from"node:fs/promises";import{dirname as be,join as xe,relative as K,resolve as Pe}from"node:path";var l=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Pe(this.root,t)}async put(e,t){let r=this.path(e);await ye(be(r),{recursive:!0}),await Se(r,t)}async get(e){try{return await ve(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 z(this.path(e)),!0}catch{return!1}}async delete(e){await we(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await z(t)}catch{return r}let s=async i=>{let a=await je(i,{withFileTypes:!0});for(let c of a){let p=xe(i,c.name);if(c.isDirectory()){await s(p);continue}let m=await V(p);r.push({key:K(this.root,p),size:m.size,updatedAt:m.mtime.toISOString()})}},n=await V(t);return n.isDirectory()?await s(t):r.push({key:K(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function L(o){let e=o.localRoot??Ee(ke(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new j({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new l(e))}return new l(e)}var w=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 r=JSON.parse(t);if(!Array.isArray(r))throw new Error("Invalid memory snapshot");return r}async save(e,t){let r=JSON.stringify(t,null,2);await this.storage.put(this.key(e),r,"application/json")}};var S=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 r=JSON.parse(t);if(r.version!==1||r.projectId!==e||!Array.isArray(r.records))throw new Error("Invalid vector snapshot");return r}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var b=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 x=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 P=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 Ae(o){return new Promise(e=>setTimeout(e,o))}async function F(o,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,n;for(let i=1;i<=t;i++)try{return await o()}catch(a){if(n=a,i>=t)break;let c=Math.min(s,r*2**(i-1)),p=Math.floor(Math.random()*Math.max(1,c*.2));await Ae(c+p)}throw n}var Re=new Set(["put","get","getText","delete","list"]);function B(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:Re.has(r)?(...n)=>F(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}var k=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`,r=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(!r.ok)throw new Error(`HF embedding failed: ${r.status} ${await r.text()}`);let s=await r.json();if(!Array.isArray(s))throw new Error("HF embedding returned invalid response");return s.map(n=>Me(n))}};function Me(o){if(!Array.isArray(o))throw new Error("Invalid embedding");if(o.length>0&&typeof o[0]=="number")return o;if(o.length>0&&Array.isArray(o[0])){let e=o;if(e.length===0)return[];let t=e[0].length,r=new Array(t).fill(0);for(let s of e)for(let n=0;n<t;n++)r[n]+=s[n]??0;for(let s=0;s<t;s++)r[s]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as Te}from"node:crypto";var E=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),r=e.toLowerCase().split(/\s+/).filter(Boolean);for(let s of r){let i=Te("sha256").update(s).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return Ce(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function Ce(o){let e=Math.sqrt(o.reduce((t,r)=>t+r*r,0));return e===0?o:o.map(t=>t/e)}var C=class{constructor(e,t=new E){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function H(){let o=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=o?new k({token:o,model:e}):null;return new C(t)}var Oe=["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",r){let s=new Date().toISOString(),n=s.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,n),c=[];for(let m of Oe){let d=`${i}/${m}`,O=await this.storage.get(d);O&&(await this.storage.put(`${a}/${m}`,O,"application/json"),c.push(m))}if(c.length===0)return null;let p={version:1,id:n,projectId:e,createdAt:s,reason:t,objects:c,metadata:r};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(p,null,2),"application/json"),p}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),s=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),n=[];for(let i of s){let a=await this.storage.getText(i.key);if(a)try{n.push(JSON.parse(a))}catch{}}return n.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.getText(`${r}/snapshot.json`);if(!s)throw new Error(`Snapshot not found: ${t}`);let n=JSON.parse(s);if(n.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of n.objects){let p=await this.storage.get(`${r}/${c}`);p&&(await this.storage.put(`${i}/${c}`,p,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.list(r);for(let n of s)await this.storage.delete(n.key);return s.length}async prune(e,t=10){let s=(await this.list(e)).slice(t),n=0;for(let i of s)await this.remove(e,i.id),n++;return n}};function J(){let o=[],e=[];if((process.env.MEMORY_STORAGE_PROVIDER??"local")==="huggingface"){let s=["HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"];for(let n of s)process.env[n]||o.push(`Missing ${n}`);process.env.HF_TOKEN||e.push("HF_TOKEN missing: semantic embedding will use fallback")}return process.env.HF_EMBEDDING_MODEL||e.push("HF_EMBEDDING_MODEL not set; default model will be used"),{ok:o.length===0,errors:o,warnings:e}}import{randomUUID as _e}from"node:crypto";var R=class{constructor(e,t){this.storage=e;this.embeddings=t}storage;embeddings;async run(){let e=`_health/production-${_e()}.txt`,t=`toolnet-memory:${Date.now()}`,r=!1;try{await this.storage.put(e,t,"text/plain"),r=await this.storage.getText(e)===t}finally{try{await this.storage.delete(e)}catch{}}let s=null;if(this.embeddings)try{let n=await this.embeddings.embed("ToolNet Memory production health check");s={ok:n.length>0,dimensions:n.length,mode:n.length===384?"huggingface":"fallback-or-custom"}}catch{s={ok:!1,dimensions:0,mode:"failed"}}return{ok:r&&(s===null||s.ok),storage:{ok:r,provider:this.storage.name},embedding:s}}};async function Ie(){let o=J();o.ok||(console.log({ok:!1,config:o}),process.exit(1));let e=_(),t=new y().detect(),r=B(L({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3}),s=H(),n=await new R(r,s).run(),i=await new w(r).load(t.id),a=await new b(r).load(t.id),c=await new S(r).load(t.id),p=await new x(r).load(t.id),m=await new P(r).load(t.id),d=await new A(r).list(t.id);console.log({ok:n.ok,project:t.name,storage:n.storage,embedding:n.embedding,memory:i.length,graphSymbols:a?.symbols.length??0,graphEdges:a?.edges.length??0,memoryVectors:c?.records.length??0,codeChunks:p?.chunks.length??0,codeVectors:m?.records.length??0,snapshots:d.length,warnings:o.warnings}),n.ok||process.exit(1)}Ie().catch(o=>{console.error(o instanceof Error?o.message:o),process.exit(1)});
1
+ import"dotenv/config";import{existsSync as W,readFileSync as Z}from"node:fs";import{homedir as Q}from"node:os";import{join as q}from"node:path";function X(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 ee(){let r=process.env.TOOLNET_GLOBAL_ENV??q(Q(),".config","toolnet-memory",".env");if(!W(r))return;let e=Z(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let s=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=X(o.slice(n+1)))}}ee();function h(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function l(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function _(){return{memory:{autoCapture:h(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:h(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:h(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:h(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:l(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:l(process.env.MEMORY_RERANK_TOP,10),finalContext:l(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:l(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:l(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as te}from"node:crypto";import{existsSync as C,mkdirSync as re,readFileSync as oe,renameSync as ne,writeFileSync as se}from"node:fs";import{basename as ie,dirname as y,join as w,parse as N,resolve as u}from"node:path";var D=".toolnet",ae="project.json";function ce(r){return te("sha256").update(r).digest("hex").slice(0,16)}function T(r){return w(r,D,ae)}function pe(r){return C(T(r))}function de(r,e){let t=u(r),o=N(t).root;for(;;){if(pe(t))return t;if(t===o||e&&t===u(e))break;let n=y(t);if(n===t)break;t=n}return null}function me(r){let e=u(r),t=N(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(s=>C(w(e,s))))return e;if(e===t)break;let n=y(e);if(n===e)break;e=n}return u(r)}function ge(r){let e;try{e=JSON.parse(oe(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:y(y(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function $(r,e){let t=w(r,D);re(t,{recursive:!0});let o=T(r),n=`${o}.tmp-${process.pid}`;se(n,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ne(n,o)}function I(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 v=class{detect(e=process.cwd()){let t=u(e),o=me(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>C(w(o,d))),i=de(t,s?o:void 0);if(i){let d=T(i),m=ge(d);return m.rootPath!==i&&(m.rootPath=i,m.updatedAt=new Date().toISOString(),$(i,m)),I(m,i)}let a=new Date().toISOString(),c=ie(o),p={version:1,id:ce(o),name:c,remote:c,rootPath:o,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return $(o,p),I(p,o)}};import{homedir as Me}from"node:os";import{join as Ae}from"node:path";import{DeleteObjectCommand as le,GetObjectCommand as ue,HeadObjectCommand as fe,ListObjectsV2Command as he,PutObjectCommand as ye,S3Client as ve}from"@aws-sdk/client-s3";import{getSignedUrl as we}from"@aws-sdk/s3-request-presigner";var j=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ve({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ye({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await we(this.client,new ue({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new fe({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 le({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new he({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let s of n.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as V,mkdir as je,readFile as Se,readdir as be,rm as xe,stat as z,writeFile as Pe}from"node:fs/promises";import{dirname as ke,join as Ee,relative as K,resolve as Re}from"node:path";var f=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Re(this.root,t)}async put(e,t){let o=this.path(e);await je(ke(o),{recursive:!0}),await Pe(o,t)}async get(e){try{return await Se(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 V(this.path(e)),!0}catch{return!1}}async delete(e){await xe(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await V(t)}catch{return o}let n=async i=>{let a=await be(i,{withFileTypes:!0});for(let c of a){let p=Ee(i,c.name);if(c.isDirectory()){await n(p);continue}let d=await z(p);o.push({key:K(this.root,p),size:d.size,updatedAt:d.mtime.toISOString()})}},s=await z(t);return s.isDirectory()?await n(t):o.push({key:K(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),o}};function L(r){let e=r.localRoot??Ae(Me(),".toolnet-memory","storage");if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new j({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new f(e))}return new f(e)}var S=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};var b=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"vectors","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return null;let o=JSON.parse(t);if(o.version!==1||o.projectId!==e||!Array.isArray(o.records))throw new Error("Invalid vector snapshot");return o}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};var x=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 P=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 k=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 Ce(r){return new Promise(e=>setTimeout(e,r))}async function F(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,s;for(let i=1;i<=t;i++)try{return await r()}catch(a){if(s=a,i>=t)break;let c=Math.min(n,o*2**(i-1)),p=Math.floor(Math.random()*Math.max(1,c*.2));await Ce(c+p)}throw s}var Te=new Set(["put","get","getText","delete","list"]);function B(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:Te.has(o)?(...s)=>F(()=>Promise.resolve(n.apply(t,s)),e):n.bind(t)}})}var E=class{constructor(e){this.options=e}options;name="huggingface";dimensions=384;async embed(e){let[t]=await this.embedMany([e]);return t}async embedMany(e){if(e.length===0)return[];let t=`https://router.huggingface.co/hf-inference/models/${this.options.model}/pipeline/feature-extraction`,o=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${this.options.token}`,"Content-Type":"application/json"},body:JSON.stringify({inputs:e,options:{wait_for_model:!0}})});if(!o.ok)throw new Error(`HF embedding failed: ${o.status} ${await o.text()}`);let n=await o.json();if(!Array.isArray(n))throw new Error("HF embedding returned invalid response");return n.map(s=>Oe(s))}};function Oe(r){if(!Array.isArray(r))throw new Error("Invalid embedding");if(r.length>0&&typeof r[0]=="number")return r;if(r.length>0&&Array.isArray(r[0])){let e=r;if(e.length===0)return[];let t=e[0].length,o=new Array(t).fill(0);for(let n of e)for(let s=0;s<t;s++)o[s]+=n[s]??0;for(let n=0;n<t;n++)o[n]/=e.length;return o}throw new Error("Unsupported embedding shape")}import{createHash as _e}from"node:crypto";var R=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),o=e.toLowerCase().split(/\s+/).filter(Boolean);for(let n of o){let i=_e("sha256").update(n).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return $e(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function $e(r){let e=Math.sqrt(r.reduce((t,o)=>t+o*o,0));return e===0?r:r.map(t=>t/e)}var O=class{constructor(e,t=new R){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function J(){let r=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=r?new E({token:r,model:e}):null;return new O(t)}var Ie=["memories/current.json","vectors/current.json","graph/current.json","graph/manifest.json","graph/resolution/current.json","code/chunks/current.json","code/vectors/current.json","code/architecture/current.json","code/architecture/entry-points.json","code/architecture/hotspots.json","code/architecture/layers.json","code/architecture/clusters.json","code/analysis/current.json","code/analysis/dead-code.json","code/analysis/dependencies.json","code/visualization/graph.json"],M=class{constructor(e){this.storage=e}storage;projectPrefix(e){return`projects/${e}`}snapshotPrefix(e,t){return[this.projectPrefix(e),"snapshots",t].join("/")}async create(e,t="automatic",o){let n=new Date().toISOString(),s=n.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,s),c=[];for(let d of Ie){let m=`${i}/${d}`,g=await this.storage.get(m);g&&(await this.storage.put(`${a}/${d}`,g,"application/json"),c.push(d))}if(c.length===0)return null;let p={version:1,id:s,projectId:e,createdAt:n,reason:t,objects:c,metadata:o};return await this.storage.put(`${a}/snapshot.json`,JSON.stringify(p,null,2),"application/json"),p}async list(e){let t=[this.projectPrefix(e),"snapshots"].join("/"),n=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),s=[];for(let i of n){let a=await this.storage.getText(i.key);if(a)try{s.push(JSON.parse(a))}catch{}}return s.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.getText(`${o}/snapshot.json`);if(!n)throw new Error(`Snapshot not found: ${t}`);let s=JSON.parse(n);if(s.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of s.objects){let p=await this.storage.get(`${o}/${c}`);p&&(await this.storage.put(`${i}/${c}`,p,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let o=this.snapshotPrefix(e,t),n=await this.storage.list(o);for(let s of n)await this.storage.delete(s.key);return n.length}async prune(e,t=10){let n=(await this.list(e)).slice(t),s=0;for(let i of n)await this.remove(e,i.id),s++;return s}};function H(){let r=[],e=[];if((process.env.MEMORY_STORAGE_PROVIDER??"local")==="huggingface"){let n=["HF_NAMESPACE","HF_BUCKET","HF_S3_ACCESS_KEY_ID","HF_S3_SECRET_ACCESS_KEY"];for(let s of n)process.env[s]||r.push(`Missing ${s}`);process.env.HF_TOKEN||e.push("HF_TOKEN missing: semantic embedding will use fallback")}return process.env.HF_EMBEDDING_MODEL||e.push("HF_EMBEDDING_MODEL not set; default model will be used"),{ok:r.length===0,errors:r,warnings:e}}import{randomUUID as Ne}from"node:crypto";var A=class{constructor(e,t){this.storage=e;this.embeddings=t}storage;embeddings;async run(){let e=`_health/production-${Ne()}.txt`,t=`toolnet-memory:${Date.now()}`,o=!1;try{await this.storage.put(e,t,"text/plain"),o=await this.storage.getText(e)===t}finally{try{await this.storage.delete(e)}catch{}}let n=null;if(this.embeddings)try{let s=await this.embeddings.embed("ToolNet Memory production health check");n={ok:s.length>0,dimensions:s.length,mode:s.length===384?"huggingface":"fallback-or-custom"}}catch{n={ok:!1,dimensions:0,mode:"failed"}}return{ok:o&&(n===null||n.ok),storage:{ok:o,provider:this.storage.name},embedding:n}}};function G(){return process.argv.includes("--json")}function De(r){if(console.log(""),console.log("ToolNet Memory Doctor"),console.log("====================="),console.log(""),r.project&&(console.log(`Project: ${r.project}`),console.log("")),r.storage)if(r.storage.ok){let n=typeof r.storage.provider=="string"?` (${r.storage.provider})`:"";console.log(`\u2713 Storage${n}`)}else console.log("\u2717 Storage");if(r.embedding)if(r.embedding.ok){let n=[];typeof r.embedding.mode=="string"&&n.push(r.embedding.mode),typeof r.embedding.dimensions=="number"&&n.push(`${r.embedding.dimensions} dimensions`),console.log(`\u2713 Embedding${n.length?` (${n.join(", ")})`:""}`)}else console.log("\u2717 Embedding");(r.memory!==void 0||r.graphSymbols!==void 0||r.codeChunks!==void 0)&&(console.log(""),console.log("Project data:"),r.memory!==void 0&&console.log(` Memories ${r.memory}`),r.graphSymbols!==void 0&&console.log(` Graph symbols ${r.graphSymbols}`),r.graphEdges!==void 0&&console.log(` Graph edges ${r.graphEdges}`),r.memoryVectors!==void 0&&console.log(` Memory vectors ${r.memoryVectors}`),r.codeChunks!==void 0&&console.log(` Code chunks ${r.codeChunks}`),r.codeVectors!==void 0&&console.log(` Code vectors ${r.codeVectors}`),r.snapshots!==void 0&&console.log(` Snapshots ${r.snapshots}`));let e=r.config?.errors??[];if(e.length>0){console.log(""),console.log("Configuration required:");for(let n of e)console.log(` - ${n}`)}let t=[...r.config?.warnings??[],...r.warnings??[]],o=[...new Set(t)];if(o.length>0){console.log(""),console.log("Warnings:");for(let n of o)console.log(` - ${n}`)}console.log(""),r.ok?console.log("\u2713 ToolNet Memory is ready"):(console.log("\u2717 ToolNet Memory requires attention"),e.length>0&&(console.log(""),console.log("Run:"),console.log(" toolnet-memory setup"))),console.log("")}function U(r){G()?console.log(JSON.stringify(r,null,2)):De(r)}async function Ve(){let r=H();if(!r.ok){let Y={ok:!1,config:r,warnings:r.warnings};U(Y),process.exitCode=1;return}let e=_(),t=new v().detect(),o=B(L({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3}),n=J(),s=await new A(o,n).run(),i=await new S(o).load(t.id),a=await new x(o).load(t.id),c=await new b(o).load(t.id),p=await new P(o).load(t.id),d=await new k(o).load(t.id),m=await new M(o).list(t.id),g={ok:s.ok,project:t.name,storage:s.storage,embedding:s.embedding,memory:i.length,graphSymbols:a?.symbols.length??0,graphEdges:a?.edges.length??0,memoryVectors:c?.records.length??0,codeChunks:p?.chunks.length??0,codeVectors:d?.records.length??0,snapshots:m.length,warnings:r.warnings};U(g),process.exitCode=g.ok?0:1}Ve().catch(r=>{let e=r instanceof Error?r.message:String(r);G()?console.log(JSON.stringify({ok:!1,error:e},null,2)):(console.error(""),console.error("ToolNet Memory Doctor"),console.error("====================="),console.error(""),console.error(`\u2717 ${e}`),console.error("")),process.exitCode=1});
@@ -0,0 +1,4 @@
1
+ import"dotenv/config";import{existsSync as ne,readFileSync as ie}from"node:fs";import{homedir as ae}from"node:os";import{join as ce}from"node:path";function le(s){let e=s.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 de(){let s=process.env.TOOLNET_GLOBAL_ENV??ce(ae(),".config","toolnet-memory",".env");if(!ne(s))return;let e=ie(s,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let n=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=le(r.slice(o+1)))}}de();function L(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function v(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function W(){return{memory:{autoCapture:L(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:L(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:L(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:L(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:v(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:v(process.env.MEMORY_RERANK_TOP,10),finalContext:v(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:v(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:v(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as pe}from"node:crypto";import{existsSync as _,mkdirSync as me,readFileSync as fe,renameSync as ue,writeFileSync as ge}from"node:fs";import{basename as he,dirname as N,join as M,parse as U,resolve as w}from"node:path";var J=".toolnet",ye="project.json";function Se(s){return pe("sha256").update(s).digest("hex").slice(0,16)}function $(s){return M(s,J,ye)}function be(s){return _($(s))}function xe(s,e){let t=w(s),r=U(t).root;for(;;){if(be(t))return t;if(t===r||e&&t===w(e))break;let o=N(t);if(o===t)break;t=o}return null}function Ce(s){let e=w(s),t=U(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>_(M(e,n))))return e;if(e===t)break;let o=N(e);if(o===e)break;e=o}return w(s)}function Ee(s){let e;try{e=JSON.parse(fe(s,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${s}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);let r=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:N(N(s)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 H(s,e){let t=M(s,J);me(t,{recursive:!0});let r=$(s),o=`${r}.tmp-${process.pid}`;ge(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ue(o,r)}function V(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var A=class{detect(e=process.cwd()){let t=w(e),r=Ce(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>_(M(r,p))),i=xe(t,n?r:void 0);if(i){let p=$(i),d=Ee(p);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),H(i,d)),V(d,i)}let l=new Date().toISOString(),f=he(r),c={version:1,id:Se(r),name:f,remote:f,rootPath:r,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return H(r,c),V(c,r)}};import{readdir as Te}from"node:fs/promises";import{extname as ke,join as je,relative as Le}from"node:path";import{basename as we}from"node:path";var Pe=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Re=new Set([".pem",".key",".p12",".pfx"]);function q(s){let e=we(s).toLowerCase();if(Pe.has(e))return!0;for(let t of Re)if(e.endsWith(t))return!0;return!1}var Ne=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Ae=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function G(s){let e=[];async function t(r){let o=await Te(r,{withFileTypes:!0});for(let n of o){if(Ae.has(n.name))continue;let i=je(r,n.name);if(n.isDirectory()){await t(i);continue}Ne.has(ke(n.name))&&(q(i)||e.push(Le(s,i)))}}return await t(s),e.sort()}import{readFile as Me}from"node:fs/promises";import{join as Ie}from"node:path";import{createHash as Oe}from"node:crypto";import g from"typescript";function Y(s,e){return Oe("sha256").update(`${s}:${e}`).digest("hex").slice(0,24)}function D(s,e){return s.getLineAndCharacterOfPosition(e.getStart(s)).line+1}async function z(s,e,t){let r=Ie(e,t),o=await Me(r,"utf8"),n=g.createSourceFile(t,o,g.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?g.ScriptKind.TSX:g.ScriptKind.TS),i=[],l=[],f=[],c=[],p={id:Y(s,`file:${t}`),projectId:s,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:n.getLineAndCharacterOfPosition(n.end).line+1};i.push(p);let d=[],S=[];function y(a,h,u,m){let x=Y(s,`${t}:${u}:${m??h}:${a.pos}`);return i.push({id:x,projectId:s,name:h,qualifiedName:m??h,type:u,filePath:t,startLine:D(n,a),endLine:n.getLineAndCharacterOfPosition(a.end).line+1}),x}function j(a){if(!g.isStringLiteral(a.moduleSpecifier))return;let h=[],u=a.importClause;if(u?.name&&h.push({localName:u.name.text,importedName:"default",kind:"default"}),u?.namedBindings&&g.isNamedImports(u.namedBindings))for(let m of u.namedBindings.elements)h.push({localName:m.name.text,importedName:m.propertyName?.text??m.name.text,kind:"named"});u?.namedBindings&&g.isNamespaceImport(u.namedBindings)&&h.push({localName:u.namedBindings.name.text,importedName:"*",kind:"namespace"}),l.push({source:a.moduleSpecifier.text,bindings:h})}function E(a,h){for(let u of a.heritageClauses??[])for(let m of u.types){let x=m.expression.getText(n).split(".").at(-1)??"";x&&c.push({fromId:h,targetName:x,type:u.token===g.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function K(a){let h=!1,u=!1;if(g.isImportDeclaration(a)&&j(a),g.isInterfaceDeclaration(a)&&y(a,a.name.text,"interface",a.name.text),g.isClassDeclaration(a)&&a.name){let m=y(a,a.name.text,"class",a.name.text);E(a,m),S.push({id:m,name:a.name.text}),u=!0}if(g.isFunctionDeclaration(a)&&a.name){let m=y(a,a.name.text,"function",a.name.text);d.push(m),h=!0}if(g.isMethodDeclaration(a)&&a.name){let m=a.name.getText(n),x=S.at(-1)?.name,oe=y(a,m,"method",x?`${x}.${m}`:m);d.push(oe),h=!0}if(g.isCallExpression(a)&&(g.isIdentifier(a.expression)&&f.push({callerId:d.at(-1),calleeName:a.expression.text,line:D(n,a)}),g.isPropertyAccessExpression(a.expression))){let m=a.expression;f.push({callerId:d.at(-1),qualifier:m.expression.getText(n),calleeName:m.name.text,line:D(n,a)})}g.forEachChild(a,K),h&&d.pop(),u&&S.pop()}return K(n),{filePath:t,symbols:i,imports:l,calls:f,heritage:c}}import{createHash as Fe}from"node:crypto";import{dirname as _e,extname as $e,normalize as Ge,posix as De}from"node:path";var P=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(r=>r.projectId===e&&(r.name===t||r.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 r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};function ze(s,e,t,r){return Fe("sha256").update(`${s}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function C(s){return Ge(s).replaceAll("\\","/")}function B(s,e,t){if(!e.startsWith("."))return;let r=C(De.join(_e(s),e)),o=$e(r),n;if(o===".js"){let i=r.slice(0,-3);n=[`${i}.ts`,`${i}.tsx`,`${i}.js`,`${i}.jsx`]}else if(o===".mjs"){let i=r.slice(0,-4);n=[`${i}.mts`,`${i}.ts`,`${i}.mjs`]}else if(o===".cjs"){let i=r.slice(0,-4);n=[`${i}.cts`,`${i}.ts`,`${i}.cjs`]}else o?n=[r]:n=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.js`,`${r}/index.jsx`];return n.find(i=>t.has(C(i)))}var R=class{build(e,t){let r=new P,o=new Map;for(let i of t)for(let l of i.symbols)r.addSymbol(l),l.type==="file"&&o.set(C(i.filePath),l);let n=new Set(o.keys());for(let i of t){let l=C(i.filePath),f=o.get(l);if(f){for(let c of i.symbols)c.id!==f.id&&r.addEdge(this.edge(e,f.id,"DEFINES",c.id));for(let c of i.imports){let p=B(l,c.source,n);if(!p)continue;let d=o.get(p);d&&r.addEdge(this.edge(e,f.id,"IMPORTS",d.id,{source:c.source}))}for(let c of i.heritage){let p=r.findByName(e,c.targetName).filter(d=>d.type==="class"||d.type==="interface");for(let d of p)r.addEdge(this.edge(e,c.fromId,c.type,d.id))}for(let c of i.calls){if(!c.callerId)continue;let p=this.resolveCallTargets(e,i,c.calleeName,c.qualifier,t,r,n);for(let d of p)d.id!==c.callerId&&r.addEdge(this.edge(e,c.callerId,"CALLS",d.id,{line:c.line,qualifier:c.qualifier}))}}}return r}resolveCallTargets(e,t,r,o,n,i,l){let f=C(t.filePath),c=i.findByName(e,r).filter(p=>C(p.filePath)===f);if(!o&&c.length)return c;if(o)for(let p of t.imports){if(!p.bindings.find(y=>y.kind==="namespace"&&y.localName===o))continue;let S=B(f,p.source,l);if(S)return i.findByName(e,r).filter(y=>C(y.filePath)===S)}for(let p of t.imports){let d=p.bindings.find(E=>E.localName===r);if(!d)continue;let S=B(f,p.source,l);if(!S)continue;let y=d.importedName==="default"?r:d.importedName,j=i.findByName(e,y).filter(E=>C(E.filePath)===S);if(j.length)return j}return i.findByName(e,r).filter(p=>p.type==="function"||p.type==="method")}edge(e,t,r,o,n){return{id:ze(e,t,r,o),projectId:e,from:t,to:o,type:r,metadata:n}}};var I=class{async index(e,t){let r=await G(t),o=[];for(let i of r)try{o.push(await z(e,t,i))}catch(l){console.warn(`[indexer] skipped ${i}:`,l instanceof Error?l.message:l)}let n=new R().build(e,o);return{files:o.length,symbols:n.allSymbols(e).length,edges:n.allEdges(e).length,graph:n}}};function Z(s,e){let t=s.allSymbols(e),r=s.allEdges(e),o=i=>t.filter(l=>l.type===i).length,n=i=>r.filter(l=>l.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:r.length,calls:n("CALLS"),callReferences:n("CALL_REFERENCE"),imports:n("IMPORTS"),inherits:n("INHERITS"),implements:n("IMPLEMENTS"),usesType:n("USES_TYPE"),tests:n("TESTS"),routeEdges:n("ROUTE"),writes:n("WRITES")}}import{execFile as Be}from"node:child_process";import{promisify as Ke}from"node:util";var Sr=Ke(Be);var T=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"graph","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));return t?JSON.parse(t):null}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};import ks from"typescript";import b from"typescript";var Is=new Set([b.SyntaxKind.EqualsToken,b.SyntaxKind.PlusEqualsToken,b.SyntaxKind.MinusEqualsToken,b.SyntaxKind.AsteriskEqualsToken,b.SyntaxKind.SlashEqualsToken,b.SyntaxKind.PercentEqualsToken,b.SyntaxKind.QuestionQuestionEqualsToken,b.SyntaxKind.AmpersandAmpersandEqualsToken,b.SyntaxKind.BarBarEqualsToken]);import{homedir as it}from"node:os";import{join as at}from"node:path";import{DeleteObjectCommand as He,GetObjectCommand as Ve,HeadObjectCommand as Ue,ListObjectsV2Command as Je,PutObjectCommand as qe,S3Client as Ye}from"@aws-sdk/client-s3";import{getSignedUrl as Ze}from"@aws-sdk/s3-request-presigner";var O=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ye({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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new qe({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Ze(this.client,new Ve({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 Ue({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 He({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Je({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as Q,mkdir as Qe,readFile as Xe,readdir as et,rm as tt,stat as X,writeFile as rt}from"node:fs/promises";import{dirname as st,join as ot,relative as ee,resolve as nt}from"node:path";var k=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return nt(this.root,t)}async put(e,t){let r=this.path(e);await Qe(st(r),{recursive:!0}),await rt(r,t)}async get(e){try{return await Xe(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 Q(this.path(e)),!0}catch{return!1}}async delete(e){await tt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await Q(t)}catch{return r}let o=async i=>{let l=await et(i,{withFileTypes:!0});for(let f of l){let c=ot(i,f.name);if(f.isDirectory()){await o(c);continue}let p=await X(c);r.push({key:ee(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},n=await X(t);return n.isDirectory()?await o(t):r.push({key:ee(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function te(s){let e=s.localRoot??at(it(),".toolnet-memory","storage");if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new O({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new k(e))}return new k(e)}function re(s){let e=s.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function se(s){let e=s.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[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 F=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=re(o??r),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(),r=t,o=await this.provider.getText(e);if(o){let i;try{i=JSON.parse(o)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}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"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=se(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}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))}};async function ct(){let s=W(),e=new A().detect(),t=te({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),r=new F(t,e.id,e.name,e.remote??e.name),o=await new I().index(e.id,e.rootPath),n=Z(o.graph,e.id);await new T(r).save({version:1,projectId:e.id,updatedAt:new Date().toISOString(),files:o.files,symbols:o.graph.allSymbols(e.id),edges:o.graph.allEdges(e.id)}),console.log({ok:!0,storage:r.name,...n})}ct().catch(s=>{console.error(s),process.exit(1)});
@@ -0,0 +1,4 @@
1
+ import"dotenv/config";import{existsSync as X,readFileSync as ee}from"node:fs";import{homedir as te}from"node:os";import{join as re}from"node:path";function se(s){let e=s.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 oe(){let s=process.env.TOOLNET_GLOBAL_ENV??re(te(),".config","toolnet-memory",".env");if(!X(s))return;let e=ee(s,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let n=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=se(r.slice(o+1)))}}oe();function x(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function g(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function F(){return{memory:{autoCapture:x(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:x(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:x(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:x(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:g(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:g(process.env.MEMORY_RERANK_TOP,10),finalContext:g(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:g(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:g(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ne}from"node:crypto";import{existsSync as A,mkdirSync as ie,readFileSync as ae,renameSync as ce,writeFileSync as le}from"node:fs";import{basename as de,dirname as C,join as v,parse as $,resolve as h}from"node:path";var G=".toolnet",pe="project.json";function me(s){return ne("sha256").update(s).digest("hex").slice(0,16)}function M(s){return v(s,G,pe)}function fe(s){return A(M(s))}function ue(s,e){let t=h(s),r=$(t).root;for(;;){if(fe(t))return t;if(t===r||e&&t===h(e))break;let o=C(t);if(o===t)break;t=o}return null}function ge(s){let e=h(s),t=$(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>A(v(e,n))))return e;if(e===t)break;let o=C(e);if(o===e)break;e=o}return h(s)}function he(s){let e;try{e=JSON.parse(ae(s,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${s}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);let r=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:C(C(s)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 O(s,e){let t=v(s,G);ie(t,{recursive:!0});let r=M(s),o=`${r}.tmp-${process.pid}`;le(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ce(o,r)}function _(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var E=class{detect(e=process.cwd()){let t=h(e),r=ge(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>A(v(r,l))),i=ue(t,n?r:void 0);if(i){let l=M(i),p=he(l);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),O(i,p)),_(p,i)}let d=new Date().toISOString(),c=de(r),a={version:1,id:me(r),name:c,remote:c,rootPath:r,createdAt:d,updatedAt:d,graphVersion:0,memoryVersion:0};return O(r,a),_(a,r)}};import{homedir as Me}from"node:os";import{join as Ie}from"node:path";import{DeleteObjectCommand as Se,GetObjectCommand as be,HeadObjectCommand as xe,ListObjectsV2Command as Ce,PutObjectCommand as Ee,S3Client as ve}from"@aws-sdk/client-s3";import{getSignedUrl as we}from"@aws-sdk/s3-request-presigner";var w=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new ve({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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ee({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await we(this.client,new be({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 xe({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 Se({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Ce({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as D,mkdir as Pe,readFile as Re,readdir as Te,rm as ke,stat as z,writeFile as je}from"node:fs/promises";import{dirname as Le,join as Ne,relative as B,resolve as Ae}from"node:path";var y=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ae(this.root,t)}async put(e,t){let r=this.path(e);await Pe(Le(r),{recursive:!0}),await je(r,t)}async get(e){try{return await Re(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 D(this.path(e)),!0}catch{return!1}}async delete(e){await ke(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await D(t)}catch{return r}let o=async i=>{let d=await Te(i,{withFileTypes:!0});for(let c of d){let a=Ne(i,c.name);if(c.isDirectory()){await o(a);continue}let l=await z(a);r.push({key:B(this.root,a),size:l.size,updatedAt:l.mtime.toISOString()})}},n=await z(t);return n.isDirectory()?await o(t):r.push({key:B(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function K(s){let e=s.localRoot??Ie(Me(),".toolnet-memory","storage");if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new w({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new y(e))}return new y(e)}var S=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")}};function Fe(s){return new Promise(e=>setTimeout(e,s))}async function W(s,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,o=e.maxDelayMs??2e3,n;for(let i=1;i<=t;i++)try{return await s()}catch(d){if(n=d,i>=t)break;let c=Math.min(o,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await Fe(c+a)}throw n}var Oe=new Set(["put","get","getText","delete","list"]);function H(s,e={}){return new Proxy(s,{get(t,r){let o=Reflect.get(t,r,t);return typeof o!="function"?o:Oe.has(r)?(...n)=>W(()=>Promise.resolve(o.apply(t,n)),e):o.bind(t)}})}function V(s){let e=s.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function U(s){let e=s.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[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 P=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=V(o??r),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(),r=t,o=await this.provider.getText(e);if(o){let i;try{i=JSON.parse(o)}catch(d){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${d instanceof Error?d.message:String(d)}`)}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"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=U(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import Fr from"typescript";var u=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(r=>r.projectId===e&&(r.name===t||r.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 r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};function De(s,e){return e.ranges.length===0?!0:typeof s.startLine!="number"||typeof s.endLine!="number"?!1:e.ranges.some(t=>s.startLine<=t.endLine&&s.endLine>=t.startLine)}var R=class{constructor(e){this.graph=e}graph;map(e,t){let r=this.graph.allSymbols(e),o=[];for(let n of t){let i=r.filter(a=>a.filePath===n.filePath),c=i.filter(a=>a.type!=="file").filter(a=>De(a,n));if(c.length===0){let a=i.find(l=>l.type==="file");a&&o.push({symbol:a,fileStatus:n.status,direct:!0});continue}for(let a of c)o.push({symbol:a,fileStatus:n.status,direct:!0})}return o}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var ze={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function Be(s){return s>=30?"CRITICAL":s>=16?"HIGH":s>=6?"MEDIUM":"LOW"}function J(s){let e=s.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var T=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let o=this.graph.allEdges(e),n=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 p=new Set([l.symbol.id]),j=[{id:l.symbol.id,depth:0}];for(;j.length;){let L=j.shift();if(L.depth>=r)continue;let Y=o.filter(f=>f.to===L.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(f.type));for(let f of Y){if(p.has(f.from))continue;p.add(f.from);let b=this.graph.getSymbol(f.from);if(!b)continue;let N=L.depth+1,Z=`${l.symbol.id}:${b.id}`;n.set(Z,{symbol:b,relation:f.type,depth:N,sourceSymbolId:l.symbol.id});let Q=ze[f.type]??1;i+=Math.max(1,Q-(N-1)),j.push({id:b.id,depth:N})}}}let d=[...n.values()].sort((l,p)=>l.depth-p.depth),c=[...new Set(d.map(l=>l.symbol.filePath))],a=c.filter(J);return a.length===0&&a.push(...c.filter(l=>!J(l)).slice(0,10)),{risk:Be(i),riskScore:i,changedSymbols:t,impacted:d,impactedFiles:c,suggestedTests:a}}};import{execFile as Ke}from"node:child_process";import{promisify as We}from"node:util";var I=We(Ke);function He(s){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let r of s.matchAll(t)){let o=Number(r[1]),n=Number(r[2]??1);e.push({startLine:o,endLine:Math.max(o,o+n-1)})}return e}function Ve(s){return s.startsWith("A")?"added":s.startsWith("D")?"deleted":s.startsWith("R")?"renamed":"modified"}async function q(s){let e="";try{e=(await I("git",["diff","HEAD","--name-status","--no-renames"],{cwd:s,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let r of e.split(/\r?\n/).filter(Boolean)){let[o,...n]=r.split(" "),i=n.at(-1);if(!i)continue;let d="";try{d=(await I("git",["diff","HEAD","--unified=0","--",i],{cwd:s,maxBuffer:20971520})).stdout}catch{d=""}t.push({filePath:i,status:Ve(o),ranges:He(d)})}try{let r=await I("git",["ls-files","--others","--exclude-standard"],{cwd:s});for(let o of r.stdout.split(/\r?\n/).filter(Boolean))t.some(n=>n.filePath===o)||t.push({filePath:o,status:"added",ranges:[]})}catch{}return t}var k=class{constructor(e){this.graph=e;this.mapper=new R(e),this.blast=new T(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let o=await q(t),n=this.mapper.map(e,o),i=this.blast.analyze(e,n,r.maxDepth??4);return{mode:"git_diff",changes:o,...i}}analyzeFile(e,t,r={}){let o=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,o,r.maxDepth??4)}}};import eo from"typescript";import m from"typescript";var io=new Set([m.SyntaxKind.EqualsToken,m.SyntaxKind.PlusEqualsToken,m.SyntaxKind.MinusEqualsToken,m.SyntaxKind.AsteriskEqualsToken,m.SyntaxKind.SlashEqualsToken,m.SyntaxKind.PercentEqualsToken,m.SyntaxKind.QuestionQuestionEqualsToken,m.SyntaxKind.AmpersandAmpersandEqualsToken,m.SyntaxKind.BarBarEqualsToken]);async function Je(){let s=F(),e=new E().detect(),t=H(K({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),{attempts:3}),r=new P(t,e.id,e.name,e.remote??e.name),o=await new S(r).load(e.id);if(!o)throw new Error("Code graph missing");let n=new u;n.import(o.symbols,o.edges);let i=new k(n),d=process.argv[2],c=d?i.analyzeFile(e.id,d):await i.analyzeGitDiff(e.id,e.rootPath);console.log({risk:c.risk,riskScore:c.riskScore,changedSymbols:c.changedSymbols.map(a=>({symbol:a.symbol.qualifiedName,file:a.symbol.filePath,type:a.symbol.type})),impactedFiles:c.impactedFiles,suggestedTests:c.suggestedTests,impactedCount:c.impacted.length})}Je().catch(s=>{console.error(s),process.exit(1)});
@@ -0,0 +1,4 @@
1
+ import"dotenv/config";import{existsSync as ae,readFileSync as ce}from"node:fs";import{homedir as de}from"node:os";import{join as pe}from"node:path";function me(o){let e=o.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 le(){let o=process.env.TOOLNET_GLOBAL_ENV??pe(de(),".config","toolnet-memory",".env");if(!ae(o))return;let e=ce(o,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let i=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=me(r.slice(s+1)))}}le();function C(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function R(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function K(){return{memory:{autoCapture:C(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:C(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:C(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:C(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:R(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:R(process.env.MEMORY_RERANK_TOP,10),finalContext:R(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:R(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:R(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ge}from"node:crypto";import{existsSync as F,mkdirSync as ue,readFileSync as fe,renameSync as ye,writeFileSync as he}from"node:fs";import{basename as Se,dirname as E,join as T,parse as J,resolve as k}from"node:path";var H=".toolnet",ve="project.json";function xe(o){return ge("sha256").update(o).digest("hex").slice(0,16)}function L(o){return T(o,H,ve)}function je(o){return F(L(o))}function be(o,e){let t=k(o),r=J(t).root;for(;;){if(je(t))return t;if(t===r||e&&t===k(e))break;let s=E(t);if(s===t)break;t=s}return null}function we(o){let e=k(o),t=J(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>F(T(e,i))))return e;if(e===t)break;let s=E(e);if(s===e)break;e=s}return k(o)}function Pe(o){let e;try{e=JSON.parse(fe(o,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${o}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${o}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${o}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${o}`);let r=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:E(E(o)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 V(o,e){let t=T(o,H);ue(t,{recursive:!0});let r=L(o),s=`${r}.tmp-${process.pid}`;he(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ye(s,r)}function G(o,e){return{id:o.id,name:o.name,remote:o.remote,rootPath:e,createdAt:o.createdAt,updatedAt:o.updatedAt,graphVersion:o.graphVersion,memoryVersion:o.memoryVersion,metadata:o.metadata}}var A=class{detect(e=process.cwd()){let t=k(e),r=we(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>F(T(r,p))),n=be(t,i?r:void 0);if(n){let p=L(n),l=Pe(p);return l.rootPath!==n&&(l.rootPath=n,l.updatedAt=new Date().toISOString(),V(n,l)),G(l,n)}let m=new Date().toISOString(),d=Se(r),c={version:1,id:xe(r),name:d,remote:d,rootPath:r,createdAt:m,updatedAt:m,graphVersion:0,memoryVersion:0};return V(r,c),G(c,r)}};import{homedir as ze}from"node:os";import{join as Be}from"node:path";import{DeleteObjectCommand as Re,GetObjectCommand as ke,HeadObjectCommand as Me,ListObjectsV2Command as Ce,PutObjectCommand as Ee,S3Client as Ae}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var I=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ae({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,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ee({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await Te(this.client,new ke({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 Me({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 Re({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new Ce({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as U,mkdir as Ie,readFile as Oe,readdir as $e,rm as Ne,stat as W,writeFile as _e}from"node:fs/promises";import{dirname as De,join as Fe,relative as Y,resolve as Le}from"node:path";var M=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Le(this.root,t)}async put(e,t){let r=this.path(e);await Ie(De(r),{recursive:!0}),await _e(r,t)}async get(e){try{return await Oe(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 U(this.path(e)),!0}catch{return!1}}async delete(e){await Ne(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await U(t)}catch{return r}let s=async n=>{let m=await $e(n,{withFileTypes:!0});for(let d of m){let c=Fe(n,d.name);if(d.isDirectory()){await s(c);continue}let p=await W(c);r.push({key:Y(this.root,c),size:p.size,updatedAt:p.mtime.toISOString()})}},i=await W(t);return i.isDirectory()?await s(t):r.push({key:Y(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),r}};function Z(o){let e=o.localRoot??Be(ze(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new I({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new M(e))}return new M(e)}var O=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 $=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")}};function X(o){let e=o.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Q(o){let e=o.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var N=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=X(s??r),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(),r=t,s=await this.provider.getText(e);if(s){let n;try{n=JSON.parse(s)}catch(m){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${m instanceof Error?m.message:String(m)}`)}if(typeof n.id=="string"&&n.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${n.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof n.createdAt=="string"&&(r=n.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Q(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as qe}from"node:path";import{readdir as Je}from"node:fs/promises";import{extname as He,join as Ue,relative as We}from"node:path";import{basename as Ke}from"node:path";var Ve=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Ge=new Set([".pem",".key",".p12",".pfx"]);function q(o){let e=Ke(o).toLowerCase();if(Ve.has(e))return!0;for(let t of Ge)if(e.endsWith(t))return!0;return!1}var Ye=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Ze=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function ee(o){let e=[];async function t(r){let s=await Je(r,{withFileTypes:!0});for(let i of s){if(Ze.has(i.name))continue;let n=Ue(r,i.name);if(i.isDirectory()){await t(n);continue}Ye.has(He(i.name))&&(q(n)||e.push(We(o,n)))}}return await t(o),e.sort()}import{createHash as Xe}from"node:crypto";import{readFile as Qe}from"node:fs/promises";async function te(o){let e=await Qe(o);return Xe("sha256").update(e).digest("hex")}async function re(o,e){let t=await ee(e),r={};for(let s of t)r[s]={path:s,hash:await te(qe(e,s))};return{version:1,projectId:o,updatedAt:new Date().toISOString(),files:r}}function oe(o,e){let t=o?.files??{},r=e.files,s=[],i=[],n=[],m=[];for(let[d,c]of Object.entries(r)){let p=t[d];p?p.hash!==c.hash?i.push(d):m.push(d):s.push(d)}for(let d of Object.keys(t))r[d]||n.push(d);return{added:s.sort(),modified:i.sort(),deleted:n.sort(),unchanged:m.sort()}}import{readFile as et}from"node:fs/promises";import{join as tt}from"node:path";import{createHash as rt}from"node:crypto";import h from"typescript";function se(o,e){return rt("sha256").update(`${o}:${e}`).digest("hex").slice(0,24)}function z(o,e){return o.getLineAndCharacterOfPosition(e.getStart(o)).line+1}async function ne(o,e,t){let r=tt(e,t),s=await et(r,"utf8"),i=h.createSourceFile(t,s,h.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?h.ScriptKind.TSX:h.ScriptKind.TS),n=[],m=[],d=[],c=[],p={id:se(o,`file:${t}`),projectId:o,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:i.getLineAndCharacterOfPosition(i.end).line+1};n.push(p);let l=[],v=[];function f(a,S,y,u){let j=se(o,`${t}:${y}:${u??S}:${a.pos}`);return n.push({id:j,projectId:o,name:S,qualifiedName:u??S,type:y,filePath:t,startLine:z(i,a),endLine:i.getLineAndCharacterOfPosition(a.end).line+1}),j}function w(a){if(!h.isStringLiteral(a.moduleSpecifier))return;let S=[],y=a.importClause;if(y?.name&&S.push({localName:y.name.text,importedName:"default",kind:"default"}),y?.namedBindings&&h.isNamedImports(y.namedBindings))for(let u of y.namedBindings.elements)S.push({localName:u.name.text,importedName:u.propertyName?.text??u.name.text,kind:"named"});y?.namedBindings&&h.isNamespaceImport(y.namedBindings)&&S.push({localName:y.namedBindings.name.text,importedName:"*",kind:"namespace"}),m.push({source:a.moduleSpecifier.text,bindings:S})}function x(a,S){for(let y of a.heritageClauses??[])for(let u of y.types){let j=u.expression.getText(i).split(".").at(-1)??"";j&&c.push({fromId:S,targetName:j,type:y.token===h.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function g(a){let S=!1,y=!1;if(h.isImportDeclaration(a)&&w(a),h.isInterfaceDeclaration(a)&&f(a,a.name.text,"interface",a.name.text),h.isClassDeclaration(a)&&a.name){let u=f(a,a.name.text,"class",a.name.text);x(a,u),v.push({id:u,name:a.name.text}),y=!0}if(h.isFunctionDeclaration(a)&&a.name){let u=f(a,a.name.text,"function",a.name.text);l.push(u),S=!0}if(h.isMethodDeclaration(a)&&a.name){let u=a.name.getText(i),j=v.at(-1)?.name,ie=f(a,u,"method",j?`${j}.${u}`:u);l.push(ie),S=!0}if(h.isCallExpression(a)&&(h.isIdentifier(a.expression)&&d.push({callerId:l.at(-1),calleeName:a.expression.text,line:z(i,a)}),h.isPropertyAccessExpression(a.expression))){let u=a.expression;d.push({callerId:l.at(-1),qualifier:u.expression.getText(i),calleeName:u.name.text,line:z(i,a)})}h.forEachChild(a,g),S&&l.pop(),y&&v.pop()}return g(i),{filePath:t,symbols:n,imports:m,calls:d,heritage:c}}import{createHash as ot}from"node:crypto";import{dirname as st,extname as nt,normalize as it,posix as at}from"node:path";var P=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(r=>r.projectId===e&&(r.name===t||r.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 r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};function ct(o,e,t,r){return ot("sha256").update(`${o}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function b(o){return it(o).replaceAll("\\","/")}function B(o,e,t){if(!e.startsWith("."))return;let r=b(at.join(st(o),e)),s=nt(r),i;if(s===".js"){let n=r.slice(0,-3);i=[`${n}.ts`,`${n}.tsx`,`${n}.js`,`${n}.jsx`]}else if(s===".mjs"){let n=r.slice(0,-4);i=[`${n}.mts`,`${n}.ts`,`${n}.mjs`]}else if(s===".cjs"){let n=r.slice(0,-4);i=[`${n}.cts`,`${n}.ts`,`${n}.cjs`]}else s?i=[r]:i=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.js`,`${r}/index.jsx`];return i.find(n=>t.has(b(n)))}var _=class{build(e,t){let r=new P,s=new Map;for(let n of t)for(let m of n.symbols)r.addSymbol(m),m.type==="file"&&s.set(b(n.filePath),m);let i=new Set(s.keys());for(let n of t){let m=b(n.filePath),d=s.get(m);if(d){for(let c of n.symbols)c.id!==d.id&&r.addEdge(this.edge(e,d.id,"DEFINES",c.id));for(let c of n.imports){let p=B(m,c.source,i);if(!p)continue;let l=s.get(p);l&&r.addEdge(this.edge(e,d.id,"IMPORTS",l.id,{source:c.source}))}for(let c of n.heritage){let p=r.findByName(e,c.targetName).filter(l=>l.type==="class"||l.type==="interface");for(let l of p)r.addEdge(this.edge(e,c.fromId,c.type,l.id))}for(let c of n.calls){if(!c.callerId)continue;let p=this.resolveCallTargets(e,n,c.calleeName,c.qualifier,t,r,i);for(let l of p)l.id!==c.callerId&&r.addEdge(this.edge(e,c.callerId,"CALLS",l.id,{line:c.line,qualifier:c.qualifier}))}}}return r}resolveCallTargets(e,t,r,s,i,n,m){let d=b(t.filePath),c=n.findByName(e,r).filter(p=>b(p.filePath)===d);if(!s&&c.length)return c;if(s)for(let p of t.imports){if(!p.bindings.find(f=>f.kind==="namespace"&&f.localName===s))continue;let v=B(d,p.source,m);if(v)return n.findByName(e,r).filter(f=>b(f.filePath)===v)}for(let p of t.imports){let l=p.bindings.find(x=>x.localName===r);if(!l)continue;let v=B(d,p.source,m);if(!v)continue;let f=l.importedName==="default"?r:l.importedName,w=n.findByName(e,f).filter(x=>b(x.filePath)===v);if(w.length)return w}return n.findByName(e,r).filter(p=>p.type==="function"||p.type==="method")}edge(e,t,r,s,i){return{id:ct(e,t,r,s),projectId:e,from:t,to:s,type:r,metadata:i}}};var D=class{constructor(e){this.storage=e}storage;async index(e,t){let r=new $(this.storage),s=new O(this.storage),i=await r.load(e),n=await s.load(e),m=await re(e,t),d=oe(i,m),c=[...d.added,...d.modified];if(i&&n&&c.length===0&&d.deleted.length===0)return{firstRun:!1,scanned:Object.keys(m.files).length,parsed:0,added:0,modified:0,deleted:0,unchanged:d.unchanged.length,symbols:n.symbols.length,edges:n.edges.length,saved:!1};let p=n?.symbols.filter(g=>d.unchanged.includes(g.filePath))??[],l=[];for(let g of c)l.push(await ne(e,t,g));let v=new _().build(e,l),f=new P;for(let g of p)f.addSymbol(g);for(let g of v.allSymbols(e))f.addSymbol(g);let w=new Set(f.allSymbols(e).map(g=>g.id));for(let g of n?.edges??[])w.has(g.from)&&w.has(g.to)&&!c.includes(n.symbols.find(a=>a.id===g.from)?.filePath??"")&&!c.includes(n.symbols.find(a=>a.id===g.to)?.filePath??"")&&f.addEdge(g);for(let g of v.allEdges(e))f.addEdge(g);let x={version:1,projectId:e,updatedAt:new Date().toISOString(),files:Object.keys(m.files).length,symbols:f.allSymbols(e),edges:f.allEdges(e)};return await s.save(x),await r.save(m),{firstRun:i===null,scanned:Object.keys(m.files).length,parsed:c.length,added:d.added.length,modified:d.modified.length,deleted:d.deleted.length,unchanged:d.unchanged.length,symbols:x.symbols.length,edges:x.edges.length,saved:!0}}};async function dt(){let o=K(),e=new A().detect(),t=Z({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),r=new N(t,e.id,e.name,e.remote??e.name),s=await new D(r).index(e.id,e.rootPath);console.log({ok:!0,storage:r.name,...s})}dt().catch(o=>{console.error(o),process.exit(1)});
@@ -0,0 +1,11 @@
1
+ import{randomUUID as Nt}from"node:crypto";var Pt={critical:100,high:75,normal:50,temporary:20};function He(o){return Pt[o]}function Ke(o,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":o==="rule"||o==="decision"?"high":o==="todo"?"normal":o==="activity"||o==="summary"?"temporary":"normal"}var Rt=[{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}],_=class{scan(e){let t=[];for(let r of Rt){let s=new RegExp(r.regex.source,r.regex.flags);for(let n of e.matchAll(s))t.push({type:r.type,value:n[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var P=class{scanner=new _;sanitize(e){let t=e,r=this.scanner.scan(e),s=new Set;for(let n of r)s.add(n.type),t=t.split(n.value).join(`[REDACTED:${n.type}]`);return{text:t,redacted:r.length,secretTypes:[...s]}}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[r,s]of Object.entries(e)){let n=r.toLowerCase();n.includes("password")||n.includes("secret")||n.includes("token")||n.includes("cookie")||n.includes("authorization")?t[r]="[REDACTED]":t[r]=this.sanitizeValue(s)}return t}return e}};var kt=new Set(["decision","rule","todo","summary","activity","user","error","file","write","command","learned","session","architecture","fix","context","opencode","agy","codex"]),Tt=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 We(o){return new Set(o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_-]+/gu," ").split(/\s+/).filter(e=>e.length>2&&!Tt.has(e)))}function Mt(o,e){let t=We(o),r=We(e);if(t.size===0||r.size===0)return 0;let s=0;for(let i of t)r.has(i)&&s++;let n=new Set([...t,...r]).size;return s/n}function Ve(o){return new Set(o.tags.filter(e=>!kt.has(e.toLowerCase())))}var G=class{findSuperseded(e,t){if(e.type!=="rule"&&e.type!=="decision")return[];let r=typeof e.metadata?.topic=="string"?e.metadata.topic:void 0,s=Ve(e);return t.filter(n=>{if(n.id===e.id||n.projectId!==e.projectId||n.type!==e.type||n.metadata?.supersededBy)return!1;let i=typeof n.metadata?.topic=="string"?n.metadata.topic:void 0;if(r&&i&&r===i)return!0;let a=Ve(n);for(let c of s)if(a.has(c))return!0;return Mt(e.content,n.content)>=.6})}};var It={critical:100,high:75,normal:50,temporary:20},At={activity:14,summary:30,todo:90,decision:365,rule:730,code:180};function Ue(o,e,t=new Date){let r;if(e==="temporary"&&(r=30),o==="activity"&&(r=Math.min(r??14,14)),o==="summary"&&(r=Math.min(r??30,30)),!!r)return new Date(t.getTime()+r*864e5).toISOString()}function Pe(o,e=Date.now()){return o.expiresAt?new Date(o.expiresAt).getTime()<=e:!1}function Lt(o){return!!o.metadata?.supersededBy}function Re(o,e=Date.now()){return!Pe(o,e)&&!Lt(o)}function M(o,e=Date.now()){if(!Re(o,e))return 0;let t=It[o.importance];if(o.importance==="critical")return t;let r=At[o.type]??180,n=Math.max(0,e-new Date(o.updatedAt).getTime())/864e5,i=Math.pow(.5,n/r);return t*i}var R=class{memories=new Map;sanitizer=new P;conflicts=new G;remember(e){let t=new Date().toISOString(),r=this.sanitizer.sanitize(e.content.trim()).text,s=e.importance??Ke(e.type,r),n={id:Nt(),projectId:e.projectId,type:e.type,content:r,importance:s,importanceScore:He(s),tags:e.tags??[],source:e.source??"agent",createdAt:t,updatedAt:t,expiresAt:e.expiresAt??Ue(e.type,s,new Date(t)),metadata:this.sanitizer.sanitizeValue(e.metadata)},i=this.conflicts.findSuperseded(n,this.list(e.projectId));if(i.length){n.metadata={...n.metadata??{},supersedes:i.map(a=>a.id)};for(let a of i)a.updatedAt=t,a.metadata={...a.metadata??{},supersededBy:n.id,supersededAt:t},this.memories.set(a.id,a)}return this.memories.set(n.id,n),n}importRecords(e){let t=0;for(let r of e)r?.id&&(this.memories.set(r.id,r),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,r)=>r.createdAt.localeCompare(t.createdAt))}list(e){return this.listAll(e).filter(t=>Re(t))}recent(e,t=10){return this.list(e).slice(0,t)}byType(e,t){return this.list(e).filter(r=>r.type===t)}search(e){let t=e.query.trim().toLowerCase(),r=e.limit??10,s=t.split(/\s+/).filter(Boolean);return this.list(e.projectId).filter(n=>{if(e.types&&!e.types.includes(n.type))return!1;let i=M(n);return!(e.minImportanceScore&&i<e.minImportanceScore||e.tags?.length&&!e.tags.some(c=>n.tags.includes(c)))}).map(n=>{let i=n.content.toLowerCase(),a=s.filter(p=>i.includes(p)).length,c=s.length===0?0:a/s.length,l=M(n)/500;return{memory:n,score:c+l,source:"memory"}}).filter(n=>t.length===0||n.score>0).sort((n,i)=>i.score-n.score).slice(0,r)}pruneExpired(e,t=Date.now()){let r=0;for(let[s,n]of this.memories)n.projectId===e&&Pe(n,t)&&(this.memories.delete(s),r++);return r}pruneSuperseded(e,t=30,r=Date.now()){let s=0,n=t*864e5;for(let[i,a]of this.memories){if(a.projectId!==e)continue;let c=a.metadata?.supersededAt;if(typeof c!="string")continue;r-new Date(c).getTime()>=n&&(this.memories.delete(i),s++)}return s}clearProject(e){let t=0;for(let[r,s]of this.memories)s.projectId===e&&(this.memories.delete(r),t++);return t}};var D=class{constructor(e){this.memory=e}memory;run(e){let t=this.memory.pruneExpired(e),r=this.memory.pruneSuperseded(e,30);return{expiredRemoved:t,supersededRemoved:r,active:this.memory.list(e).length,total:this.memory.listAll(e).length}}};function ke(o){return[...new Set(o.filter(Boolean))]}var z=class{constructor(e){this.memory=e}memory;consolidate(e,t={}){let r=t.minItems??4,s=t.maxItems??50,n=t.retentionDays??90,i=this.memory.byType(e,"activity").slice(0,s);if(i.length<r)return{scanned:i.length,consolidated:0,summaryCreated:!1};let a=this.buildSummary(i),c=new Date,l=new Date(c.getTime()+n*864e5).toISOString(),p=this.memory.remember({projectId:e,type:"summary",content:a,importance:"normal",tags:["consolidated","activity-summary"],source:"auto-consolidation",expiresAt:l,metadata:{consolidatedFrom:i.map(u=>u.id),itemCount:i.length}}),d=c.toISOString();for(let u of i){let f=this.memory.get(u.id);f&&(f.updatedAt=d,f.metadata={...f.metadata??{},consolidated:!0,supersededBy:p.id,supersededAt:d})}return{scanned:i.length,consolidated:i.length,summaryCreated:!0,summaryId:p.id}}buildSummary(e){let t=ke(e.filter(i=>i.content.startsWith("Modified file:")).map(i=>i.content.replace("Modified file:","").trim())),r=ke(e.filter(i=>i.content.startsWith("Command:")).map(i=>i.content.replace("Command:","").trim())),s=ke(e.filter(i=>i.content.startsWith("Error:")).map(i=>i.content.replace("Error:","").trim())),n=["Activity consolidation:",`- Activities: ${e.length}`];return t.length&&n.push(`- Files changed: ${t.slice(0,15).join(", ")}`),r.length&&n.push(`- Commands: ${r.slice(0,10).join("; ")}`),s.length&&n.push(`- Errors: ${s.slice(0,10).join("; ")}`),n.join(`
2
+ `)}};function B(o){return o.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}var H=class{score(e,t){let r=B(e),s=B([t.content,...t.tags??[],t.type].join(" "));if(r.length===0||s.length===0)return 0;let n=new Map;for(let a of s)n.set(a,(n.get(a)??0)+1);let i=0;for(let a of r){let c=n.get(a)??0;c!==0&&(i+=1+Math.log(1+c))}return i/r.length}};function qe(o,e=Date.now()){let t=o.updatedAt??o.createdAt,r=new Date(t).getTime();if(!Number.isFinite(r))return 0;let s=Math.max(0,e-r)/864e5;return Math.exp(-Math.LN2*s/30)}function Je(o){return M(o)/100}var Ot={rule:1,decision:.9,todo:.8,summary:.6,activity:.3};function Ye(o){return Ot[o]??.4}var K=class{analyze(e){let t=e.toLowerCase(),r=[];return(t.includes("quy\u1EBFt \u0111\u1ECBnh")||t.includes("decision")||t.includes("\u0111\xE3 ch\u1ECDn"))&&r.push("decision"),(t.includes("todo")||t.includes("c\u1EA7n l\xE0m")||t.includes("ti\u1EBFp theo")||t.includes("ch\u01B0a xong"))&&r.push("todo"),(t.includes("quy t\u1EAFc")||t.includes("rule")||t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("b\u1EAFt bu\u1ED9c"))&&r.push("rule"),(t.includes("t\xF3m t\u1EAFt")||t.includes("summary")||t.includes("\u0111\xE3 l\xE0m"))&&r.push("summary"),{query:e,preferredTypes:r}}};var W=class{bm25=new H;analyzer=new K;search(e,t,r={}){let s=r.topK??8,n=r.minScore??.05,i=this.analyzer.analyze(e),a=[];for(let c of t){if(r.types?.length&&!r.types.includes(c.type))continue;let l=this.bm25.score(e,c),p=qe(c),d=Je(c),u=Ye(c.type);i.preferredTypes.includes(c.type)&&(u=Math.min(1,u+.25));let f=l*.55+d*.2+p*.15+u*.1;l<=0||f<n||a.push({memory:c,score:f,scores:{keyword:l,recency:p,importance:d,type:u}})}return a.sort((c,l)=>l.score-c.score).slice(0,s)}};var V=class{build(e,t=6e3){let r=[],s=0;for(let n of e){let i=n.memory,a=[`[${i.type.toUpperCase()}]`,i.content].join(" ");if(s+a.length>t)break;r.push(a),s+=a.length}return r.join(`
3
+ `)}};var U=class{constructor(e){this.memory=e}memory;searcher=new W;contextBuilder=new V;search(e,t,r={}){return this.searcher.search(t,this.memory.list(e),r)}context(e,t,r={}){let s=this.search(e,t,r);return this.contextBuilder.build(s)}};var q=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`,r=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(!r.ok)throw new Error(`HF embedding failed: ${r.status} ${await r.text()}`);let s=await r.json();if(!Array.isArray(s))throw new Error("HF embedding returned invalid response");return s.map(n=>Ft(n))}};function Ft(o){if(!Array.isArray(o))throw new Error("Invalid embedding");if(o.length>0&&typeof o[0]=="number")return o;if(o.length>0&&Array.isArray(o[0])){let e=o;if(e.length===0)return[];let t=e[0].length,r=new Array(t).fill(0);for(let s of e)for(let n=0;n<t;n++)r[n]+=s[n]??0;for(let s=0;s<t;s++)r[s]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as $t}from"node:crypto";var J=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),r=e.toLowerCase().split(/\s+/).filter(Boolean);for(let s of r){let i=$t("sha256").update(s).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return _t(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function _t(o){let e=Math.sqrt(o.reduce((t,r)=>t+r*r,0));return e===0?o:o.map(t=>t/e)}var Te=class{constructor(e,t=new J){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function Me(){let o=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=o?new q({token:o,model:e}):null;return new Te(t)}import{readdir as Bt}from"node:fs/promises";import{extname as Ht,join as Kt,relative as Wt}from"node:path";import{basename as Gt}from"node:path";var Dt=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),zt=new Set([".pem",".key",".p12",".pfx"]);function Ie(o){let e=Gt(o).toLowerCase();if(Dt.has(e))return!0;for(let t of zt)if(e.endsWith(t))return!0;return!1}var Vt=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Ut=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function Ae(o){let e=[];async function t(r){let s=await Bt(r,{withFileTypes:!0});for(let n of s){if(Ut.has(n.name))continue;let i=Kt(r,n.name);if(n.isDirectory()){await t(i);continue}Vt.has(Ht(n.name))&&(Ie(i)||e.push(Wt(o,i)))}}return await t(o),e.sort()}import{readFile as qt}from"node:fs/promises";import{join as Jt}from"node:path";import{createHash as Yt}from"node:crypto";import v from"typescript";function Ze(o,e){return Yt("sha256").update(`${o}:${e}`).digest("hex").slice(0,24)}function Le(o,e){return o.getLineAndCharacterOfPosition(e.getStart(o)).line+1}async function Ne(o,e,t){let r=Jt(e,t),s=await qt(r,"utf8"),n=v.createSourceFile(t,s,v.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?v.ScriptKind.TSX:v.ScriptKind.TS),i=[],a=[],c=[],l=[],p={id:Ze(o,`file:${t}`),projectId:o,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:n.getLineAndCharacterOfPosition(n.end).line+1};i.push(p);let d=[],u=[];function f(m,S,b,y){let E=Ze(o,`${t}:${b}:${y??S}:${m.pos}`);return i.push({id:E,projectId:o,name:S,qualifiedName:y??S,type:b,filePath:t,startLine:Le(n,m),endLine:n.getLineAndCharacterOfPosition(m.end).line+1}),E}function x(m){if(!v.isStringLiteral(m.moduleSpecifier))return;let S=[],b=m.importClause;if(b?.name&&S.push({localName:b.name.text,importedName:"default",kind:"default"}),b?.namedBindings&&v.isNamedImports(b.namedBindings))for(let y of b.namedBindings.elements)S.push({localName:y.name.text,importedName:y.propertyName?.text??y.name.text,kind:"named"});b?.namedBindings&&v.isNamespaceImport(b.namedBindings)&&S.push({localName:b.namedBindings.name.text,importedName:"*",kind:"namespace"}),a.push({source:m.moduleSpecifier.text,bindings:S})}function h(m,S){for(let b of m.heritageClauses??[])for(let y of b.types){let E=y.expression.getText(n).split(".").at(-1)??"";E&&l.push({fromId:S,targetName:E,type:b.token===v.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function g(m){let S=!1,b=!1;if(v.isImportDeclaration(m)&&x(m),v.isInterfaceDeclaration(m)&&f(m,m.name.text,"interface",m.name.text),v.isClassDeclaration(m)&&m.name){let y=f(m,m.name.text,"class",m.name.text);h(m,y),u.push({id:y,name:m.name.text}),b=!0}if(v.isFunctionDeclaration(m)&&m.name){let y=f(m,m.name.text,"function",m.name.text);d.push(y),S=!0}if(v.isMethodDeclaration(m)&&m.name){let y=m.name.getText(n),E=u.at(-1)?.name,jt=f(m,y,"method",E?`${E}.${y}`:y);d.push(jt),S=!0}if(v.isCallExpression(m)&&(v.isIdentifier(m.expression)&&c.push({callerId:d.at(-1),calleeName:m.expression.text,line:Le(n,m)}),v.isPropertyAccessExpression(m.expression))){let y=m.expression;c.push({callerId:d.at(-1),qualifier:y.expression.getText(n),calleeName:y.name.text,line:Le(n,m)})}v.forEachChild(m,g),S&&d.pop(),b&&u.pop()}return g(n),{filePath:t,symbols:i,imports:a,calls:c,heritage:l}}import{createHash as Zt}from"node:crypto";import{dirname as Qt,extname as Xt,normalize as er,posix as tr}from"node:path";var C=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(r=>r.projectId===e&&(r.name===t||r.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 r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};function rr(o,e,t,r){return Zt("sha256").update(`${o}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function j(o){return er(o).replaceAll("\\","/")}function Oe(o,e,t){if(!e.startsWith("."))return;let r=j(tr.join(Qt(o),e)),s=Xt(r),n;if(s===".js"){let i=r.slice(0,-3);n=[`${i}.ts`,`${i}.tsx`,`${i}.js`,`${i}.jsx`]}else if(s===".mjs"){let i=r.slice(0,-4);n=[`${i}.mts`,`${i}.ts`,`${i}.mjs`]}else if(s===".cjs"){let i=r.slice(0,-4);n=[`${i}.cts`,`${i}.ts`,`${i}.cjs`]}else s?n=[r]:n=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.js`,`${r}/index.jsx`];return n.find(i=>t.has(j(i)))}var I=class{build(e,t){let r=new C,s=new Map;for(let i of t)for(let a of i.symbols)r.addSymbol(a),a.type==="file"&&s.set(j(i.filePath),a);let n=new Set(s.keys());for(let i of t){let a=j(i.filePath),c=s.get(a);if(c){for(let l of i.symbols)l.id!==c.id&&r.addEdge(this.edge(e,c.id,"DEFINES",l.id));for(let l of i.imports){let p=Oe(a,l.source,n);if(!p)continue;let d=s.get(p);d&&r.addEdge(this.edge(e,c.id,"IMPORTS",d.id,{source:l.source}))}for(let l of i.heritage){let p=r.findByName(e,l.targetName).filter(d=>d.type==="class"||d.type==="interface");for(let d of p)r.addEdge(this.edge(e,l.fromId,l.type,d.id))}for(let l of i.calls){if(!l.callerId)continue;let p=this.resolveCallTargets(e,i,l.calleeName,l.qualifier,t,r,n);for(let d of p)d.id!==l.callerId&&r.addEdge(this.edge(e,l.callerId,"CALLS",d.id,{line:l.line,qualifier:l.qualifier}))}}}return r}resolveCallTargets(e,t,r,s,n,i,a){let c=j(t.filePath),l=i.findByName(e,r).filter(p=>j(p.filePath)===c);if(!s&&l.length)return l;if(s)for(let p of t.imports){if(!p.bindings.find(f=>f.kind==="namespace"&&f.localName===s))continue;let u=Oe(c,p.source,a);if(u)return i.findByName(e,r).filter(f=>j(f.filePath)===u)}for(let p of t.imports){let d=p.bindings.find(h=>h.localName===r);if(!d)continue;let u=Oe(c,p.source,a);if(!u)continue;let f=d.importedName==="default"?r:d.importedName,x=i.findByName(e,f).filter(h=>j(h.filePath)===u);if(x.length)return x}return i.findByName(e,r).filter(p=>p.type==="function"||p.type==="method")}edge(e,t,r,s,n){return{id:rr(e,t,r,s),projectId:e,from:t,to:s,type:r,metadata:n}}};function Qe(o,e){let t=o.allSymbols(e),r=o.allEdges(e),s=i=>t.filter(a=>a.type===i).length,n=i=>r.filter(a=>a.type===i).length;return{files:s("file"),classes:s("class"),interfaces:s("interface"),functions:s("function"),methods:s("method"),properties:s("property"),routes:s("route"),symbols:t.length,edges:r.length,calls:n("CALLS"),callReferences:n("CALL_REFERENCE"),imports:n("IMPORTS"),inherits:n("INHERITS"),implements:n("IMPLEMENTS"),usesType:n("USES_TYPE"),tests:n("TESTS"),routeEdges:n("ROUTE"),writes:n("WRITES")}}var Y=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(s=>s.type==="CALLS"&&s.to===t).map(s=>s.from).map(s=>this.graph.getSymbol(s)).filter(s=>!!s)}};function or(o,e){return e.ranges.length===0?!0:typeof o.startLine!="number"||typeof o.endLine!="number"?!1:e.ranges.some(t=>o.startLine<=t.endLine&&o.endLine>=t.startLine)}var Z=class{constructor(e){this.graph=e}graph;map(e,t){let r=this.graph.allSymbols(e),s=[];for(let n of t){let i=r.filter(l=>l.filePath===n.filePath),c=i.filter(l=>l.type!=="file").filter(l=>or(l,n));if(c.length===0){let l=i.find(p=>p.type==="file");l&&s.push({symbol:l,fileStatus:n.status,direct:!0});continue}for(let l of c)s.push({symbol:l,fileStatus:n.status,direct:!0})}return s}mapFile(e,t){return this.map(e,[{filePath:t,status:"modified",ranges:[]}])}};var sr={CALLS:4,CALL_REFERENCE:6,USES_TYPE:4,TESTS:2,ROUTE:4,WRITES:3,IMPORTS:3,INHERITS:5,IMPLEMENTS:5,DEFINES:1};function nr(o){return o>=30?"CRITICAL":o>=16?"HIGH":o>=6?"MEDIUM":"LOW"}function Xe(o){let e=o.toLowerCase().replaceAll("\\","/");return e.startsWith("tests/")||e.includes("/tests/")||e.includes("__tests__")||/\.(test|spec)\.[^.]+$/.test(e)}var Q=class{constructor(e){this.graph=e}graph;analyze(e,t,r=4){let s=this.graph.allEdges(e),n=new Map,i=0;for(let p of t){p.fileStatus==="deleted"?i+=8:p.fileStatus==="renamed"?i+=5:i+=2,p.symbol.type==="interface"&&(i+=5),p.symbol.type==="class"&&(i+=3);let d=new Set([p.symbol.id]),u=[{id:p.symbol.id,depth:0}];for(;u.length;){let f=u.shift();if(f.depth>=r)continue;let x=s.filter(h=>h.to===f.id&&["CALLS","CALL_REFERENCE","USES_TYPE","TESTS","ROUTE","WRITES","IMPORTS","INHERITS","IMPLEMENTS","DEFINES"].includes(h.type));for(let h of x){if(d.has(h.from))continue;d.add(h.from);let g=this.graph.getSymbol(h.from);if(!g)continue;let m=f.depth+1,S=`${p.symbol.id}:${g.id}`;n.set(S,{symbol:g,relation:h.type,depth:m,sourceSymbolId:p.symbol.id});let b=sr[h.type]??1;i+=Math.max(1,b-(m-1)),u.push({id:g.id,depth:m})}}}let a=[...n.values()].sort((p,d)=>p.depth-d.depth),c=[...new Set(a.map(p=>p.symbol.filePath))],l=c.filter(Xe);return l.length===0&&l.push(...c.filter(p=>!Xe(p)).slice(0,10)),{risk:nr(i),riskScore:i,changedSymbols:t,impacted:a,impactedFiles:c,suggestedTests:l}}};import{execFile as ir}from"node:child_process";import{promisify as ar}from"node:util";var Fe=ar(ir);function cr(o){let e=[],t=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/gm;for(let r of o.matchAll(t)){let s=Number(r[1]),n=Number(r[2]??1);e.push({startLine:s,endLine:Math.max(s,s+n-1)})}return e}function lr(o){return o.startsWith("A")?"added":o.startsWith("D")?"deleted":o.startsWith("R")?"renamed":"modified"}async function et(o){let e="";try{e=(await Fe("git",["diff","HEAD","--name-status","--no-renames"],{cwd:o,maxBuffer:10485760})).stdout}catch{return[]}let t=[];for(let r of e.split(/\r?\n/).filter(Boolean)){let[s,...n]=r.split(" "),i=n.at(-1);if(!i)continue;let a="";try{a=(await Fe("git",["diff","HEAD","--unified=0","--",i],{cwd:o,maxBuffer:20971520})).stdout}catch{a=""}t.push({filePath:i,status:lr(s),ranges:cr(a)})}try{let r=await Fe("git",["ls-files","--others","--exclude-standard"],{cwd:o});for(let s of r.stdout.split(/\r?\n/).filter(Boolean))t.some(n=>n.filePath===s)||t.push({filePath:s,status:"added",ranges:[]})}catch{}return t}var X=class{constructor(e){this.graph=e;this.mapper=new Z(e),this.blast=new Q(e)}graph;mapper;blast;async analyzeGitDiff(e,t,r={}){let s=await et(t),n=this.mapper.map(e,s),i=this.blast.analyze(e,n,r.maxDepth??4);return{mode:"git_diff",changes:s,...i}}analyzeFile(e,t,r={}){let s=this.mapper.mapFile(e,t);return{mode:"planned_file",filePath:t,...this.blast.analyze(e,s,r.maxDepth??4)}}};var dr=/(^|[_-])(write|edit|patch|replace|multiedit|create|delete|remove|rename|move)([_-]|$)/i,pr=new Set(["path","filepath","file_path","filename","file","target","targetpath","target_path","sourcepath","source_path"]);function tt(o){return o.trim().replace(/^["']|["']$/g,"").replace(/^a\//,"").replace(/^b\//,"").replaceAll("\\","/")}function mr(o){return o.length>0&&o.length<500&&!o.includes(`
4
+ `)&&/(^|\/)[^/]+\.[A-Za-z0-9]+$/.test(o)}function ur(o){let e=[],t=[/^\*\*\* (?:Update|Add|Delete) File:\s*(.+)$/gm,/^\+\+\+\s+b\/(.+)$/gm,/^---\s+a\/(.+)$/gm];for(let r of t)for(let s of o.matchAll(r))s[1]&&e.push(tt(s[1]));return e}function $e(o,e,t){if(typeof o=="string"){let r=t?.toLowerCase();if(r&&pr.has(r)&&mr(o)&&e.add(tt(o)),o.includes("*** Update File:")||o.includes("*** Add File:")||o.includes("*** Delete File:")||o.includes("+++ b/"))for(let s of ur(o))e.add(s);return}if(Array.isArray(o)){for(let r of o)$e(r,e,t);return}if(o&&typeof o=="object")for(let[r,s]of Object.entries(o))$e(s,e,r)}function fr(o){return dr.test(o.toLowerCase())}function rt(o,e){if(!fr(o))return[];let t=new Set;return $e(e,t),[...t]}import{createHash as gr}from"node:crypto";import{readFile as hr}from"node:fs/promises";async function ot(o){let e=await hr(o);return gr("sha256").update(e).digest("hex")}function st(o,e){let t=o?.files??{},r=e.files,s=[],n=[],i=[],a=[];for(let[c,l]of Object.entries(r)){let p=t[c];p?p.hash!==l.hash?n.push(c):a.push(c):s.push(c)}for(let c of Object.keys(t))r[c]||i.push(c);return{added:s.sort(),modified:n.sort(),deleted:i.sort(),unchanged:a.sort()}}import{join as yr}from"node:path";async function nt(o,e){let t=await Ae(e),r={};for(let s of t)r[s]={path:s,hash:await ot(yr(e,s))};return{version:1,projectId:o,updatedAt:new Date().toISOString(),files:r}}var k=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 ee=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 te=class{constructor(e){this.storage=e}storage;async index(e,t){let r=new ee(this.storage),s=new k(this.storage),n=await r.load(e),i=await s.load(e),a=await nt(e,t),c=st(n,a),l=[...c.added,...c.modified];if(n&&i&&l.length===0&&c.deleted.length===0)return{firstRun:!1,scanned:Object.keys(a.files).length,parsed:0,added:0,modified:0,deleted:0,unchanged:c.unchanged.length,symbols:i.symbols.length,edges:i.edges.length,saved:!1};let p=i?.symbols.filter(g=>c.unchanged.includes(g.filePath))??[],d=[];for(let g of l)d.push(await Ne(e,t,g));let u=new I().build(e,d),f=new C;for(let g of p)f.addSymbol(g);for(let g of u.allSymbols(e))f.addSymbol(g);let x=new Set(f.allSymbols(e).map(g=>g.id));for(let g of i?.edges??[])x.has(g.from)&&x.has(g.to)&&!l.includes(i.symbols.find(m=>m.id===g.from)?.filePath??"")&&!l.includes(i.symbols.find(m=>m.id===g.to)?.filePath??"")&&f.addEdge(g);for(let g of u.allEdges(e))f.addEdge(g);let h={version:1,projectId:e,updatedAt:new Date().toISOString(),files:Object.keys(a.files).length,symbols:f.allSymbols(e),edges:f.allEdges(e)};return await s.save(h),await r.save(a),{firstRun:n===null,scanned:Object.keys(a.files).length,parsed:l.length,added:c.added.length,modified:c.modified.length,deleted:c.deleted.length,unchanged:c.unchanged.length,symbols:h.symbols.length,edges:h.edges.length,saved:!0}}};var A=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[r,s]of this.records)s.projectId===e&&(this.records.delete(r),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let r of e)!r?.id||!r?.projectId||!Array.isArray(r.vector)||(this.records.set(r.id,r),t++);return t}search(e,t,r=10){let s=[];for(let n of this.records.values()){if(n.projectId!==e)continue;let i=Sr(t,n.vector);s.push({id:n.id,score:i,metadata:n.metadata})}return s.sort((n,i)=>i.score-n.score).slice(0,r)}size(){return this.records.size}};function Sr(o,e){if(o.length===0||e.length===0||o.length!==e.length)return 0;let t=0,r=0,s=0;for(let n=0;n<o.length;n++){let i=o[n]??0,a=e[n]??0;t+=i*a,r+=i*i,s+=a*a}return r===0||s===0?0:t/(Math.sqrt(r)*Math.sqrt(s))}import zn from"typescript";import w from"typescript";var Un=new Set([w.SyntaxKind.EqualsToken,w.SyntaxKind.PlusEqualsToken,w.SyntaxKind.MinusEqualsToken,w.SyntaxKind.AsteriskEqualsToken,w.SyntaxKind.SlashEqualsToken,w.SyntaxKind.PercentEqualsToken,w.SyntaxKind.QuestionQuestionEqualsToken,w.SyntaxKind.AmpersandAmpersandEqualsToken,w.SyntaxKind.BarBarEqualsToken]);var re=class{constructor(e,t){this.embeddings=e;this.store=t}embeddings;store;async index(e){let t=e.filter(n=>!this.store.has(n.id));if(t.length===0)return 0;let r=await this.embeddings.embedMany(t.map(n=>[n.type,n.content,...n.tags??[]].join(" "))),s=0;for(let n=0;n<t.length;n++){let i=t[n],a=r[n];!i||!a||(this.store.upsert({id:i.id,projectId:i.projectId,vector:a,metadata:{type:i.type,updatedAt:i.updatedAt}}),s++)}return s}};var L=class{constructor(e,t,r,s,n){this.projectId=e;this.model=t;this.embeddings=r;this.store=s;this.persistence=n}projectId;model;embeddings;store;persistence;async initialize(e){let t=0,r=await this.persistence.load(this.projectId);r&&r.model===this.model&&(t=this.store.importRecords(r.records));let s=new Set(e.map(d=>d.id)),n=0;for(let d of this.store.exportProject(this.projectId))s.has(d.id)||this.store.remove(d.id)&&n++;let a=await new re(this.embeddings,this.store).index(e),c=this.store.exportProject(this.projectId),l=c[0]?.vector.length??this.embeddings.dimensions??0,p=!1;return(a>0||n>0||!r)&&(await this.persistence.save({version:1,projectId:this.projectId,model:this.model,dimensions:l,updatedAt:new Date().toISOString(),records:c}),p=!0),{loaded:t,indexed:a,removed:n,total:c.length,saved:p}}};var oe=class{events=[];push(e){this.events.push(e)}drain(){let e=[...this.events];return this.events.length=0,e}list(){return[...this.events]}size(){return this.events.length}shouldFlush(e){return this.events.length>=e}};import{createHash as xr}from"node:crypto";var se=class{seen=new Set;fingerprint(e){return xr("sha256").update(JSON.stringify({projectId:e.projectId,type:e.type,data:e.data})).digest("hex")}filter(e){let t=[];for(let r of e){let s=this.fingerprint(r);this.seen.has(s)||(this.seen.add(s),t.push(r))}return t}clear(){this.seen.clear()}};import{randomUUID as vr}from"node:crypto";var ne=class{constructor(e){this.queue=e}queue;sanitizer=new P;capture(e,t,r={}){let s={id:vr(),projectId:e,type:t,timestamp:new Date().toISOString(),data:this.sanitizer.sanitizeValue(r)};return this.queue.push(s),s}};import{randomUUID as wr}from"node:crypto";var ie=class{constructor(e){this.capture=e}capture;sessionId=wr();start(e){return this.capture.capture(e,"session_start",{sessionId:this.sessionId})}end(e){return this.capture.capture(e,"session_end",{sessionId:this.sessionId})}};var ae=class{extract(e){switch(e.type){case"decision":return{type:"decision",content:String(e.data.content??"Decision recorded"),tags:["decision"],source:"auto-extractor",metadata:e.data};case"todo":return{type:"todo",content:String(e.data.content??"TODO recorded"),tags:["todo"],source:"auto-extractor",metadata:e.data};case"error":return{type:"activity",content:`Error: ${String(e.data.message??"")}`,tags:["error"],source:"auto-extractor",metadata:e.data};case"file_write":return{type:"activity",content:`Modified file: ${String(e.data.filePath??"")}`,tags:["file","write"],source:"auto-extractor",metadata:e.data};case"command":return{type:"activity",content:`Command: ${String(e.data.command??"")}`,tags:["command"],source:"auto-extractor",metadata:e.data};case"session_start":case"session_end":case"file_read":case"tool_call":case"user_prompt":case"test":case"commit":case"deploy":return null;default:return null}}};function _e(o){let e=o.toLowerCase();return["kh\xF4ng \u0111\u01B0\u1EE3c","b\u1EAFt bu\u1ED9c","ph\u1EA3i lu\xF4n","tuy\u1EC7t \u0111\u1ED1i","never ","must ","always ","do not "].some(t=>e.includes(t))}function Ge(o){let e=o.toLowerCase();return["quy\u1EBFt \u0111\u1ECBnh","ch\u1ECDn ","s\u1EED d\u1EE5ng ","d\xF9ng ","decided","decision","we will use","use "].some(t=>e.includes(t))}function De(o){let e=o.toLowerCase();return["todo","c\u1EA7n l\xE0m","ch\u01B0a xong","c\xF2n ph\u1EA3i","next:","next step","pending"].some(t=>e.includes(t))}function ce(o,e){let t=e.toLowerCase();return t.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||t.includes("tuy\u1EC7t \u0111\u1ED1i")||t.includes("must not")||t.includes("never ")?"critical":o==="rule"||o==="decision"?"high":o==="todo"||t.includes("error")||t.includes("failed")||t.includes("exception")?"normal":"temporary"}function N(o){return[...new Set(o.filter(Boolean))]}function le(o,e=120){return o.length>e?`${o.slice(0,e)}\u2026`:o}var de=class{summarize(e){if(e.length===0)return null;let t=N(e.filter(c=>c.type==="file_write").map(c=>String(c.data.filePath??""))),r=N(e.filter(c=>c.type==="command").map(c=>le(String(c.data.command??"")))),s=N(e.filter(c=>c.type==="error").map(c=>le(String(c.data.message??"")))),n=N(e.filter(c=>c.type==="decision").map(c=>le(String(c.data.content??"")))),i=N(e.filter(c=>c.type==="todo").map(c=>le(String(c.data.content??""))));if(t.length===0&&r.length===0&&s.length===0&&n.length===0&&i.length===0)return null;let a=["Session summary:"];return t.length&&a.push(`- Files changed (${t.length}): ${t.slice(0,10).join(", ")}`),r.length&&a.push(`- Commands (${r.length}): ${r.slice(0,5).join("; ")}`),s.length&&a.push(`- Errors (${s.length}): ${s.slice(0,5).join("; ")}`),n.length&&a.push(`- Decisions: ${n.slice(0,5).join("; ")}`),i.length&&a.push(`- TODO: ${i.slice(0,5).join("; ")}`),a.join(`
5
+ `)}};var pe=class{constructor(e){this.memory=e}memory;extractor=new ae;summarizer=new de;process(e){let t=0;for(let s of e){let n=this.extractor.extract(s);if(n){let i=this.refineType(n.type,n.content);this.memory.remember({projectId:s.projectId,type:i,content:n.content,importance:ce(i,n.content),tags:n.tags,source:n.source,metadata:{eventId:s.id,timestamp:s.timestamp,...n.metadata}}),t++}if(s.type==="user_prompt"){let i=String(s.data.content??""),a=this.detectPromptMemoryType(i);a&&(this.memory.remember({projectId:s.projectId,type:a,content:i,importance:ce(a,i),tags:["user",a],source:"auto-prompt-extractor",metadata:{eventId:s.id,timestamp:s.timestamp}}),t++)}}let r=this.summarizer.summarize(e);if(r){let s=e[0]?.projectId;s&&(this.memory.remember({projectId:s,type:"summary",content:r,importance:"temporary",tags:["summary"],source:"auto-summary",metadata:{eventCount:e.length}}),t++)}return t}refineType(e,t){return _e(t)?"rule":De(t)?"todo":Ge(t)?"decision":e}detectPromptMemoryType(e){return _e(e)?"rule":De(e)?"todo":Ge(e)?"decision":null}};import{createHash as Er}from"node:crypto";function Cr(o){return Er("sha256").update([o.projectId,o.type,o.content.trim().toLowerCase()].join("|")).digest("hex")}function it(o){let e=new Set,t=[];for(let r of o){let s=Cr(r);e.has(s)||(e.add(s),t.push(r))}return t}var me=class{projectId;memory;memoryStore;queue=new oe;capture=new ne(this.queue);session=new ie(this.capture);processor;dedup=new se;maxEventsBeforeFlush;constructor(e){this.projectId=e.projectId,this.memory=e.memory,this.memoryStore=e.memoryStore,this.maxEventsBeforeFlush=e.maxEventsBeforeFlush??100,this.processor=new pe(this.memory)}async sessionStart(){this.session.start(this.projectId),await this.flushIfNeeded()}async sessionEnd(){this.session.end(this.projectId),await this.flush()}async userPrompt(e){this.capture.capture(this.projectId,"user_prompt",{content:e}),await this.flushIfNeeded()}async beforeTool(e,t){this.capture.capture(this.projectId,"tool_call",{phase:"before",tool:e,input:t}),await this.flushIfNeeded()}async afterTool(e,t){this.capture.capture(this.projectId,"tool_call",{phase:"after",tool:e,output:t}),await this.flushIfNeeded()}async fileRead(e){this.capture.capture(this.projectId,"file_read",{filePath:e}),await this.flushIfNeeded()}async fileWrite(e){this.capture.capture(this.projectId,"file_write",{filePath:e}),await this.flushIfNeeded()}async command(e,t){this.capture.capture(this.projectId,"command",{command:e,exitCode:t}),await this.flushIfNeeded()}async error(e){let t=e instanceof Error?e.message:String(e);this.capture.capture(this.projectId,"error",{message:t}),await this.flushIfNeeded()}async decision(e,t={}){this.capture.capture(this.projectId,"decision",{content:e,...t}),await this.flushIfNeeded()}async todo(e,t={}){this.capture.capture(this.projectId,"todo",{content:e,...t}),await this.flushIfNeeded()}async flushIfNeeded(){this.queue.shouldFlush(this.maxEventsBeforeFlush)&&await this.flush()}async flush(){let e=this.queue.drain();if(e.length===0)return 0;let t=this.dedup.filter(e);if(t.length===0)return 0;let r=this.processor.process(t),s=it(this.memory.exportProject(this.projectId));return this.memory.clearProject(this.projectId),this.memory.importRecords(s),await this.memoryStore.save(this.projectId,s),r}pendingEvents(){return this.queue.size()}};var ue=class{constructor(e,t,r){this.memory=e;this.retrieval=t;this.graph=r}memory;retrieval;graph;build(e,t,r={}){let s=r.maxRules??3,n=r.maxTodos??3,i=r.maxDecisions??3,a=r.maxRelevant??5,c=r.maxCharacters??7e3,l=this.memory.byType(e,"rule").slice(0,s),p=this.memory.byType(e,"todo").slice(0,n),d=this.memory.byType(e,"decision").slice(0,i),u=this.retrieval.search(e,t,{topK:a}),f=Qe(this.graph,e),x=[];x.push(["[PROJECT]",`files=${f.files}`,`classes=${f.classes}`,`functions=${f.functions}`,`methods=${f.methods}`,`calls=${f.calls}`].join(" "));for(let g of l)x.push(`[RULE] ${g.content}`);for(let g of d)x.push(`[DECISION] ${g.content}`);for(let g of p)x.push(`[TODO] ${g.content}`);for(let g of u){let S=`[${g.memory.type.toUpperCase()}] ${g.memory.content}`;x.includes(S)||x.push(S)}let h="";for(let g of x){let m=h.length===0?g:`${h}
6
+ ${g}`;if(m.length>c)break;h=m}return h}};var fe=class{constructor(e,t,r){this.runtime=e;this.builder=t;this.projectId=r}runtime;builder;projectId;async prepare(e){await this.runtime.userPrompt(e);let t=this.builder.build(this.projectId,e);return{originalPrompt:e,context:t,augmentedPrompt:t?["<toolnet_memory>",t,"</toolnet_memory>","",e].join(`
7
+ `):e}}};var at={LOW:0,MEDIUM:1,HIGH:2,CRITICAL:3},ge=class{constructor(e,t){this.guard=e;this.projectId=t}guard;projectId;async beforeTool(e,t){let r=rt(e,t);if(r.length===0)return{triggered:!1,tool:e,highestRisk:"LOW",totalRiskScore:0,files:[],impactedFiles:[],suggestedTests:[],requiresVerification:!1,context:""};let s=[];for(let d of r){let u=this.guard.analyzeFile(this.projectId,d);s.push({filePath:d,risk:u.risk,riskScore:u.riskScore,impactedFiles:u.impactedFiles,suggestedTests:u.suggestedTests,impactedCount:u.impacted.length})}let n="LOW";for(let d of s)at[d.risk]>at[n]&&(n=d.risk);let i=[...new Set(s.flatMap(d=>d.impactedFiles))],a=[...new Set(s.flatMap(d=>d.suggestedTests))],c=s.reduce((d,u)=>d+u.riskScore,0),l=n==="HIGH"||n==="CRITICAL",p=["[TOOLNET IMPACT GUARD]",`Risk: ${n}`,`Risk score: ${c}`,`Files being changed: ${r.join(", ")}`,`Impacted files: ${i.length}`];return i.length&&p.push("Blast radius:",...i.slice(0,20).map(d=>`- ${d}`)),a.length&&p.push("Verify/tests:",...a.slice(0,15).map(d=>`- ${d}`)),l&&p.push("IMPORTANT: High blast radius. Inspect affected dependencies and run relevant tests after the edit."),{triggered:!0,tool:e,highestRisk:n,totalRiskScore:c,files:s,impactedFiles:i,suggestedTests:a,requiresVerification:l,context:p.join(`
8
+ `)}}};import{homedir as Dr}from"node:os";import{join as zr}from"node:path";import{DeleteObjectCommand as jr,GetObjectCommand as Pr,HeadObjectCommand as Rr,ListObjectsV2Command as kr,PutObjectCommand as Tr,S3Client as Mr}from"@aws-sdk/client-s3";import{getSignedUrl as Ir}from"@aws-sdk/s3-request-presigner";var he=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Mr({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,r="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Tr({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let t=await Ir(this.client,new Pr({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 Rr({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 jr({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let s=await this.client.send(new kr({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of s.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return t}};import{access as ct,mkdir as Ar,readFile as Lr,readdir as Nr,rm as Or,stat as lt,writeFile as Fr}from"node:fs/promises";import{dirname as $r,join as _r,relative as dt,resolve as Gr}from"node:path";var O=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Gr(this.root,t)}async put(e,t){let r=this.path(e);await Ar($r(r),{recursive:!0}),await Fr(r,t)}async get(e){try{return await Lr(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 ct(this.path(e)),!0}catch{return!1}}async delete(e){await Or(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await ct(t)}catch{return r}let s=async i=>{let a=await Nr(i,{withFileTypes:!0});for(let c of a){let l=_r(i,c.name);if(c.isDirectory()){await s(l);continue}let p=await lt(l);r.push({key:dt(this.root,l),size:p.size,updatedAt:p.mtime.toISOString()})}},n=await lt(t);return n.isDirectory()?await s(t):r.push({key:dt(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function pt(o){let e=o.localRoot??zr(Dr(),".toolnet-memory","storage");if(o.provider==="huggingface"){let t=o.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new he({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new O(e))}return new O(e)}var T=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 r=JSON.parse(t);if(!Array.isArray(r))throw new Error("Invalid memory snapshot");return r}async save(e,t){let r=JSON.stringify(t,null,2);await this.storage.put(this.key(e),r,"application/json")}};var ye=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 r=JSON.parse(t);if(r.version!==1||r.projectId!==e||!Array.isArray(r.records))throw new Error("Invalid vector snapshot");return r}async save(e){await this.storage.put(this.key(e.projectId),JSON.stringify(e),"application/json")}};function Br(o){return new Promise(e=>setTimeout(e,o))}async function mt(o,e={}){let t=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,n;for(let i=1;i<=t;i++)try{return await o()}catch(a){if(n=a,i>=t)break;let c=Math.min(s,r*2**(i-1)),l=Math.floor(Math.random()*Math.max(1,c*.2));await Br(c+l)}throw n}var Hr=new Set(["put","get","getText","delete","list"]);function ut(o,e={}){return new Proxy(o,{get(t,r){let s=Reflect.get(t,r,t);return typeof s!="function"?s:Hr.has(r)?(...n)=>mt(()=>Promise.resolve(s.apply(t,n)),e):s.bind(t)}})}function ft(o){let e=o.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function gt(o){let e=o.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var Se=class{constructor(e,t,r,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ft(s??r),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(),r=t,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}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"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
9
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=gt(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}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))}};function Wr(o){let e=o.metadata?.learningFingerprint;return typeof e=="string"?e:void 0}async function Vr(o,e){let t=`projects/${o.id}/memory/learned/`,r=await e.list(t),s=[];for(let n of r.filter(i=>i.key.includes("/batches/")&&i.key.endsWith(".json")).sort((i,a)=>i.key.localeCompare(a.key))){let i=await e.getText(n.key);if(i)try{let a=JSON.parse(i);if(a.version!==1||!Array.isArray(a.candidates))continue;s.push(a)}catch{}}return s}async function ht(o,e){let t=await Vr(o,e),r=new T(e),s=await r.load(o.id),n=new R;n.importRecords(s);let i=new Set(s.map(p=>Wr(p)).filter(p=>!!p)),a=0,c=0,l=0;for(let p of t)for(let d of p.candidates){if(a+=1,i.has(d.fingerprint)){l+=1;continue}n.remember({projectId:o.id,type:d.type,content:d.content,importance:d.importance,tags:d.tags,source:"session-memory-learner",metadata:{learningFingerprint:d.fingerprint,learningKind:d.kind,confidence:d.confidence,provenance:d.provenance,sourceCreatedAt:d.createdAt,sessionKey:d.sessionKey,agent:d.agent,nativeSessionId:d.nativeSessionId}}),i.add(d.fingerprint),c+=1}return c>0&&await r.save(o.id,n.exportProject(o.id)),{batches:t.length,candidates:a,added:c,duplicates:l,memories:n.exportProject(o.id).length}}var Ur=["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"],be=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",r){let s=new Date().toISOString(),n=s.replace(/[:.]/g,"-"),i=this.projectPrefix(e),a=this.snapshotPrefix(e,n),c=[];for(let p of Ur){let d=`${i}/${p}`,u=await this.storage.get(d);u&&(await this.storage.put(`${a}/${p}`,u,"application/json"),c.push(p))}if(c.length===0)return null;let l={version:1,id:n,projectId:e,createdAt:s,reason:t,objects:c,metadata:r};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("/"),s=(await this.storage.list(t)).filter(i=>i.key.endsWith("/snapshot.json")),n=[];for(let i of s){let a=await this.storage.getText(i.key);if(a)try{n.push(JSON.parse(a))}catch{}}return n.sort((i,a)=>a.createdAt.localeCompare(i.createdAt))}async restore(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.getText(`${r}/snapshot.json`);if(!s)throw new Error(`Snapshot not found: ${t}`);let n=JSON.parse(s);if(n.projectId!==e)throw new Error("Snapshot project mismatch");let i=this.projectPrefix(e),a=[];for(let c of n.objects){let l=await this.storage.get(`${r}/${c}`);l&&(await this.storage.put(`${i}/${c}`,l,"application/json"),a.push(c))}return{restored:a}}async remove(e,t){let r=this.snapshotPrefix(e,t),s=await this.storage.list(r);for(let n of s)await this.storage.delete(n.key);return s.length}async prune(e,t=10){let s=(await this.list(e)).slice(t),n=0;for(let i of s)await this.remove(e,i.id),n++;return n}};import{closeSync as qr,mkdirSync as Jr,openSync as Yr,readFileSync as Zr,unlinkSync as yt,writeFileSync as Qr}from"node:fs";import{tmpdir as Xr}from"node:os";import{join as St}from"node:path";function eo(o){try{return process.kill(o,0),!0}catch(e){return e?.code==="EPERM"}}var xe=class{acquired=!1;path;exitHandler=()=>{this.releaseSync()};constructor(e){let t=St(Xr(),"toolnet-memory-locks");Jr(t,{recursive:!0});let r=e.replace(/[^A-Za-z0-9_.-]/g,"_");this.path=St(t,`${r}.lock`)}async acquire(){if(!this.acquired){for(let e=0;e<2;e++)try{let t=Yr(this.path,"wx");Qr(t,JSON.stringify({pid:process.pid,createdAt:new Date().toISOString()})),qr(t),this.acquired=!0,process.once("exit",this.exitHandler);return}catch(t){if(t?.code!=="EEXIST")throw t;let r=!0;try{let s=JSON.parse(Zr(this.path,"utf8"));Number.isInteger(s.pid)&&eo(s.pid)&&(r=!1)}catch{r=!0}if(!r)throw new Error("ToolNet Memory is already running for this project");try{yt(this.path)}catch{}}throw new Error("Unable to acquire ToolNet Memory project lock")}}async release(){this.releaseSync()}releaseSync(){if(this.acquired){try{yt(this.path)}catch{}this.acquired=!1,process.off("exit",this.exitHandler)}}};var ve=class{constructor(e){this.options=e;this.memoryStore=new T(e.storage),this.graphStore=new k(e.storage),this.vectorStore=new ye(e.storage),this.processLock=new xe(e.project.id),this.retrieval=new U(this.memory),this.references=new Y(this.graph),this.hooks=new me({projectId:e.project.id,memory:this.memory,memoryStore:this.memoryStore,maxEventsBeforeFlush:100});let t=new ue(this.memory,this.retrieval,this.graph);this.autoRetrieval=new fe(this.hooks,t,e.project.id),this.impactGuard=new X(this.graph),this.autoImpactGuard=new ge(this.impactGuard,e.project.id)}options;memory=new R;graph=new C;vectors=new A;retrieval;references;hooks;autoRetrieval;impactGuard;autoImpactGuard;memoryStore;graphStore;vectorStore;processLock;async start(){let{project:e}=this.options;await this.processLock.acquire(),await ht(e,this.options.storage);let t=await this.memoryStore.load(e.id);this.memory.importRecords(t);let s=new D(this.memory).run(e.id);(s.expiredRemoved>0||s.supersededRemoved>0)&&await this.memoryStore.save(e.id,this.memory.exportProject(e.id));let n=await this.graphStore.load(e.id);n&&this.graph.import(n.symbols,n.edges);let i=Me(),c=await new L(e.id,this.options.embeddingModel,i,this.vectors,this.vectorStore).initialize(this.memory.list(e.id));return await this.hooks.sessionStart(),{memories:t.length,graphSymbols:this.graph.allSymbols(e.id).length,graphEdges:this.graph.allEdges(e.id).length,vectors:c.total,vectorsIndexed:c.indexed}}async preparePrompt(e){return this.autoRetrieval.prepare(e)}async beforeTool(e,t){let r=await this.autoImpactGuard.beforeTool(e,t);return await this.hooks.beforeTool(e,t),r}async afterTool(e,t){return this.hooks.afterTool(e,t)}async stop(){let{project:e,storage:t,embeddingModel:r}=this.options,s=new be(t),n=await s.create(e.id,"session-end-auto");await s.prune(e.id,10),await this.hooks.sessionEnd();let i=new z(this.memory).consolidate(e.id);i.summaryCreated&&await this.memoryStore.save(e.id,this.memory.exportProject(e.id));let a=await new te(t).index(e.id,e.rootPath),c=await this.graphStore.load(e.id);c&&(this.graph.clearProject(e.id),this.graph.import(c.symbols,c.edges));let l=Me(),d=await new L(e.id,r,l,this.vectors,this.vectorStore).initialize(this.memory.list(e.id)),u={code:a,vectors:d,consolidation:i,snapshot:n?.id,memories:this.memory.list(e.id).length};return await this.processLock.release(),u}};import"dotenv/config";import{existsSync as to,readFileSync as ro}from"node:fs";import{homedir as oo}from"node:os";import{join as so}from"node:path";function no(o){let e=o.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
10
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function io(){let o=process.env.TOOLNET_GLOBAL_ENV??so(oo(),".config","toolnet-memory",".env");if(!to(o))return;let e=ro(o,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let n=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=no(r.slice(s+1)))}}io();function we(o,e){return o===void 0?e:["1","true","yes","on"].includes(o.toLowerCase())}function F(o,e){if(!o)return e;let t=Number(o);return Number.isFinite(t)?t:e}function bt(){return{memory:{autoCapture:we(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:we(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:we(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:we(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:F(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:F(process.env.MEMORY_RERANK_TOP,10),finalContext:F(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:F(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",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:F(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ao}from"node:crypto";import{existsSync as ze,mkdirSync as co,readFileSync as lo,renameSync as po,writeFileSync as mo}from"node:fs";import{basename as uo,dirname as Ee,join as je,parse as wt,resolve as $}from"node:path";var Et=".toolnet",fo="project.json";function go(o){return ao("sha256").update(o).digest("hex").slice(0,16)}function Be(o){return je(o,Et,fo)}function ho(o){return ze(Be(o))}function yo(o,e){let t=$(o),r=wt(t).root;for(;;){if(ho(t))return t;if(t===r||e&&t===$(e))break;let s=Ee(t);if(s===t)break;t=s}return null}function So(o){let e=$(o),t=wt(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>ze(je(e,n))))return e;if(e===t)break;let s=Ee(e);if(s===e)break;e=s}return $(o)}function bo(o){let e;try{e=JSON.parse(lo(o,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${o}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${o}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${o}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${o}`);let r=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:Ee(Ee(o)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 xt(o,e){let t=je(o,Et);co(t,{recursive:!0});let r=Be(o),s=`${r}.tmp-${process.pid}`;mo(s,JSON.stringify(e,null,2)+`
11
+ `,{encoding:"utf8",mode:384}),po(s,r)}function vt(o,e){return{id:o.id,name:o.name,remote:o.remote,rootPath:e,createdAt:o.createdAt,updatedAt:o.updatedAt,graphVersion:o.graphVersion,memoryVersion:o.memoryVersion,metadata:o.metadata}}var Ce=class{detect(e=process.cwd()){let t=$(e),r=So(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>ze(je(r,p))),i=yo(t,n?r:void 0);if(i){let p=Be(i),d=bo(p);return d.rootPath!==i&&(d.rootPath=i,d.updatedAt=new Date().toISOString(),xt(i,d)),vt(d,i)}let a=new Date().toISOString(),c=uo(r),l={version:1,id:go(r),name:c,remote:c,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return xt(r,l),vt(l,r)}};function Ct(o=process.cwd()){let e=bt(),t=new Ce().detect(o),r=pt({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),s=ut(r,{attempts:Number(process.env.TOOLNET_STORAGE_RETRIES??3)}),n=new Se(s,t.id,t.name,t.remote??t.name),i=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2";return new ve({project:t,storage:n,embeddingModel:i})}async function xo(){let o=Ct(),e=await o.start(),t=await o.preparePrompt("Ti\u1EBFp t\u1EE5c c\xF4ng vi\u1EC7c hi\u1EC7n t\u1EA1i");console.log({started:!0,...e,contextCharacters:t.context.length});let r=await o.stop();console.log({stopped:!0,memories:r.memories,codeParsed:r.code.parsed,vectorsIndexed:r.vectors.indexed})}xo().catch(o=>{console.error(o),process.exit(1)});
@@ -0,0 +1,6 @@
1
+ import"dotenv/config";import{existsSync as ue,readFileSync as ge}from"node:fs";import{homedir as he}from"node:os";import{join as ye}from"node:path";function Se(s){let e=s.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 be(){let s=process.env.TOOLNET_GLOBAL_ENV??ye(he(),".config","toolnet-memory",".env");if(!ue(s))return;let e=ge(s,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let n=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(n)&&process.env[n]===void 0&&(process.env[n]=Se(r.slice(o+1)))}}be();function N(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function k(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function Q(){return{memory:{autoCapture:N(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:N(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:N(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:N(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:k(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:k(process.env.MEMORY_RERANK_TOP,10),finalContext:k(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:k(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:k(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as xe}from"node:crypto";import{existsSync as V,mkdirSync as Ee,readFileSync as Ce,renameSync as we,writeFileSync as ve}from"node:fs";import{basename as Pe,dirname as A,join as I,parse as te,resolve as T}from"node:path";var re=".toolnet",ke="project.json";function Te(s){return xe("sha256").update(s).digest("hex").slice(0,16)}function U(s){return I(s,re,ke)}function Re(s){return V(U(s))}function je(s,e){let t=T(s),r=te(t).root;for(;;){if(Re(t))return t;if(t===r||e&&t===T(e))break;let o=A(t);if(o===t)break;t=o}return null}function Le(s){let e=T(s),t=te(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(n=>V(I(e,n))))return e;if(e===t)break;let o=A(e);if(o===e)break;e=o}return T(s)}function Ne(s){let e;try{e=JSON.parse(Ce(s,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${s}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);let r=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:A(A(s)),createdAt:typeof t.createdAt=="string"?t.createdAt:r,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:r,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 X(s,e){let t=I(s,re);Ee(t,{recursive:!0});let r=U(s),o=`${r}.tmp-${process.pid}`;ve(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),we(o,r)}function ee(s,e){return{id:s.id,name:s.name,remote:s.remote,rootPath:e,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var M=class{detect(e=process.cwd()){let t=T(e),r=Le(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>V(I(r,d))),i=je(t,n?r:void 0);if(i){let d=U(i),p=Ne(d);return p.rootPath!==i&&(p.rootPath=i,p.updatedAt=new Date().toISOString(),X(i,p)),ee(p,i)}let c=new Date().toISOString(),l=Pe(r),a={version:1,id:Te(r),name:l,remote:l,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return X(r,a),ee(a,r)}};var Ae=[{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}],O=class{scan(e){let t=[];for(let r of Ae){let o=new RegExp(r.regex.source,r.regex.flags);for(let n of e.matchAll(o))t.push({type:r.type,value:n[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var R=class{scanner=new O;sanitize(e){let t=e,r=this.scanner.scan(e),o=new Set;for(let n of r)o.add(n.type),t=t.split(n.value).join(`[REDACTED:${n.type}]`);return{text:t,redacted:r.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[r,o]of Object.entries(e)){let n=r.toLowerCase();n.includes("password")||n.includes("secret")||n.includes("token")||n.includes("cookie")||n.includes("authorization")?t[r]="[REDACTED]":t[r]=this.sanitizeValue(o)}return t}return e}};import{homedir as Je}from"node:os";import{join as qe}from"node:path";import{DeleteObjectCommand as Me,GetObjectCommand as Ie,HeadObjectCommand as Oe,ListObjectsV2Command as Fe,PutObjectCommand as _e,S3Client as $e}from"@aws-sdk/client-s3";import{getSignedUrl as Ge}from"@aws-sdk/s3-request-presigner";var F=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new $e({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,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new _e({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await Ge(this.client,new Ie({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(t,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.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 Oe({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 Me({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Fe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let n of o.Contents??[])n.Key&&t.push({key:n.Key,size:n.Size,updatedAt:n.LastModified?.toISOString()});r=o.IsTruncated?o.NextContinuationToken:void 0}while(r);return t}};import{access as se,mkdir as De,readFile as ze,readdir as Be,rm as He,stat as oe,writeFile as Ke}from"node:fs/promises";import{dirname as We,join as Ve,relative as ne,resolve as Ue}from"node:path";var j=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return Ue(this.root,t)}async put(e,t){let r=this.path(e);await De(We(r),{recursive:!0}),await Ke(r,t)}async get(e){try{return await ze(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 se(this.path(e)),!0}catch{return!1}}async delete(e){await He(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await se(t)}catch{return r}let o=async i=>{let c=await Be(i,{withFileTypes:!0});for(let l of c){let a=Ve(i,l.name);if(l.isDirectory()){await o(a);continue}let d=await oe(a);r.push({key:ne(this.root,a),size:d.size,updatedAt:d.mtime.toISOString()})}},n=await oe(t);return n.isDirectory()?await o(t):r.push({key:ne(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};function ie(s){let e=s.localRoot??qe(Je(),".toolnet-memory","storage");if(s.provider==="huggingface"){let t=s.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new F({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new j(e))}return new j(e)}var L=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 _=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 $=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 ae(s){let e=s.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function ce(s){let e=s.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 r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[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 G=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ae(o??r),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(),r=t,o=await this.provider.getText(e);if(o){let i;try{i=JSON.parse(o)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}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"&&(r=i.createdAt)}let n={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(n,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=ce(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,r){return await this.ensureRegistered(),this.provider.put(this.key(e),t,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import Yr from"typescript";var C=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(r=>r.projectId===e&&(r.name===t||r.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 r of e)this.addSymbol(r);for(let r of t)this.addEdge(r)}clearProject(e){for(let[t,r]of this.symbols)r.projectId===e&&this.symbols.delete(t);for(let[t,r]of this.edges)r.projectId===e&&this.edges.delete(t)}};import{execFile as Xe}from"node:child_process";import{promisify as et}from"node:util";var fs=et(Xe);import{createHash as tt}from"node:crypto";import{readFile as rt}from"node:fs/promises";import{join as st}from"node:path";function le(s){return tt("sha256").update(s).digest("hex")}var D=class{sanitizer=new R;async build(e,t,r,o={}){let n=o.maxLines??80,i=o.overlapLines??10,c=new Map;for(let a of r){let d=c.get(a.filePath)??[];d.push(a),c.set(a.filePath,d)}let l=[];for(let[a,d]of c){let p;try{p=await rt(st(t,a),"utf8")}catch{continue}let f=p.split(/\r?\n/),g=d.filter(u=>u.type!=="file"&&typeof u.startLine=="number"&&typeof u.endLine=="number");if(g.length>0)for(let u of g)l.push(...this.chunkRange({projectId:e,filePath:a,lines:f,symbol:u,startLine:u.startLine,endLine:u.endLine,maxLines:n,overlapLines:i}));else l.push(...this.chunkRange({projectId:e,filePath:a,lines:f,startLine:1,endLine:Math.max(1,f.length),maxLines:n,overlapLines:i}))}return l}chunkRange(e){let{projectId:t,filePath:r,lines:o,symbol:n,maxLines:i}=e,c=Math.min(e.overlapLines,Math.max(0,i-1)),l=Math.max(1,e.startLine),a=Math.min(o.length,Math.max(l,e.endLine)),d=[],p=l,f=0;for(;p<=a;){let g=Math.min(a,p+i-1),u=o.slice(p-1,g).join(`
5
+ `).trim();if(u){let S=this.sanitizer.sanitize(u).text,w=le(S),v=[t,r,n?.id??"file",String(f),w].join(":");d.push({id:le(v).slice(0,32),projectId:t,filePath:r,symbolId:n?.id,symbolName:n?.qualifiedName??n?.name,symbolType:n?.type,startLine:p,endLine:g,content:S,contentHash:w})}if(g>=a)break;p=g-c+1,f++}return d}};var z=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[r,o]of this.records)o.projectId===e&&(this.records.delete(r),t++);return t}exportProject(e){return[...this.records.values()].filter(t=>t.projectId===e)}importRecords(e){let t=0;for(let r of e)!r?.id||!r?.projectId||!Array.isArray(r.vector)||(this.records.set(r.id,r),t++);return t}search(e,t,r=10){let o=[];for(let n of this.records.values()){if(n.projectId!==e)continue;let i=ot(t,n.vector);o.push({id:n.id,score:i,metadata:n.metadata})}return o.sort((n,i)=>i.score-n.score).slice(0,r)}size(){return this.records.size}};function ot(s,e){if(s.length===0||e.length===0||s.length!==e.length)return 0;let t=0,r=0,o=0;for(let n=0;n<s.length;n++){let i=s[n]??0,c=e[n]??0;t+=i*c,r+=i*i,o+=c*c}return r===0||o===0?0:t/(Math.sqrt(r)*Math.sqrt(o))}function J(s){return s.toLowerCase().normalize("NFKC").replace(/[^\p{L}\p{N}_\-./]+/gu," ").split(/\s+/).map(e=>e.trim()).filter(e=>e.length>1)}function de(s,e){let t=s.toLowerCase().replaceAll("\\","/"),r=e.toLowerCase(),o=/\b(test|tests|spec|fixture|mock)\b/.test(r);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 B=class{constructor(e){this.options=e}options;vectors=new z;chunks=new Map;async initialize(){let{projectId:e,rootPath:t,storage:r,embeddings:o,graph:n,model:i}=this.options,c=new _(r),l=new $(r),a=await new D().build(e,t,n.allSymbols(e));this.chunks.clear();for(let m of a)this.chunks.set(m.id,m);let d=await c.load(e),p=!d||d.chunks.length!==a.length||d.chunks.some(m=>!this.chunks.has(m.id));p&&await c.save({version:1,projectId:e,updatedAt:new Date().toISOString(),chunks:a});let f=await l.load(e),g=0;f&&f.model===i&&(g=this.vectors.importRecords(f.records));let u=new Set(a.map(m=>m.id)),S=0;for(let m of this.vectors.exportProject(e))u.has(m.id)||this.vectors.remove(m.id)&&S++;let w=a.filter(m=>{let x=this.vectors.get(m.id);return x?x.metadata?.contentHash!==m.contentHash:!0}),v=0,Y=8,P=this.vectors.exportProject(e)[0]?.vector.length;for(let m=0;m<w.length;m+=Y){let x=w.slice(m,m+Y),me=x.map(h=>[`file: ${h.filePath}`,h.symbolName?`symbol: ${h.symbolName}`:"",h.symbolType?`type: ${h.symbolType}`:"",h.content].filter(Boolean).join(`
6
+ `)),fe=await o.embedMany(me);for(let h=0;h<x.length;h++){let b=x[h],E=fe[h];if(!(!b||!E||E.length===0)){if(P===void 0&&(P=E.length),E.length!==P){console.warn(`[code-semantic] skip dimension mismatch: ${E.length} != ${P}`);continue}this.vectors.upsert({id:b.id,projectId:e,vector:E,metadata:{contentHash:b.contentHash,filePath:b.filePath,symbolName:b.symbolName,symbolType:b.symbolType,startLine:b.startLine,endLine:b.endLine}}),v++}}}let W=this.vectors.exportProject(e),Z=v>0||S>0||!f||f.model!==i;return Z&&await l.save({version:1,projectId:e,model:i,dimensions:W[0]?.vector.length??P??0,updatedAt:new Date().toISOString(),records:W}),{chunks:a.length,vectorsLoaded:g,vectorsIndexed:v,vectorsRemoved:S,totalVectors:W.length,savedChunks:p,savedVectors:Z}}async search(e,t=8){let r=await this.options.embeddings.embed(e),o=this.vectors.search(this.options.projectId,r,Math.max(t*4,20)),n=new Set(J(e)),i=[];for(let c of o){let l=this.chunks.get(c.id);if(!l)continue;let a=new Set(J([l.filePath,l.symbolName??"",l.symbolType??"",l.content].join(" "))),d=0;for(let S of n)a.has(S)&&d++;let p=n.size===0?0:d/n.size,f=Math.max(0,c.score),g=de(l.filePath,e),u=(f*.75+p*.25)*g;i.push({chunk:l,score:u,vectorScore:f,lexicalScore:p})}return i.sort((c,l)=>l.score-c.score).slice(0,t)}size(){return this.chunks.size}};import yo from"typescript";import y from"typescript";var wo=new Set([y.SyntaxKind.EqualsToken,y.SyntaxKind.PlusEqualsToken,y.SyntaxKind.MinusEqualsToken,y.SyntaxKind.AsteriskEqualsToken,y.SyntaxKind.SlashEqualsToken,y.SyntaxKind.PercentEqualsToken,y.SyntaxKind.QuestionQuestionEqualsToken,y.SyntaxKind.AmpersandAmpersandEqualsToken,y.SyntaxKind.BarBarEqualsToken]);var H=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`,r=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(!r.ok)throw new Error(`HF embedding failed: ${r.status} ${await r.text()}`);let o=await r.json();if(!Array.isArray(o))throw new Error("HF embedding returned invalid response");return o.map(n=>it(n))}};function it(s){if(!Array.isArray(s))throw new Error("Invalid embedding");if(s.length>0&&typeof s[0]=="number")return s;if(s.length>0&&Array.isArray(s[0])){let e=s;if(e.length===0)return[];let t=e[0].length,r=new Array(t).fill(0);for(let o of e)for(let n=0;n<t;n++)r[n]+=o[n]??0;for(let o=0;o<t;o++)r[o]/=e.length;return r}throw new Error("Unsupported embedding shape")}import{createHash as at}from"node:crypto";var K=class{name="hash-fallback";dimensions=128;async embed(e){let t=new Array(this.dimensions).fill(0),r=e.toLowerCase().split(/\s+/).filter(Boolean);for(let o of r){let i=at("sha256").update(o).digest().readUInt32BE(0)%this.dimensions;t[i]+=1}return ct(t)}async embedMany(e){return Promise.all(e.map(t=>this.embed(t)))}};function ct(s){let e=Math.sqrt(s.reduce((t,r)=>t+r*r,0));return e===0?s:s.map(t=>t/e)}var q=class{constructor(e,t=new K){this.primary=e;this.fallback=t}primary;fallback;name="resilient";async embed(e){if(this.primary)try{return await this.primary.embed(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embed(e)}async embedMany(e){if(this.primary)try{return await this.primary.embedMany(e)}catch(t){console.warn("[embedding] primary failed, fallback enabled:",t instanceof Error?t.message:t)}return this.fallback.embedMany(e)}};function pe(){let s=process.env.HF_TOKEN,e=process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",t=s?new H({token:s,model:e}):null;return new q(t)}async function lt(){let s=Q(),e=new M().detect(),t=ie({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),r=new G(t,e.id,e.name,e.remote??e.name),o=new C,n=await new L(r).load(e.id);if(!n)throw new Error("Code graph missing. Run npm run code:index:test first.");o.import(n.symbols,n.edges);let i=new B({projectId:e.id,rootPath:e.rootPath,model:process.env.HF_EMBEDDING_MODEL??"sentence-transformers/all-MiniLM-L6-v2",storage:r,embeddings:pe(),graph:o}),c=await i.initialize(),l=process.argv.slice(2).join(" ")||"memory storage hugging face",a=await i.search(l,5);console.log({ok:!0,query:l,...c,results:a.map(d=>({score:Number(d.score.toFixed(4)),file:d.chunk.filePath,symbol:d.chunk.symbolName,lines:`${d.chunk.startLine}-${d.chunk.endLine}`,preview:d.chunk.content.replace(/\s+/g," ").slice(0,140)}))})}lt().catch(s=>{console.error(s),process.exit(1)});
@@ -0,0 +1 @@
1
+ import a from"node:fs";import n from"node:path";import{fileURLToPath as u}from"node:url";import{spawnSync as p}from"node:child_process";var s="toolnet-memory";function i(o,e,t={}){return p(o,e,{encoding:"utf8",stdio:t.capture?["ignore","pipe","pipe"]:"inherit"})}function g(){let o=n.dirname(u(import.meta.url));return n.resolve(o,"..")}function m(o){try{let e=JSON.parse(a.readFileSync(n.join(o,"package.json"),"utf8"));return String(e.version??"unknown")}catch{return"unknown"}}function d(o){let e=`${n.sep}lib${n.sep}node_modules${n.sep}${s}`;return o.endsWith(e)?o.slice(0,-e.length)||n.parse(o).root:null}function f(){let o=g(),e=m(o),t=i("npm",["view",`${s}@latest`,"version","--silent"],{capture:!0});t.status!==0&&(console.error("Unable to check the latest ToolNet Memory version."),t.stderr&&console.error(t.stderr.trim()),process.exit(1));let r=(t.stdout??"").trim();if(console.log(""),console.log("ToolNet Memory Update"),console.log("====================="),console.log(""),console.log(`Current: v${e}`),console.log(`Latest : v${r}`),console.log(""),e===r){console.log("\u2713 ToolNet Memory is already up to date"),console.log("");return}let l=d(o);l||(console.log("This appears to be a development checkout."),console.log(""),console.log("Self-update is disabled for source checkouts."),console.log(""),console.log("For the published CLI, install/update with:"),console.log(" npx toolnet-memory-install"),console.log(""),process.exit(1)),console.log(`Updating to v${r}...`),console.log("");let c=i("npm",["install","-g","--prefix",l,`${s}@latest`,"--no-fund","--no-audit","--loglevel=error"]);c.status!==0&&(console.error(""),console.error("\u2717 Update failed"),console.error(""),console.error("You can retry using:"),console.error(" npx toolnet-memory-install"),process.exit(c.status??1)),console.log(""),console.log(`\u2713 ToolNet Memory updated to v${r}`),console.log("")}f();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolnet-memory",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "tsx src/index.ts",