toolnet-memory 0.3.14 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +0 -1
- package/.release-target +1 -1
- package/README.md +25 -1
- package/bin/toolnet-memory +5 -0
- package/bundle/agy-hook.js +67 -67
- package/bundle/agy.js +61 -61
- package/bundle/api.js +15 -15
- package/bundle/auto-integrate.js +28 -28
- package/bundle/background-refresh.js +7 -7
- package/bundle/claude-hook.js +51 -50
- package/bundle/codex-context.js +25 -24
- package/bundle/codex.js +71 -71
- package/bundle/context-runtime.js +45 -44
- package/bundle/context.js +15 -15
- package/bundle/continuity-certify.js +13 -13
- package/bundle/copilot-hook.js +87 -85
- package/bundle/copilot.js +4 -4
- package/bundle/cursor-hook.js +87 -85
- package/bundle/cursor.js +4 -4
- package/bundle/doctor.js +4 -4
- package/bundle/full-index.js +20 -20
- package/bundle/gc.js +3 -0
- package/bundle/graph-index.js +4 -4
- package/bundle/graph-ui.js +3 -3
- package/bundle/grok-hook.js +60 -59
- package/bundle/grok.js +5 -5
- package/bundle/handoff-refresh.js +10 -10
- package/bundle/help-cli.js +4 -4
- package/bundle/impact.js +4 -4
- package/bundle/incremental.js +5 -4
- package/bundle/init.js +37 -37
- package/bundle/integration-status.js +4 -4
- package/bundle/kiro-hook.js +82 -81
- package/bundle/learner.js +6 -6
- package/bundle/mcp.js +17 -17
- package/bundle/memory-agent.js +7 -7
- package/bundle/memory-query.js +7 -7
- package/bundle/opencode.js +80 -80
- package/bundle/project-manual.js +7 -7
- package/bundle/recovery-certify.js +15 -15
- package/bundle/runtime.js +13 -12
- package/bundle/semantic.js +5 -5
- package/bundle/snapshot.js +4 -4
- package/bundle/status-cli.js +4 -4
- package/bundle/toolnet-cli.js +60 -60
- package/bundle/work-continuity.js +7 -7
- package/package.json +9 -3
- package/release-manifest.json +54 -3
package/bundle/graph-index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"dotenv/config";import{existsSync as
|
|
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
|
|
3
|
-
`,{encoding:"utf8",mode:384}),ye(o,r)}function J(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 I=class{detect(e=process.cwd()){let t=P(e),r=ve(t),n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>$(O(r,f))),i=we(t,n?r:void 0);if(i){let f=G(i),u=ke(f);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Y(i,u)),J(u,i)}let d=new Date().toISOString(),m=be(r),c={version:1,id:xe(r),name:m,remote:m,rootPath:r,createdAt:d,updatedAt:d,graphVersion:0,memoryVersion:0};return Y(r,c),J(c,r)}};import{readdir as Ae}from"node:fs/promises";import{extname as je,join as Le,relative as Ne}from"node:path";import{basename as Re}from"node:path";var Te=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Me=new Set([".pem",".key",".p12",".pfx"]);function Z(s){let e=Re(s).toLowerCase();if(Te.has(e))return!0;for(let t of Me)if(e.endsWith(t))return!0;return!1}var Ie=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Oe=new Set(["node_modules",".git","dist","build","coverage",".next",".cache",".toolnet-memory"]);async function K(s){let e=[];async function t(r){let o=await Ae(r,{withFileTypes:!0});for(let n of o){if(Oe.has(n.name))continue;let i=Le(r,n.name);if(n.isDirectory()){await t(i);continue}Ie.has(je(n.name))&&(Z(i)||e.push(Ne(s,i)))}}return await t(s),e.sort()}import{readFile as _e}from"node:fs/promises";import{join as Fe}from"node:path";import{createHash as De}from"node:crypto";import*as l from"typescript";function X(s,e){return De("sha256").update(`${s}:${e}`).digest("hex").slice(0,24)}function z(s,e){return s.getLineAndCharacterOfPosition(e.getStart(s)).line+1}async function B(s,e,t){let r=Fe(e,t),o=await _e(r,"utf8"),n=l.createSourceFile(t,o,l.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?l.ScriptKind.TSX:l.ScriptKind.TS),i=[],d=[],m=[],c=[],f={id:X(s,`file:${t}`),projectId:s,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:n.getLineAndCharacterOfPosition(n.end).line+1};i.push(f);let u=[],C=[];function b(a,y,h,g){let x=X(s,`${t}:${h}:${g??y}:${a.pos}`);return i.push({id:x,projectId:s,name:y,qualifiedName:g??y,type:h,filePath:t,startLine:z(n,a),endLine:n.getLineAndCharacterOfPosition(a.end).line+1}),x}function L(a){if(!l.isStringLiteral(a.moduleSpecifier))return;let y=[],h=a.importClause;if(h?.name&&y.push({localName:h.name.text,importedName:"default",kind:"default"}),h?.namedBindings&&l.isNamedImports(h.namedBindings))for(let g of h.namedBindings.elements)y.push({localName:g.name.text,importedName:g.propertyName?.text??g.name.text,kind:"named"});h?.namedBindings&&l.isNamespaceImport(h.namedBindings)&&y.push({localName:h.namedBindings.name.text,importedName:"*",kind:"namespace"}),d.push({source:a.moduleSpecifier.text,bindings:y})}function w(a,y){for(let h of a.heritageClauses??[])for(let g of h.types){let x=g.expression.getText(n).split(".").at(-1)??"";x&&c.push({fromId:y,targetName:x,type:h.token===l.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function H(a){let y=!1,h=!1;if(l.isImportDeclaration(a)&&L(a),l.isInterfaceDeclaration(a)&&b(a,a.name.text,"interface",a.name.text),l.isClassDeclaration(a)&&a.name){let g=b(a,a.name.text,"class",a.name.text);w(a,g),C.push({id:g,name:a.name.text}),h=!0}if(l.isFunctionDeclaration(a)&&a.name){let g=b(a,a.name.text,"function",a.name.text);u.push(g),y=!0}if(l.isMethodDeclaration(a)&&a.name){let g=a.name.getText(n),x=C.at(-1)?.name,ae=b(a,g,"method",x?`${x}.${g}`:g);u.push(ae),y=!0}if(l.isCallExpression(a)&&(l.isIdentifier(a.expression)&&m.push({callerId:u.at(-1),calleeName:a.expression.text,line:z(n,a)}),l.isPropertyAccessExpression(a.expression))){let g=a.expression;m.push({callerId:u.at(-1),qualifier:g.expression.getText(n),calleeName:g.name.text,line:z(n,a)})}l.forEachChild(a,H),y&&u.pop(),h&&C.pop()}return H(n),{filePath:t,symbols:i,imports:d,calls:m,heritage:c}}import{createHash as $e}from"node:crypto";import{dirname as Ge,extname as Ke,normalize as ze,posix as Be}from"node:path";var R=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 We(s,e,t,r){return $e("sha256").update(`${s}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function E(s){return ze(s).replaceAll("\\","/")}function W(s,e,t){if(!e.startsWith("."))return;let r=E(Be.join(Ge(s),e)),o=Ke(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(E(i)))}var T=class{build(e,t){let r=new R,o=new Map;for(let i of t)for(let d of i.symbols)r.addSymbol(d),d.type==="file"&&o.set(E(i.filePath),d);let n=new Set(o.keys());for(let i of t){let d=E(i.filePath),m=o.get(d);if(m){for(let c of i.symbols)c.id!==m.id&&r.addEdge(this.edge(e,m.id,"DEFINES",c.id));for(let c of i.imports){let f=W(d,c.source,n);if(!f)continue;let u=o.get(f);u&&r.addEdge(this.edge(e,m.id,"IMPORTS",u.id,{source:c.source}))}for(let c of i.heritage){let f=r.findByName(e,c.targetName).filter(u=>u.type==="class"||u.type==="interface");for(let u of f)r.addEdge(this.edge(e,c.fromId,c.type,u.id))}for(let c of i.calls){if(!c.callerId)continue;let f=this.resolveCallTargets(e,i,c.calleeName,c.qualifier,t,r,n);for(let u of f)u.id!==c.callerId&&r.addEdge(this.edge(e,c.callerId,"CALLS",u.id,{line:c.line,qualifier:c.qualifier}))}}}return r}resolveCallTargets(e,t,r,o,n,i,d){let m=E(t.filePath),c=i.findByName(e,r).filter(f=>E(f.filePath)===m);if(!o&&c.length)return c;if(o)for(let f of t.imports){if(!f.bindings.find(b=>b.kind==="namespace"&&b.localName===o))continue;let C=W(m,f.source,d);if(C)return i.findByName(e,r).filter(b=>E(b.filePath)===C)}for(let f of t.imports){let u=f.bindings.find(w=>w.localName===r);if(!u)continue;let C=W(m,f.source,d);if(!C)continue;let b=u.importedName==="default"?r:u.importedName,L=i.findByName(e,b).filter(w=>E(w.filePath)===C);if(L.length)return L}return i.findByName(e,r).filter(f=>f.type==="function"||f.type==="method")}edge(e,t,r,o,n){return{id:We(e,t,r,o),projectId:e,from:t,to:o,type:r,metadata:n}}};var _=class{async index(e,t,r={}){let o=await K(t);r.onProgress?.({phase:"scan",current:o.length,total:o.length});let n=[],i=0;for(let m of o)try{n.push(await B(e,t,m))}catch(c){console.warn(`[indexer] skipped ${m}:`,c instanceof Error?c.message:c)}finally{i+=1,r.onProgress?.({phase:"parse",current:i,total:o.length,file:m})}let d=new T().build(e,n);return{files:n.length,symbols:d.allSymbols(e).length,edges:d.allEdges(e).length,graph:d}}};function ee(s,e){let t=s.allSymbols(e),r=s.allEdges(e),o=i=>t.filter(d=>d.type===i).length,n=i=>r.filter(d=>d.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 Ue}from"node:child_process";import{promisify as He}from"node:util";var Nr=He(Ue);var M=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{DatabaseSync as xs}from"node:sqlite";import*as S from"typescript";import*as p from"typescript";var zs=new Set([p.SyntaxKind.EqualsToken,p.SyntaxKind.PlusEqualsToken,p.SyntaxKind.MinusEqualsToken,p.SyntaxKind.AsteriskEqualsToken,p.SyntaxKind.SlashEqualsToken,p.SyntaxKind.PercentEqualsToken,p.SyntaxKind.QuestionQuestionEqualsToken,p.SyntaxKind.AmpersandAmpersandEqualsToken,p.SyntaxKind.BarBarEqualsToken]);import{homedir as ht}from"node:os";import{join as yt}from"node:path";import{DeleteObjectCommand as Ye,GetObjectCommand as Je,HeadObjectCommand as qe,ListObjectsV2Command as Qe,PutObjectCommand as Ze,S3Client as Xe}from"@aws-sdk/client-s3";import{getSignedUrl as et}from"@aws-sdk/s3-request-presigner";var F=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Xe({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 Ze({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await et(this.client,new Je({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 qe({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 Ye({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new Qe({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 te,mkdir as tt,readFile as rt,readdir as st,rm as ot,stat as re,writeFile as nt}from"node:fs/promises";import{dirname as it,join as at,relative as se,resolve as ct}from"node:path";var A=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return ct(this.root,t)}async put(e,t){let r=this.path(e);await tt(it(r),{recursive:!0}),await nt(r,t)}async get(e){try{return await rt(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 te(this.path(e)),!0}catch{return!1}}async delete(e){await ot(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await te(t)}catch{return r}let o=async i=>{let d=await st(i,{withFileTypes:!0});for(let m of d){let c=at(i,m.name);if(m.isDirectory()){await o(c);continue}let f=await re(c);r.push({key:se(this.root,c),size:f.size,updatedAt:f.mtime.toISOString()})}},n=await re(t);return n.isDirectory()?await o(t):r.push({key:se(this.root,t),size:n.size,updatedAt:n.mtime.toISOString()}),r}};import{DeleteObjectCommand as lt,GetObjectCommand as dt,HeadObjectCommand as pt,ListObjectsV2Command as ut,PutObjectCommand as ft,S3Client as mt}from"@aws-sdk/client-s3";import{getSignedUrl as gt}from"@aws-sdk/s3-request-presigner";var j=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new mt({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new ft({Bucket:this.bucket,Key:e,Body:o,ContentType:r}))}async get(e){let t=await gt(this.client,new dt({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(`${this.name} 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 pt({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 lt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let o=await this.client.send(new ut({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}};function U(s,e){return console.warn(e),new A(s)}function oe(s){let e=s.localRoot??yt(ht(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new j({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):U(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new j({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):U(e,"[storage] S3 credentials missing. Using local fallback.")}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}):U(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new A(e)}function ne(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 ie(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 D=class{constructor(e,t,r,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ne(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=
|
|
1
|
+
import"dotenv/config";import{existsSync as xe,readFileSync as Ce}from"node:fs";import{homedir as Ee}from"node:os";import{join as we}from"node:path";function ve(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 ke(){let s=process.env.TOOLNET_GLOBAL_ENV??we(Ee(),".config","toolnet-memory",".env");if(!xe(s))return;let e=Ce(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 n=r.indexOf("=");if(n<=0)continue;let o=r.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=ve(r.slice(n+1)))}}ke();function M(s,e){return s===void 0?e:["1","true","yes","on"].includes(s.toLowerCase())}function T(s,e){if(!s)return e;let t=Number(s);return Number.isFinite(t)?t:e}function Z(){return{memory:{autoCapture:M(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:M(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:M(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:M(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:T(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:T(process.env.MEMORY_RERANK_TOP,10),finalContext:T(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:T(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:M(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:T(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Pe}from"node:crypto";import{existsSync as _,mkdirSync as Re,readFileSync as Me,renameSync as Te,writeFileSync as Ae}from"node:fs";import{basename as je,dirname as F,join as A,parse as re,resolve as R}from"node:path";var se=".toolnet",Ie="project.json";function Le(s){return Pe("sha256").update(s).digest("hex").slice(0,16)}function D(s){return A(s,se,Ie)}function Ne(s){return _(D(s))}function Q(s,e){let t=R(s),r=re(t).root;for(;;){if(Ne(t))return t;if(t===r||e&&t===R(e))break;let n=F(t);if(n===t)break;t=n}return null}function X(s){let e=R(s),t=re(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>_(A(e,o))))return e;if(e===t)break;let n=F(e);if(n===e)break;e=n}return R(s)}function ee(s){let e;try{e=JSON.parse(Me(s,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${s}: ${n instanceof Error?n.message:String(n)}`)}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:F(F(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 te(s,e){let t=A(s,se);Re(t,{recursive:!0});let r=D(s),n=`${r}.tmp-${process.pid}`;Ae(n,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Te(n,r)}function H(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 $=class{findExisting(e=process.cwd()){let t=R(e),r=X(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>_(A(r,p))),i=Q(t,o?r:void 0);if(!i)return null;let a=ee(D(i));return H(a,i)}requireExisting(e=process.cwd()){let t=this.findExisting(e);if(!t)throw new Error("PROJECT_NOT_INITIALIZED");return t}detect(e=process.cwd()){let t=R(e),r=X(t),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>_(A(r,l))),i=Q(t,o?r:void 0);if(i){let l=D(i),u=ee(l);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),te(i,u)),H(u,i)}let a=new Date().toISOString(),p=je(r),c={version:1,id:Le(r),name:p,remote:p,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return te(r,c),H(c,r)}};var Oe=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],_e=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function ne(s){return s.normalize("NFKC").trim().toLowerCase()}function Fe(s){if(s.length===0)return 0;let e=new Map;for(let r of s)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let n=r/s.length;t-=n*Math.log2(n)}return t}function De(s){return/^[a-f0-9]{32}$/iu.test(s)||/^[a-f0-9]{40}$/iu.test(s)||/^[a-f0-9]{64}$/iu.test(s)}function $e(s,e,t){let r=s.slice(Math.max(0,e-48),e),n=s.slice(t,Math.min(s.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${n}`)}function Ge(s,e){return s.start<e.end&&e.start<s.end}function oe(s){return s.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var G=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=ne(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let o of Oe){let i=new RegExp(o.regex.source,o.regex.flags);for(let a of e.matchAll(i))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:o.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=oe(t),n=[];for(let o of r)n.some(i=>Ge(i,o))||n.push(o);return oe(n)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=ne(e);return _e.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let n of e.matchAll(r)){if(n.index===void 0||!n[0])continue;let o=n[0];this.allowed(o)||De(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||$e(e,n.index,n.index+o.length)&&(Fe(o)<3.7||t.push({type:"high_entropy_secret",value:o,start:n.index,end:n.index+o.length,confidence:"heuristic"}))}return t}};var j=class{scanner;constructor(e={}){this.scanner=new G(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,n=[...t].sort((i,a)=>a.start-i.start),o=new Set;for(let i of n)o.add(i.type),r=r.slice(0,i.start)+`[REDACTED:${i.type}]`+r.slice(i.end);return{text:r,redacted:t.length,secretTypes:[...o].sort()}}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,n]of Object.entries(e)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){t[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(n)}return t}return e}};var nr=new j;import{lstat as We,readdir as Ue}from"node:fs/promises";import{extname as He,join as Ve,relative as Ye,resolve as Je}from"node:path";import{basename as ze}from"node:path";var Ke=new Set([".env",".env.local",".env.production",".env.development","id_rsa","id_ed25519","credentials","credentials.json","service-account.json"]),Be=new Set([".pem",".key",".p12",".pfx"]);function ie(s){let e=ze(s).toLowerCase();if(Ke.has(e))return!0;for(let t of Be)if(e.endsWith(t))return!0;return!1}var qe=2*1024*1024,Ze=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".mts",".cts"]),Qe=new Set(["node_modules",".git",".toolnet",".toolnet-memory","dist","build","out","coverage",".next",".nuxt",".cache",".parcel-cache",".turbo","vendor","target"]);function ae(s,e){if(!Number.isSafeInteger(s)||s<1)throw new Error(`${e} must be a positive integer`);return s}function ce(s){if(s?.aborted)throw new Error("Repository scan aborted")}function Xe(s){let e=s.trim().toLowerCase();if(!e)throw new Error("Repository scan extension cannot be empty");return e.startsWith(".")?e:`.${e}`}function et(s){let e=s.toLowerCase();return/\.min\.(?:js|mjs|cjs)$/u.test(e)||/\.bundle\.(?:js|mjs|cjs)$/u.test(e)}function tt(s){return s.replaceAll("\\","/")}async function le(s,e={}){let t=Je(s),r=e.maxFileBytes??qe;if(!Number.isSafeInteger(r)||r<1)throw new Error("maxFileBytes must be a positive integer");let n=e.maxFiles??Number.MAX_SAFE_INTEGER;ae(n,"maxFiles");let o=e.progressInterval??1e3;ae(o,"progressInterval");let i=new Set(e.extensions?[...e.extensions].map(Xe):Ze),a=new Set(Qe);for(let u of e.extraIgnoredDirectories??[]){let f=u.trim();f&&a.add(f)}let p=[],c={directories:0,entries:0,accepted:0,skippedIgnoredDirectories:0,skippedSymlinks:0,skippedGenerated:0,skippedSensitive:0,skippedOversized:0,skippedUnreadable:0},l=[t];for(;l.length>0;){ce(e.signal);let u=l.pop(),f;try{f=await Ue(u,{withFileTypes:!0})}catch{c.skippedUnreadable+=1;continue}c.directories+=1;for(let h of f){ce(e.signal),c.entries+=1,c.entries%o===0&&e.onProgress?.({directories:c.directories,entries:c.entries,accepted:c.accepted});let C=Ve(u,h.name);if(h.isSymbolicLink()){c.skippedSymlinks+=1;continue}if(h.isDirectory()){if(a.has(h.name)){c.skippedIgnoredDirectories+=1;continue}l.push(C);continue}if(!h.isFile())continue;let k=He(h.name).toLowerCase();if(!i.has(k))continue;if(et(h.name)){c.skippedGenerated+=1;continue}if(ie(C)){c.skippedSensitive+=1;continue}let P;try{P=await We(C)}catch{c.skippedUnreadable+=1;continue}if(P.isSymbolicLink()){c.skippedSymlinks+=1;continue}if(P.isFile()){if(P.size>r){c.skippedOversized+=1;continue}if(p.length>=n)throw new Error(`Repository scan file limit exceeded: ${n}`);p.push(tt(Ye(t,C))),c.accepted+=1}}}return p.sort(),e.onProgress?.({directories:c.directories,entries:c.entries,accepted:c.accepted}),{files:p,stats:c}}import{createHash as rt}from"node:crypto";import{dirname as st,extname as nt,normalize as ot,posix as it}from"node:path";var z=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 at(s,e,t,r){return rt("sha256").update(`${s}:${e}:${t}:${r}`).digest("hex").slice(0,24)}function E(s){return ot(s).replaceAll("\\","/")}function ct(s,e,t){if(!e.startsWith("."))return;let r=E(it.join(st(s),e)),n=nt(r),o;if(n===".js"){let i=r.slice(0,-3);o=[`${i}.ts`,`${i}.tsx`,`${i}.js`,`${i}.jsx`]}else if(n===".mjs"){let i=r.slice(0,-4);o=[`${i}.mts`,`${i}.ts`,`${i}.mjs`]}else if(n===".cjs"){let i=r.slice(0,-4);o=[`${i}.cts`,`${i}.ts`,`${i}.cjs`]}else n?o=[r]:o=[`${r}.ts`,`${r}.tsx`,`${r}.mts`,`${r}.cts`,`${r}.js`,`${r}.jsx`,`${r}.mjs`,`${r}.cjs`,`${r}/index.ts`,`${r}/index.tsx`,`${r}/index.mts`,`${r}/index.cts`,`${r}/index.js`,`${r}/index.jsx`,`${r}/index.mjs`,`${r}/index.cjs`];return o.find(i=>t.has(E(i)))}function V(s,e,t,r){let n=r?.(s,e,t);if(n){let o=E(n);if(t.has(o))return o}return ct(s,e,t)}var I=class{build(e,t,r={}){let n=new z;for(let a of r.seedSymbols??[])n.addSymbol(a);for(let a of t)for(let p of a.symbols)n.addSymbol(p);let o=new Map;for(let a of n.allSymbols(e))a.type==="file"&&o.set(E(a.filePath),a);let i=new Set(o.keys());for(let a of t){let p=E(a.filePath),c=o.get(p);if(c){for(let l of a.symbols)l.id!==c.id&&n.addEdge(this.edge(e,c.id,"DEFINES",l.id));for(let l of a.imports){let u=V(p,l.source,i,r.resolveModule);if(!u)continue;let f=o.get(u);f&&n.addEdge(this.edge(e,c.id,"IMPORTS",f.id,{source:l.source,resolvedFile:u}))}for(let l of a.heritage){let u=n.findByName(e,l.targetName).filter(f=>f.type==="class"||f.type==="interface");for(let f of u)n.addEdge(this.edge(e,l.fromId,l.type,f.id))}for(let l of a.calls){if(!l.callerId)continue;let u=this.resolveCallTargets(e,a,l.calleeName,l.qualifier,n,i,r.resolveModule);for(let f of u)f.id!==l.callerId&&n.addEdge(this.edge(e,l.callerId,"CALLS",f.id,{line:l.line,qualifier:l.qualifier}))}}}return n}resolveCallTargets(e,t,r,n,o,i,a){let p=E(t.filePath),c=o.findByName(e,r).filter(l=>E(l.filePath)===p);if(!n&&c.length)return c;if(n)for(let l of t.imports){if(!l.bindings.find(h=>h.kind==="namespace"&&h.localName===n))continue;let f=V(p,l.source,i,a);if(f)return o.findByName(e,r).filter(h=>E(h.filePath)===f)}for(let l of t.imports){let u=l.bindings.find(k=>k.localName===r);if(!u)continue;let f=V(p,l.source,i,a);if(!f)continue;let h=u.importedName==="default"?r:u.importedName,C=o.findByName(e,h).filter(k=>E(k.filePath)===f);if(C.length)return C}return o.findByName(e,r).filter(l=>l.type==="function"||l.type==="method")}edge(e,t,r,n,o){return{id:at(e,t,r,n),projectId:e,from:t,to:n,type:r,metadata:o}}};import{readFile as lt}from"node:fs/promises";import{join as dt}from"node:path";import{createHash as pt}from"node:crypto";import*as m from"typescript";function de(s,e){return pt("sha256").update(`${s}:${e}`).digest("hex").slice(0,24)}function Y(s,e){return s.getLineAndCharacterOfPosition(e.getStart(s)).line+1}async function J(s,e,t){let r=dt(e,t),n=await lt(r,"utf8"),o=m.createSourceFile(t,n,m.ScriptTarget.Latest,!0,t.endsWith(".tsx")||t.endsWith(".jsx")?m.ScriptKind.TSX:m.ScriptKind.TS),i=[],a=[],p=[],c=[],l={id:de(s,`file:${t}`),projectId:s,name:t,qualifiedName:t,type:"file",filePath:t,startLine:1,endLine:o.getLineAndCharacterOfPosition(o.end).line+1};i.push(l);let u=[],f=[];function h(d,b,S,y){let w=de(s,`${t}:${S}:${y??b}:${d.pos}`);return i.push({id:w,projectId:s,name:b,qualifiedName:y??b,type:S,filePath:t,startLine:Y(o,d),endLine:o.getLineAndCharacterOfPosition(d.end).line+1}),w}function C(d){if(!m.isStringLiteral(d.moduleSpecifier))return;let b=[],S=d.importClause;if(S?.name&&b.push({localName:S.name.text,importedName:"default",kind:"default"}),S?.namedBindings&&m.isNamedImports(S.namedBindings))for(let y of S.namedBindings.elements)b.push({localName:y.name.text,importedName:y.propertyName?.text??y.name.text,kind:"named"});S?.namedBindings&&m.isNamespaceImport(S.namedBindings)&&b.push({localName:S.namedBindings.name.text,importedName:"*",kind:"namespace"}),a.push({source:d.moduleSpecifier.text,bindings:b})}function k(d,b){for(let S of d.heritageClauses??[])for(let y of S.types){let w=y.expression.getText(o).split(".").at(-1)??"";w&&c.push({fromId:b,targetName:w,type:S.token===m.SyntaxKind.ExtendsKeyword?"INHERITS":"IMPLEMENTS"})}}function P(d){let b=!1,S=!1;if(m.isImportDeclaration(d)&&C(d),m.isInterfaceDeclaration(d)&&h(d,d.name.text,"interface",d.name.text),m.isClassDeclaration(d)&&d.name){let y=h(d,d.name.text,"class",d.name.text);k(d,y),f.push({id:y,name:d.name.text}),S=!0}if(m.isFunctionDeclaration(d)&&d.name){let y=h(d,d.name.text,"function",d.name.text);u.push(y),b=!0}if(m.isMethodDeclaration(d)&&d.name){let y=d.name.getText(o),w=f.at(-1)?.name,be=h(d,y,"method",w?`${w}.${y}`:y);u.push(be),b=!0}if(m.isCallExpression(d)&&(m.isIdentifier(d.expression)&&p.push({callerId:u.at(-1),calleeName:d.expression.text,line:Y(o,d)}),m.isPropertyAccessExpression(d.expression))){let y=d.expression;p.push({callerId:u.at(-1),qualifier:y.expression.getText(o),calleeName:y.name.text,line:Y(o,d)})}m.forEachChild(d,P),b&&u.pop(),S&&f.pop()}return P(o),{filePath:t,symbols:i,imports:a,calls:p,heritage:c}}function ut(s){let e=s??4;if(!Number.isSafeInteger(e)||e<1||e>64)throw new Error("concurrency must be an integer between 1 and 64");return e}function ft(s){if(s?.aborted)throw new Error("Operation aborted")}async function K(s,e,t={}){if(s.length===0)return[];let r=Math.min(ut(t.concurrency),s.length),n=new Array(s.length),o=0,i=0,a=async()=>{for(;;){ft(t.signal);let c=o;if(o+=1,c>=s.length)return;n[c]=await e(s[c],c),i+=1,t.onProgress?.({completed:i,total:s.length,index:c})}},p=Array.from({length:r},()=>a());return await Promise.all(p),n}var B=class{async index(e,t,r={}){let n={...r.scan};r.signal&&(n.signal=r.signal);let o=await le(t,n),i=o.files;r.onProgress?.({phase:"scan",current:i.length,total:i.length});let a=r.maxWarnings??20;if(!Number.isSafeInteger(a)||a<0)throw new Error("maxWarnings must be a non-negative integer");let p=0,c=await K(i,async f=>{try{return await J(e,t,f)}catch(h){return p+=1,p<=a&&console.warn(`[indexer] skipped ${f}:`,h instanceof Error?h.message:h),null}},{concurrency:r.concurrency??4,signal:r.signal,onProgress:({completed:f,total:h,index:C})=>{r.onProgress?.({phase:"parse",current:f,total:h,file:i[C]})}});p>a&&console.warn(`[indexer] ${p-a} additional parse warnings suppressed`);let l=c.filter(f=>f!==null),u=new I().build(e,l);return{files:l.length,symbols:u.allSymbols(e).length,edges:u.allEdges(e).length,parseFailures:p,scan:o.stats,graph:u}}};function ue(s,e){let t=s.allSymbols(e),r=s.allEdges(e),n=i=>t.filter(a=>a.type===i).length,o=i=>r.filter(a=>a.type===i).length;return{files:n("file"),classes:n("class"),interfaces:n("interface"),functions:n("function"),methods:n("method"),properties:n("property"),routes:n("route"),symbols:t.length,edges:r.length,calls:o("CALLS"),callReferences:o("CALL_REFERENCE"),imports:o("IMPORTS"),inherits:o("INHERITS"),implements:o("IMPLEMENTS"),usesType:o("USES_TYPE"),tests:o("TESTS"),routeEdges:o("ROUTE"),writes:o("WRITES")}}import{execFile as mt}from"node:child_process";import{promisify as gt}from"node:util";var ps=gt(mt);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")}};import*as v from"typescript";import{DatabaseSync as an}from"node:sqlite";import*as x from"typescript";import*as g from"typescript";var Tn=new Set([g.SyntaxKind.EqualsToken,g.SyntaxKind.PlusEqualsToken,g.SyntaxKind.MinusEqualsToken,g.SyntaxKind.AsteriskEqualsToken,g.SyntaxKind.SlashEqualsToken,g.SyntaxKind.PercentEqualsToken,g.SyntaxKind.QuestionQuestionEqualsToken,g.SyntaxKind.AmpersandAmpersandEqualsToken,g.SyntaxKind.BarBarEqualsToken]);import{homedir as Gt}from"node:os";import{join as zt}from"node:path";import{DeleteObjectCommand as St,GetObjectCommand as bt,HeadObjectCommand as xt,ListObjectsV2Command as Ct,PutObjectCommand as Et,S3Client as wt}from"@aws-sdk/client-s3";import{getSignedUrl as vt}from"@aws-sdk/s3-request-presigner";var W=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new wt({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 n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Et({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await vt(this.client,new bt({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 xt({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 St({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let n=await this.client.send(new Ct({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};import{access as fe,mkdir as kt,readFile as Pt,readdir as Rt,rm as Mt,stat as me,writeFile as Tt}from"node:fs/promises";import{dirname as At,join as jt,relative as ge,resolve as It}from"node:path";var N=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return It(this.root,t)}async put(e,t){let r=this.path(e);await kt(At(r),{recursive:!0}),await Tt(r,t)}async get(e){try{return await Pt(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 fe(this.path(e)),!0}catch{return!1}}async delete(e){await Mt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),r=[];try{await fe(t)}catch{return r}let n=async i=>{let a=await Rt(i,{withFileTypes:!0});for(let p of a){let c=jt(i,p.name);if(p.isDirectory()){await n(c);continue}let l=await me(c);r.push({key:ge(this.root,c),size:l.size,updatedAt:l.mtime.toISOString()})}},o=await me(t);return o.isDirectory()?await n(t):r.push({key:ge(this.root,t),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Lt,GetObjectCommand as Nt,HeadObjectCommand as Ot,ListObjectsV2Command as _t,PutObjectCommand as Ft,S3Client as Dt}from"@aws-sdk/client-s3";import{getSignedUrl as $t}from"@aws-sdk/s3-request-presigner";var O=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Dt({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,r="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ft({Bucket:this.bucket,Key:e,Body:n,ContentType:r}))}async get(e){let t=await $t(this.client,new Nt({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(`${this.name} 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 Ot({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 Lt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],r;do{let n=await this.client.send(new _t({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of n.Contents??[])o.Key&&t.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=n.IsTruncated?n.NextContinuationToken:void 0}while(r);return t}};function q(s,e){return console.warn(e),new N(s)}function he(s){let e=s.localRoot??zt(Gt(),".toolnet-memory","storage");if(s.provider==="r2"){let t=s.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new O({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):q(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let t=s.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new O({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):q(e,"[storage] S3 credentials missing. Using local fallback.")}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}):q(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new N(e)}function ye(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 n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var U=class{constructor(e,t,r,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=r,this.folder=ye(n??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,n=await this.provider.getText(e);if(n){let i;try{i=JSON.parse(n)}catch(a){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${a instanceof Error?a.message:String(a)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:t};await this.provider.put(e,JSON.stringify(o,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 Kt(){let s=Z(),e=new $().detect(),t=he({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),r=new U(t,e.id,e.name,e.remote??e.name),n=await new B().index(e.id,e.rootPath),o=ue(n.graph,e.id);await new L(r).save({version:1,projectId:e.id,updatedAt:new Date().toISOString(),files:n.files,symbols:n.graph.allSymbols(e.id),edges:n.graph.allEdges(e.id)}),console.log({ok:!0,storage:r.name,...o})}Kt().catch(s=>{console.error(s),process.exit(1)});
|
package/bundle/graph-ui.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import"dotenv/config";import{createReadStream as
|
|
2
|
-
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function
|
|
3
|
-
`,{encoding:"utf8",mode:384}),ve(a,s)}function se(o,t){return{id:o.id,name:o.name,remote:o.remote,rootPath:t,createdAt:o.createdAt,updatedAt:o.updatedAt,graphVersion:o.graphVersion,memoryVersion:o.memoryVersion,metadata:o.metadata}}var z=class{detect(t=process.cwd()){let e=I(t),s=Me(e),c=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(v=>J(B(s,v))),p=Ae(e,c?s:void 0);if(p){let v=Y(p),R=Ne(v);return R.rootPath!==p&&(R.rootPath=p,R.updatedAt=new Date().toISOString(),re(p,R)),se(R,p)}let P=new Date().toISOString(),b=Pe(s),E={version:1,id:je(s),name:b,remote:b,rootPath:s,createdAt:P,updatedAt:P,graphVersion:0,memoryVersion:0};return re(s,E),se(E,s)}};import*as w from"typescript";var A=class{symbols=new Map;edges=new Map;addSymbol(t){this.symbols.set(t.id,t)}addEdge(t){this.edges.set(t.id,t)}getSymbol(t){return this.symbols.get(t)}findByName(t,e){return[...this.symbols.values()].filter(s=>s.projectId===t&&(s.name===e||s.qualifiedName===e))}allSymbols(t){return[...this.symbols.values()].filter(e=>e.projectId===t)}allEdges(t){return[...this.edges.values()].filter(e=>e.projectId===t)}import(t,e){for(let s of t)this.addSymbol(s);for(let s of e)this.addEdge(s)}clearProject(t){for(let[e,s]of this.symbols)s.projectId===t&&this.symbols.delete(e);for(let[e,s]of this.edges)s.projectId===t&&this.edges.delete(e)}};import{execFile as Fe}from"node:child_process";import{promisify as $e}from"node:util";var Pr=$e(Fe);import{DatabaseSync as gs}from"node:sqlite";import*as k from"typescript";import*as f from"typescript";var _s=new Set([f.SyntaxKind.EqualsToken,f.SyntaxKind.PlusEqualsToken,f.SyntaxKind.MinusEqualsToken,f.SyntaxKind.AsteriskEqualsToken,f.SyntaxKind.SlashEqualsToken,f.SyntaxKind.PercentEqualsToken,f.SyntaxKind.QuestionQuestionEqualsToken,f.SyntaxKind.AmpersandAmpersandEqualsToken,f.SyntaxKind.BarBarEqualsToken]);var H=class{constructor(t){this.graph=t}graph;build(t,e,s,a){let c=this.graph.allSymbols(t),p=this.graph.allEdges(t),P=new Map(e?.layers.map(n=>[n.filePath,n.layer])??[]),b=new Map;for(let n of e?.clusters??[])for(let r of n.files)b.set(r,{id:n.id,label:n.label});let E=new Map(e?.hotspots.map(n=>[n.filePath,n.score])??[]),v=new Map(s?.deadCode.map(n=>[n.symbolId,{confidence:n.confidence,score:n.score}])??[]),R=new Map,M=new Map;for(let n of p)M.set(n.from,(M.get(n.from)??0)+1),R.set(n.to,(R.get(n.to)??0)+1);let j=[];for(let n=0;n<c.length;n++){let r=c[n],l=b.get(r.filePath);j.push({id:r.id,name:r.name,qualifiedName:r.qualifiedName,type:r.type,filePath:r.filePath,layer:P.get(r.filePath),cluster:l?.id,clusterLabel:l?.label,hotspotScore:E.get(r.filePath),deadCode:v.get(r.id),incoming:R.get(r.id)??0,outgoing:M.get(r.id)??0}),((n+1)%100===0||n===c.length-1)&&a?.({current:n+1,total:c.length,phase:"nodes"})}let $=new Set(j.map(n=>n.id)),T=p.filter(n=>$.has(n.from)&&$.has(n.to)),D=[];for(let n=0;n<T.length;n++){let r=T[n];D.push({source:r.from,target:r.to,type:r.type,confidence:typeof r.metadata?.confidence=="string"?r.metadata.confidence:void 0,resolver:typeof r.metadata?.resolver=="string"?r.metadata.resolver:void 0}),((n+1)%100===0||n===T.length-1)&&a?.({current:n+1,total:T.length,phase:"links"})}return{version:1,projectId:t,generatedAt:new Date().toISOString(),summary:{nodes:j.length,links:D.length,files:new Set(j.map(n=>n.filePath)).size,clusters:new Set(j.map(n=>n.cluster).filter(Boolean)).size},nodes:j,links:D}}};import{homedir as ct}from"node:os";import{join as lt}from"node:path";import{DeleteObjectCommand as Ge,GetObjectCommand as Ke,HeadObjectCommand as ze,ListObjectsV2Command as Be,PutObjectCommand as He,S3Client as We}from"@aws-sdk/client-s3";import{getSignedUrl as Ue}from"@aws-sdk/s3-request-presigner";var W=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new We({region:"us-east-1",endpoint:`https://s3.hf.co/${t.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,e,s="application/octet-stream"){let a=typeof e=="string"?Buffer.from(e,"utf8"):e;await this.client.send(new He({Bucket:this.bucket,Key:t,Body:a,ContentType:s}))}async get(t){let e=await Ue(this.client,new Ke({Bucket:this.bucket,Key:t}),{expiresIn:60}),s=await fetch(e,{redirect:"follow"});if(s.status===404)return null;if(!s.ok)throw new Error(`HF download failed: ${s.status} ${s.statusText}`);return new Uint8Array(await s.arrayBuffer())}async getText(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await this.client.send(new ze({Bucket:this.bucket,Key:t})),!0}catch(e){if(typeof e=="object"&&e!==null&&"$metadata"in e&&e.$metadata?.httpStatusCode===404)return!1;throw e}}async delete(t){await this.client.send(new Ge({Bucket:this.bucket,Key:t}))}async list(t=""){let e=[],s;do{let a=await this.client.send(new Be({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:s}));for(let c of a.Contents??[])c.Key&&e.push({key:c.Key,size:c.Size,updatedAt:c.LastModified?.toISOString()});s=a.IsTruncated?a.NextContinuationToken:void 0}while(s);return e}};import{access as ie,mkdir as Ve,readFile as Je,readdir as Ye,rm as qe,stat as ae,writeFile as Qe}from"node:fs/promises";import{dirname as Xe,join as Ze,relative as ce,resolve as et}from"node:path";var O=class{constructor(t){this.root=t}root;name="local";path(t){let e=t.replace(/^\/+/,"");return et(this.root,e)}async put(t,e){let s=this.path(t);await Ve(Xe(s),{recursive:!0}),await Qe(s,e)}async get(t){try{return await Je(this.path(t))}catch(e){if(typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT")return null;throw e}}async getText(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await ie(this.path(t)),!0}catch{return!1}}async delete(t){await qe(this.path(t),{force:!0})}async list(t=""){let e=this.path(t),s=[];try{await ie(e)}catch{return s}let a=async p=>{let P=await Ye(p,{withFileTypes:!0});for(let b of P){let E=Ze(p,b.name);if(b.isDirectory()){await a(E);continue}let v=await ae(E);s.push({key:ce(this.root,E),size:v.size,updatedAt:v.mtime.toISOString()})}},c=await ae(e);return c.isDirectory()?await a(e):s.push({key:ce(this.root,e),size:c.size,updatedAt:c.mtime.toISOString()}),s}};import{DeleteObjectCommand as tt,GetObjectCommand as rt,HeadObjectCommand as st,ListObjectsV2Command as nt,PutObjectCommand as ot,S3Client as it}from"@aws-sdk/client-s3";import{getSignedUrl as at}from"@aws-sdk/s3-request-presigner";var _=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new it({region:t.region??"us-east-1",endpoint:t.endpoint||void 0,forcePathStyle:t.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,e,s="application/octet-stream"){let a=typeof e=="string"?Buffer.from(e,"utf8"):e;await this.client.send(new ot({Bucket:this.bucket,Key:t,Body:a,ContentType:s}))}async get(t){let e=await at(this.client,new rt({Bucket:this.bucket,Key:t}),{expiresIn:60}),s=await fetch(e,{redirect:"follow"});if(s.status===404)return null;if(!s.ok)throw new Error(`${this.name} download failed: ${s.status} ${s.statusText}`);return new Uint8Array(await s.arrayBuffer())}async getText(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await this.client.send(new st({Bucket:this.bucket,Key:t})),!0}catch(e){if(typeof e=="object"&&e!==null&&"$metadata"in e&&e.$metadata?.httpStatusCode===404)return!1;throw e}}async delete(t){await this.client.send(new tt({Bucket:this.bucket,Key:t}))}async list(t=""){let e=[],s;do{let a=await this.client.send(new nt({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:s}));for(let c of a.Contents??[])c.Key&&e.push({key:c.Key,size:c.Size,updatedAt:c.LastModified?.toISOString()});s=a.IsTruncated?a.NextContinuationToken:void 0}while(s);return e}};function q(o,t){return console.warn(t),new O(o)}function le(o){let t=o.localRoot??lt(ct(),".toolnet-memory","storage");if(o.provider==="r2"){let e=o.r2;return e?.accountId&&e.bucket&&e.accessKeyId&&e.secretAccessKey?new _({name:"r2",endpoint:`https://${e.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:e.bucket,forcePathStyle:!0,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):q(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(o.provider==="s3"){let e=o.s3;return e?.bucket&&e.accessKeyId&&e.secretAccessKey?new _({name:"s3",endpoint:e.endpoint,region:e.region??"us-east-1",bucket:e.bucket,forcePathStyle:e.forcePathStyle??!1,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):q(t,"[storage] S3 credentials missing. Using local fallback.")}if(o.provider==="huggingface"){let e=o.huggingface;return e?.namespace&&e.bucket&&e.accessKeyId&&e.secretAccessKey?new W({namespace:e.namespace,bucket:e.bucket,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):q(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new O(t)}function dt(o){return new Promise(t=>setTimeout(t,o))}async function de(o,t={}){let e=Math.max(1,t.attempts??3),s=t.baseDelayMs??150,a=t.maxDelayMs??2e3,c;for(let p=1;p<=e;p++)try{return await o()}catch(P){if(c=P,p>=e)break;let b=Math.min(a,s*2**(p-1)),E=Math.floor(Math.random()*Math.max(1,b*.2));await dt(b+E)}throw c}var pt=new Set(["put","get","getText","delete","list"]);function pe(o,t={}){return new Proxy(o,{get(e,s){let a=Reflect.get(e,s,e);return typeof a!="function"?a:pt.has(s)?(...c)=>de(()=>Promise.resolve(a.apply(e,c)),t):a.bind(e)}})}var fe=Number(process.env.TOOLNET_GRAPH_PORT??9749),me=process.env.TOOLNET_GRAPH_HOST??"127.0.0.1";function gt(o){if(typeof o=="string")return o;if(!o||typeof o!="object")return null;let t=o;for(let e of["key","Key","path","name"])if(typeof t[e]=="string")return t[e];return null}async function ht(o,t){return(await o.list(t)).map(gt).filter(s=>!!s)}async function F(o,t){let e=await o.getText(t);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function yt(o){let t=await ht(o,"projects/"),e=[...new Set(t.filter(c=>/^projects\/[^/]+\/project\.json$/.test(c)).map(c=>c.split("/")[1]))],s=new Set(t),a=[];for(let c of e){let p=await F(o,`projects/${c}/project.json`);!p||typeof p.id!="string"||a.push({id:p.id,name:typeof p.name=="string"?p.name:c,remote:c,hasGraph:s.has(`projects/${c}/code/graph/current.json`),hasArchitecture:s.has(`projects/${c}/code/architecture/current.json`),hasAnalysis:s.has(`projects/${c}/code/analysis/current.json`),hasVisualization:s.has(`projects/${c}/code/visualization/graph.json`)})}return a.sort((c,p)=>c.name.localeCompare(p.name))}async function St(){let o=te(),t=new z().detect(),e=pe(le({provider:o.storage.provider,huggingface:o.storage.huggingface,localRoot:o.storage.localRoot}),{attempts:3});e.name!=="huggingface"&&console.warn("[graph-ui] Remote Hugging Face storage is not active.");let s=ft(mt(import.meta.url)),a=Q(s,"public"),c=Q(a,"vendor","3d-force-graph.min.js");async function p(){let n=await yt(e),r=t.remote??t.name,l=n.find(m=>m.remote===r&&m.hasGraph),S=n.find(m=>m.hasGraph);return{projects:n,defaultProject:l?.remote??S?.remote??null}}let P=new Map;function b(n){return String(typeof n=="object"&&n!==null?n.id:n)}function E(n){return n.clusterLabel||n.cluster||n.layer||"Unclustered"}function v(n,r={}){return{id:n.id,name:n.name,remote:n.remote,hasArchitecture:n.hasArchitecture,hasAnalysis:n.hasAnalysis,...r}}async function R(n){let r=`projects/${n.remote}`,l=await F(e,`${r}/code/graph/current.json`);if(!l||!Array.isArray(l.symbols)||!Array.isArray(l.edges))throw new Error(`Code graph missing for project ${n.name}`);let S=await F(e,`${r}/code/architecture/current.json`),m=await F(e,`${r}/code/analysis/current.json`),y=new A;y.import(l.symbols,l.edges);let C=new H(y).build(n.id,S,m);return await e.put(`${r}/code/visualization/graph.json`,JSON.stringify(C),"application/json"),{...C,dashboard:v(n)}}async function M(n,r=!1){r&&P.delete(n.remote);let l=P.get(n.remote);if(l)return l;let S=`projects/${n.remote}`,m=await F(e,`${S}/code/visualization/graph.json`);if(m&&Array.isArray(m.nodes)&&Array.isArray(m.links)){let C={...m,dashboard:v(n)};return P.set(n.remote,C),C}let y=await R(n);return P.set(n.remote,y),y}function j(n,r){let l=new Map,S=new Map;for(let d of r.nodes){let u=E(d),g=`cluster:${u}`;S.set(d.id,g);let i=l.get(g);i||(i={id:g,name:u,qualifiedName:u,type:"subsystem",filePath:"",clusterLabel:u,incoming:0,outgoing:0,memberCount:0,files:new Set,viewKind:"cluster"},l.set(g,i)),i.memberCount+=1,d.filePath&&i.files.add(d.filePath)}let m=new Map;for(let d of r.links){let u=S.get(b(d.source)),g=S.get(b(d.target));if(!u||!g||u===g)continue;let i=`${u}\0${g}`,h=m.get(i);h||(h={source:u,target:g,type:"SUBSYSTEM_DEPENDENCY",count:0},m.set(i,h)),h.count+=1}for(let d of m.values()){let u=l.get(d.source),g=l.get(d.target);u&&(u.outgoing+=d.count),g&&(g.incoming+=d.count)}let y=[...l.values()].map(d=>({...d,filePath:`${d.files.size} files \xB7 ${d.memberCount} symbols`,files:void 0})),C=[...m.values()];return{version:2,projectId:r.projectId,generatedAt:r.generatedAt,summary:{nodes:y.length,links:C.length,files:r.summary?.files??0,clusters:y.length},nodes:y,links:C,dashboard:v(n,{viewMode:"overview",totalNodes:r.nodes.length,totalLinks:r.links.length})}}function $(n,r,l){let S=r.nodes.filter(i=>!l||E(i)===l),m=new Set(S.map(i=>i.id)),y=new Map,C=new Map;for(let i of S){let h=i.filePath||"(unknown)";y.set(i.id,h);let x=C.get(h);x||(x={id:`file:${h}`,name:h.split("/").pop()||h,qualifiedName:h,type:"file",filePath:h,clusterLabel:E(i),incoming:0,outgoing:0,memberCount:0,viewKind:"file"},C.set(h,x)),x.memberCount+=1}let d=new Map;for(let i of r.links){let h=b(i.source),x=b(i.target);if(!m.has(h)||!m.has(x))continue;let U=y.get(h),V=y.get(x);if(!U||!V||U===V)continue;let X=`file:${U}`,Z=`file:${V}`,ee=`${X}\0${Z}`,G=d.get(ee);G||(G={source:X,target:Z,type:"FILE_DEPENDENCY",count:0},d.set(ee,G)),G.count+=1}for(let i of d.values()){let h=C.get(String(i.source).slice(5)),x=C.get(String(i.target).slice(5));h&&(h.outgoing+=i.count),x&&(x.incoming+=i.count)}let u=[...C.values()],g=[...d.values()];return{version:2,projectId:r.projectId,generatedAt:r.generatedAt,summary:{nodes:u.length,links:g.length,files:u.length,clusters:l?1:0},nodes:u,links:g,dashboard:v(n,{viewMode:"files",selection:l,totalNodes:r.nodes.length,totalLinks:r.links.length})}}function T(n,r,l){let y=r.nodes.filter(i=>i.filePath===l),C=new Set(y.map(i=>i.id)),d=new Set;for(let i of y.slice(0,1800))d.add(i.id);for(let i of r.links){if(d.size>=1800)break;let h=b(i.source),x=b(i.target);(C.has(h)||C.has(x))&&(d.add(h),d.size<1800&&d.add(x))}let u=r.nodes.filter(i=>d.has(i.id)).map(i=>({...i,viewKind:"symbol"})),g=[];for(let i of r.links){if(g.length>=12e3)break;let h=b(i.source),x=b(i.target);d.has(h)&&d.has(x)&&g.push({...i,source:h,target:x})}return{version:2,projectId:r.projectId,generatedAt:r.generatedAt,summary:{nodes:u.length,links:g.length,files:new Set(u.map(i=>i.filePath)).size,clusters:new Set(u.map(i=>E(i))).size},nodes:u,links:g,dashboard:v(n,{viewMode:"symbols",selection:l,focused:!0,truncated:u.length>=1800||g.length>=12e3,totalNodes:r.nodes.length,totalLinks:r.links.length})}}ut(async(n,r)=>{try{let l=new URL(n.url??"/",`http://${n.headers.host??"localhost"}`);if(l.pathname==="/api/health"){let S=await p();r.setHeader("content-type","application/json; charset=utf-8"),r.setHeader("cache-control","no-store"),r.end(JSON.stringify({ok:!0,mode:"multi-project",projects:S.projects.length,indexedProjects:S.projects.filter(m=>m.hasGraph).length,defaultProject:S.defaultProject}));return}if(l.pathname==="/api/projects"){let S=await p();r.setHeader("content-type","application/json; charset=utf-8"),r.setHeader("cache-control","no-store"),r.end(JSON.stringify(S));return}if(l.pathname==="/api/graph"){let S=await p(),m=l.searchParams.get("project")??S.defaultProject;if(!m){r.statusCode=404,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:"No indexed ToolNet project found."}));return}let y=S.projects.find(i=>i.remote===m);if(!y){r.statusCode=404,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:"Project not found.",project:m}));return}if(!y.hasGraph){r.statusCode=409,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:"Project is registered but has not been indexed yet.",project:y}));return}let C=l.searchParams.get("refresh")==="1",d=await M(y,C),u=l.searchParams.get("mode")??"full",g=d;if(u==="overview")g=j(y,d);else if(u==="files")g=$(y,d,l.searchParams.get("cluster")??"");else if(u==="symbols"){let i=l.searchParams.get("file");if(!i){r.statusCode=400,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:"file is required for symbols mode."}));return}g=T(y,d,i)}else if(u!=="full"){r.statusCode=400,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:`Unknown graph mode: ${u}`}));return}r.setHeader("content-type","application/json; charset=utf-8"),r.setHeader("cache-control","no-store"),r.end(JSON.stringify(g));return}if(l.pathname==="/vendor/3d-force-graph.min.js"){r.setHeader("content-type","application/javascript; charset=utf-8"),ue(c).pipe(r);return}if(l.pathname==="/"||l.pathname==="/index.html"){r.setHeader("content-type","text/html; charset=utf-8"),r.setHeader("cache-control","no-store"),ue(Q(a,"index.html")).pipe(r);return}r.statusCode=404,r.end("Not found")}catch(l){console.error(l),r.statusCode=500,r.setHeader("content-type","application/json; charset=utf-8"),r.end(JSON.stringify({error:l instanceof Error?l.message:String(l)}))}}).listen(fe,me,()=>{console.log("ToolNet Multi-Project 3D Graph"),console.log(`Listening: http://${me}:${fe}`)})}St().catch(o=>{console.error(o),process.exit(1)});
|
|
1
|
+
import"dotenv/config";import{createReadStream as Ce}from"node:fs";import{createServer as vt}from"node:http";import{dirname as kt,resolve as te}from"node:path";import{fileURLToPath as Pt}from"node:url";import{existsSync as ve,readFileSync as ke}from"node:fs";import{homedir as Pe}from"node:os";import{join as Re}from"node:path";function Ae(s){let t=s.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
|
|
2
|
+
`).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function je(){let s=process.env.TOOLNET_GLOBAL_ENV??Re(Pe(),".config","toolnet-memory",".env");if(!ve(s))return;let t=ke(s,"utf8");for(let e of t.split(/\r?\n/)){let r=e.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let a=r.indexOf("=");if(a<=0)continue;let o=r.slice(0,a).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=Ae(r.slice(a+1)))}}je();function I(s,t){return s===void 0?t:["1","true","yes","on"].includes(s.toLowerCase())}function L(s,t){if(!s)return t;let e=Number(s);return Number.isFinite(e)?e:t}function oe(){return{memory:{autoCapture:I(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:I(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:I(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:I(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",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:I(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:L(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as Me}from"node:crypto";import{existsSync as H,mkdirSync as Te,readFileSync as Ne,renameSync as Ie,writeFileSync as Le}from"node:fs";import{basename as Oe,dirname as W,join as O,parse as de,resolve as T}from"node:path";var pe=".toolnet",_e="project.json";function Fe(s){return Me("sha256").update(s).digest("hex").slice(0,16)}function U(s){return O(s,pe,_e)}function $e(s){return H(U(s))}function ie(s,t){let e=T(s),r=de(e).root;for(;;){if($e(e))return e;if(e===r||t&&e===T(t))break;let a=W(e);if(a===e)break;e=a}return null}function ae(s){let t=T(s),e=de(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>H(O(t,o))))return t;if(t===e)break;let a=W(t);if(a===t)break;t=a}return T(s)}function ce(s){let t;try{t=JSON.parse(Ne(s,"utf8"))}catch(a){throw new Error(`Invalid ToolNet project manifest: ${s}: ${a instanceof Error?a.message:String(a)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${s}`);let e=t;if(typeof e.id!="string"||!e.id.trim())throw new Error(`ToolNet project manifest is missing id: ${s}`);if(typeof e.name!="string"||!e.name.trim())throw new Error(`ToolNet project manifest is missing name: ${s}`);let r=new Date().toISOString();return{version:1,id:e.id,name:e.name,remote:typeof e.remote=="string"&&e.remote.trim()?e.remote:e.name,rootPath:typeof e.rootPath=="string"?e.rootPath:W(W(s)),createdAt:typeof e.createdAt=="string"?e.createdAt:r,updatedAt:typeof e.updatedAt=="string"?e.updatedAt:r,graphVersion:typeof e.graphVersion=="number"?e.graphVersion:0,memoryVersion:typeof e.memoryVersion=="number"?e.memoryVersion:0,metadata:e.metadata&&typeof e.metadata=="object"?e.metadata:void 0}}function le(s,t){let e=O(s,pe);Te(e,{recursive:!0});let r=U(s),a=`${r}.tmp-${process.pid}`;Le(a,JSON.stringify(t,null,2)+`
|
|
3
|
+
`,{encoding:"utf8",mode:384}),Ie(a,r)}function X(s,t){return{id:s.id,name:s.name,remote:s.remote,rootPath:t,createdAt:s.createdAt,updatedAt:s.updatedAt,graphVersion:s.graphVersion,memoryVersion:s.memoryVersion,metadata:s.metadata}}var V=class{findExisting(t=process.cwd()){let e=T(t),r=ae(e),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(b=>H(O(r,b))),l=ie(e,o?r:void 0);if(!l)return null;let h=ce(U(l));return X(h,l)}requireExisting(t=process.cwd()){let e=this.findExisting(t);if(!e)throw new Error("PROJECT_NOT_INITIALIZED");return e}detect(t=process.cwd()){let e=T(t),r=ae(e),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(k=>H(O(r,k))),l=ie(e,o?r:void 0);if(l){let k=U(l),R=ce(k);return R.rootPath!==l&&(R.rootPath=l,R.updatedAt=new Date().toISOString(),le(l,R)),X(R,l)}let h=new Date().toISOString(),b=Oe(r),v={version:1,id:Fe(r),name:b,remote:b,rootPath:r,createdAt:h,updatedAt:h,graphVersion:0,memoryVersion:0};return le(r,v),X(v,r)}};var De=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_-]{20,}\b/g,confidence:"exact"},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g,confidence:"exact"},{type:"aws_access_key",regex:/\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,confidence:"exact"},{type:"github_token",regex:/\b(?:gh[pousr]_[A-Za-z0-9]{30,255}|github_pat_[A-Za-z0-9_]{40,255})\b/g,confidence:"exact"},{type:"stripe_secret_key",regex:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g,confidence:"exact"},{type:"google_api_key",regex:/\bAIza[A-Za-z0-9_-]{30,}\b/g,confidence:"exact"},{type:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{16,}\b/g,confidence:"exact"},{type:"npm_token",regex:/\bnpm_[A-Za-z0-9]{20,}\b/g,confidence:"exact"},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi,confidence:"high"},{type:"jwt",regex:/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,confidence:"exact"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,confidence:"exact"},{type:"password_assignment",regex:/\b(?:password|passwd|pwd)\s*[:=]\s*["']?[^"' \t\r\n]{6,}["']?/gi,confidence:"high"},{type:"secret_assignment",regex:/\b(?:secret|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)\s*[:=]\s*["']?[^"' \t\r\n]{8,}["']?/gi,confidence:"high"},{type:"cookie",regex:/\b(?:cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi,confidence:"high"},{type:"url_credentials",regex:/\bhttps?:\/\/[^:/@\s]+:[^/@\s]{4,}@[^/\s]+/gi,confidence:"high"}],Ge=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function ue(s){return s.normalize("NFKC").trim().toLowerCase()}function Ke(s){if(s.length===0)return 0;let t=new Map;for(let r of s)t.set(r,(t.get(r)??0)+1);let e=0;for(let r of t.values()){let a=r/s.length;e-=a*Math.log2(a)}return e}function ze(s){return/^[a-f0-9]{32}$/iu.test(s)||/^[a-f0-9]{40}$/iu.test(s)||/^[a-f0-9]{64}$/iu.test(s)}function Be(s,t,e){let r=s.slice(Math.max(0,t-48),t),a=s.slice(e,Math.min(s.length,e+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${a}`)}function He(s,t){return s.start<t.end&&t.start<s.end}function fe(s){return s.sort((t,e)=>t.start!==e.start?t.start-e.start:e.end-e.start-(t.end-t.start))}var J=class{allowValues=new Set;enableEntropyHeuristic;constructor(t={}){for(let e of t.allowValues??[]){let r=ue(e);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=t.enableEntropyHeuristic??!0}scan(t){let e=[];for(let o of De){let l=new RegExp(o.regex.source,o.regex.flags);for(let h of t.matchAll(l))h.index===void 0||!h[0]||this.allowed(h[0])||e.push({type:o.type,value:h[0],start:h.index,end:h.index+h[0].length,confidence:o.confidence})}this.enableEntropyHeuristic&&e.push(...this.entropyMatches(t));let r=fe(e),a=[];for(let o of r)a.some(l=>He(l,o))||a.push(o);return fe(a)}hasSecrets(t){return this.scan(t).length>0}allowed(t){let e=ue(t);return Ge.has(e)?!0:this.allowValues.has(e)}entropyMatches(t){let e=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let a of t.matchAll(r)){if(a.index===void 0||!a[0])continue;let o=a[0];this.allowed(o)||ze(o)||!/[A-Za-z]/u.test(o)||!/[0-9]/u.test(o)||Be(t,a.index,a.index+o.length)&&(Ke(o)<3.7||e.push({type:"high_entropy_secret",value:o,start:a.index,end:a.index+o.length,confidence:"heuristic"}))}return e}};var _=class{scanner;constructor(t={}){this.scanner=new J(t)}sanitize(t){let e=this.scanner.scan(t);if(e.length===0)return{text:t,redacted:0,secretTypes:[]};let r=t,a=[...e].sort((l,h)=>h.start-l.start),o=new Set;for(let l of a)o.add(l.type),r=r.slice(0,l.start)+`[REDACTED:${l.type}]`+r.slice(l.end);return{text:r,redacted:e.length,secretTypes:[...o].sort()}}sanitizeValue(t){if(typeof t=="string")return this.sanitize(t).text;if(Array.isArray(t))return t.map(e=>this.sanitizeValue(e));if(t&&typeof t=="object"){let e={};for(let[r,a]of Object.entries(t)){let o=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(o.includes("password")||o.includes("passwd")||o==="pwd"||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")||o.includes("apikey")||o.includes("accesskey")||o.includes("privatekey")||o.includes("clientsecret")||o.includes("credential")){e[r]="[REDACTED]";continue}e[r]=this.sanitizeValue(a)}return e}return t}};var Ut=new _;var kr=2*1024*1024;var F=class{symbols=new Map;edges=new Map;addSymbol(t){this.symbols.set(t.id,t)}addEdge(t){this.edges.set(t.id,t)}getSymbol(t){return this.symbols.get(t)}findByName(t,e){return[...this.symbols.values()].filter(r=>r.projectId===t&&(r.name===e||r.qualifiedName===e))}allSymbols(t){return[...this.symbols.values()].filter(e=>e.projectId===t)}allEdges(t){return[...this.edges.values()].filter(e=>e.projectId===t)}import(t,e){for(let r of t)this.addSymbol(r);for(let r of e)this.addEdge(r)}clearProject(t){for(let[e,r]of this.symbols)r.projectId===t&&this.symbols.delete(e);for(let[e,r]of this.edges)r.projectId===t&&this.edges.delete(e)}};import*as E from"typescript";import{execFile as Je}from"node:child_process";import{promisify as Ye}from"node:util";var Jr=Ye(Je);import*as j from"typescript";import{DatabaseSync as Hs}from"node:sqlite";import*as P from"typescript";import*as f from"typescript";var fn=new Set([f.SyntaxKind.EqualsToken,f.SyntaxKind.PlusEqualsToken,f.SyntaxKind.MinusEqualsToken,f.SyntaxKind.AsteriskEqualsToken,f.SyntaxKind.SlashEqualsToken,f.SyntaxKind.PercentEqualsToken,f.SyntaxKind.QuestionQuestionEqualsToken,f.SyntaxKind.AmpersandAmpersandEqualsToken,f.SyntaxKind.BarBarEqualsToken]);var Y=class{constructor(t){this.graph=t}graph;build(t,e,r,a){let o=this.graph.allSymbols(t),l=this.graph.allEdges(t),h=new Map(e?.layers.map(i=>[i.filePath,i.layer])??[]),b=new Map;for(let i of e?.clusters??[])for(let n of i.files)b.set(n,{id:i.id,label:i.label});let v=new Map(e?.hotspots.map(i=>[i.filePath,i.score])??[]),k=new Map(r?.deadCode.map(i=>[i.symbolId,{confidence:i.confidence,score:i.score}])??[]),R=new Map,N=new Map;for(let i of l)N.set(i.from,(N.get(i.from)??0)+1),R.set(i.to,(R.get(i.to)??0)+1);let A=[];for(let i=0;i<o.length;i++){let n=o[i],d=b.get(n.filePath);A.push({id:n.id,name:n.name,qualifiedName:n.qualifiedName,type:n.type,filePath:n.filePath,layer:h.get(n.filePath),cluster:d?.id,clusterLabel:d?.label,hotspotScore:v.get(n.filePath),deadCode:k.get(n.id),incoming:R.get(n.id)??0,outgoing:N.get(n.id)??0}),((i+1)%100===0||i===o.length-1)&&a?.({current:i+1,total:o.length,phase:"nodes"})}let K=new Set(A.map(i=>i.id)),M=l.filter(i=>K.has(i.from)&&K.has(i.to)),z=[];for(let i=0;i<M.length;i++){let n=M[i];z.push({source:n.from,target:n.to,type:n.type,confidence:typeof n.metadata?.confidence=="string"?n.metadata.confidence:void 0,resolver:typeof n.metadata?.resolver=="string"?n.metadata.resolver:void 0}),((i+1)%100===0||i===M.length-1)&&a?.({current:i+1,total:M.length,phase:"links"})}return{version:1,projectId:t,generatedAt:new Date().toISOString(),summary:{nodes:A.length,links:z.length,files:new Set(A.map(i=>i.filePath)).size,clusters:new Set(A.map(i=>i.cluster).filter(Boolean)).size},nodes:A,links:z}}};import{homedir as xt}from"node:os";import{join as Ct}from"node:path";import{DeleteObjectCommand as Qe,GetObjectCommand as Xe,HeadObjectCommand as et,ListObjectsV2Command as tt,PutObjectCommand as rt,S3Client as st}from"@aws-sdk/client-s3";import{getSignedUrl as nt}from"@aws-sdk/s3-request-presigner";var q=class{name="huggingface";client;bucket;constructor(t){this.bucket=t.bucket,this.client=new st({region:"us-east-1",endpoint:`https://s3.hf.co/${t.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,e,r="application/octet-stream"){let a=typeof e=="string"?Buffer.from(e,"utf8"):e;await this.client.send(new rt({Bucket:this.bucket,Key:t,Body:a,ContentType:r}))}async get(t){let e=await nt(this.client,new Xe({Bucket:this.bucket,Key:t}),{expiresIn:60}),r=await fetch(e,{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(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await this.client.send(new et({Bucket:this.bucket,Key:t})),!0}catch(e){if(typeof e=="object"&&e!==null&&"$metadata"in e&&e.$metadata?.httpStatusCode===404)return!1;throw e}}async delete(t){await this.client.send(new Qe({Bucket:this.bucket,Key:t}))}async list(t=""){let e=[],r;do{let a=await this.client.send(new tt({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let o of a.Contents??[])o.Key&&e.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=a.IsTruncated?a.NextContinuationToken:void 0}while(r);return e}};import{access as ge,mkdir as ot,readFile as it,readdir as at,rm as ct,stat as he,writeFile as lt}from"node:fs/promises";import{dirname as dt,join as pt,relative as ye,resolve as ut}from"node:path";var $=class{constructor(t){this.root=t}root;name="local";path(t){let e=t.replace(/^\/+/,"");return ut(this.root,e)}async put(t,e){let r=this.path(t);await ot(dt(r),{recursive:!0}),await lt(r,e)}async get(t){try{return await it(this.path(t))}catch(e){if(typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT")return null;throw e}}async getText(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await ge(this.path(t)),!0}catch{return!1}}async delete(t){await ct(this.path(t),{force:!0})}async list(t=""){let e=this.path(t),r=[];try{await ge(e)}catch{return r}let a=async l=>{let h=await at(l,{withFileTypes:!0});for(let b of h){let v=pt(l,b.name);if(b.isDirectory()){await a(v);continue}let k=await he(v);r.push({key:ye(this.root,v),size:k.size,updatedAt:k.mtime.toISOString()})}},o=await he(e);return o.isDirectory()?await a(e):r.push({key:ye(this.root,e),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as ft,GetObjectCommand as mt,HeadObjectCommand as gt,ListObjectsV2Command as ht,PutObjectCommand as yt,S3Client as St}from"@aws-sdk/client-s3";import{getSignedUrl as bt}from"@aws-sdk/s3-request-presigner";var D=class{name;client;bucket;constructor(t){this.name=t.name??"s3",this.bucket=t.bucket,this.client=new St({region:t.region??"us-east-1",endpoint:t.endpoint||void 0,forcePathStyle:t.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}})}async put(t,e,r="application/octet-stream"){let a=typeof e=="string"?Buffer.from(e,"utf8"):e;await this.client.send(new yt({Bucket:this.bucket,Key:t,Body:a,ContentType:r}))}async get(t){let e=await bt(this.client,new mt({Bucket:this.bucket,Key:t}),{expiresIn:60}),r=await fetch(e,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(t){let e=await this.get(t);return e?Buffer.from(e).toString("utf8"):null}async exists(t){try{return await this.client.send(new gt({Bucket:this.bucket,Key:t})),!0}catch(e){if(typeof e=="object"&&e!==null&&"$metadata"in e&&e.$metadata?.httpStatusCode===404)return!1;throw e}}async delete(t){await this.client.send(new ft({Bucket:this.bucket,Key:t}))}async list(t=""){let e=[],r;do{let a=await this.client.send(new ht({Bucket:this.bucket,Prefix:t||void 0,ContinuationToken:r}));for(let o of a.Contents??[])o.Key&&e.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=a.IsTruncated?a.NextContinuationToken:void 0}while(r);return e}};function ee(s,t){return console.warn(t),new $(s)}function Se(s){let t=s.localRoot??Ct(xt(),".toolnet-memory","storage");if(s.provider==="r2"){let e=s.r2;return e?.accountId&&e.bucket&&e.accessKeyId&&e.secretAccessKey?new D({name:"r2",endpoint:`https://${e.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:e.bucket,forcePathStyle:!0,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):ee(t,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(s.provider==="s3"){let e=s.s3;return e?.bucket&&e.accessKeyId&&e.secretAccessKey?new D({name:"s3",endpoint:e.endpoint,region:e.region??"us-east-1",bucket:e.bucket,forcePathStyle:e.forcePathStyle??!1,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):ee(t,"[storage] S3 credentials missing. Using local fallback.")}if(s.provider==="huggingface"){let e=s.huggingface;return e?.namespace&&e.bucket&&e.accessKeyId&&e.secretAccessKey?new q({namespace:e.namespace,bucket:e.bucket,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}):ee(t,"[storage] Hugging Face credentials missing. Using local fallback.")}return new $(t)}function wt(s){return new Promise(t=>setTimeout(t,s))}async function be(s,t={}){let e=Math.max(1,t.attempts??3),r=t.baseDelayMs??150,a=t.maxDelayMs??2e3,o;for(let l=1;l<=e;l++)try{return await s()}catch(h){if(o=h,l>=e)break;let b=Math.min(a,r*2**(l-1)),v=Math.floor(Math.random()*Math.max(1,b*.2));await wt(b+v)}throw o}var Et=new Set(["put","get","getText","delete","list"]);function xe(s,t={}){return new Proxy(s,{get(e,r){let a=Reflect.get(e,r,e);return typeof a!="function"?a:Et.has(r)?(...o)=>be(()=>Promise.resolve(a.apply(e,o)),t):a.bind(e)}})}var we=Number(process.env.TOOLNET_GRAPH_PORT??9749),Ee=process.env.TOOLNET_GRAPH_HOST??"127.0.0.1";function Rt(s){if(typeof s=="string")return s;if(!s||typeof s!="object")return null;let t=s;for(let e of["key","Key","path","name"])if(typeof t[e]=="string")return t[e];return null}async function At(s,t){return(await s.list(t)).map(Rt).filter(r=>!!r)}async function G(s,t){let e=await s.getText(t);if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function jt(s){let t=await At(s,"projects/"),e=[...new Set(t.filter(o=>/^projects\/[^/]+\/project\.json$/.test(o)).map(o=>o.split("/")[1]))],r=new Set(t),a=[];for(let o of e){let l=await G(s,`projects/${o}/project.json`);!l||typeof l.id!="string"||a.push({id:l.id,name:typeof l.name=="string"?l.name:o,remote:o,hasGraph:r.has(`projects/${o}/code/graph/current.json`),hasArchitecture:r.has(`projects/${o}/code/architecture/current.json`),hasAnalysis:r.has(`projects/${o}/code/analysis/current.json`),hasVisualization:r.has(`projects/${o}/code/visualization/graph.json`)})}return a.sort((o,l)=>o.name.localeCompare(l.name))}async function Mt(){let s=oe(),t=new V().detect(),e=xe(Se({provider:s.storage.provider,huggingface:s.storage.huggingface,localRoot:s.storage.localRoot}),{attempts:3});e.name!=="huggingface"&&console.warn("[graph-ui] Remote Hugging Face storage is not active.");let r=kt(Pt(import.meta.url)),a=te(r,"public"),o=te(a,"vendor","3d-force-graph.min.js");async function l(){let i=await jt(e),n=t.remote??t.name,d=i.find(m=>m.remote===n&&m.hasGraph),x=i.find(m=>m.hasGraph);return{projects:i,defaultProject:d?.remote??x?.remote??null}}let h=new Map;function b(i){return String(typeof i=="object"&&i!==null?i.id:i)}function v(i){return i.clusterLabel||i.cluster||i.layer||"Unclustered"}function k(i,n={}){return{id:i.id,name:i.name,remote:i.remote,hasArchitecture:i.hasArchitecture,hasAnalysis:i.hasAnalysis,...n}}async function R(i){let n=`projects/${i.remote}`,d=await G(e,`${n}/code/graph/current.json`);if(!d||!Array.isArray(d.symbols)||!Array.isArray(d.edges))throw new Error(`Code graph missing for project ${i.name}`);let x=await G(e,`${n}/code/architecture/current.json`),m=await G(e,`${n}/code/analysis/current.json`),S=new F;S.import(d.symbols,d.edges);let C=new Y(S).build(i.id,x,m);return await e.put(`${n}/code/visualization/graph.json`,JSON.stringify(C),"application/json"),{...C,dashboard:k(i)}}async function N(i,n=!1){n&&h.delete(i.remote);let d=h.get(i.remote);if(d)return d;let x=`projects/${i.remote}`,m=await G(e,`${x}/code/visualization/graph.json`);if(m&&Array.isArray(m.nodes)&&Array.isArray(m.links)){let C={...m,dashboard:k(i)};return h.set(i.remote,C),C}let S=await R(i);return h.set(i.remote,S),S}function A(i,n){let d=new Map,x=new Map;for(let p of n.nodes){let u=v(p),g=`cluster:${u}`;x.set(p.id,g);let c=d.get(g);c||(c={id:g,name:u,qualifiedName:u,type:"subsystem",filePath:"",clusterLabel:u,incoming:0,outgoing:0,memberCount:0,files:new Set,viewKind:"cluster"},d.set(g,c)),c.memberCount+=1,p.filePath&&c.files.add(p.filePath)}let m=new Map;for(let p of n.links){let u=x.get(b(p.source)),g=x.get(b(p.target));if(!u||!g||u===g)continue;let c=`${u}\0${g}`,y=m.get(c);y||(y={source:u,target:g,type:"SUBSYSTEM_DEPENDENCY",count:0},m.set(c,y)),y.count+=1}for(let p of m.values()){let u=d.get(p.source),g=d.get(p.target);u&&(u.outgoing+=p.count),g&&(g.incoming+=p.count)}let S=[...d.values()].map(p=>({...p,filePath:`${p.files.size} files \xB7 ${p.memberCount} symbols`,files:void 0})),C=[...m.values()];return{version:2,projectId:n.projectId,generatedAt:n.generatedAt,summary:{nodes:S.length,links:C.length,files:n.summary?.files??0,clusters:S.length},nodes:S,links:C,dashboard:k(i,{viewMode:"overview",totalNodes:n.nodes.length,totalLinks:n.links.length})}}function K(i,n,d){let x=n.nodes.filter(c=>!d||v(c)===d),m=new Set(x.map(c=>c.id)),S=new Map,C=new Map;for(let c of x){let y=c.filePath||"(unknown)";S.set(c.id,y);let w=C.get(y);w||(w={id:`file:${y}`,name:y.split("/").pop()||y,qualifiedName:y,type:"file",filePath:y,clusterLabel:v(c),incoming:0,outgoing:0,memberCount:0,viewKind:"file"},C.set(y,w)),w.memberCount+=1}let p=new Map;for(let c of n.links){let y=b(c.source),w=b(c.target);if(!m.has(y)||!m.has(w))continue;let Z=S.get(y),Q=S.get(w);if(!Z||!Q||Z===Q)continue;let re=`file:${Z}`,se=`file:${Q}`,ne=`${re}\0${se}`,B=p.get(ne);B||(B={source:re,target:se,type:"FILE_DEPENDENCY",count:0},p.set(ne,B)),B.count+=1}for(let c of p.values()){let y=C.get(String(c.source).slice(5)),w=C.get(String(c.target).slice(5));y&&(y.outgoing+=c.count),w&&(w.incoming+=c.count)}let u=[...C.values()],g=[...p.values()];return{version:2,projectId:n.projectId,generatedAt:n.generatedAt,summary:{nodes:u.length,links:g.length,files:u.length,clusters:d?1:0},nodes:u,links:g,dashboard:k(i,{viewMode:"files",selection:d,totalNodes:n.nodes.length,totalLinks:n.links.length})}}function M(i,n,d){let S=n.nodes.filter(c=>c.filePath===d),C=new Set(S.map(c=>c.id)),p=new Set;for(let c of S.slice(0,1800))p.add(c.id);for(let c of n.links){if(p.size>=1800)break;let y=b(c.source),w=b(c.target);(C.has(y)||C.has(w))&&(p.add(y),p.size<1800&&p.add(w))}let u=n.nodes.filter(c=>p.has(c.id)).map(c=>({...c,viewKind:"symbol"})),g=[];for(let c of n.links){if(g.length>=12e3)break;let y=b(c.source),w=b(c.target);p.has(y)&&p.has(w)&&g.push({...c,source:y,target:w})}return{version:2,projectId:n.projectId,generatedAt:n.generatedAt,summary:{nodes:u.length,links:g.length,files:new Set(u.map(c=>c.filePath)).size,clusters:new Set(u.map(c=>v(c))).size},nodes:u,links:g,dashboard:k(i,{viewMode:"symbols",selection:d,focused:!0,truncated:u.length>=1800||g.length>=12e3,totalNodes:n.nodes.length,totalLinks:n.links.length})}}vt(async(i,n)=>{try{let d=new URL(i.url??"/",`http://${i.headers.host??"localhost"}`);if(d.pathname==="/api/health"){let x=await l();n.setHeader("content-type","application/json; charset=utf-8"),n.setHeader("cache-control","no-store"),n.end(JSON.stringify({ok:!0,mode:"multi-project",projects:x.projects.length,indexedProjects:x.projects.filter(m=>m.hasGraph).length,defaultProject:x.defaultProject}));return}if(d.pathname==="/api/projects"){let x=await l();n.setHeader("content-type","application/json; charset=utf-8"),n.setHeader("cache-control","no-store"),n.end(JSON.stringify(x));return}if(d.pathname==="/api/graph"){let x=await l(),m=d.searchParams.get("project")??x.defaultProject;if(!m){n.statusCode=404,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:"No indexed ToolNet project found."}));return}let S=x.projects.find(c=>c.remote===m);if(!S){n.statusCode=404,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:"Project not found.",project:m}));return}if(!S.hasGraph){n.statusCode=409,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:"Project is registered but has not been indexed yet.",project:S}));return}let C=d.searchParams.get("refresh")==="1",p=await N(S,C),u=d.searchParams.get("mode")??"full",g=p;if(u==="overview")g=A(S,p);else if(u==="files")g=K(S,p,d.searchParams.get("cluster")??"");else if(u==="symbols"){let c=d.searchParams.get("file");if(!c){n.statusCode=400,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:"file is required for symbols mode."}));return}g=M(S,p,c)}else if(u!=="full"){n.statusCode=400,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:`Unknown graph mode: ${u}`}));return}n.setHeader("content-type","application/json; charset=utf-8"),n.setHeader("cache-control","no-store"),n.end(JSON.stringify(g));return}if(d.pathname==="/vendor/3d-force-graph.min.js"){n.setHeader("content-type","application/javascript; charset=utf-8"),Ce(o).pipe(n);return}if(d.pathname==="/"||d.pathname==="/index.html"){n.setHeader("content-type","text/html; charset=utf-8"),n.setHeader("cache-control","no-store"),Ce(te(a,"index.html")).pipe(n);return}n.statusCode=404,n.end("Not found")}catch(d){console.error(d),n.statusCode=500,n.setHeader("content-type","application/json; charset=utf-8"),n.end(JSON.stringify({error:d instanceof Error?d.message:String(d)}))}}).listen(we,Ee,()=>{console.log("ToolNet Multi-Project 3D Graph"),console.log(`Listening: http://${Ee}:${we}`)})}Mt().catch(s=>{console.error(s),process.exit(1)});
|