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.
Files changed (48) hide show
  1. package/.env.example +0 -1
  2. package/.release-target +1 -1
  3. package/README.md +25 -1
  4. package/bin/toolnet-memory +5 -0
  5. package/bundle/agy-hook.js +67 -67
  6. package/bundle/agy.js +61 -61
  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 +25 -24
  12. package/bundle/codex.js +71 -71
  13. package/bundle/context-runtime.js +45 -44
  14. package/bundle/context.js +15 -15
  15. package/bundle/continuity-certify.js +13 -13
  16. package/bundle/copilot-hook.js +87 -85
  17. package/bundle/copilot.js +4 -4
  18. package/bundle/cursor-hook.js +87 -85
  19. package/bundle/cursor.js +4 -4
  20. package/bundle/doctor.js +4 -4
  21. package/bundle/full-index.js +20 -20
  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 +60 -59
  26. package/bundle/grok.js +5 -5
  27. package/bundle/handoff-refresh.js +10 -10
  28. package/bundle/help-cli.js +4 -4
  29. package/bundle/impact.js +4 -4
  30. package/bundle/incremental.js +5 -4
  31. package/bundle/init.js +37 -37
  32. package/bundle/integration-status.js +4 -4
  33. package/bundle/kiro-hook.js +82 -81
  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 +80 -80
  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 +9 -3
  48. package/release-manifest.json +54 -3
@@ -1,8 +1,8 @@
1
- import*as m from"fs";import*as d from"path";function A(n){let e=d.resolve(n),t=d.parse(e).root;for(;e!==t;){let r=d.join(e,".toolnet");if(m.existsSync(r)&&m.statSync(r).isDirectory())return e;e=d.dirname(e)}return null}import{existsSync as ce,readFileSync as ae}from"node:fs";import{join as ue}from"node:path";var tt=new Int32Array(new SharedArrayBuffer(4));import{closeSync as it,existsSync as K,fsyncSync as ct,mkdirSync as at,openSync as ut,readFileSync as W,renameSync as lt,writeFileSync as dt}from"node:fs";import{dirname as mt,join as z}from"node:path";function q(n){return z(n.rootPath,".toolnet","work","current.json")}function M(n){let e=q(n);if(!K(e))return null;try{let t=JSON.parse(W(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}import{existsSync as H,mkdirSync as yt,readFileSync as V,renameSync as ht,writeFileSync as kt}from"node:fs";import{dirname as St,join as B}from"node:path";function G(n){return B(n.rootPath,".toolnet","context","session-origin.json")}function x(n){let e=G(n);if(!H(e))return null;try{let t=JSON.parse(V(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}function Y(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function E(n){let e=Y(n),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),r=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&r?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as ne,mkdirSync as gn,readFileSync as re}from"node:fs";import{join as T}from"node:path";var J=[{type:"openai_key",regex:/\bsk-[A-Za-z0-9_\-]{20,}\b/g},{type:"huggingface_token",regex:/\bhf_[A-Za-z0-9]{20,}\b/g},{type:"hf_s3_access_key",regex:/\bHFAK[A-Za-z0-9]{8,}\b/g},{type:"bearer_token",regex:/\bBearer\s+[A-Za-z0-9._\-]{16,}\b/gi},{type:"jwt",regex:/\beyJ[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\.[A-Za-z0-9_\-]{8,}\b/g},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{type:"password_assignment",regex:/\b(password|passwd|pwd)\s*[:=]\s*["']?[^"'\s]{6,}["']?/gi},{type:"secret_assignment",regex:/\b(secret|api[_-]?key|access[_-]?token|refresh[_-]?token)\s*[:=]\s*["']?[^"'\s]{8,}["']?/gi},{type:"cookie",regex:/\b(cookie|set-cookie)\s*[:=]\s*[^;\n]{8,}/gi}],h=class{scan(e){let t=[];for(let r of J){let o=new RegExp(r.regex.source,r.regex.flags);for(let i of e.matchAll(o))t.push({type:r.type,value:i[0]})}return t}hasSecrets(e){return this.scan(e).length>0}};var p=class{scanner=new h;sanitize(e){let t=e,r=this.scanner.scan(e),o=new Set;for(let i of r)o.add(i.type),t=t.split(i.value).join(`[REDACTED:${i.type}]`);return{text:t,redacted:r.length,secretTypes:[...o]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(t=>this.sanitizeValue(t));if(e&&typeof e=="object"){let t={};for(let[r,o]of Object.entries(e)){let i=r.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");i.includes("password")||i.includes("passwd")||i==="pwd"||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")||i.includes("apikey")||i.includes("accesskey")||i.includes("privatekey")||i.includes("clientsecret")||i.includes("credential")?t[r]="[REDACTED]":t[r]=this.sanitizeValue(o)}return t}return e}};import{existsSync as U,readFileSync as Q}from"node:fs";import{homedir as X}from"node:os";import{join as Z}from"node:path";function ee(n){let e=n.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 te(){let n=process.env.TOOLNET_GLOBAL_ENV??Z(X(),".config","toolnet-memory",".env");if(!U(n))return;let e=Q(n,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let i=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=ee(r.slice(o+1)))}}te();var en=new p;function oe(n){return T(n.rootPath,".toolnet","memory","checkpoints")}function se(n){return T(oe(n),"latest.json")}function ie(n){let e=se(n);if(!ne(e))return null;try{let t=JSON.parse(re(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==n.id?null:t}catch{return null}}function I(n){return ie(n)}var le={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},de={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function fe(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function s(n,e){let t=e.value.replace(/\s+/g," ").trim();t&&n.push({...e,value:t,score:0})}function me(n){let e=ue(n.rootPath,".toolnet","work","handoff-latest.json");if(!ce(e))return null;try{let r=JSON.parse(ae(e,"utf8")).continuity;return r?.schema!=="toolnet.handoff.v2"||r.project.id!==n.id?null:r}catch{return null}}function pe(n){let e=I(n);if(!e)return[];let t=[];e.request&&s(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&s(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&s(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&s(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let r=e.files.active.at(-1);r&&s(t,{kind:"file",value:r,source:"checkpoint"});for(let o of e.nextActions)s(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)s(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)s(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)s(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)s(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function ge(n){let e=me(n);if(!e)return[];let t=[];s(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&s(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&s(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&s(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&s(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&s(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&s(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&s(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let r of e.blockers)s(t,{kind:"blocker",value:r,source:"handoff"});for(let r of e.decisions)s(t,{kind:"decision",value:r,source:"handoff"});for(let r of e.completed.tasks)s(t,{kind:"completed",value:r,source:"handoff"});for(let r of e.remaining.todos)s(t,{kind:"todo",value:r,source:"handoff"});return s(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),s(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function ye(n){let e=x(n);if(!e)return[];let t=[];return s(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&s(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&s(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&s(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&s(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&s(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&s(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function he(n){let e=M(n);if(!e)return[];let t=[];e.currentRequest&&s(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&s(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&s(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&s(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&s(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let r=e.activeFiles?.at(-1)??e.filesTouched.at(-1);r&&s(t,{kind:"file",value:r,source:"work-state"});for(let o of e.nextActions.slice(0,5))s(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))s(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))s(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(i=>i.status==="completed").slice(-8))s(t,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(i=>i.status!=="completed"&&i.status!=="cancelled").slice(0,8))s(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))s(t,{kind:"test",value:o,source:"work-state"});return s(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function ke(n,e){let t=le[n];return e.map((r,o)=>({...r,score:(t[r.kind]??10)+de[r.source]+Math.max(0,5-o*.01)}))}function be(n){let e=new Map;for(let t of n){let r=`${t.kind}:${fe(t.value)}`,o=e.get(r);(!o||t.score>o.score)&&e.set(r,t)}return[...e.values()]}function R(n,e,t={}){let r=E(e),o=[...pe(n),...ge(n),...ye(n),...he(n)],i=be(ke(r,o)).sort((c,u)=>u.score-c.score),a=Math.max(1,t.maxFacts??12),y=Math.max(300,t.maxChars??3200),l=[],f=0;for(let c of i){if(l.length>=a)break;let u=c.kind.length+c.value.length+c.source.length+16;l.length>0&&f+u>y||(l.push(c),f+=u)}return{intent:r,facts:l,context:{project:{id:n.id,name:n.name},intent:r,selectedFacts:l.map(c=>({kind:c.kind,value:c.value,source:c.source}))},stats:{candidates:o.length,selected:l.length,chars:f}}}var F={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},P=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Se={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:P};function Me(n){let e=n.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function xe(n){let e=n.filter(r=>r.source==="handoff");if(e.length===0)return n;let t=n.filter(r=>r.source==="checkpoint"&&["rule","architecture","fix"].includes(r.kind));return[...e,...t]}function ve(n){let e=new Set,t=[];for(let r of n){let o=`${r.kind}:${r.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),t.push(r))}return t}function _(n){switch(n){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function we(n,e){let t=[];for(let r of e){let o=n.filter(i=>i.kind===r).slice(0,_(r));for(let i of o)t.push(`${F[r]}: ${i.value}`)}return t.join(`
3
- `)}function Ce(n,e){let t=Se[e]??P,r=[];for(let o of t){let i=n.filter(a=>a.kind===o).slice(0,_(o));for(let a of i)r.push(`${F[o]}: ${a.value}`)}return r.join(`
4
- `)}function O(n,e){let t=R(n,e,{maxFacts:32,maxChars:6400}),r=ve(xe(t.facts)),o=Me(e)?we(r,["todo","task","next_action","file"]):Ce(r,String(t.intent));return o?{intent:String(t.intent),answer:o,source:r[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}async function N(n,e){let t=O(n,e);return t.answer?{answer:t.answer,usedAi:!1}:{answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",usedAi:!1}}import{createHash as Ae}from"node:crypto";import{existsSync as v,mkdirSync as Ee,readFileSync as Te,renameSync as Ie,writeFileSync as Re}from"node:fs";import{basename as Fe,dirname as k,join as S,parse as D,resolve as g}from"node:path";var $=".toolnet",Pe="project.json";function _e(n){return Ae("sha256").update(n).digest("hex").slice(0,16)}function w(n){return S(n,$,Pe)}function Oe(n){return v(w(n))}function Ne(n,e){let t=g(n),r=D(t).root;for(;;){if(Oe(t))return t;if(t===r||e&&t===g(e))break;let o=k(t);if(o===t)break;t=o}return null}function je(n){let e=g(n),t=D(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>v(S(e,i))))return e;if(e===t)break;let o=k(e);if(o===e)break;e=o}return g(n)}function Le(n){let e;try{e=JSON.parse(Te(n,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${n}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${n}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${n}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${n}`);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:k(k(n)),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 j(n,e){let t=S(n,$);Ee(t,{recursive:!0});let r=w(n),o=`${r}.tmp-${process.pid}`;Re(o,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),Ie(o,r)}function L(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}var b=class{detect(e=process.cwd()){let t=g(e),r=je(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(c=>v(S(r,c))),a=Ne(t,i?r:void 0);if(a){let c=w(a),u=Le(c);return u.rootPath!==a&&(u.rootPath=a,u.updatedAt=new Date().toISOString(),j(a,u)),L(u,a)}let y=new Date().toISOString(),l=Fe(r),f={version:1,id:_e(r),name:l,remote:l,rootPath:r,createdAt:y,updatedAt:y,graphVersion:0,memoryVersion:0};return j(r,f),L(f,r)}};async function De(){let n=process.argv.slice(2).join(" ").trim();if(!n){console.error('Usage: toolnet-memory ask "<question>"'),process.exitCode=1;return}let e=A(process.cwd());if(!e){console.error("Not in a ToolNet project."),process.exitCode=1;return}let t=new b().detect(e);if(!t){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let r=await N(t,n);process.stdout.write(`${r.answer}
6
- `),process.env.TOOLNET_MEMORY_AGENT_DEBUG==="1"&&process.stderr.write(["",`[ToolNet Memory Agent] AI: ${r.usedAi?"yes":"fallback"}`].filter(Boolean).join(`
1
+ import{existsSync as ge,readFileSync as ye}from"node:fs";import{join as ke}from"node:path";var Ve=new Int32Array(new SharedArrayBuffer(4));import{closeSync as tt,existsSync as J,fsyncSync as nt,mkdirSync as rt,openSync as ot,readFileSync as U,renameSync as st,writeFileSync as it}from"node:fs";import{dirname as at,join as Q}from"node:path";var z=[{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"}],W=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function w(n){return n.normalize("NFKC").trim().toLowerCase()}function q(n){if(n.length===0)return 0;let e=new Map;for(let r of n)e.set(r,(e.get(r)??0)+1);let t=0;for(let r of e.values()){let o=r/n.length;t-=o*Math.log2(o)}return t}function V(n){return/^[a-f0-9]{32}$/iu.test(n)||/^[a-f0-9]{40}$/iu.test(n)||/^[a-f0-9]{64}$/iu.test(n)}function B(n,e,t){let r=n.slice(Math.max(0,e-48),e),o=n.slice(t,Math.min(n.length,t+16));return/\b(?:token|secret|key|credential|authorization|password|passwd|apikey|api_key|access[_-]?key)\b/iu.test(`${r} ${o}`)}function H(n,e){return n.start<e.end&&e.start<n.end}function C(n){return n.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var y=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let r=w(t);r&&this.allowValues.add(r)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let s of z){let c=new RegExp(s.regex.source,s.regex.flags);for(let a of e.matchAll(c))a.index===void 0||!a[0]||this.allowed(a[0])||t.push({type:s.type,value:a[0],start:a.index,end:a.index+a[0].length,confidence:s.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let r=C(t),o=[];for(let s of r)o.some(c=>H(c,s))||o.push(s);return C(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=w(e);return W.has(t)?!0:this.allowValues.has(t)}entropyMatches(e){let t=[],r=/[A-Za-z0-9_+/=-]{32,160}/g;for(let o of e.matchAll(r)){if(o.index===void 0||!o[0])continue;let s=o[0];this.allowed(s)||V(s)||!/[A-Za-z]/u.test(s)||!/[0-9]/u.test(s)||B(e,o.index,o.index+s.length)&&(q(s)<3.7||t.push({type:"high_entropy_secret",value:s,start:o.index,end:o.index+s.length,confidence:"heuristic"}))}return t}};var f=class{scanner;constructor(e={}){this.scanner=new y(e)}sanitize(e){let t=this.scanner.scan(e);if(t.length===0)return{text:e,redacted:0,secretTypes:[]};let r=e,o=[...t].sort((c,a)=>a.start-c.start),s=new Set;for(let c of o)s.add(c.type),r=r.slice(0,c.start)+`[REDACTED:${c.type}]`+r.slice(c.end);return{text:r,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[r,o]of Object.entries(e)){let s=r.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[r]="[REDACTED]";continue}t[r]=this.sanitizeValue(o)}return t}return e}};var Qe=new f;function Z(n){return Q(n.rootPath,".toolnet","work","current.json")}function S(n){let e=Z(n);if(!J(e))return null;try{let t=JSON.parse(U(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}import{existsSync as G,mkdirSync as mt,readFileSync as X,renameSync as ft,writeFileSync as pt}from"node:fs";import{dirname as yt,join as ee}from"node:path";function te(n){return ee(n.rootPath,".toolnet","context","session-origin.json")}function x(n){let e=te(n);if(!G(e))return null;try{let t=JSON.parse(X(e,"utf8"));return t.version!==1||t.projectId!==n.id?null:t}catch{return null}}function ne(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function A(n){let e=ne(n),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),r=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&r?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}import{existsSync as le,mkdirSync as ln,readFileSync as de}from"node:fs";import{join as T}from"node:path";import{existsSync as oe,readFileSync as se}from"node:fs";import{homedir as ie}from"node:os";import{join as ce}from"node:path";function ae(n){let e=n.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 ue(){let n=process.env.TOOLNET_GLOBAL_ENV??ce(ie(),".config","toolnet-memory",".env");if(!oe(n))return;let e=se(n,"utf8");for(let t of e.split(/\r?\n/)){let r=t.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let o=r.indexOf("=");if(o<=0)continue;let s=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(s)&&process.env[s]===void 0&&(process.env[s]=ae(r.slice(o+1)))}}ue();var Ut=new f;function me(n){return T(n.rootPath,".toolnet","memory","checkpoints")}function fe(n){return T(me(n),"latest.json")}function pe(n){let e=fe(n);if(!le(e))return null;try{let t=JSON.parse(de(e,"utf8"));return t.schema!=="toolnet.memory.checkpoint.v1"||t.project.id!==n.id?null:t}catch{return null}}function I(n){return pe(n)}var he={previous_agent:{previous_agent:100,task:35,phase:25},current_task:{task:100,request:95,activity:90,phase:75,file:65,next_action:55,blocker:45},next_action:{next_action:100,todo:80,task:65,blocker:60,file:40},last_file:{file:100,task:65,next_action:40},blocker:{blocker:100,task:60,next_action:50,file:35},decision:{decision:100,rule:85,architecture:80,task:45,file:30},completed:{completed:100,progress:70,task:30},status:{progress:100,task:85,phase:75,blocker:65,next_action:60},summary:{task:100,request:98,activity:96,next_action:95,file:90,blocker:85,previous_agent:80,phase:75,completed:60,todo:60,decision:55,rule:54,architecture:53,fix:52,progress:50,test:45,goal:35}},be={checkpoint:20,handoff:18,"session-origin":14,"work-state":8};function Me(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function i(n,e){let t=e.value.replace(/\s+/g," ").trim();t&&n.push({...e,value:t,score:0})}function Se(n){let e=ke(n.rootPath,".toolnet","work","handoff-latest.json");if(!ge(e))return null;try{let r=JSON.parse(ye(e,"utf8")).continuity;return r?.schema!=="toolnet.handoff.v2"||r.project.id!==n.id?null:r}catch{return null}}function xe(n){let e=I(n);if(!e)return[];let t=[];e.request&&i(t,{kind:"request",value:e.request,source:"checkpoint"}),e.activity&&i(t,{kind:"activity",value:e.activity,source:"checkpoint"}),e.current.phase&&i(t,{kind:"phase",value:e.current.phase.title,source:"checkpoint"}),e.current.task&&i(t,{kind:"task",value:e.current.task.title,source:"checkpoint"});let r=e.files.active.at(-1);r&&i(t,{kind:"file",value:r,source:"checkpoint"});for(let o of e.nextActions)i(t,{kind:"next_action",value:o,source:"checkpoint"});for(let o of e.blockers)i(t,{kind:"blocker",value:o,source:"checkpoint"});for(let o of e.completed.tasks)i(t,{kind:"completed",value:o,source:"checkpoint"});for(let o of e.remaining.tasks)i(t,{kind:"todo",value:o,source:"checkpoint"});for(let o of e.durableFacts)i(t,{kind:o.kind,value:o.content,source:"checkpoint"});return t}function ve(n){let e=Se(n);if(!e)return[];let t=[];i(t,{kind:"previous_agent",value:e.source.agent,source:"handoff"}),e.request&&i(t,{kind:"request",value:e.request,source:"handoff"}),e.activity&&i(t,{kind:"activity",value:e.activity,source:"handoff"}),e.goal&&i(t,{kind:"goal",value:e.goal,source:"handoff"}),e.current.phase&&i(t,{kind:"phase",value:e.current.phase.title,source:"handoff"}),e.current.task&&i(t,{kind:"task",value:e.current.task.title,source:"handoff"}),e.files.current&&i(t,{kind:"file",value:e.files.current,source:"handoff"}),e.nextAction&&i(t,{kind:"next_action",value:e.nextAction,source:"handoff"});for(let r of e.blockers)i(t,{kind:"blocker",value:r,source:"handoff"});for(let r of e.decisions)i(t,{kind:"decision",value:r,source:"handoff"});for(let r of e.completed.tasks)i(t,{kind:"completed",value:r,source:"handoff"});for(let r of e.remaining.todos)i(t,{kind:"todo",value:r,source:"handoff"});return i(t,{kind:"test",value:`Test status: ${e.tests.status}`,source:"handoff"}),i(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"handoff"}),t}function we(n){let e=x(n);if(!e)return[];let t=[];return i(t,{kind:"previous_agent",value:e.agent,source:"session-origin"}),e.currentPhase&&i(t,{kind:"phase",value:e.currentPhase,source:"session-origin"}),e.currentTask&&i(t,{kind:"task",value:e.currentTask,source:"session-origin"}),e.lastTouchedFile&&i(t,{kind:"file",value:e.lastTouchedFile,source:"session-origin"}),e.latestNextAction&&i(t,{kind:"next_action",value:e.latestNextAction,source:"session-origin"}),e.latestBlocker&&i(t,{kind:"blocker",value:e.latestBlocker,source:"session-origin"}),e.latestDecision&&i(t,{kind:"decision",value:e.latestDecision,source:"session-origin"}),t}function Ce(n){let e=S(n);if(!e)return[];let t=[];e.currentRequest&&i(t,{kind:"request",value:e.currentRequest,source:"work-state"}),e.currentActivity&&i(t,{kind:"activity",value:e.currentActivity,source:"work-state"}),e.goal&&i(t,{kind:"goal",value:e.goal,source:"work-state"}),e.currentPhase&&i(t,{kind:"phase",value:e.currentPhase.title,source:"work-state"}),e.currentTask&&i(t,{kind:"task",value:e.currentTask.title,source:"work-state"});let r=e.activeFiles?.at(-1)??e.filesTouched.at(-1);r&&i(t,{kind:"file",value:r,source:"work-state"});for(let o of e.nextActions.slice(0,5))i(t,{kind:"next_action",value:o,source:"work-state"});for(let o of e.blockers.slice(-5))i(t,{kind:"blocker",value:o,source:"work-state"});for(let o of e.decisions.slice(-5))i(t,{kind:"decision",value:o,source:"work-state"});for(let o of e.tasks.filter(s=>s.status==="completed").slice(-8))i(t,{kind:"completed",value:o.title,source:"work-state"});for(let o of e.tasks.filter(s=>s.status!=="completed"&&s.status!=="cancelled").slice(0,8))i(t,{kind:"todo",value:o.title,source:"work-state"});for(let o of e.tests.slice(-5))i(t,{kind:"test",value:o,source:"work-state"});return i(t,{kind:"progress",value:`${e.progress.tasksCompleted}/${e.progress.tasksTotal} tasks completed; ${e.progress.blocked} blocked`,source:"work-state"}),t}function Ae(n,e){let t=he[n];return e.map((r,o)=>({...r,score:(t[r.kind]??10)+be[r.source]+Math.max(0,5-o*.01)}))}function Te(n){let e=new Map;for(let t of n){let r=`${t.kind}:${Me(t.value)}`,o=e.get(r);(!o||t.score>o.score)&&e.set(r,t)}return[...e.values()]}function E(n,e,t={}){let r=A(e),o=[...xe(n),...ve(n),...we(n),...Ce(n)],s=Te(Ae(r,o)).sort((u,d)=>d.score-u.score),c=Math.max(1,t.maxFacts??12),a=Math.max(300,t.maxChars??3200),l=[],m=0;for(let u of s){if(l.length>=c)break;let d=u.kind.length+u.value.length+u.source.length+16;l.length>0&&m+d>a||(l.push(u),m+=d)}return{intent:r,facts:l,context:{project:{id:n.id,name:n.name},intent:r,selectedFacts:l.map(u=>({kind:u.kind,value:u.value,source:u.source}))},stats:{candidates:o.length,selected:l.length,chars:m}}}var R={previous_agent:"Agent tr\u01B0\u1EDBc",request:"Y\xEAu c\u1EA7u hi\u1EC7n t\u1EA1i",activity:"\u0110ang l\xE0m",goal:"M\u1EE5c ti\xEAu",phase:"Phase",task:"Task hi\u1EC7n t\u1EA1i",file:"File hi\u1EC7n t\u1EA1i",todo:"TODO",next_action:"Ti\u1EBFp theo",blocker:"Blocker",decision:"Quy\u1EBFt \u0111\u1ECBnh",rule:"Quy t\u1EAFc",architecture:"Ki\u1EBFn tr\xFAc",fix:"\u0110\xE3 s\u1EEDa",completed:"\u0110\xE3 ho\xE0n th\xE0nh",test:"Test",progress:"Ti\u1EBFn \u0111\u1ED9"},_=["previous_agent","request","activity","phase","task","file","todo","next_action","blocker","decision","rule","architecture","fix","completed","test","progress","goal"],Ie={previous_agent:["previous_agent"],current_task:["request","activity","task","file","next_action"],next_action:["next_action","task","file","todo"],last_file:["file","task","next_action"],blocker:["blocker"],decision:["decision"],completed:["completed"],status:["progress","task","next_action","blocker"],summary:_};function Ee(n){let e=n.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim();return/(?:^|\s)(?:todo|to-do)(?:\s|$)/u.test(e)||/(?:việc|task)\s+(?:còn lại|chưa làm|chưa xong|chưa hoàn thành)/u.test(e)}function Re(n){let e=n.filter(r=>r.source==="handoff");if(e.length===0)return n;let t=n.filter(r=>r.source==="checkpoint"&&["rule","architecture","fix"].includes(r.kind));return[...e,...t]}function _e(n){let e=new Set,t=[];for(let r of n){let o=`${r.kind}:${r.value.normalize("NFKC").toLowerCase().replace(/\s+/gu," ").trim()}`;e.has(o)||(e.add(o),t.push(r))}return t}function P(n){switch(n){case"todo":case"blocker":case"decision":case"completed":return 3;default:return 1}}function Pe(n,e){let t=[];for(let r of e){let o=n.filter(s=>s.kind===r).slice(0,P(r));for(let s of o)t.push(`${R[r]}: ${s.value}`)}return t.join(`
3
+ `)}function Fe(n,e){let t=Ie[e]??_,r=[];for(let o of t){let s=n.filter(c=>c.kind===o).slice(0,P(o));for(let c of s)r.push(`${R[o]}: ${c.value}`)}return r.join(`
4
+ `)}function F(n,e){let t=E(n,e,{maxFacts:32,maxChars:6400}),r=_e(Re(t.facts)),o=Ee(e)?Pe(r,["todo","task","next_action","file"]):Fe(r,String(t.intent));return o?{intent:String(t.intent),answer:o,source:r[0]?.source??"none"}:{intent:String(t.intent),answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}async function O(n,e){let t=F(n,e);return t.answer?{answer:t.answer,usedAi:!1}:{answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",usedAi:!1}}import{createHash as Oe}from"node:crypto";import{existsSync as k,mkdirSync as Ne,readFileSync as je,renameSync as Le,writeFileSync as De}from"node:fs";import{basename as $e,dirname as h,join as g,parse as $,resolve as p}from"node:path";var K=".toolnet",Ke="project.json";function ze(n){return Oe("sha256").update(n).digest("hex").slice(0,16)}function b(n){return g(n,K,Ke)}function We(n){return k(b(n))}function N(n,e){let t=p(n),r=$(t).root;for(;;){if(We(t))return t;if(t===r||e&&t===p(e))break;let o=h(t);if(o===t)break;t=o}return null}function j(n){let e=p(n),t=$(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(s=>k(g(e,s))))return e;if(e===t)break;let o=h(e);if(o===e)break;e=o}return p(n)}function L(n){let e;try{e=JSON.parse(je(n,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${n}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${n}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${n}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${n}`);let r=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:h(h(n)),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 D(n,e){let t=g(n,K);Ne(t,{recursive:!0});let r=b(n),o=`${r}.tmp-${process.pid}`;De(o,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Le(o,r)}function v(n,e){return{id:n.id,name:n.name,remote:n.remote,rootPath:e,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}var M=class{findExisting(e=process.cwd()){let t=p(e),r=j(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>k(g(r,l))),c=N(t,s?r:void 0);if(!c)return null;let a=L(b(c));return v(a,c)}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=p(e),r=j(t),s=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(u=>k(g(r,u))),c=N(t,s?r:void 0);if(c){let u=b(c),d=L(u);return d.rootPath!==c&&(d.rootPath=c,d.updatedAt=new Date().toISOString(),D(c,d)),v(d,c)}let a=new Date().toISOString(),l=$e(r),m={version:1,id:ze(r),name:l,remote:l,rootPath:r,createdAt:a,updatedAt:a,graphVersion:0,memoryVersion:0};return D(r,m),v(m,r)}};async function qe(){let n=process.argv.slice(2).join(" ").trim();if(!n){console.error('Usage: toolnet-memory ask "<question>"'),process.exitCode=1;return}let e;try{e=new M().requireExisting(process.cwd())}catch(r){if(r instanceof Error&&r.message==="PROJECT_NOT_INITIALIZED"){console.error("PROJECT_NOT_INITIALIZED"),process.exitCode=1;return}throw r}let t=await O(e,n);process.stdout.write(`${t.answer}
6
+ `),process.env.TOOLNET_MEMORY_AGENT_DEBUG==="1"&&process.stderr.write(["",`[ToolNet Memory Agent] local=${t.usedAi?"no":"yes"}`].filter(Boolean).join(`
7
7
  `)+`
8
- `)}De().catch(n=>{console.error(n instanceof Error?n.message:String(n)),process.exitCode=1});
8
+ `)}qe().catch(n=>{console.error(n instanceof Error?n.message:String(n)),process.exitCode=1});
@@ -1,7 +1,7 @@
1
- import*as d from"fs";import*as u from"path";function x(n){let t=u.resolve(n),e=u.parse(t).root;for(;t!==e;){let r=u.join(t,".toolnet");if(d.existsSync(r)&&d.statSync(r).isDirectory())return t;t=u.dirname(t)}return null}import{existsSync as F,readFileSync as $}from"node:fs";import{join as D}from"node:path";var Me=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Ie,existsSync as E,fsyncSync as Oe,mkdirSync as je,openSync as _e,readFileSync as R,renameSync as Ne,writeFileSync as Pe}from"node:fs";import{dirname as $e,join as I}from"node:path";function O(n){return I(n.rootPath,".toolnet","work","current.json")}function w(n){let t=O(n);if(!E(t))return null;try{let e=JSON.parse(R(t,"utf8"));return e.version!==1||e.projectId!==n.id?null:e}catch{return null}}import{existsSync as j,mkdirSync as We,readFileSync as _,renameSync as Ve,writeFileSync as ze}from"node:fs";import{dirname as Ke,join as N}from"node:path";function P(n){return N(n.rootPath,".toolnet","context","session-origin.json")}function b(n){let t=P(n);if(!j(t))return null;try{let e=JSON.parse(_(t,"utf8"));return e.version!==1||e.projectId!==n.id?null:e}catch{return null}}function L(n){return n.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function W(n){let t=L(n),e=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(t),r=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(t);return e&&r?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(t)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(t)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(t)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(t)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(t)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(t)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(t)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(t)?"status":"summary"}function V(n){let t=D(n.rootPath,".toolnet","context","handoff.md");if(!F(t))return null;try{let e=$(t,"utf8").trim();return e||null}catch{return null}}function z(n,t=5){return n.slice(0,t).map(e=>`- ${e}`).join(`
2
- `)}function v(n,t){let e=W(t),r=b(n),o=w(n);switch(e){case"previous_agent":{if(r)return{intent:e,answer:`Agent tr\u01B0\u1EDBc l\xE0 ${r.agent}. Session: ${r.nativeSessionId}.`,source:"session-origin"};break}case"current_task":{if(r?.currentTask){let s=[`Task hi\u1EC7n t\u1EA1i: ${r.currentTask}.`];return r.lastTouchedFile&&s.push(`File g\u1EA7n nh\u1EA5t: ${r.lastTouchedFile}.`),r.latestNextAction&&s.push(`Ti\u1EBFp theo: ${r.latestNextAction}.`),{intent:e,answer:s.join(" "),source:"session-origin"}}if(o?.currentTask)return{intent:e,answer:`Task hi\u1EC7n t\u1EA1i: ${o.currentTask.title} (${o.currentTask.status}).`,source:"work-state"};break}case"next_action":{let s=r?.latestNextAction??o?.nextActions?.[0];if(s)return{intent:e,answer:`Vi\u1EC7c n\xEAn l\xE0m ti\u1EBFp: ${s}.`,source:r?.latestNextAction?"session-origin":"work-state"};break}case"last_file":{let s=r?.lastTouchedFile??o?.filesTouched?.at(-1);if(s)return{intent:e,answer:`File g\u1EA7n nh\u1EA5t \u0111\u01B0\u1EE3c nh\u1EAFc ho\u1EB7c s\u1EEDa: ${s}.`,source:r?.lastTouchedFile?"session-origin":"work-state"};break}case"blocker":{let s=r?.latestBlocker??o?.blockers?.at(-1);return s?{intent:e,answer:`Blocker hi\u1EC7n t\u1EA1i: ${s}.`,source:r?.latestBlocker?"session-origin":"work-state"}:{intent:e,answer:"Hi\u1EC7n ToolNet ch\u01B0a ghi nh\u1EADn blocker n\xE0o.",source:o?"work-state":"none"}}case"decision":{let s=r?.latestDecision??o?.decisions?.at(-1);if(s)return{intent:e,answer:`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${s}.`,source:r?.latestDecision?"session-origin":"work-state"};break}case"completed":{let s=o?.tasks?.filter(c=>c.status==="completed").map(c=>c.title)??[];if(s.length)return{intent:e,answer:`C\xE1c task \u0111\xE3 ho\xE0n th\xE0nh:
3
- ${z(s,8)}`,source:"work-state"};break}case"status":{if(o){let s=[`Progress: ${o.progress.tasksCompleted}/${o.progress.tasksTotal} task ho\xE0n th\xE0nh.`];return o.currentTask&&s.push(`\u0110ang l\xE0m: ${o.currentTask.title}.`),o.progress.blocked>0&&s.push(`Blocked: ${o.progress.blocked}.`),{intent:e,answer:s.join(" "),source:"work-state"}}break}case"summary":{if(r||o){let s=[];r&&s.push(`Agent tr\u01B0\u1EDBc: ${r.agent}.`);let c=r?.currentTask??o?.currentTask?.title;c&&s.push(`Task hi\u1EC7n t\u1EA1i: ${c}.`);let f=r?.lastTouchedFile??o?.filesTouched?.at(-1);f&&s.push(`File g\u1EA7n nh\u1EA5t: ${f}.`);let p=r?.latestNextAction??o?.nextActions?.[0];p&&s.push(`Ti\u1EBFp theo: ${p}.`);let l=r?.latestBlocker??o?.blockers?.at(-1);l&&s.push(`Blocker: ${l}.`);let a=r?.latestDecision??o?.decisions?.at(-1);return a&&s.push(`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${a}.`),{intent:e,answer:s.join(" "),source:r?"session-origin":"work-state"}}break}}let i=V(n);if(i){let s=i.length>900?`${i.slice(0,900)}
4
- [truncated]`:i;return{intent:e,answer:s,source:"handoff"}}return{intent:e,answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}import{existsSync as B,readFileSync as K}from"node:fs";import{homedir as H}from"node:os";import{join as G}from"node:path";function J(n){let t=n.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?(t=t.slice(1,-1),t.replace(/\\n/g,`
5
- `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):t.length>=2&&t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function Y(){let n=process.env.TOOLNET_GLOBAL_ENV??G(H(),".config","toolnet-memory",".env");if(!B(n))return;let t=K(n,"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 o=r.indexOf("=");if(o<=0)continue;let i=r.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=J(r.slice(o+1)))}}Y();import{createHash as q}from"node:crypto";import{existsSync as k,mkdirSync as U,readFileSync as Q,renameSync as Z,writeFileSync as X}from"node:fs";import{basename as ee,dirname as g,join as h,parse as C,resolve as m}from"node:path";var T=".toolnet",te="project.json";function ne(n){return q("sha256").update(n).digest("hex").slice(0,16)}function S(n){return h(n,T,te)}function re(n){return k(S(n))}function oe(n,t){let e=m(n),r=C(e).root;for(;;){if(re(e))return e;if(e===r||t&&e===m(t))break;let o=g(e);if(o===e)break;e=o}return null}function se(n){let t=m(n),e=C(t).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(i=>k(h(t,i))))return t;if(t===e)break;let o=g(t);if(o===t)break;t=o}return m(n)}function ie(n){let t;try{t=JSON.parse(Q(n,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${n}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${n}`);let e=t;if(typeof e.id!="string"||!e.id.trim())throw new Error(`ToolNet project manifest is missing id: ${n}`);if(typeof e.name!="string"||!e.name.trim())throw new Error(`ToolNet project manifest is missing name: ${n}`);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:g(g(n)),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 A(n,t){let e=h(n,T);U(e,{recursive:!0});let r=S(n),o=`${r}.tmp-${process.pid}`;X(o,JSON.stringify(t,null,2)+`
6
- `,{encoding:"utf8",mode:384}),Z(o,r)}function M(n,t){return{id:n.id,name:n.name,remote:n.remote,rootPath:t,createdAt:n.createdAt,updatedAt:n.updatedAt,graphVersion:n.graphVersion,memoryVersion:n.memoryVersion,metadata:n.metadata}}var y=class{detect(t=process.cwd()){let e=m(t),r=se(e),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>k(h(r,l))),s=oe(e,i?r:void 0);if(s){let l=S(s),a=ie(l);return a.rootPath!==s&&(a.rootPath=s,a.updatedAt=new Date().toISOString(),A(s,a)),M(a,s)}let c=new Date().toISOString(),f=ee(r),p={version:1,id:ne(r),name:f,remote:f,rootPath:r,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return A(r,p),M(p,r)}};function ce(){let n=process.argv.slice(2).join(" ").trim();if(!n){console.error('Usage: toolnet-memory ask "<question>"'),process.exitCode=1;return}let t=process.cwd(),e=x(t);if(!e){console.error("Not in a ToolNet project."),process.exitCode=1;return}let r=new y().detect(e);if(!r){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let o=v(r,n);process.stdout.write(`${o.answer}
7
- `)}ce();
1
+ import*as f from"fs";import*as u from"path";function A(r){let e=u.resolve(r),t=u.parse(e).root;for(;e!==t;){let n=u.join(e,".toolnet");if(f.existsSync(n)&&f.statSync(n).isDirectory())return e;e=u.dirname(e)}return null}import{existsSync as Y,readFileSync as Z}from"node:fs";import{join as Q}from"node:path";var Le=new Int32Array(new SharedArrayBuffer(4));import{closeSync as Ye,existsSync as V,fsyncSync as Ze,mkdirSync as Qe,openSync as Xe,readFileSync as B,renameSync as et,writeFileSync as tt}from"node:fs";import{dirname as rt,join as H}from"node:path";var P=[{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"}],$=new Set(["example","example-key","example-token","changeme","change-me","password","secret","your-api-key","your-token","<token>","<secret>","<password>","[redacted]"]);function M(r){return r.normalize("NFKC").trim().toLowerCase()}function F(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 D(r){return/^[a-f0-9]{32}$/iu.test(r)||/^[a-f0-9]{40}$/iu.test(r)||/^[a-f0-9]{64}$/iu.test(r)}function L(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 W(r,e){return r.start<e.end&&e.start<r.end}function v(r){return r.sort((e,t)=>e.start!==t.start?e.start-t.start:t.end-t.start-(e.end-e.start))}var y=class{allowValues=new Set;enableEntropyHeuristic;constructor(e={}){for(let t of e.allowValues??[]){let n=M(t);n&&this.allowValues.add(n)}this.enableEntropyHeuristic=e.enableEntropyHeuristic??!0}scan(e){let t=[];for(let i of P){let s=new RegExp(i.regex.source,i.regex.flags);for(let c of e.matchAll(s))c.index===void 0||!c[0]||this.allowed(c[0])||t.push({type:i.type,value:c[0],start:c.index,end:c.index+c[0].length,confidence:i.confidence})}this.enableEntropyHeuristic&&t.push(...this.entropyMatches(e));let n=v(t),o=[];for(let i of n)o.some(s=>W(s,i))||o.push(i);return v(o)}hasSecrets(e){return this.scan(e).length>0}allowed(e){let t=M(e);return $.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 i=o[0];this.allowed(i)||D(i)||!/[A-Za-z]/u.test(i)||!/[0-9]/u.test(i)||L(e,o.index,o.index+i.length)&&(F(i)<3.7||t.push({type:"high_entropy_secret",value:i,start:o.index,end:o.index+i.length,confidence:"heuristic"}))}return t}};var h=class{scanner;constructor(e={}){this.scanner=new y(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((s,c)=>c.start-s.start),i=new Set;for(let s of o)i.add(s.type),n=n.slice(0,s.start)+`[REDACTED:${s.type}]`+n.slice(s.end);return{text:n,redacted:t.length,secretTypes:[...i].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 i=n.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]+/g,"");if(i.includes("password")||i.includes("passwd")||i==="pwd"||i.includes("secret")||i.includes("token")||i.includes("cookie")||i.includes("authorization")||i.includes("apikey")||i.includes("accesskey")||i.includes("privatekey")||i.includes("clientsecret")||i.includes("credential")){t[n]="[REDACTED]";continue}t[n]=this.sanitizeValue(o)}return t}return e}};var Ke=new h;function K(r){return H(r.rootPath,".toolnet","work","current.json")}function T(r){let e=K(r);if(!V(e))return null;try{let t=JSON.parse(B(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}import{existsSync as G,mkdirSync as ct,readFileSync as J,renameSync as at,writeFileSync as ut}from"node:fs";import{dirname as dt,join as q}from"node:path";function U(r){return q(r.rootPath,".toolnet","context","session-origin.json")}function E(r){let e=U(r);if(!G(e))return null;try{let t=JSON.parse(J(e,"utf8"));return t.version!==1||t.projectId!==r.id?null:t}catch{return null}}function X(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function ee(r){let e=X(r),t=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(e),n=/(?:đang làm gì|làm tới đâu|dừng ở đâu|dở ở đâu|stopped where|working on|current task|file nào|last touched|làm gì tiếp|next action|next step)/u.test(e);return t&&n?"summary":/(?:agent trước là ai|previous agent|ai trước là ai|phiên trước là ai)/u.test(e)?"previous_agent":/(?:task hiện tại|current task|đang làm gì|đang làm task nào|dở ở đâu|dừng ở đâu|stopped where)/u.test(e)?"current_task":/(?:tiếp theo|next action|next step|làm gì tiếp|phải làm gì tiếp)/u.test(e)?"next_action":/(?:file cuối|last file|file nào|đang sửa file|last touched)/u.test(e)?"last_file":/(?:blocker|vướng|kẹt|lỗi gì|blocked)/u.test(e)?"blocker":/(?:decision|quyết định|đã chốt|important decision)/u.test(e)?"decision":/(?:đã xong|completed|hoàn thành|done|todo nào xong)/u.test(e)?"completed":/(?:status|trạng thái|tiến độ|progress)/u.test(e)?"status":"summary"}function te(r){let e=Q(r.rootPath,".toolnet","context","handoff.md");if(!Y(e))return null;try{let t=Z(e,"utf8").trim();return t||null}catch{return null}}function ne(r,e=5){return r.slice(0,e).map(t=>`- ${t}`).join(`
2
+ `)}function R(r,e){let t=ee(e),n=E(r),o=T(r);switch(t){case"previous_agent":{if(n)return{intent:t,answer:`Agent tr\u01B0\u1EDBc l\xE0 ${n.agent}. Session: ${n.nativeSessionId}.`,source:"session-origin"};break}case"current_task":{if(n?.currentTask){let s=[`Task hi\u1EC7n t\u1EA1i: ${n.currentTask}.`];return n.lastTouchedFile&&s.push(`File g\u1EA7n nh\u1EA5t: ${n.lastTouchedFile}.`),n.latestNextAction&&s.push(`Ti\u1EBFp theo: ${n.latestNextAction}.`),{intent:t,answer:s.join(" "),source:"session-origin"}}if(o?.currentTask)return{intent:t,answer:`Task hi\u1EC7n t\u1EA1i: ${o.currentTask.title} (${o.currentTask.status}).`,source:"work-state"};break}case"next_action":{let s=n?.latestNextAction??o?.nextActions?.[0];if(s)return{intent:t,answer:`Vi\u1EC7c n\xEAn l\xE0m ti\u1EBFp: ${s}.`,source:n?.latestNextAction?"session-origin":"work-state"};break}case"last_file":{let s=n?.lastTouchedFile??o?.filesTouched?.at(-1);if(s)return{intent:t,answer:`File g\u1EA7n nh\u1EA5t \u0111\u01B0\u1EE3c nh\u1EAFc ho\u1EB7c s\u1EEDa: ${s}.`,source:n?.lastTouchedFile?"session-origin":"work-state"};break}case"blocker":{let s=n?.latestBlocker??o?.blockers?.at(-1);return s?{intent:t,answer:`Blocker hi\u1EC7n t\u1EA1i: ${s}.`,source:n?.latestBlocker?"session-origin":"work-state"}:{intent:t,answer:"Hi\u1EC7n ToolNet ch\u01B0a ghi nh\u1EADn blocker n\xE0o.",source:o?"work-state":"none"}}case"decision":{let s=n?.latestDecision??o?.decisions?.at(-1);if(s)return{intent:t,answer:`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${s}.`,source:n?.latestDecision?"session-origin":"work-state"};break}case"completed":{let s=o?.tasks?.filter(c=>c.status==="completed").map(c=>c.title)??[];if(s.length)return{intent:t,answer:`C\xE1c task \u0111\xE3 ho\xE0n th\xE0nh:
3
+ ${ne(s,8)}`,source:"work-state"};break}case"status":{if(o){let s=[`Progress: ${o.progress.tasksCompleted}/${o.progress.tasksTotal} task ho\xE0n th\xE0nh.`];return o.currentTask&&s.push(`\u0110ang l\xE0m: ${o.currentTask.title}.`),o.progress.blocked>0&&s.push(`Blocked: ${o.progress.blocked}.`),{intent:t,answer:s.join(" "),source:"work-state"}}break}case"summary":{if(n||o){let s=[];n&&s.push(`Agent tr\u01B0\u1EDBc: ${n.agent}.`);let c=n?.currentTask??o?.currentTask?.title;c&&s.push(`Task hi\u1EC7n t\u1EA1i: ${c}.`);let l=n?.lastTouchedFile??o?.filesTouched?.at(-1);l&&s.push(`File g\u1EA7n nh\u1EA5t: ${l}.`);let m=n?.latestNextAction??o?.nextActions?.[0];m&&s.push(`Ti\u1EBFp theo: ${m}.`);let d=n?.latestBlocker??o?.blockers?.at(-1);d&&s.push(`Blocker: ${d}.`);let a=n?.latestDecision??o?.decisions?.at(-1);return a&&s.push(`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${a}.`),{intent:t,answer:s.join(" "),source:n?"session-origin":"work-state"}}break}}let i=te(r);if(i){let s=i.length>900?`${i.slice(0,900)}
4
+ [truncated]`:i;return{intent:t,answer:s,source:"handoff"}}return{intent:t,answer:"ToolNet ch\u01B0a c\xF3 \u0111\u1EE7 memory cho c\xE2u h\u1ECFi n\xE0y.",source:"none"}}import{existsSync as re,readFileSync as oe}from"node:fs";import{homedir as se}from"node:os";import{join as ie}from"node:path";function ce(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
5
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function ae(){let r=process.env.TOOLNET_GLOBAL_ENV??ie(se(),".config","toolnet-memory",".env");if(!re(r))return;let e=oe(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 i=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=ce(n.slice(o+1)))}}ae();import{createHash as ue}from"node:crypto";import{existsSync as k,mkdirSync as le,readFileSync as de,renameSync as fe,writeFileSync as pe}from"node:fs";import{basename as me,dirname as x,join as g,parse as j,resolve as p}from"node:path";var N=".toolnet",ge="project.json";function ye(r){return ue("sha256").update(r).digest("hex").slice(0,16)}function S(r){return g(r,N,ge)}function he(r){return k(S(r))}function C(r,e){let t=p(r),n=j(t).root;for(;;){if(he(t))return t;if(t===n||e&&t===p(e))break;let o=x(t);if(o===t)break;t=o}return null}function I(r){let e=p(r),t=j(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>k(g(e,i))))return e;if(e===t)break;let o=x(e);if(o===e)break;e=o}return p(r)}function O(r){let e;try{e=JSON.parse(de(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:x(x(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=g(r,N);le(t,{recursive:!0});let n=S(r),o=`${n}.tmp-${process.pid}`;pe(o,JSON.stringify(e,null,2)+`
6
+ `,{encoding:"utf8",mode:384}),fe(o,n)}function w(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 b=class{findExisting(e=process.cwd()){let t=p(e),n=I(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>k(g(n,l))),s=C(t,i?n:void 0);if(!s)return null;let c=O(S(s));return w(c,s)}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=p(e),n=I(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(d=>k(g(n,d))),s=C(t,i?n:void 0);if(s){let d=S(s),a=O(d);return a.rootPath!==s&&(a.rootPath=s,a.updatedAt=new Date().toISOString(),_(s,a)),w(a,s)}let c=new Date().toISOString(),l=me(n),m={version:1,id:ye(n),name:l,remote:l,rootPath:n,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return _(n,m),w(m,n)}};function ke(){let r=process.argv.slice(2).join(" ").trim();if(!r){console.error('Usage: toolnet-memory ask "<question>"'),process.exitCode=1;return}let e=process.cwd(),t=A(e);if(!t){console.error("Not in a ToolNet project."),process.exitCode=1;return}let n=new b().detect(t);if(!n){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let o=R(n,r);process.stdout.write(`${o.answer}
7
+ `)}ke();