toolnet-memory 0.3.14 → 0.3.16

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.
Files changed (48) hide show
  1. package/.env.example +0 -1
  2. package/.release-target +1 -1
  3. package/README.md +182 -6
  4. package/bin/toolnet-memory +5 -0
  5. package/bundle/agy-hook.js +71 -71
  6. package/bundle/agy.js +65 -65
  7. package/bundle/api.js +15 -15
  8. package/bundle/auto-integrate.js +28 -28
  9. package/bundle/background-refresh.js +7 -7
  10. package/bundle/claude-hook.js +51 -50
  11. package/bundle/codex-context.js +29 -28
  12. package/bundle/codex.js +77 -77
  13. package/bundle/context-runtime.js +44 -43
  14. package/bundle/context.js +15 -15
  15. package/bundle/continuity-certify.js +13 -13
  16. package/bundle/copilot-hook.js +88 -86
  17. package/bundle/copilot.js +4 -4
  18. package/bundle/cursor-hook.js +88 -86
  19. package/bundle/cursor.js +4 -4
  20. package/bundle/doctor.js +4 -4
  21. package/bundle/full-index.js +21 -21
  22. package/bundle/gc.js +3 -0
  23. package/bundle/graph-index.js +4 -4
  24. package/bundle/graph-ui.js +3 -3
  25. package/bundle/grok-hook.js +64 -63
  26. package/bundle/grok.js +5 -5
  27. package/bundle/handoff-refresh.js +10 -10
  28. package/bundle/help-cli.js +3 -3
  29. package/bundle/impact.js +4 -4
  30. package/bundle/incremental.js +5 -4
  31. package/bundle/init.js +38 -37
  32. package/bundle/integration-status.js +4 -4
  33. package/bundle/kiro-hook.js +93 -92
  34. package/bundle/learner.js +6 -6
  35. package/bundle/mcp.js +17 -17
  36. package/bundle/memory-agent.js +7 -7
  37. package/bundle/memory-query.js +7 -7
  38. package/bundle/opencode.js +84 -84
  39. package/bundle/project-manual.js +7 -7
  40. package/bundle/recovery-certify.js +15 -15
  41. package/bundle/runtime.js +13 -12
  42. package/bundle/semantic.js +5 -5
  43. package/bundle/snapshot.js +4 -4
  44. package/bundle/status-cli.js +4 -4
  45. package/bundle/toolnet-cli.js +60 -60
  46. package/bundle/work-continuity.js +7 -7
  47. package/package.json +21 -3
  48. package/release-manifest.json +104 -3
@@ -1,7 +1,7 @@
1
- import{existsSync as Ce,readFileSync as Oe}from"node:fs";import{homedir as Te}from"node:os";import{join as Ee}from"node:path";function _e(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Ne(){let r=process.env.TOOLNET_GLOBAL_ENV??Ee(Te(),".config","toolnet-memory",".env");if(!Ce(r))return;let e=Oe(r,"utf8");for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7));let n=o.indexOf("=");if(n<=0)continue;let i=o.slice(0,n).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=_e(o.slice(n+1)))}}Ne();function j(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function M(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function X(){return{memory:{autoCapture:j(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:j(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:j(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:j(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:M(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:M(process.env.MEMORY_RERANK_TOP,10),finalContext:M(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:M(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:j(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:M(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as $e}from"node:crypto";import{existsSync as H,mkdirSync as Ke,readFileSync as De,renameSync as ze,writeFileSync as He}from"node:fs";import{basename as Le,dirname as I,join as O,parse as re,resolve as x}from"node:path";var oe=".toolnet",Ve="project.json";function Be(r){return $e("sha256").update(r).digest("hex").slice(0,16)}function L(r){return O(r,oe,Ve)}function Fe(r){return H(L(r))}function We(r,e){let t=x(r),o=re(t).root;for(;;){if(Fe(t))return t;if(t===o||e&&t===x(e))break;let n=I(t);if(n===t)break;t=n}return null}function Je(r){let e=x(r),t=re(e).root,o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(o.some(i=>H(O(e,i))))return e;if(e===t)break;let n=I(e);if(n===e)break;e=n}return x(r)}function Ue(r){let e;try{e=JSON.parse(De(r,"utf8"))}catch(n){throw new Error(`Invalid ToolNet project manifest: ${r}: ${n instanceof Error?n.message:String(n)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let o=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:I(I(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:o,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:o,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function ee(r,e){let t=O(r,oe);Ke(t,{recursive:!0});let o=L(r),n=`${o}.tmp-${process.pid}`;He(n,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),ze(n,o)}function te(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var C=class{detect(e=process.cwd()){let t=x(e),o=Je(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(m=>H(O(o,m))),a=We(t,i?o:void 0);if(a){let m=L(a),f=Ue(m);return f.rootPath!==a&&(f.rootPath=a,f.updatedAt=new Date().toISOString(),ee(a,f)),te(f,a)}let c=new Date().toISOString(),p=Le(o),d={version:1,id:Be(o),name:p,remote:p,rootPath:o,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return ee(o,d),te(d,o)}};import{homedir as yt}from"node:os";import{join as ht}from"node:path";import{DeleteObjectCommand as Ye,GetObjectCommand as Ge,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 T=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,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ze({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await et(this.client,new Ge({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`HF download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new 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=[],o;do{let n=await this.client.send(new Qe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};import{access as ne,mkdir as tt,readFile as rt,readdir as ot,rm as nt,stat as se,writeFile as st}from"node:fs/promises";import{dirname as it,join as at,relative as ie,resolve as ct}from"node:path";var R=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 o=this.path(e);await tt(it(o),{recursive:!0}),await st(o,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 ne(this.path(e)),!0}catch{return!1}}async delete(e){await nt(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),o=[];try{await ne(t)}catch{return o}let n=async a=>{let c=await ot(a,{withFileTypes:!0});for(let p of c){let d=at(a,p.name);if(p.isDirectory()){await n(d);continue}let m=await se(d);o.push({key:ie(this.root,d),size:m.size,updatedAt:m.mtime.toISOString()})}},i=await se(t);return i.isDirectory()?await n(t):o.push({key:ie(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),o}};import{DeleteObjectCommand as ut,GetObjectCommand as dt,HeadObjectCommand as pt,ListObjectsV2Command as lt,PutObjectCommand as mt,S3Client as ft}from"@aws-sdk/client-s3";import{getSignedUrl as gt}from"@aws-sdk/s3-request-presigner";var A=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new ft({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,o="application/octet-stream"){let n=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new mt({Bucket:this.bucket,Key:e,Body:n,ContentType:o}))}async get(e){let t=await gt(this.client,new dt({Bucket:this.bucket,Key:e}),{expiresIn:60}),o=await fetch(t,{redirect:"follow"});if(o.status===404)return null;if(!o.ok)throw new Error(`${this.name} download failed: ${o.status} ${o.statusText}`);return new Uint8Array(await o.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new 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 ut({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],o;do{let n=await this.client.send(new lt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:o}));for(let i of n.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});o=n.IsTruncated?n.NextContinuationToken:void 0}while(o);return t}};function V(r,e){return console.warn(e),new R(r)}function ae(r){let e=r.localRoot??ht(yt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new A({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new A({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new T({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):V(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new R(e)}var E=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let o=JSON.parse(t);if(!Array.isArray(o))throw new Error("Invalid memory snapshot");return o}async save(e,t){let o=JSON.stringify(t,null,2);await this.storage.put(this.key(e),o,"application/json")}};function St(r){return new Promise(e=>setTimeout(e,r))}async function ce(r,e={}){let t=Math.max(1,e.attempts??3),o=e.baseDelayMs??150,n=e.maxDelayMs??2e3,i;for(let a=1;a<=t;a++)try{return await r()}catch(c){if(i=c,a>=t)break;let p=Math.min(n,o*2**(a-1)),d=Math.floor(Math.random()*Math.max(1,p*.2));await St(p+d)}throw i}var kt=new Set(["put","get","getText","delete","list"]);function ue(r,e={}){return new Proxy(r,{get(t,o){let n=Reflect.get(t,o,t);return typeof n!="function"?n:kt.has(o)?(...i)=>ce(()=>Promise.resolve(n.apply(t,i)),e):n.bind(t)}})}function de(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function pe(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(o)return`${o[1]}memory/records/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),o)return`${o[1]}memory/vectors/${o[2]}`;if(o=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),o)return`${o[1]}code/graph/${o[2]}`;let n=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return n?`${n[1]}memory/records/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),n?`${n[1]}memory/vectors/${n[2]}`:(n=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),n?`${n[1]}code/graph/${n[2]}`:e))}var _=class{constructor(e,t,o,n){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=o,this.folder=de(n??o),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),o=t,n=await this.provider.getText(e);if(n){let a;try{a=JSON.parse(n)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof a.id=="string"&&a.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${a.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof a.createdAt=="string"&&(o=a.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:o,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=pe(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,o){return await this.ensureRegistered(),this.provider.put(this.key(e),t,o)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as fe}from"node:path";import{mkdirSync as xt}from"node:fs";import{createHash as vt}from"node:crypto";import{dirname as wt}from"node:path";import{mkdirSync as bt,readFileSync as Wo,renameSync as jt,writeFileSync as Mt}from"node:fs";function le(r){return vt("sha256").update(r).digest("hex")}function me(r,e){bt(wt(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;Mt(t,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),jt(t,r)}function ye(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function y(r,e=20){let t=[],o=new Set;for(let n of r.slice().reverse()){let i=ye(n);if(!(!i||o.has(i))&&(o.add(i),t.push(n),t.length>=e))break}return t.reverse()}function Rt(r,e=20){let t=new Map;for(let o of r){let n=`${o.kind}|${ye(o.command)}`;t.delete(n),t.set(n,o)}return Array.from(t.values()).slice(-e)}function At(r){return r.kind==="phase"?/^Phase\s+\d+$/iu.test(r.text):r.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(r.text):!1}function ge(r,e){let t=e.status??r?.status??"pending",o=t;r&&(r.status==="completed"&&t!=="completed"?o="completed":t==="pending"&&(r.status==="in_progress"||r.status==="blocked")&&(o=r.status));let n=r&&At(e)?r.title:e.text;return{id:r?.id??le(e.key).slice(0,24),title:n,status:o,order:e.order??r?.order,confidence:Math.max(e.confidence,r?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function he(r,e){let t=`projects/${r.id}/work/observations/`,o=await e.list(t),n=[];for(let i of o.filter(a=>a.key.endsWith(".json")).sort((a,c)=>a.key.localeCompare(c.key))){let a=await e.getText(i.key);if(a)try{let c=JSON.parse(a);c.version===1&&Array.isArray(c.observations)&&n.push(c)}catch{}}return n}async function Pt(r,e){let o=(await he(r,e)).flatMap(s=>s.observations).sort((s,g)=>{let Q=s.occurredAt.localeCompare(g.occurredAt);if(Q!==0)return Q;let Z=s.sequence-g.sequence;return Z!==0?Z:s.id.localeCompare(g.id)}),n=new Map,i=new Map,a,c,p,d,m,f=[],u=[],l=[],S=[],w=[],b=new Map,F=[],W=[],J=[],U=[],Y=[],G=[];for(let s of o)switch(s.kind){case"request":a=s.text;break;case"activity":c=s.text;break;case"goal":p=s.text;break;case"plan":d=s.text;break;case"phase":n.set(s.key,ge(n.get(s.key),s));break;case"task":i.set(s.key,ge(i.get(s.key),s));break;case"decision":f.push(s.text);break;case"blocker":u.push(s.text);break;case"warning":l.push(s.text);break;case"next_action":S.push(s.text);break;case"file":{w.push(s.text);let g=s.fileAction??"active";b.delete(s.text),b.set(s.text,g),g==="modified"?F.push(s.text):g==="created"?W.push(s.text):g==="deleted"&&J.push(s.text);break}case"command":U.push(s.text);break;case"test":Y.push(s.text),s.checkKind&&G.push({kind:s.checkKind,command:s.text,status:s.checkStatus??"unknown",updatedAt:s.occurredAt,agent:s.agent,nativeSessionId:s.nativeSessionId});break;case"session":m={agent:s.agent,nativeSessionId:s.nativeSessionId,sessionKey:s.sessionKey,updatedAt:s.occurredAt};break}let k=Array.from(n.values()).sort((s,g)=>(s.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),h=Array.from(i.values()).sort((s,g)=>(s.order??Number.MAX_SAFE_INTEGER)-(g.order??Number.MAX_SAFE_INTEGER)),D=k.find(s=>s.status==="in_progress")??k.find(s=>s.status==="blocked")??k.find(s=>s.status==="pending"),P=h.find(s=>s.status==="in_progress")??h.find(s=>s.status==="blocked")??h.find(s=>s.status==="pending"),Pe=y([...S,...P?[P.title]:[],...!P&&D?[D.title]:[],...h.filter(s=>s.status==="pending").slice(0,5).map(s=>s.title)],8),Ie=y([...u,...k.filter(s=>s.status==="blocked").map(s=>s.title),...h.filter(s=>s.status==="blocked").map(s=>s.title)],20),z={version:1,projectId:r.id,projectName:r.name,currentRequest:a,currentActivity:c,goal:p,plan:d,phases:k,tasks:h,decisions:y(f,20),blockers:Ie,warnings:y(l,20),nextActions:Pe,filesTouched:y(w,30),activeFiles:Array.from(b.entries()).filter(([,s])=>s!=="deleted").map(([s])=>s).slice(-5),modifiedFiles:y(F,30),createdFiles:y(W,30),deletedFiles:y(J,30),commands:y(U,20),tests:y(Y,20),checks:Rt(G,20),currentPhase:D,currentTask:P,progress:{phasesTotal:k.length,phasesCompleted:k.filter(s=>s.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(s=>s.status==="completed").length,blocked:k.filter(s=>s.status==="blocked").length+h.filter(s=>s.status==="blocked").length},lastSession:m,updatedAt:o.length?o[o.length-1].occurredAt:new Date().toISOString()},q=fe(r.rootPath,".toolnet","work");return xt(q,{recursive:!0}),me(fe(q,"current.json"),z),await e.put(`projects/${r.id}/work/current.json`,JSON.stringify(z,null,2)+`
6
- `,"application/json"),z}async function Se(r,e){if((await he(r,e)).length>0)return Pt(r,e);let o=await e.getText(`projects/${r.id}/work/current.json`);if(!o)return null;try{return JSON.parse(o)}catch{return null}}import{createHash as Nt}from"node:crypto";import{hostname as $t}from"node:os";import{createHash as It,randomUUID as Ct}from"node:crypto";function v(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function N(r,e){return encodeURIComponent(v(r,e))}function Ot(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function ve(r){return It("sha256").update(r).digest("hex")}function we(r){return ve(Ot(r))}function be(r){return Number.isFinite(Date.parse(r))}function Tt(r){return ve(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function je(r){let e=v(r.projectId,"projectId"),t=v(r.scope,"scope"),o=v(r.hostId,"hostId"),n=v(r.operationId??Ct(),"operationId"),i=r.occurredAt??new Date().toISOString();if(!be(i))throw new Error(`Invalid operation timestamp: ${i}`);return{version:1,operationId:n,projectId:e,scope:t,hostId:o,occurredAt:i,payloadSha256:we(r.payload),payload:r.payload}}function Me(r,e){let t=["projects",N(r,"projectId"),"operations"];return e?`${[...t,N(e,"scope")].join("/")}/`:`${t.join("/")}/`}function Et(r){return[Me(r.projectId,r.scope).replace(/\/$/,""),N(r.hostId,"hostId"),`${N(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function xe(r,e){let t=Et(e);return await r.put(t,`${JSON.stringify(e,null,2)}
7
- `,"application/json"),t}function _t(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!be(e.occurredAt)||typeof e.payloadSha256!="string"||we(e.payload)!==e.payloadSha256?null:e}function ke(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let o=r.hostId.localeCompare(e.hostId);if(o!==0)return o;let n=r.operationId.localeCompare(e.operationId);return n!==0?n:r.payloadSha256.localeCompare(e.payloadSha256)}async function Re(r,e,t){let o=v(e,"projectId"),n=v(t,"scope"),i=Me(o,n),a=await r.list(i),c=[],p=[];for(let u of a){let l=await r.getText(u.key);if(!l){c.push(u.key);continue}let S=_t(l);if(!S){c.push(u.key);continue}if(S.projectId!==o){c.push(u.key);continue}if(S.scope!==n){c.push(u.key);continue}p.push(S)}let d=new Map;for(let u of p){let l=d.get(u.operationId);if(!l){d.set(u.operationId,[u]);continue}l.push(u)}let m=[],f=[];for(let[u,l]of d){if(new Set(l.map(b=>Tt(b))).size>1){f.push({operationId:u,variants:[...l].sort(ke)});continue}let w=l[0];w&&m.push(w)}return m.sort(ke),f.sort((u,l)=>u.operationId.localeCompare(l.operationId)),c.sort(),{operations:m,conflicts:f,invalidKeys:c}}function Kt(r){let t=(r??process.env.TOOLNET_HOST_ID??$t()).trim();return t||`pid-${process.pid}`}function Dt(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>e(n));let o=t;return Object.fromEntries(Object.keys(o).sort().map(n=>[n,e(o[n])]))};return JSON.stringify(e(r))}function $(r){return Nt("sha256").update(Dt(r)).digest("hex")}function zt(r,e){let t=$(r).slice(0,12),o=$(e);return["memory",t,o].join("-")}function Ht(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let o=r.createdAt.localeCompare(e.createdAt);return o!==0?o:$(r).localeCompare($(e))}function Lt(r,e){return Ht(r,e)>=0?r:e}function B(r,e){let t=new Map;for(let o of r)t.set(o.id,o);for(let o of e){if(o.payload.kind!=="upsert")continue;let n=o.payload.memory,i=t.get(n.id);if(!i){t.set(n.id,n);continue}t.set(n.id,Lt(i,n))}return[...t.values()].sort((o,n)=>o.id.localeCompare(n.id))}var K=class{constructor(e,t={}){this.storage=e;this.legacy=new E(e),this.hostId=Kt(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Re(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),o=await this.operations(e);return B(t,o)}async appendMemory(e,t){let o=je({projectId:e,scope:"memory",hostId:this.hostId,operationId:zt(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await xe(this.storage,o)}async refreshProjection(e){let t=await this.legacy.load(e),o=await this.operations(e),n=B(t,o);return await this.legacy.save(e,n),n}async save(e,t){let o=[...t].sort((a,c)=>a.id.localeCompare(c.id));for(let a of o)await this.appendMemory(e,a);let n=await this.operations(e),i=B(t,n);await this.legacy.save(e,i)}};async function Ae(r,e){let t=new Date().toISOString(),n=await new K(e).refreshProjection(r.id),i=await Se(r,e);return{startedAt:t,finishedAt:new Date().toISOString(),memories:n.length,workAvailable:i!==null}}function Vt(r,e){let t=r.indexOf(e);if(!(t<0))return r[t+1]}function Bt(r){return{projectPath:Vt(r,"--project"),json:r.includes("--json"),quiet:r.includes("--quiet")}}async function Ft(r){let e=X(),t=ue(ae({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new _(t,r.id,r.name,r.remote??r.name)}async function Wt(){let r=Bt(process.argv.slice(2)),e=r.projectPath??process.cwd(),t=new C().detect(e);if(!t){r.quiet||console.error(`ToolNet project not found: ${e}`),process.exitCode=2;return}let o;try{o=await Ft(t)}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=3;return}try{let n=await Ae(t,o);if(r.quiet)return;if(r.json){console.log(JSON.stringify(n));return}console.log(["ToolNet Memory refreshed",`memory=${n.memories}`,`work=${n.workAvailable?"yes":"no"}`].join(" "))}catch(n){r.quiet||console.error(n instanceof Error?n.message:String(n)),process.exitCode=4}}Wt().then(()=>{process.exit(process.exitCode??0)});
1
+ import{existsSync as Ge,readFileSync as Ue}from"node:fs";import{homedir as Ye}from"node:os";import{join as qe}from"node:path";function Ze(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Qe(){let r=process.env.TOOLNET_GLOBAL_ENV??qe(Ye(),".config","toolnet-memory",".env");if(!Ge(r))return;let e=Ue(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let s=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=Ze(n.slice(o+1)))}}Qe();function R(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function A(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function ce(){return{memory:{autoCapture:R(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:R(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:R(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:R(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:A(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:A(process.env.MEMORY_RERANK_TOP,10),finalContext:A(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:A(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:R(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:A(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as st}from"node:crypto";import{existsSync as N,mkdirSync as it,readFileSync as at,renameSync as ct,writeFileSync as ut}from"node:fs";import{basename as dt,dirname as K,join as P,parse as ye,resolve as w}from"node:path";import{createHash as le}from"node:crypto";import{spawnSync as Xe}from"node:child_process";var I="git-remote-v1",et=new Set(["github.com","gitlab.com","bitbucket.org"]);function pe(r,e){let t=e.replaceAll("\\","/").replace(/^\/+/u,"").replace(/\/+$/u,"").replace(/\.git$/iu,"").replace(/\/+/gu,"/");return!t||t==="."||t===".."||t.split("/").some(n=>!n||n==="."||n==="..")?null:(et.has(r)&&(t=t.toLowerCase()),t)}function tt(r){let e;try{e=new URL(r)}catch{return null}if(!["https:","http:","ssh:","git:"].includes(e.protocol))return null;let t=e.hostname.trim().toLowerCase();if(!t)return null;let n=e.protocol==="https:"&&e.port==="443"||e.protocol==="http:"&&e.port==="80"||e.protocol==="ssh:"&&e.port==="22",o=e.port&&!n?`${t}:${e.port}`:t,s=pe(t,e.pathname);return s?`${o}/${s}`:null}function rt(r){let e=r.match(/^(?:[^@\s/:]+@)?([^:/\s]+):(.+)$/u);if(!e)return null;let t=e[1]?.trim().toLowerCase();if(!t||t.length===1)return null;let n=pe(t,e[2]??"");return n?`${t}/${n}`:null}function ue(r){let e=r.trim();return e?e.includes("://")?tt(e):rt(e):null}function nt(r){return le("sha256").update(`${I}:${r}`).digest("hex")}function me(r){return le("sha256").update(`toolnet-project:${I}:${r}`).digest("hex").slice(0,16)}function ot(r){return r.split("/").filter(Boolean).at(-1)?.trim()||null}function U(r,e){let t=Xe("git",["-C",r,...e],{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]});return t.error||t.status!==0?null:t.stdout?.trim()||null}function de(r,e){let t=ot(r);return t?{scheme:I,canonicalRemote:r,fingerprint:nt(r),repositoryName:t,source:e}:null}function fe(r){let e=U(r,["remote","get-url","origin"]);if(e){let o=ue(e);if(o)return de(o,"origin")}let t=U(r,["remote"]);if(!t)return null;let n=new Set;for(let o of t.split(/\r?\n/u).map(s=>s.trim()).filter(Boolean)){let s=U(r,["remote","get-url",o]);if(!s)continue;let a=ue(s);a&&n.add(a)}return n.size!==1?null:de([...n][0],"unique-remote")}var he=".toolnet",lt="project.json";function pt(r){return st("sha256").update(r).digest("hex").slice(0,16)}function v(r){return P(r,he,lt)}function Se(r){return N(v(r))}function ge(r,e){let t=w(r),n=ye(t).root;for(;;){if(Se(t))return t;if(t===n||e&&t===w(e))break;let o=K(t);if(o===t)break;t=o}return null}function Y(r){let e=w(r),t=ye(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(s=>N(P(e,s))))return e;if(e===t)break;let o=K(e);if(o===e)break;e=o}return w(r)}function O(r){let e;try{e=JSON.parse(at(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:K(K(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function _(r,e){let t=P(r,he);it(t,{recursive:!0});let n=v(r),o=`${n}.tmp-${process.pid}`;ut(o,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ct(o,n)}function k(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}function q(r){return{version:1,scheme:I,canonicalRemote:r.canonicalRemote,fingerprint:r.fingerprint,repositoryName:r.repositoryName}}function mt(r){let e=r.metadata?.toolnetIdentity;if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return typeof t.fingerprint=="string"?t.fingerprint:null}var D=class{adopt(e,t){let n=Y(w(e));if(!t.id.trim())throw new Error("PROJECT_ADOPTION_INVALID_ID");if(!t.name.trim())throw new Error("PROJECT_ADOPTION_INVALID_NAME");if(!t.remote.trim())throw new Error("PROJECT_ADOPTION_INVALID_REMOTE");if(Se(n)){let c=O(v(n));if(c.id!==t.id)throw new Error(["PROJECT_IDENTITY_ALREADY_EXISTS",`existing=${c.id}`,`requested=${t.id}`].join(" "));return k(c,n)}let o=new Date().toISOString(),s={...t.metadata};t.gitIdentity&&(s.toolnetIdentity=q(t.gitIdentity));let a={version:1,id:t.id.trim(),name:t.name.trim(),remote:t.remote.trim(),rootPath:n,createdAt:t.createdAt??o,updatedAt:o,graphVersion:t.graphVersion??0,memoryVersion:t.memoryVersion??0,metadata:Object.keys(s).length?s:void 0};return _(n,a),k(a,n)}recordGitIdentity(e,t,n={}){let o=this.requireExisting(e),s=v(o.rootPath),a=O(s),c=mt(a);if(c&&c!==t.fingerprint&&!n.allowRebind)throw new Error(["PROJECT_GIT_REMOTE_CHANGED",`existing=${c}`,`current=${t.fingerprint}`,"Use explicit rebind only when this repository identity change is intentional."].join(" "));let d=a.metadata?.toolnetIdentity;return d&&typeof d=="object"&&!Array.isArray(d)&&d.fingerprint===t.fingerprint||(a.metadata={...a.metadata,toolnetIdentity:q(t)},a.updatedAt=new Date().toISOString(),_(o.rootPath,a)),k(a,o.rootPath)}findExisting(e=process.cwd()){let t=w(e),n=Y(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>N(P(n,d))),a=ge(t,s?n:void 0);if(!a)return null;let c=O(v(a));return k(c,a)}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=w(e),n=Y(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(g=>N(P(n,g))),a=ge(t,s?n:void 0);if(a){let g=v(a),u=O(g);return u.rootPath!==a&&(u.rootPath=a,u.updatedAt=new Date().toISOString(),_(a,u)),k(u,a)}let c=new Date().toISOString(),d=dt(n),l=fe(n),m={version:1,id:l?me(l.canonicalRemote):pt(n),name:d,remote:l?.repositoryName??d,rootPath:n,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0,metadata:l?{toolnetIdentity:q(l)}:void 0};return _(n,m),k(m,n)}};var ft=[{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"}],gt=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function be(r){return r.normalize("NFKC").trim().toLowerCase()}function yt(r){if(r.length===0)return 0;let e=new Map;for(let n of r)e.set(n,(e.get(n)??0)+1);let t=0;for(let n of e.values()){let o=n/r.length;t-=o*Math.log2(o)}return t}function ht(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function St(r,e,t){let n=r.slice(Math.max(0,e-48),e),o=r.slice(t,Math.min(r.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${n} ${o}`)}function bt(r,e){return r.start<e.end&&e.start<r.end}function ke(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var $=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=be(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let s of ft){let a=new RegExp(s.regex.source,s.regex.flags);for(let c of e.matchAll(a))c.index===void 0||!c[0]||this.allowed(c[0])||t.push({type:s.type,value:c[0],start:c.index,end:c.index+c[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let n=ke(t),o=[];for(let s of n)o.some(a=>bt(a,s))||o.push(s);return ke(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=be(e);return gt.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],n=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of e.matchAll(n)){if(o.index===void 0||!o[0])continue;let s=o[0];this.allowed(s)||ht(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||St(e,o.index,o.index+s.length)&&(yt(s)<3.7||t.push({type:"high_entropy_secret",value:s,start:o.index,end:o.index+s.length,confidence:"heuristic"}))}return t}};var z=class{scanner;constructor(e={}){this.scanner=new $(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let n=e,o=[...t].sort((a,c)=>c.start-a.start),s=new Set;for(let a of o)s.add(a.type),n=n.slice(0,a.start)+`[REDACTED:${a.type}]`+n.slice(a.end);return{text:n,redacted:t.length,secretTypes:[...s].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[n,o]of Object.entries(e)){let s=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(s.includes("password")||s.includes("passwd")||s==="pwd"||s.includes("secret")||s.includes("token")||s.includes("cookie")||s.includes("authorization")||s.includes("apikey")||s.includes("accesskey")||s.includes("privatekey")||s.includes("clientsecret")||s.includes("credential")){t[n]="[REDACTED]";continue}t[n]=this.sanitizeValue(o)}return t}return e}};var Dr=new z;import{homedir as Vt}from"node:os";import{join as Ft}from"node:path";import{DeleteObjectCommand as kt,GetObjectCommand as wt,HeadObjectCommand as xt,ListObjectsV2Command as vt,PutObjectCommand as Mt,S3Client as jt}from"@aws-sdk/client-s3";import{getSignedUrl as Rt}from"@aws-sdk/s3-request-presigner";var L=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new jt({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Mt({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Rt(this.client,new wt({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new 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 kt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new vt({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let s of o.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{access as we,mkdir as At,readFile as It,readdir as Pt,rm as Ct,stat as xe,writeFile as Tt}from"node:fs/promises";import{dirname as Et,join as Ot,relative as ve,resolve as _t}from"node:path";var C=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return _t(this.root,t)}async put(e,t){let n=this.path(e);await At(Et(n),{recursive:!0}),await Tt(n,t)}async get(e){try{return await It(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 we(this.path(e)),!0}catch{return!1}}async delete(e){await Ct(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await we(t)}catch{return n}let o=async a=>{let c=await Pt(a,{withFileTypes:!0});for(let d of c){let l=Ot(a,d.name);if(d.isDirectory()){await o(l);continue}let m=await xe(l);n.push({key:ve(this.root,l),size:m.size,updatedAt:m.mtime.toISOString()})}},s=await xe(t);return s.isDirectory()?await o(t):n.push({key:ve(this.root,t),size:s.size,updatedAt:s.mtime.toISOString()}),n}};import{DeleteObjectCommand as Nt,GetObjectCommand as Kt,HeadObjectCommand as Dt,ListObjectsV2Command as $t,PutObjectCommand as zt,S3Client as Lt}from"@aws-sdk/client-s3";import{getSignedUrl as Ht}from"@aws-sdk/s3-request-presigner";var T=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Lt({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new zt({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Ht(this.client,new Kt({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Dt({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 Nt({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new $t({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let s of o.Contents??[])s.Key&&t.push({key:s.Key,size:s.Size,updatedAt:s.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};function Z(r,e){return console.warn(e),new C(r)}function Me(r){let e=r.localRoot??Ft(Vt(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new T({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Z(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new T({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Z(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new L({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):Z(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new C(e)}var H=class{constructor(e){this.storage=e}storage;key(e){return["projects",e,"memories","current.json"].join("/")}async load(e){let t=await this.storage.getText(this.key(e));if(!t)return[];let n=JSON.parse(t);if(!Array.isArray(n))throw new Error("Invalid memory snapshot");return n}async save(e,t){let n=JSON.stringify(t,null,2);await this.storage.put(this.key(e),n,"application/json")}};function Bt(r){return new Promise(e=>setTimeout(e,r))}async function je(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,s;for(let a=1;a<=t;a++)try{return await r()}catch(c){if(s=c,a>=t)break;let d=Math.min(o,n*2**(a-1)),l=Math.floor(Math.random()*Math.max(1,d*.2));await Bt(d+l)}throw s}var Wt=new Set(["put","get","getText","delete","list"]);function Re(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Wt.has(n)?(...s)=>je(()=>Promise.resolve(o.apply(t,s)),e):o.bind(t)}})}function Ae(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function Ie(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var V=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=Ae(o??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,o=await this.provider.getText(e);if(o){let a;try{a=JSON.parse(o)}catch(c){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${c instanceof Error?c.message:String(c)}`)}if(typeof a.id=="string"&&a.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${a.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof a.createdAt=="string"&&(n=a.createdAt)}let s={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(s,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Ie(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{join as Te}from"node:path";import{mkdirSync as Zt}from"node:fs";import{createHash as Jt}from"node:crypto";import{dirname as Gt}from"node:path";import{mkdirSync as Ut,readFileSync as Po,renameSync as Yt,writeFileSync as qt}from"node:fs";function Pe(r){return Jt("sha256").update(r).digest("hex")}function Ce(r,e){Ut(Gt(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;qt(t,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Yt(t,r)}function Oe(r){return r.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function y(r,e=20){let t=[],n=new Set;for(let o of r.slice().reverse()){let s=Oe(o);if(!(!s||n.has(s))&&(n.add(s),t.push(o),t.length>=e))break}return t.reverse()}function Qt(r,e=20){let t=new Map;for(let n of r){let o=`${n.kind}|${Oe(n.command)}`;t.delete(o),t.set(o,n)}return Array.from(t.values()).slice(-e)}function Xt(r){return r.kind==="phase"?/^Phase\s+\d+$/iu.test(r.text):r.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(r.text):!1}function Ee(r,e){let t=e.status??r?.status??"pending",n=t;r&&(r.status==="completed"&&t!=="completed"?n="completed":t==="pending"&&(r.status==="in_progress"||r.status==="blocked")&&(n=r.status));let o=r&&Xt(e)?r.title:e.text;return{id:r?.id??Pe(e.key).slice(0,24),title:o,status:n,order:e.order??r?.order,confidence:Math.max(e.confidence,r?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function _e(r,e){let t=`projects/${r.id}/work/observations/`,n=await e.list(t),o=[];for(let s of n.filter(a=>a.key.endsWith(".json")).sort((a,c)=>a.key.localeCompare(c.key))){let a=await e.getText(s.key);if(a)try{let c=JSON.parse(a);c.version===1&&Array.isArray(c.observations)&&o.push(c)}catch{}}return o}async function er(r,e){let n=(await _e(r,e)).flatMap(i=>i.observations).sort((i,f)=>{let ie=i.occurredAt.localeCompare(f.occurredAt);if(ie!==0)return ie;let ae=i.sequence-f.sequence;return ae!==0?ae:i.id.localeCompare(f.id)}),o=new Map,s=new Map,a,c,d,l,m,g=[],u=[],p=[],S=[],M=[],j=new Map,X=[],ee=[],te=[],re=[],ne=[],oe=[];for(let i of n)switch(i.kind){case"request":a=i.text;break;case"activity":c=i.text;break;case"goal":d=i.text;break;case"plan":l=i.text;break;case"phase":o.set(i.key,Ee(o.get(i.key),i));break;case"task":s.set(i.key,Ee(s.get(i.key),i));break;case"decision":g.push(i.text);break;case"blocker":u.push(i.text);break;case"warning":p.push(i.text);break;case"next_action":S.push(i.text);break;case"file":{M.push(i.text);let f=i.fileAction??"active";j.delete(i.text),j.set(i.text,f),f==="modified"?X.push(i.text):f==="created"?ee.push(i.text):f==="deleted"&&te.push(i.text);break}case"command":re.push(i.text);break;case"test":ne.push(i.text),i.checkKind&&oe.push({kind:i.checkKind,command:i.text,status:i.checkStatus??"unknown",updatedAt:i.occurredAt,agent:i.agent,nativeSessionId:i.nativeSessionId});break;case"session":m={agent:i.agent,nativeSessionId:i.nativeSessionId,sessionKey:i.sessionKey,updatedAt:i.occurredAt};break}let b=Array.from(o.values()).sort((i,f)=>(i.order??Number.MAX_SAFE_INTEGER)-(f.order??Number.MAX_SAFE_INTEGER)),h=Array.from(s.values()).sort((i,f)=>(i.order??Number.MAX_SAFE_INTEGER)-(f.order??Number.MAX_SAFE_INTEGER)),J=b.find(i=>i.status==="in_progress")??b.find(i=>i.status==="blocked")??b.find(i=>i.status==="pending"),E=h.find(i=>i.status==="in_progress")??h.find(i=>i.status==="blocked")??h.find(i=>i.status==="pending"),We=y([...S,...E?[E.title]:[],...!E&&J?[J.title]:[],...h.filter(i=>i.status==="pending").slice(0,5).map(i=>i.title)],8),Je=y([...u,...b.filter(i=>i.status==="blocked").map(i=>i.title),...h.filter(i=>i.status==="blocked").map(i=>i.title)],20),G={version:1,projectId:r.id,projectName:r.name,currentRequest:a,currentActivity:c,goal:d,plan:l,phases:b,tasks:h,decisions:y(g,20),blockers:Je,warnings:y(p,20),nextActions:We,filesTouched:y(M,30),activeFiles:Array.from(j.entries()).filter(([,i])=>i!=="deleted").map(([i])=>i).slice(-5),modifiedFiles:y(X,30),createdFiles:y(ee,30),deletedFiles:y(te,30),commands:y(re,20),tests:y(ne,20),checks:Qt(oe,20),currentPhase:J,currentTask:E,progress:{phasesTotal:b.length,phasesCompleted:b.filter(i=>i.status==="completed").length,tasksTotal:h.length,tasksCompleted:h.filter(i=>i.status==="completed").length,blocked:b.filter(i=>i.status==="blocked").length+h.filter(i=>i.status==="blocked").length},lastSession:m,updatedAt:n.length?n[n.length-1].occurredAt:new Date().toISOString()},se=Te(r.rootPath,".toolnet","work");return Zt(se,{recursive:!0}),Ce(Te(se,"current.json"),G),await e.put(`projects/${r.id}/work/current.json`,JSON.stringify(G,null,2)+`
6
+ `,"application/json"),G}async function Ne(r,e){if((await _e(r,e)).length>0)return er(r,e);let n=await e.getText(`projects/${r.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}import{createHash as ar}from"node:crypto";import{hostname as cr}from"node:os";import{createHash as tr,randomUUID as rr}from"node:crypto";function x(r,e){let t=r.trim();if(!t)throw new Error(`${e} is required`);return t}function F(r,e){return encodeURIComponent(x(r,e))}function nr(r){let e=JSON.stringify(r);if(e===void 0)throw new Error("Multi-host operation payload must be JSON serializable");return e}function De(r){return tr("sha256").update(r).digest("hex")}function $e(r){return De(nr(r))}function ze(r){return Number.isFinite(Date.parse(r))}function or(r){return De(JSON.stringify({version:r.version,operationId:r.operationId,projectId:r.projectId,scope:r.scope,hostId:r.hostId,occurredAt:r.occurredAt,payloadSha256:r.payloadSha256,payload:r.payload}))}function Le(r){let e=x(r.projectId,"projectId"),t=x(r.scope,"scope"),n=x(r.hostId,"hostId"),o=x(r.operationId??rr(),"operationId"),s=r.occurredAt??new Date().toISOString();if(!ze(s))throw new Error(`Invalid operation timestamp: ${s}`);return{version:1,operationId:o,projectId:e,scope:t,hostId:n,occurredAt:s,payloadSha256:$e(r.payload),payload:r.payload}}function He(r,e){let t=["projects",F(r,"projectId"),"operations"];return e?`${[...t,F(e,"scope")].join("/")}/`:`${t.join("/")}/`}function sr(r){return[He(r.projectId,r.scope).replace(/\/$/,""),F(r.hostId,"hostId"),`${F(r.operationId,"operationId")}-${r.payloadSha256}.json`].join("/")}async function Ve(r,e){let t=sr(e);return await r.put(t,`${JSON.stringify(e,null,2)}
7
+ `,"application/json"),t}function ir(r){let e;try{e=JSON.parse(r)}catch{return null}return e.version!==1||typeof e.operationId!="string"||typeof e.projectId!="string"||typeof e.scope!="string"||typeof e.hostId!="string"||typeof e.occurredAt!="string"||!ze(e.occurredAt)||typeof e.payloadSha256!="string"||$e(e.payload)!==e.payloadSha256?null:e}function Ke(r,e){let t=r.occurredAt.localeCompare(e.occurredAt);if(t!==0)return t;let n=r.hostId.localeCompare(e.hostId);if(n!==0)return n;let o=r.operationId.localeCompare(e.operationId);return o!==0?o:r.payloadSha256.localeCompare(e.payloadSha256)}async function Fe(r,e,t){let n=x(e,"projectId"),o=x(t,"scope"),s=He(n,o),a=await r.list(s),c=[],d=[];for(let u of a){let p=await r.getText(u.key);if(!p){c.push(u.key);continue}let S=ir(p);if(!S){c.push(u.key);continue}if(S.projectId!==n){c.push(u.key);continue}if(S.scope!==o){c.push(u.key);continue}d.push(S)}let l=new Map;for(let u of d){let p=l.get(u.operationId);if(!p){l.set(u.operationId,[u]);continue}p.push(u)}let m=[],g=[];for(let[u,p]of l){if(new Set(p.map(j=>or(j))).size>1){g.push({operationId:u,variants:[...p].sort(Ke)});continue}let M=p[0];M&&m.push(M)}return m.sort(Ke),g.sort((u,p)=>u.operationId.localeCompare(p.operationId)),c.sort(),{operations:m,conflicts:g,invalidKeys:c}}function ur(r){let t=(r??process.env.TOOLNET_HOST_ID??cr()).trim();return t||`pid-${process.pid}`}function dr(r){let e=t=>{if(t===null||typeof t!="object")return t;if(Array.isArray(t))return t.map(o=>e(o));let n=t;return Object.fromEntries(Object.keys(n).sort().map(o=>[o,e(n[o])]))};return JSON.stringify(e(r))}function B(r){return ar("sha256").update(dr(r)).digest("hex")}function lr(r,e){let t=B(r).slice(0,12),n=B(e);return["memory",t,n].join("-")}function pr(r,e){let t=r.updatedAt.localeCompare(e.updatedAt);if(t!==0)return t;let n=r.createdAt.localeCompare(e.createdAt);return n!==0?n:B(r).localeCompare(B(e))}function mr(r,e){return pr(r,e)>=0?r:e}function Q(r,e){let t=new Map;for(let n of r)t.set(n.id,n);for(let n of e){if(n.payload.kind!=="upsert")continue;let o=n.payload.memory,s=t.get(o.id);if(!s){t.set(o.id,o);continue}t.set(o.id,mr(s,o))}return[...t.values()].sort((n,o)=>n.id.localeCompare(o.id))}var W=class{constructor(e,t={}){this.storage=e;this.legacy=new H(e),this.hostId=ur(t.hostId)}storage;legacy;hostId;diagnostics={operationCount:0,conflicts:0,invalidKeys:0};getDiagnostics(){return{...this.diagnostics}}async operations(e){let t=await Fe(this.storage,e,"memory");return this.diagnostics={operationCount:t.operations.length,conflicts:t.conflicts.length,invalidKeys:t.invalidKeys.length},t.operations}async load(e){let t=await this.legacy.load(e),n=await this.operations(e);return Q(t,n)}async appendMemory(e,t){let n=Le({projectId:e,scope:"memory",hostId:this.hostId,operationId:lr(this.hostId,t),occurredAt:t.updatedAt,payload:{kind:"upsert",memory:t}});await Ve(this.storage,n)}async refreshProjection(e){let t=await this.legacy.load(e),n=await this.operations(e),o=Q(t,n);return await this.legacy.save(e,o),o}async save(e,t){let n=[...t].sort((a,c)=>a.id.localeCompare(c.id));for(let a of n)await this.appendMemory(e,a);let o=await this.operations(e),s=Q(t,o);await this.legacy.save(e,s)}};async function Be(r,e){let t=new Date().toISOString(),o=await new W(e).refreshProjection(r.id),s=await Ne(r,e);return{startedAt:t,finishedAt:new Date().toISOString(),memories:o.length,workAvailable:s!==null}}function fr(r,e){let t=r.indexOf(e);if(!(t<0))return r[t+1]}function gr(r){return{projectPath:fr(r,"--project"),json:r.includes("--json"),quiet:r.includes("--quiet")}}async function yr(r){let e=ce(),t=Re(Me({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new V(t,r.id,r.name,r.remote??r.name)}async function hr(){let r=gr(process.argv.slice(2)),e=r.projectPath??process.cwd(),t=new D().detect(e);if(!t){r.quiet||console.error(`ToolNet project not found: ${e}`),process.exitCode=2;return}let n;try{n=await yr(t)}catch(o){r.quiet||console.error(o instanceof Error?o.message:String(o)),process.exitCode=3;return}try{let o=await Be(t,n);if(r.quiet)return;if(r.json){console.log(JSON.stringify(o));return}console.log(["ToolNet Memory refreshed",`memory=${o.memories}`,`work=${o.workAvailable?"yes":"no"}`].join(" "))}catch(o){r.quiet||console.error(o instanceof Error?o.message:String(o)),process.exitCode=4}}hr().then(()=>{process.exit(process.exitCode??0)});