toolnet-memory 0.2.18 → 0.2.20

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.
@@ -1,7 +1,7 @@
1
- import*as d from"fs";import*as u from"path";function x(r){let t=u.resolve(r),e=u.parse(t).root;for(;t!==e;){let n=u.join(t,".toolnet");if(d.existsSync(n)&&d.statSync(n).isDirectory())return t;t=u.dirname(t)}return null}import{existsSync as $,readFileSync as F}from"node:fs";import{join as D}from"node:path";import{existsSync as C,mkdirSync as be,readFileSync as I,renameSync as Ae,writeFileSync as Me}from"node:fs";import{dirname as Ee,join as j}from"node:path";function _(r){return j(r.rootPath,".toolnet","work","current.json")}function w(r){let t=_(r);if(!C(t))return null;try{let e=JSON.parse(I(t,"utf8"));return e.version!==1||e.projectId!==r.id?null:e}catch{return null}}import{existsSync as R,mkdirSync as je,readFileSync as O,renameSync as _e,writeFileSync as Re}from"node:fs";import{dirname as Pe,join as P}from"node:path";function N(r){return P(r.rootPath,".toolnet","context","session-origin.json")}function T(r){let t=N(r);if(!R(t))return null;try{let e=JSON.parse(O(t,"utf8"));return e.version!==1||e.projectId!==r.id?null:e}catch{return null}}function L(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function W(r){let t=L(r),e=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(t),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(t);return e&&n?"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 B(r){let t=D(r.rootPath,".toolnet","context","handoff.md");if(!$(t))return null;try{let e=F(t,"utf8").trim();return e||null}catch{return null}}function K(r,t=5){return r.slice(0,t).map(e=>`- ${e}`).join(`
1
+ import*as d from"fs";import*as u from"path";function x(r){let t=u.resolve(r),e=u.parse(t).root;for(;t!==e;){let n=u.join(t,".toolnet");if(d.existsSync(n)&&d.statSync(n).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";import{existsSync as j,mkdirSync as be,readFileSync as C,renameSync as Ae,writeFileSync as ve}from"node:fs";import{dirname as Ee,join as I}from"node:path";function R(r){return I(r.rootPath,".toolnet","work","current.json")}function w(r){let t=R(r);if(!j(t))return null;try{let e=JSON.parse(C(t,"utf8"));return e.version!==1||e.projectId!==r.id?null:e}catch{return null}}import{existsSync as _,mkdirSync as Ie,readFileSync as O,renameSync as Re,writeFileSync as _e}from"node:fs";import{dirname as Ne,join as N}from"node:path";function P(r){return N(r.rootPath,".toolnet","context","session-origin.json")}function T(r){let t=P(r);if(!_(t))return null;try{let e=JSON.parse(O(t,"utf8"));return e.version!==1||e.projectId!==r.id?null:e}catch{return null}}function L(r){return r.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim()}function W(r){let t=L(r),e=/(?:agent trước|previous agent|ai trước|phiên trước)/u.test(t),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(t);return e&&n?"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 B(r){let t=D(r.rootPath,".toolnet","context","handoff.md");if(!F(t))return null;try{let e=$(t,"utf8").trim();return e||null}catch{return null}}function K(r,t=5){return r.slice(0,t).map(e=>`- ${e}`).join(`
2
2
  `)}function b(r,t){let e=W(t),n=T(r),o=w(r);switch(e){case"previous_agent":{if(n)return{intent:e,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: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=n?.latestNextAction??o?.nextActions?.[0];if(s)return{intent:e,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:e,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:e,answer:`Blocker hi\u1EC7n t\u1EA1i: ${s}.`,source:n?.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=n?.latestDecision??o?.decisions?.at(-1);if(s)return{intent:e,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:e,answer:`C\xE1c task \u0111\xE3 ho\xE0n th\xE0nh:
3
3
  ${K(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(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 f=n?.lastTouchedFile??o?.filesTouched?.at(-1);f&&s.push(`File g\u1EA7n nh\u1EA5t: ${f}.`);let p=n?.latestNextAction??o?.nextActions?.[0];p&&s.push(`Ti\u1EBFp theo: ${p}.`);let l=n?.latestBlocker??o?.blockers?.at(-1);l&&s.push(`Blocker: ${l}.`);let a=n?.latestDecision??o?.decisions?.at(-1);return a&&s.push(`Quy\u1EBFt \u0111\u1ECBnh g\u1EA7n nh\u1EA5t: ${a}.`),{intent:e,answer:s.join(" "),source:n?"session-origin":"work-state"}}break}}let i=B(r);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 z,readFileSync as H}from"node:fs";import{homedir as Y}from"node:os";import{join as V}from"node:path";function U(r){let t=r.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 J(){let r=process.env.TOOLNET_GLOBAL_ENV??V(Y(),".config","toolnet-memory",".env");if(!z(r))return;let t=H(r,"utf8");for(let e of t.split(/\r?\n/)){let n=e.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]=U(n.slice(o+1)))}}J();import{createHash as G}from"node:crypto";import{existsSync as k,mkdirSync as Q,readFileSync as Z,renameSync as q,writeFileSync as X}from"node:fs";import{basename as ee,dirname as g,join as y,parse as v,resolve as m}from"node:path";var E=".toolnet",te="project.json";function re(r){return G("sha256").update(r).digest("hex").slice(0,16)}function S(r){return y(r,E,te)}function ne(r){return k(S(r))}function oe(r,t){let e=m(r),n=v(e).root;for(;;){if(ne(e))return e;if(e===n||t&&e===m(t))break;let o=g(e);if(o===e)break;e=o}return null}function se(r){let t=m(r),e=v(t).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>k(y(t,i))))return t;if(t===e)break;let o=g(t);if(o===t)break;t=o}return m(r)}function ie(r){let t;try{t=JSON.parse(Z(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let e=t;if(typeof e.id!="string"||!e.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof e.name!="string"||!e.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=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(r)),createdAt:typeof e.createdAt=="string"?e.createdAt:n,updatedAt:typeof e.updatedAt=="string"?e.updatedAt:n,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(r,t){let e=y(r,E);Q(e,{recursive:!0});let n=S(r),o=`${n}.tmp-${process.pid}`;X(o,JSON.stringify(t,null,2)+`
6
- `,{encoding:"utf8",mode:384}),q(o,n)}function M(r,t){return{id:r.id,name:r.name,remote:r.remote,rootPath:t,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var h=class{detect(t=process.cwd()){let e=m(t),n=se(e),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>k(y(n,l))),s=oe(e,i?n: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(n),p={version:1,id:re(n),name:f,remote:f,rootPath:n,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return A(n,p),M(p,n)}};function ce(){let r=process.argv.slice(2).join(" ").trim();if(!r){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 n=new h().detect(e);if(!n){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let o=b(n,r);process.stdout.write(`${o.answer}
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 z,readFileSync as H}from"node:fs";import{homedir as V}from"node:os";import{join as Y}from"node:path";function U(r){let t=r.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 J(){let r=process.env.TOOLNET_GLOBAL_ENV??Y(V(),".config","toolnet-memory",".env");if(!z(r))return;let t=H(r,"utf8");for(let e of t.split(/\r?\n/)){let n=e.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]=U(n.slice(o+1)))}}J();import{createHash as G}from"node:crypto";import{existsSync as k,mkdirSync as Q,readFileSync as q,renameSync as Z,writeFileSync as X}from"node:fs";import{basename as ee,dirname as g,join as y,parse as M,resolve as m}from"node:path";var E=".toolnet",te="project.json";function re(r){return G("sha256").update(r).digest("hex").slice(0,16)}function S(r){return y(r,E,te)}function ne(r){return k(S(r))}function oe(r,t){let e=m(r),n=M(e).root;for(;;){if(ne(e))return e;if(e===n||t&&e===m(t))break;let o=g(e);if(o===e)break;e=o}return null}function se(r){let t=m(r),e=M(t).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>k(y(t,i))))return t;if(t===e)break;let o=g(t);if(o===t)break;t=o}return m(r)}function ie(r){let t;try{t=JSON.parse(q(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!t||typeof t!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let e=t;if(typeof e.id!="string"||!e.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof e.name!="string"||!e.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=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(r)),createdAt:typeof e.createdAt=="string"?e.createdAt:n,updatedAt:typeof e.updatedAt=="string"?e.updatedAt:n,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(r,t){let e=y(r,E);Q(e,{recursive:!0});let n=S(r),o=`${n}.tmp-${process.pid}`;X(o,JSON.stringify(t,null,2)+`
6
+ `,{encoding:"utf8",mode:384}),Z(o,n)}function v(r,t){return{id:r.id,name:r.name,remote:r.remote,rootPath:t,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var h=class{detect(t=process.cwd()){let e=m(t),n=se(e),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(l=>k(y(n,l))),s=oe(e,i?n: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)),v(a,s)}let c=new Date().toISOString(),f=ee(n),p={version:1,id:re(n),name:f,remote:f,rootPath:n,createdAt:c,updatedAt:c,graphVersion:0,memoryVersion:0};return A(n,p),v(p,n)}};function ce(){let r=process.argv.slice(2).join(" ").trim();if(!r){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 n=new h().detect(e);if(!n){console.error("Unable to detect ToolNet project."),process.exitCode=1;return}let o=b(n,r);process.stdout.write(`${o.answer}
7
7
  `)}ce();
@@ -1,26 +1,26 @@
1
1
  import{existsSync as Zt,readFileSync as en}from"node:fs";import{homedir as tn}from"node:os";import{join as nn}from"node:path";function rn(t){let e=t.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 sn(){let t=process.env.TOOLNET_GLOBAL_ENV??nn(tn(),".config","toolnet-memory",".env");if(!Zt(t))return;let e=en(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=rn(r.slice(s+1)))}}sn();function W(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function H(){return{memory:{autoCapture:W(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:W(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:W(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:W(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:W(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as on}from"node:crypto";import{existsSync as we,mkdirSync as an,readFileSync as cn,renameSync as un,writeFileSync as ln}from"node:fs";import{basename as dn,dirname as Y,join as X,parse as ze,resolve as q}from"node:path";var qe=".toolnet",pn="project.json";function fn(t){return on("sha256").update(t).digest("hex").slice(0,16)}function je(t){return X(t,qe,pn)}function mn(t){return we(je(t))}function gn(t,e){let n=q(t),r=ze(n).root;for(;;){if(mn(n))return n;if(n===r||e&&n===q(e))break;let s=Y(n);if(s===n)break;n=s}return null}function yn(t){let e=q(t),n=ze(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>we(X(e,o))))return e;if(e===n)break;let s=Y(e);if(s===e)break;e=s}return q(t)}function hn(t){let e;try{e=JSON.parse(cn(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:Y(Y(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function Be(t,e){let n=X(t,qe);an(n,{recursive:!0});let r=je(t),s=`${r}.tmp-${process.pid}`;ln(s,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),un(s,r)}function We(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var G=class{detect(e=process.cwd()){let n=q(e),r=yn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>we(X(r,p))),i=gn(n,o?r:void 0);if(i){let p=je(i),u=hn(p);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Be(i,u)),We(u,i)}let l=new Date().toISOString(),c=dn(r),a={version:1,id:fn(r),name:c,remote:c,rootPath:r,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return Be(r,a),We(a,r)}};var Sn=[{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}],Q=class{scan(e){let n=[];for(let r of Sn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var J=class{scanner=new Q;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Bn}from"node:os";import{join as Wn}from"node:path";import{DeleteObjectCommand as vn,GetObjectCommand as bn,HeadObjectCommand as kn,ListObjectsV2Command as wn,PutObjectCommand as jn,S3Client as xn}from"@aws-sdk/client-s3";import{getSignedUrl as In}from"@aws-sdk/s3-request-presigner";var Z=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new xn({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,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new jn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await In(this.client,new bn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new kn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new vn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new wn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as Je,mkdir as En,readFile as On,readdir as Pn,rm as Tn,stat as Ve,writeFile as Cn}from"node:fs/promises";import{dirname as Rn,join as Mn,relative as Ue,resolve as An}from"node:path";var V=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return An(this.root,n)}async put(e,n){let r=this.path(e);await En(Rn(r),{recursive:!0}),await Cn(r,n)}async get(e){try{return await On(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await Je(this.path(e)),!0}catch{return!1}}async delete(e){await Tn(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Je(n)}catch{return r}let s=async i=>{let l=await Pn(i,{withFileTypes:!0});for(let c of l){let a=Mn(i,c.name);if(c.isDirectory()){await s(a);continue}let p=await Ve(a);r.push({key:Ue(this.root,a),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await Ve(n);return o.isDirectory()?await s(n):r.push({key:Ue(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Nn,GetObjectCommand as _n,HeadObjectCommand as $n,ListObjectsV2Command as Ln,PutObjectCommand as Dn,S3Client as Fn}from"@aws-sdk/client-s3";import{getSignedUrl as Kn}from"@aws-sdk/s3-request-presigner";var U=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Fn({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,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Dn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Kn(this.client,new _n({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new $n({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Nn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Ln({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function xe(t,e){return console.warn(e),new V(t)}function He(t){let e=t.localRoot??Wn(Bn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new U({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new U({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Z({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new V(e)}function zn(t){return new Promise(e=>setTimeout(e,t))}async function Ye(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(l){if(o=l,i>=n)break;let c=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await zn(c+a)}throw o}var qn=new Set(["put","get","getText","delete","list"]);function Ge(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:qn.has(r)?(...o)=>Ye(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Xe(t){let e=t.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 Qe(t){let e=t.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 n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var ee=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Xe(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Qe(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,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as ws}from"node:fs";import{execFileSync as js}from"node:child_process";import{homedir as xs}from"node:os";import{isAbsolute as Is,join as _t,relative as Es,resolve as $t}from"node:path";import{DatabaseSync as Os}from"node:sqlite";import{join as Xn}from"node:path";import{createHash as Jn}from"node:crypto";import{dirname as Vn}from"node:path";import{mkdirSync as Un,readFileSync as Hn,renameSync as Yn,writeFileSync as Gn}from"node:fs";function v(t){return Jn("sha256").update(t).digest("hex")}function Ie(t){if(Array.isArray(t))return t.map(Ie);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Ie(e[r]);return n}return t}function Ze(t){return JSON.stringify(Ie(t))}function et(t){try{return JSON.parse(Hn(t,"utf8"))}catch{return null}}function I(t,e){Un(Vn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Gn(n,JSON.stringify(e,null,2)+`
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 sn(){let t=process.env.TOOLNET_GLOBAL_ENV??nn(tn(),".config","toolnet-memory",".env");if(!Zt(t))return;let e=en(t,"utf8");for(let n of e.split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;r.startsWith("export ")&&(r=r.slice(7));let s=r.indexOf("=");if(s<=0)continue;let o=r.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(o)&&process.env[o]===void 0&&(process.env[o]=rn(r.slice(s+1)))}}sn();function W(t,e){return t===void 0?e:["1","true","yes","on"].includes(t.toLowerCase())}function z(t,e){if(!t)return e;let n=Number(t);return Number.isFinite(n)?n:e}function H(){return{memory:{autoCapture:W(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:W(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:W(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:W(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:z(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:z(process.env.MEMORY_RERANK_TOP,10),finalContext:z(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:z(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",r2:{accountId:process.env.R2_ACCOUNT_ID,bucket:process.env.R2_BUCKET,accessKeyId:process.env.R2_ACCESS_KEY_ID,secretAccessKey:process.env.R2_SECRET_ACCESS_KEY},s3:{endpoint:process.env.S3_ENDPOINT,region:process.env.S3_REGION,bucket:process.env.S3_BUCKET,accessKeyId:process.env.S3_ACCESS_KEY_ID,secretAccessKey:process.env.S3_SECRET_ACCESS_KEY,forcePathStyle:W(process.env.S3_FORCE_PATH_STYLE,!1)},huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:z(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as on}from"node:crypto";import{existsSync as we,mkdirSync as an,readFileSync as cn,renameSync as un,writeFileSync as ln}from"node:fs";import{basename as dn,dirname as Y,join as X,parse as ze,resolve as q}from"node:path";var qe=".toolnet",pn="project.json";function fn(t){return on("sha256").update(t).digest("hex").slice(0,16)}function je(t){return X(t,qe,pn)}function mn(t){return we(je(t))}function gn(t,e){let n=q(t),r=ze(n).root;for(;;){if(mn(n))return n;if(n===r||e&&n===q(e))break;let s=Y(n);if(s===n)break;n=s}return null}function hn(t){let e=q(t),n=ze(e).root,r=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(r.some(o=>we(X(e,o))))return e;if(e===n)break;let s=Y(e);if(s===e)break;e=s}return q(t)}function yn(t){let e;try{e=JSON.parse(cn(t,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${t}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${t}`);let n=e;if(typeof n.id!="string"||!n.id.trim())throw new Error(`ToolNet project manifest is missing id: ${t}`);if(typeof n.name!="string"||!n.name.trim())throw new Error(`ToolNet project manifest is missing name: ${t}`);let r=new Date().toISOString();return{version:1,id:n.id,name:n.name,remote:typeof n.remote=="string"&&n.remote.trim()?n.remote:n.name,rootPath:typeof n.rootPath=="string"?n.rootPath:Y(Y(t)),createdAt:typeof n.createdAt=="string"?n.createdAt:r,updatedAt:typeof n.updatedAt=="string"?n.updatedAt:r,graphVersion:typeof n.graphVersion=="number"?n.graphVersion:0,memoryVersion:typeof n.memoryVersion=="number"?n.memoryVersion:0,metadata:n.metadata&&typeof n.metadata=="object"?n.metadata:void 0}}function Be(t,e){let n=X(t,qe);an(n,{recursive:!0});let r=je(t),s=`${r}.tmp-${process.pid}`;ln(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),un(s,r)}function We(t,e){return{id:t.id,name:t.name,remote:t.remote,rootPath:e,createdAt:t.createdAt,updatedAt:t.updatedAt,graphVersion:t.graphVersion,memoryVersion:t.memoryVersion,metadata:t.metadata}}var G=class{detect(e=process.cwd()){let n=q(e),r=hn(n),o=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(p=>we(X(r,p))),i=gn(n,o?r:void 0);if(i){let p=je(i),u=yn(p);return u.rootPath!==i&&(u.rootPath=i,u.updatedAt=new Date().toISOString(),Be(i,u)),We(u,i)}let l=new Date().toISOString(),c=dn(r),a={version:1,id:fn(r),name:c,remote:c,rootPath:r,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return Be(r,a),We(a,r)}};var Sn=[{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}],Q=class{scan(e){let n=[];for(let r of Sn){let s=new RegExp(r.regex.source,r.regex.flags);for(let o of e.matchAll(s))n.push({type:r.type,value:o[0]})}return n}hasSecrets(e){return this.scan(e).length>0}};var J=class{scanner=new Q;sanitize(e){let n=e,r=this.scanner.scan(e),s=new Set;for(let o of r)s.add(o.type),n=n.split(o.value).join(`[REDACTED:${o.type}]`);return{text:n,redacted:r.length,secretTypes:[...s]}}sanitizeValue(e){if(typeof e=="string")return this.sanitize(e).text;if(Array.isArray(e))return e.map(n=>this.sanitizeValue(n));if(e&&typeof e=="object"){let n={};for(let[r,s]of Object.entries(e)){let o=r.toLowerCase();o.includes("password")||o.includes("secret")||o.includes("token")||o.includes("cookie")||o.includes("authorization")?n[r]="[REDACTED]":n[r]=this.sanitizeValue(s)}return n}return e}};import{homedir as Bn}from"node:os";import{join as Wn}from"node:path";import{DeleteObjectCommand as vn,GetObjectCommand as bn,HeadObjectCommand as kn,ListObjectsV2Command as wn,PutObjectCommand as jn,S3Client as xn}from"@aws-sdk/client-s3";import{getSignedUrl as En}from"@aws-sdk/s3-request-presigner";var Z=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new xn({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,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new jn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await En(this.client,new bn({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`HF download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new kn({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new vn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new wn({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};import{access as Je,mkdir as In,readFile as On,readdir as Pn,rm as Tn,stat as Ve,writeFile as Cn}from"node:fs/promises";import{dirname as Rn,join as Mn,relative as Ue,resolve as An}from"node:path";var V=class{constructor(e){this.root=e}root;name="local";path(e){let n=e.replace(/^\/+/,"");return An(this.root,n)}async put(e,n){let r=this.path(e);await In(Rn(r),{recursive:!0}),await Cn(r,n)}async get(e){try{return await On(this.path(e))}catch(n){if(typeof n=="object"&&n!==null&&"code"in n&&n.code==="ENOENT")return null;throw n}}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await Je(this.path(e)),!0}catch{return!1}}async delete(e){await Tn(this.path(e),{force:!0})}async list(e=""){let n=this.path(e),r=[];try{await Je(n)}catch{return r}let s=async i=>{let l=await Pn(i,{withFileTypes:!0});for(let c of l){let a=Mn(i,c.name);if(c.isDirectory()){await s(a);continue}let p=await Ve(a);r.push({key:Ue(this.root,a),size:p.size,updatedAt:p.mtime.toISOString()})}},o=await Ve(n);return o.isDirectory()?await s(n):r.push({key:Ue(this.root,n),size:o.size,updatedAt:o.mtime.toISOString()}),r}};import{DeleteObjectCommand as Nn,GetObjectCommand as _n,HeadObjectCommand as $n,ListObjectsV2Command as Ln,PutObjectCommand as Dn,S3Client as Fn}from"@aws-sdk/client-s3";import{getSignedUrl as Kn}from"@aws-sdk/s3-request-presigner";var U=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Fn({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,n,r="application/octet-stream"){let s=typeof n=="string"?Buffer.from(n,"utf8"):n;await this.client.send(new Dn({Bucket:this.bucket,Key:e,Body:s,ContentType:r}))}async get(e){let n=await Kn(this.client,new _n({Bucket:this.bucket,Key:e}),{expiresIn:60}),r=await fetch(n,{redirect:"follow"});if(r.status===404)return null;if(!r.ok)throw new Error(`${this.name} download failed: ${r.status} ${r.statusText}`);return new Uint8Array(await r.arrayBuffer())}async getText(e){let n=await this.get(e);return n?Buffer.from(n).toString("utf8"):null}async exists(e){try{return await this.client.send(new $n({Bucket:this.bucket,Key:e})),!0}catch(n){if(typeof n=="object"&&n!==null&&"$metadata"in n&&n.$metadata?.httpStatusCode===404)return!1;throw n}}async delete(e){await this.client.send(new Nn({Bucket:this.bucket,Key:e}))}async list(e=""){let n=[],r;do{let s=await this.client.send(new Ln({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:r}));for(let o of s.Contents??[])o.Key&&n.push({key:o.Key,size:o.Size,updatedAt:o.LastModified?.toISOString()});r=s.IsTruncated?s.NextContinuationToken:void 0}while(r);return n}};function xe(t,e){return console.warn(e),new V(t)}function He(t){let e=t.localRoot??Wn(Bn(),".toolnet-memory","storage");if(t.provider==="r2"){let n=t.r2;return n?.accountId&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new U({name:"r2",endpoint:`https://${n.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:n.bucket,forcePathStyle:!0,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(t.provider==="s3"){let n=t.s3;return n?.bucket&&n.accessKeyId&&n.secretAccessKey?new U({name:"s3",endpoint:n.endpoint,region:n.region??"us-east-1",bucket:n.bucket,forcePathStyle:n.forcePathStyle??!1,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] S3 credentials missing. Using local fallback.")}if(t.provider==="huggingface"){let n=t.huggingface;return n?.namespace&&n.bucket&&n.accessKeyId&&n.secretAccessKey?new Z({namespace:n.namespace,bucket:n.bucket,accessKeyId:n.accessKeyId,secretAccessKey:n.secretAccessKey}):xe(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new V(e)}function zn(t){return new Promise(e=>setTimeout(e,t))}async function Ye(t,e={}){let n=Math.max(1,e.attempts??3),r=e.baseDelayMs??150,s=e.maxDelayMs??2e3,o;for(let i=1;i<=n;i++)try{return await t()}catch(l){if(o=l,i>=n)break;let c=Math.min(s,r*2**(i-1)),a=Math.floor(Math.random()*Math.max(1,c*.2));await zn(c+a)}throw o}var qn=new Set(["put","get","getText","delete","list"]);function Ge(t,e={}){return new Proxy(t,{get(n,r){let s=Reflect.get(n,r,n);return typeof s!="function"?s:qn.has(r)?(...o)=>Ye(()=>Promise.resolve(s.apply(n,o)),e):s.bind(n)}})}function Xe(t){let e=t.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 Qe(t){let e=t.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 n=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(r)return`${r[1]}memory/records/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),r)return`${r[1]}memory/vectors/${r[2]}`;if(r=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),r)return`${r[1]}code/graph/${r[2]}`;let s=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return s?`${s[1]}memory/records/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),s?`${s[1]}memory/vectors/${s[2]}`:(s=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),s?`${s[1]}code/graph/${s[2]}`:e))}var ee=class{constructor(e,n,r,s){this.provider=e;this.name=e.name,this.projectId=n,this.projectName=r,this.folder=Xe(s??r),this.sourcePrefix=`projects/${n}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,n=new Date().toISOString(),r=n,s=await this.provider.getText(e);if(s){let i;try{i=JSON.parse(s)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof i.id=="string"&&i.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${i.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof i.createdAt=="string"&&(r=i.createdAt)}let o={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:r,updatedAt:n};await this.provider.put(e,JSON.stringify(o,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=Qe(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,n,r){return await this.ensureRegistered(),this.provider.put(this.key(e),n,r)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{existsSync as ws}from"node:fs";import{execFileSync as js}from"node:child_process";import{homedir as xs}from"node:os";import{isAbsolute as Es,join as _t,relative as Is,resolve as $t}from"node:path";import{DatabaseSync as Os}from"node:sqlite";import{join as Xn}from"node:path";import{createHash as Jn}from"node:crypto";import{dirname as Vn}from"node:path";import{mkdirSync as Un,readFileSync as Hn,renameSync as Yn,writeFileSync as Gn}from"node:fs";function v(t){return Jn("sha256").update(t).digest("hex")}function Ee(t){if(Array.isArray(t))return t.map(Ee);if(t&&typeof t=="object"){let e=t,n={};for(let r of Object.keys(e).sort())n[r]=Ee(e[r]);return n}return t}function Ze(t){return JSON.stringify(Ee(t))}function et(t){try{return JSON.parse(Hn(t,"utf8"))}catch{return null}}function E(t,e){Un(Vn(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;Gn(n,JSON.stringify(e,null,2)+`
5
5
  `,{encoding:"utf8",mode:384}),Yn(n,t)}function tt(t,e){let n=t.trim(),r=n.replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,""),s=v(n).slice(0,12);if(!r||r==="."||r==="..")return`${e}--${s}`;let o=r.slice(0,100);return o===n&&n.length<=100?o:`${o.slice(0,85)}--${s}`}function nt(t,e,n){let r=e.trim(),s=n.trim();if(!r)throw new Error("Session agent is required");if(!s)throw new Error("Native session ID is required");let o=tt(r.toLowerCase(),"agent"),i=tt(s,"session");return{projectId:t.id,projectName:t.name,projectRoot:t.rootPath,agent:r,nativeSessionId:s,sessionKey:`${r}:${s}`,remotePrefix:["projects",t.id,"sessions",o,i].join("/"),localDirectory:Xn(t.rootPath,".toolnet","sessions",o,i)}}function rt(t){return String(t).padStart(12,"0")}var te=class{constructor(e,n=100,r=512*1024){this.storage=e;this.maxEventsPerChunk=n;this.maxChunkBytes=r;if(n<1)throw new Error("maxEventsPerChunk must be positive");if(r<1024)throw new Error("maxChunkBytes is too small")}storage;maxEventsPerChunk;maxChunkBytes;async getJson(e){let n=await this.storage.getText(e);return n?JSON.parse(n):null}async putJson(e,n){await this.storage.put(e,JSON.stringify(n,null,2)+`
6
6
  `,"application/json")}async scan(e){let n=`${e.remotePrefix}/events/`,r=await this.storage.list(n),s=[],o=0;for(let i of r){let l=i.key.match(/\/events\/(\d+)-(\d+)-[a-f0-9]+\.jsonl$/);if(!l)continue;let c=Number(l[1]),a=Number(l[2]);!Number.isFinite(c)||!Number.isFinite(a)||(s.push({key:i.key,start:c,end:a}),o=Math.max(o,a))}return s.sort((i,l)=>i.start-l.start),{chunks:s,maxSequence:o}}split(e){let n=[],r=[],s=0;for(let o of e){let i=Buffer.byteLength(JSON.stringify(o)+`
7
- `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),l=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(l)){let y=g[0],w=g[g.length-1],T=g.map(A=>JSON.stringify(A)).join(`
7
+ `,"utf8");r.length>0&&(r.length>=this.maxEventsPerChunk||s+i>this.maxChunkBytes)&&(n.push(r),r=[],s=0),r.push(o),s+=i}return r.length>0&&n.push(r),n}async loadManifest(e){return this.getJson(`${e.remotePrefix}/session.json`)}async loadCursor(e){return this.getJson(`${e.remotePrefix}/cursor.json`)}async recover(e){let n=await this.scan(e);return{maxSequence:n.maxSequence,chunkCount:n.chunks.length}}async append(e,n,r,s={}){let o=await this.loadManifest(e),i=await this.scan(e),l=n.filter(g=>g.sequence>i.maxSequence),c=0;for(let g of this.split(l)){let h=g[0],w=g[g.length-1],T=g.map(A=>JSON.stringify(A)).join(`
8
8
  `)+`
9
- `,$=v(T).slice(0,16),C=[e.remotePrefix,"events",`${rt(y.sequence)}-${rt(w.sequence)}-${$}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,T,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),p=n[n.length-1],u=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?u="idle":p?.type==="error"?u="error":n.length>0&&(u="active");let m=new Date().toISOString(),d=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:u,createdAt:o?.createdAt??d?.timestamp??m,updatedAt:p?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let h={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,h),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:u}}};import{closeSync as Ee,existsSync as Qn,fsyncSync as Zn,mkdirSync as er,openSync as Oe,readSync as tr,rmSync as st,statSync as ot,writeSync as nr}from"node:fs";import{join as Pe}from"node:path";var rr=12e4,sr=80,or=2e3;function ir(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ne=class{constructor(e){this.identity=e;er(e.localDirectory,{recursive:!0}),this.eventsFile=Pe(e.localDirectory,"events.jsonl"),this.stateFile=Pe(e.localDirectory,"state.json"),this.lockFile=Pe(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return et(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){I(this.stateFile,e)}acquireLock(){for(let e=0;e<sr;e+=1)try{return Oe(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-ot(this.lockFile).mtimeMs>rr){st(this.lockFile,{force:!0});continue}}catch{}ir(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ee(n),st(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let u of e){let m=u.timestamp??new Date().toISOString(),d=u.data??{},S=u.provenance?.rawDigest??v(Ze(d)),h=u.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,u.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,u.type,m,S].join("|"),g=v(h).slice(0,32);if(r.has(g))continue;s+=1;let y={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:u.type,timestamp:m,data:d,provenance:{...u.provenance,rawDigest:S}};u.role!==void 0&&(y.role=u.role),u.sourceEventId!==void 0&&(y.sourceEventId=u.sourceEventId),u.sourceSequence!==void 0&&(y.sourceSequence=u.sourceSequence),o.push(y),r.add(g)}if(o.length===0)return[];let i=o.map(u=>JSON.stringify(u)).join(`
9
+ `,$=v(T).slice(0,16),C=[e.remotePrefix,"events",`${rt(h.sequence)}-${rt(w.sequence)}-${$}.jsonl`].join("/");await this.storage.exists(C)||await this.storage.put(C,T,"application/x-ndjson"),c+=g.length}let a=await this.scan(e),p=n[n.length-1],u=o?.status??"active";p?.type==="session_end"||p?.type==="session_idle"?u="idle":p?.type==="error"?u="error":n.length>0&&(u="active");let m=new Date().toISOString(),d=n[0],S={version:1,projectId:e.projectId,projectName:e.projectName,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,status:u,createdAt:o?.createdAt??d?.timestamp??m,updatedAt:p?.timestamp??m,firstEventAt:o?.firstEventAt??d?.timestamp,lastEventAt:p?.timestamp??o?.lastEventAt,eventCount:a.maxSequence,chunkCount:a.chunks.length,metadata:{...o?.metadata,...s.metadata}};(s.title??o?.title)&&(S.title=s.title??o?.title);let y={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,lastLocalSequence:n.length>0?n[n.length-1].sequence:a.maxSequence,lastRemoteSequence:a.maxSequence,sourceCursors:r,updatedAt:m};return await this.putJson(`${e.remotePrefix}/cursor.json`,y),await this.putJson(`${e.remotePrefix}/session.json`,S),{uploadedEvents:c,lastRemoteSequence:a.maxSequence,eventCount:S.eventCount,chunkCount:S.chunkCount,status:u}}};import{closeSync as Ie,existsSync as Qn,fsyncSync as Zn,mkdirSync as er,openSync as Oe,readSync as tr,rmSync as st,statSync as ot,writeSync as nr}from"node:fs";import{join as Pe}from"node:path";var rr=12e4,sr=80,or=2e3;function ir(t){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,t)}var ne=class{constructor(e){this.identity=e;er(e.localDirectory,{recursive:!0}),this.eventsFile=Pe(e.localDirectory,"events.jsonl"),this.stateFile=Pe(e.localDirectory,"state.json"),this.lockFile=Pe(e.localDirectory,"journal.lock")}identity;eventsFile;stateFile;lockFile;initialState(){let e=new Date().toISOString();return{version:1,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,status:"idle",createdAt:e,updatedAt:e,lastSequence:0,lastRemoteSequence:0,remoteByteOffset:0,sourceCursors:{},recentEventIds:[]}}loadStateUnsafe(){return et(this.stateFile)??this.initialState()}loadState(){return this.withLock(()=>this.loadStateUnsafe())}saveStateUnsafe(e){E(this.stateFile,e)}acquireLock(){for(let e=0;e<sr;e+=1)try{return Oe(this.lockFile,"wx",384)}catch(n){if(n.code!=="EEXIST")throw n;try{if(Date.now()-ot(this.lockFile).mtimeMs>rr){st(this.lockFile,{force:!0});continue}}catch{}ir(25)}throw new Error(`Session journal is locked: ${this.lockFile}`)}withLock(e){let n=this.acquireLock();try{return e()}finally{Ie(n),st(this.lockFile,{force:!0})}}append(e){return e.length===0?[]:this.withLock(()=>{let n=this.loadStateUnsafe(),r=new Set(n.recentEventIds),s=n.lastSequence,o=[];for(let u of e){let m=u.timestamp??new Date().toISOString(),d=u.data??{},S=u.provenance?.rawDigest??v(Ze(d)),y=u.sourceEventId?[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,u.sourceEventId].join("|"):[this.identity.projectId,this.identity.agent,this.identity.nativeSessionId,s+1,u.type,m,S].join("|"),g=v(y).slice(0,32);if(r.has(g))continue;s+=1;let h={version:1,id:g,sequence:s,projectId:this.identity.projectId,agent:this.identity.agent,nativeSessionId:this.identity.nativeSessionId,type:u.type,timestamp:m,data:d,provenance:{...u.provenance,rawDigest:S}};u.role!==void 0&&(h.role=u.role),u.sourceEventId!==void 0&&(h.sourceEventId=u.sourceEventId),u.sourceSequence!==void 0&&(h.sourceSequence=u.sourceSequence),o.push(h),r.add(g)}if(o.length===0)return[];let i=o.map(u=>JSON.stringify(u)).join(`
10
10
  `)+`
11
- `,l=Oe(this.eventsFile,"a",384);try{nr(l,i,null,"utf8"),Zn(l)}finally{Ee(l)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let p=Array.from(r).slice(-or);return this.saveStateUnsafe({...n,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Qn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=ot(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Oe(this.eventsFile,"r");try{tr(i,o,0,s,r)}finally{Ee(i)}return{events:o.toString("utf8").split(`
12
- `).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as wr,existsSync as jr,openSync as xr,readSync as Ir,statSync as Er}from"node:fs";function it(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var lt=[/không được/iu,/tuyệt đối/iu,/bắt buộc/iu,/đừng\s+/iu,/must not/iu,/do not/iu,/don't/iu,/\bnever\b/iu],ar=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],cr=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],ur=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],lr=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],at=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],dr=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],pr=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],fr=[/\blà\b/iu,/\bở\b/iu,/\bdùng\b/iu,/\bnằm\b/iu,/\bis\b/iu,/\buse\b/iu,/located/iu,/runs on/iu],ct=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),mr=new Set(["payload","data","content","message","messages","parts","summary"]);function E(t,e){return e.some(n=>n.test(t))}function dt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function gr(t){return dt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function yr(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function Te(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ct.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Te(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ct.has(s)||mr.has(s))&&Te(o,s,n,r+1)}}function hr(t){let e=[];Te(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=dt(o);if(yr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function ut(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Sr(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&E(t,lt)?{kind:"rule",confidence:.98}:r&&E(t,ar)?{kind:"rule",confidence:.92}:E(t,cr)?{kind:E(t,at)?"architecture":"decision",confidence:r?.93:.86}:r&&E(t,ur)?{kind:"todo",confidence:.87}:E(t,at)&&E(t,dr)?{kind:"architecture",confidence:r?.88:.82}:s&&E(t,lr)?{kind:"fix",confidence:.8}:r&&E(t,pr)&&E(t,fr)?{kind:"context",confidence:.79}:null}function vr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function br(t,e,n){return t==="rule"&&E(n,lt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":it(e,n)}function pt(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,l=ut(o);i&&l&&s.set(i,l)}for(let o of e){let i=ut(o),l=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&l&&(i=s.get(l)??"");for(let c of hr(o)){let a=Sr(c,i,o);if(!a||a.confidence<.75)continue;let p=vr(a.kind),u=gr(c),m=v([t.projectId,a.kind,u].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:p,content:c,confidence:a.confidence,importance:br(a.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function ft(t){return String(t).padStart(12,"0")}function kr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var re=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},l=JSON.stringify(i,null,2)+`
13
- `,c=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),a=[kr(e),"batches",`${ft(s)}-${ft(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,l,"application/json"),a}};function Or(t,e){if(!jr(t))return{events:[],nextOffset:e};let n=Er(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=xr(t,"r");try{Ir(i,o,0,s,r)}finally{wr(i)}let l=o.toString("utf8"),c=l.lastIndexOf(`
11
+ `,l=Oe(this.eventsFile,"a",384);try{nr(l,i,null,"utf8"),Zn(l)}finally{Ie(l)}let c=o[o.length-1],a="active";c.type==="session_end"||c.type==="session_idle"?a="idle":c.type==="error"&&(a="error");let p=Array.from(r).slice(-or);return this.saveStateUnsafe({...n,status:a,updatedAt:c.timestamp,lastSequence:c.sequence,recentEventIds:p}),o})}readPending(){return this.withLock(()=>{let e=this.loadStateUnsafe();if(!Qn(this.eventsFile))return{events:[],startOffset:e.remoteByteOffset,endOffset:e.remoteByteOffset};let n=ot(this.eventsFile).size,r=Math.min(e.remoteByteOffset,n);if(n<=r)return{events:[],startOffset:r,endOffset:n};let s=n-r,o=Buffer.alloc(s),i=Oe(this.eventsFile,"r");try{tr(i,o,0,s,r)}finally{Ie(i)}return{events:o.toString("utf8").split(`
12
+ `).filter(Boolean).map(a=>JSON.parse(a)),startOffset:r,endOffset:n}})}markRemote(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,lastRemoteSequence:Math.max(r.lastRemoteSequence,e),remoteByteOffset:Math.max(r.remoteByteOffset,n),updatedAt:new Date().toISOString()})})}setSourceCursor(e,n){this.withLock(()=>{let r=this.loadStateUnsafe();this.saveStateUnsafe({...r,sourceCursors:{...r.sourceCursors,[e]:String(n)},updatedAt:new Date().toISOString()})})}};import{closeSync as wr,existsSync as jr,openSync as xr,readSync as Er,statSync as Ir}from"node:fs";function it(t,e){let n=e.toLowerCase();return n.includes("kh\xF4ng \u0111\u01B0\u1EE3c")||n.includes("tuy\u1EC7t \u0111\u1ED1i")||n.includes("must not")||n.includes("never ")?"critical":t==="rule"||t==="decision"?"high":t==="todo"||n.includes("error")||n.includes("failed")||n.includes("exception")?"normal":"temporary"}var lt=[/không được/iu,/tuyệt đối/iu,/bắt buộc/iu,/đừng\s+/iu,/must not/iu,/do not/iu,/don't/iu,/\bnever\b/iu],ar=[/từ giờ/iu,/về sau/iu,/mỗi lần/iu,/luôn luôn/iu,/\bluôn\b/iu,/quy tắc/iu,/workflow/iu,/\balways\b/iu,/\brequired\b/iu,/\bmust\b/iu,/from now on/iu],cr=[/\bchốt\b/iu,/quyết định/iu,/sẽ dùng/iu,/chọn .+ thay/iu,/đổi sang/iu,/chuyển sang/iu,/\bdecided\b/iu,/\bchosen\b/iu,/we will use/iu,/use .+ instead/iu,/switch(?:ed)? to/iu],ur=[/\btodo\b/iu,/cần làm/iu,/cần thêm/iu,/cần sửa/iu,/cần kiểm tra/iu,/tiếp theo/iu,/bước tiếp theo/iu,/còn phải/iu,/còn cần/iu,/next step/iu,/\bneed to\b/iu,/\bremaining\b/iu,/follow[- ]?up/iu],lr=[/đã sửa/iu,/đã fix/iu,/đã khắc phục/iu,/đã xử lý/iu,/hoàn tất/iu,/hoàn thành/iu,/\bfixed\b/iu,/\bresolved\b/iu,/\bimplemented\b/iu,/\bcompleted\b/iu,/\bpasses?\b/iu],at=[/kiến trúc/iu,/pipeline/iu,/adapter/iu,/schema/iu,/runtime/iu,/namespace/iu,/storage/iu,/lưu trữ/iu,/workflow/iu,/session core/iu,/memory engine/iu,/retrieval/iu],dr=[/\bdùng\b/iu,/\btách\b/iu,/\bthay\b/iu,/\bchuyển\b/iu,/\blưu\b/iu,/\bmap\b/iu,/\buse\b/iu,/\bsplit\b/iu,/\bstore\b/iu,/\breplace\b/iu,/\bmove\b/iu],pr=[/đường dẫn/iu,/\bpath\b/iu,/\bport\b/iu,/\bendpoint\b/iu,/\bdomain\b/iu,/\bbucket\b/iu,/\brepository\b/iu,/\brepo\b/iu,/\bbranch\b/iu,/\/[A-Za-z0-9._/-]{4,}/u],fr=[/\blà\b/iu,/\bở\b/iu,/\bdùng\b/iu,/\bnằm\b/iu,/\bis\b/iu,/\buse\b/iu,/located/iu,/runs on/iu],ct=new Set(["content","text","message","prompt","summary","description","reason","title","last_assistant_message","lastAssistantMessage","input_messages","inputMessages"]),mr=new Set(["payload","data","content","message","messages","parts","summary"]);function I(t,e){return e.some(n=>n.test(t))}function dt(t){return t.normalize("NFKC").replace(/\r/g,"").replace(/^[\s>*#\-•]+/u,"").replace(/\s+/g," ").trim()}function gr(t){return dt(t).toLowerCase().replace(/[^\p{L}\p{N}:/._-]+/gu," ").replace(/\s+/g," ").trim()}function hr(t){return!(t.length<12||t.length>1e3||(t.match(new RegExp("\\p{L}","gu"))??[]).length<6||/^(?:https?:\/\/\S+|[A-Za-z0-9+/=]{80,})$/u.test(t))}function Te(t,e,n,r=0){if(!(r>6)){if(typeof t=="string"){(!e||ct.has(e))&&n.push(t);return}if(Array.isArray(t)){for(let s of t.slice(0,50))Te(s,e,n,r+1);return}if(!(!t||typeof t!="object"))for(let[s,o]of Object.entries(t))(ct.has(s)||mr.has(s))&&Te(o,s,n,r+1)}}function yr(t){let e=[];Te(t.data,void 0,e);let n=[],r=new Set;for(let s of e)for(let o of s.split(/\n+|(?<=[.!?])\s+/u)){let i=dt(o);if(hr(i)&&!r.has(i)&&(r.add(i),n.push(i),n.length>=50))return n}return n}function ut(t){return(t.role??(typeof t.data.role=="string"?t.data.role:"")).toLowerCase()}function Sr(t,e,n){if(n.type==="decision")return{kind:"decision",confidence:1};if(n.type==="todo")return{kind:"todo",confidence:1};let r=e==="user"||n.type==="user_prompt",s=e==="assistant"||n.type==="assistant_message";return r&&I(t,lt)?{kind:"rule",confidence:.98}:r&&I(t,ar)?{kind:"rule",confidence:.92}:I(t,cr)?{kind:I(t,at)?"architecture":"decision",confidence:r?.93:.86}:r&&I(t,ur)?{kind:"todo",confidence:.87}:I(t,at)&&I(t,dr)?{kind:"architecture",confidence:r?.88:.82}:s&&I(t,lr)?{kind:"fix",confidence:.8}:r&&I(t,pr)&&I(t,fr)?{kind:"context",confidence:.79}:null}function vr(t){switch(t){case"rule":return"rule";case"decision":case"architecture":return"decision";case"todo":return"todo";case"fix":case"context":return"code"}}function br(t,e,n){return t==="rule"&&I(n,lt)?"critical":t==="architecture"||t==="decision"||t==="rule"?"high":t==="fix"||t==="context"?"normal":it(e,n)}function pt(t,e){let n=[],r=new Set,s=new Map;for(let o of e){let i=typeof o.data.messageId=="string"?o.data.messageId:void 0,l=ut(o);i&&l&&s.set(i,l)}for(let o of e){let i=ut(o),l=typeof o.data.messageId=="string"?o.data.messageId:void 0;!i&&l&&(i=s.get(l)??"");for(let c of yr(o)){let a=Sr(c,i,o);if(!a||a.confidence<.75)continue;let p=vr(a.kind),u=gr(c),m=v([t.projectId,a.kind,u].join("|"));if(r.has(m))continue;r.add(m);let d=o.provenance.sourcePath?[o.provenance.sourcePath]:[],S=o.sourceEventId?[o.sourceEventId]:[];n.push({version:1,fingerprint:m,projectId:t.projectId,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,kind:a.kind,type:p,content:c,confidence:a.confidence,importance:br(a.kind,p,c),tags:[p],provenance:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventIds:[o.id],sourceEventIds:S,sourcePaths:d,firstSequence:o.sequence,lastSequence:o.sequence},createdAt:o.timestamp})}}return n}function ft(t){return String(t).padStart(12,"0")}function kr(t){return t.remotePrefix.replace("/sessions/","/memory/learned/")}var re=class{constructor(e){this.storage=e}storage;async write(e,n,r){if(r.length===0||n.length===0)return null;let s=Math.min(...n.map(p=>p.sequence)),o=Math.max(...n.map(p=>p.sequence)),i={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:s,lastSequence:o,candidateCount:r.length,candidates:r},l=JSON.stringify(i,null,2)+`
13
+ `,c=v(r.map(p=>p.fingerprint).sort().join("|")).slice(0,16),a=[kr(e),"batches",`${ft(s)}-${ft(o)}-${c}.json`].join("/");return await this.storage.exists(a)||await this.storage.put(a,l,"application/json"),a}};function Or(t,e){if(!jr(t))return{events:[],nextOffset:e};let n=Ir(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=xr(t,"r");try{Er(i,o,0,s,r)}finally{wr(i)}let l=o.toString("utf8"),c=l.lastIndexOf(`
14
14
  `);if(c<0)return{events:[],nextOffset:r};let a=l.slice(0,c+1);return{events:a.split(`
15
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var se=class{constructor(e){this.options=e;this.journal=new re(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Or(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=pt(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as Nr,existsSync as _r,openSync as $r,readSync as Lr,statSync as Dr}from"node:fs";var Pr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function D(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function gt(t){return D(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))L(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Pr.has(r)||["data","payload","parts","messages"].includes(r))&&L(s,e,n+1)}}function oe(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function mt(t){let e=D(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function j(t,e,n,r,s={}){let o=D(r),i=s.key??gt(o);return{version:1,id:v([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function Tr(t,e,n){let r=D(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(j(t,e,"goal",i[1],{confidence:.97}));let l=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);l?.[1]&&s.push(j(t,e,"plan",l[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=c.exec(r));){let m=Number(a[1]),d=D(a[2]??""),S=d&&!mt(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(j(t,e,"phase",S,{key:`phase:${m}`,order:m,status:oe(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(j(t,e,"task",p[2],{status:p[1].trim()?"completed":oe(p[2]),confidence:.96}));let u=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(u?.[2]){let m=u[1]?Number(u[1]):void 0,d=D(u[2]),S=mt(d);s.push(j(t,e,"task",S&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:gt(d),order:m,status:oe(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let m=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");m&&s.push(j(t,e,"next_action",m,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(j(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(j(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(j(t,e,"decision",r,{confidence:.9})),s}function yt(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"task",a,{status:oe(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let a=i.data[c];typeof a=="string"&&a&&s(j(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"test",a,{confidence:1}))}let l=[];L(i.data,l);for(let c of l)for(let a of c.split(/\n+/u))for(let p of Tr(t,i,a))s(p)}let o=e[e.length-1];return s(j(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function ht(t){return String(t).padStart(12,"0")}var ie=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
- `,l=v(n.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${ht(r)}-${ht(s)}-${l}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as St}from"node:path";import{mkdirSync as Cr}from"node:fs";function Rr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Rr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Mr(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function vt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Mr(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function Ar(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}async function ae(t,e){let r=(await Ar(t,e)).flatMap(f=>f.observations).sort((f,x)=>{let Fe=f.occurredAt.localeCompare(x.occurredAt);if(Fe!==0)return Fe;let Ke=f.sequence-x.sequence;return Ke!==0?Ke:f.id.localeCompare(x.id)}),s=new Map,o=new Map,i,l,c,a=[],p=[],u=[],m=[],d=[],S=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":l=f.text;break;case"phase":s.set(f.key,vt(s.get(f.key),f));break;case"task":o.set(f.key,vt(o.get(f.key),f));break;case"decision":a.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":u.push(f.text);break;case"next_action":m.push(f.text);break;case"file":d.push(f.text);break;case"test":S.push(f.text);break;case"session":c={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let h=Array.from(s.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),y=h.find(f=>f.status==="in_progress")??h.find(f=>f.status==="blocked")??h.find(f=>f.status==="pending"),w=g.find(f=>f.status==="in_progress")??g.find(f=>f.status==="blocked")??g.find(f=>f.status==="pending"),T=F([...m,...w?[w.title]:[],...!w&&y?[y.title]:[],...g.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),$=F([...p,...h.filter(f=>f.status==="blocked").map(f=>f.title),...g.filter(f=>f.status==="blocked").map(f=>f.title)],20),C={version:1,projectId:t.id,projectName:t.name,goal:i,plan:l,phases:h,tasks:g,decisions:F(a,20),blockers:$,warnings:F(u,20),nextActions:T,filesTouched:F(d,30),tests:F(S,20),currentPhase:y,currentTask:w,progress:{phasesTotal:h.length,phasesCompleted:h.filter(f=>f.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(f=>f.status==="completed").length,blocked:h.filter(f=>f.status==="blocked").length+g.filter(f=>f.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},A=St(t.rootPath,".toolnet","work");return Cr(A,{recursive:!0}),I(St(A,"current.json"),C),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(C,null,2)+`
15
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var se=class{constructor(e){this.options=e;this.journal=new re(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["memory.learner.offset"]??0),r=Number.isFinite(n)?n:0,s=Or(this.options.wal.eventsFile,r);if(s.events.length===0)return{scannedEvents:0,candidates:0,journalWritten:!1,nextOffset:s.nextOffset};let o=pt(this.options.identity,s.events),i=!1;return o.length>0&&(i=!!await this.journal.write(this.options.identity,s.events,o)),this.options.wal.setSourceCursor("memory.learner.offset",s.nextOffset),{scannedEvents:s.events.length,candidates:o.length,journalWritten:i,nextOffset:s.nextOffset}}};import{closeSync as Nr,existsSync as _r,openSync as $r,readSync as Lr,statSync as Dr}from"node:fs";var Pr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function D(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function gt(t){return D(t).toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function L(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))L(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Pr.has(r)||["data","payload","parts","messages"].includes(r))&&L(s,e,n+1)}}function oe(t){return/\b(cancelled|canceled)\b|đã hủy|bỏ qua/iu.test(t)?"cancelled":/\b(blocked|blocker)\b|đang vướng|bị vướng|đang kẹt|chưa thể/iu.test(t)?"blocked":/\b(completed|complete|done|finished|passed)\b|hoàn thành|hoàn tất|đã xong|đã làm xong|\bxong\b/iu.test(t)?"completed":/\bin[\s_-]*progress\b|working on|đang làm|đang thực hiện|đang xử lý|đang triển khai/iu.test(t)?"in_progress":"pending"}function mt(t){let e=D(t);return/^(?:đang\s+làm|đang\s+thực\s+hiện|đang\s+xử\s+lý|đang\s+triển\s+khai|hoàn\s+thành|hoàn\s+tất|đã\s+xong|đã\s+làm\s+xong|xong|pending|in[\s_-]*progress|completed|complete|done|finished|blocked|cancelled|canceled)[.!]*$/iu.test(e)}function j(t,e,n,r,s={}){let o=D(r),i=s.key??gt(o);return{version:1,id:v([t.projectId,n,i,e.id,o,s.status??"",s.order??""].join("|")).slice(0,32),projectId:t.projectId,kind:n,key:i,text:o,status:s.status,order:s.order,confidence:s.confidence??.85,occurredAt:e.timestamp,sequence:e.sequence,agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId}}function Tr(t,e,n){let r=D(n);if(r.length<5||r.length>1200)return[];let s=[],o=/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r),i=r.match(/^(?:mục tiêu|goal|objective)\s*(?::|-)\s*(.+)$/iu);i?.[1]&&s.push(j(t,e,"goal",i[1],{confidence:.97}));let l=r.match(/^(?:kế hoạch|plan)\s*(?::|-)\s*(.+)$/iu);l?.[1]&&s.push(j(t,e,"plan",l[1],{confidence:.95}));let c=/\b(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?([^.;\n]{0,220})/giu,a;for(;!o&&(a=c.exec(r));){let m=Number(a[1]),d=D(a[2]??""),S=d&&!mt(d)?`Phase ${m} - ${d}`:`Phase ${m}`;s.push(j(t,e,"phase",S,{key:`phase:${m}`,order:m,status:oe(r),confidence:.93}))}let p=n.match(/^\s*[-*]\s*\[([ xX])\]\s*(.+)$/u);p?.[2]&&s.push(j(t,e,"task",p[2],{status:p[1].trim()?"completed":oe(p[2]),confidence:.96}));let u=r.match(/^(?:todo|task|việc)\s*(\d+)?(?:\s*[:.\-–—]\s*|\s+)(.+)$/iu);if(u?.[2]){let m=u[1]?Number(u[1]):void 0,d=D(u[2]),S=mt(d);s.push(j(t,e,"task",S&&m!==void 0?`TODO ${m}`:d,{key:m!==void 0?`task:${m}`:gt(d),order:m,status:oe(r),confidence:.93}))}if(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\b/iu.test(r)){let m=r.replace(/^(?:next|next action|next step|tiếp theo|bước tiếp theo|cần làm tiếp)\s*(?::|-)?\s*/iu,"");m&&s.push(j(t,e,"next_action",m,{confidence:.9}))}return/\b(blocker|blocked)\b|đang vướng|bị vướng|đang kẹt/iu.test(r)&&s.push(j(t,e,"blocker",r,{confidence:.9})),/\b(chú ý|lưu ý|warning|attention|cẩn thận)\b/iu.test(r)&&s.push(j(t,e,"warning",r,{confidence:.88})),/\b(chốt|quyết định|decided|decision)\b/iu.test(r)&&s.push(j(t,e,"decision",r,{confidence:.9})),s}function ht(t,e){if(e.length===0)return[];let n=[],r=new Set;function s(i){r.has(i.id)||(r.add(i.id),n.push(i))}for(let i of e){if(i.type==="decision"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"decision",a,{confidence:1}))}if(i.type==="todo"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"task",a,{status:oe(a),confidence:1}))}if(["file_write","file_edit"].includes(i.type))for(let c of["filePath","path","file"]){let a=i.data[c];typeof a=="string"&&a&&s(j(t,i,"file",a,{confidence:1}))}if(i.type==="test"){let c=[];L(i.data,c);for(let a of c)s(j(t,i,"test",a,{confidence:1}))}let l=[];L(i.data,l);for(let c of l)for(let a of c.split(/\n+/u))for(let p of Tr(t,i,a))s(p)}let o=e[e.length-1];return s(j(t,o,"session",`${t.agent}:${t.nativeSessionId}`,{key:t.sessionKey,confidence:1})),n}function yt(t){return String(t).padStart(12,"0")}var ie=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(a=>a.sequence)),s=Math.max(...n.map(a=>a.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,createdAt:new Date().toISOString(),firstSequence:r,lastSequence:s,observations:n},i=JSON.stringify(o,null,2)+`
16
+ `,l=v(n.map(a=>a.id).sort().join("|")).slice(0,16),c=[`projects/${e.projectId}`,"work","observations",e.agent,e.nativeSessionId,`${yt(r)}-${yt(s)}-${l}.json`].join("/");return await this.storage.exists(c)||await this.storage.put(c,i,"application/json"),c}};import{join as St}from"node:path";import{mkdirSync as Cr}from"node:fs";function Rr(t){return t.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}]+/gu," ").replace(/\s+/g," ").trim()}function F(t,e=20){let n=[],r=new Set;for(let s of t.slice().reverse()){let o=Rr(s);if(!(!o||r.has(o))&&(r.add(o),n.push(s),n.length>=e))break}return n.reverse()}function Mr(t){return t.kind==="phase"?/^Phase\s+\d+$/iu.test(t.text):t.kind==="task"?/^(?:TODO|Task|Việc)\s+\d+$/iu.test(t.text):!1}function vt(t,e){let n=e.status??t?.status??"pending",r=n;t&&(t.status==="completed"&&n!=="completed"?r="completed":n==="pending"&&(t.status==="in_progress"||t.status==="blocked")&&(r=t.status));let s=t&&Mr(e)?t.title:e.text;return{id:t?.id??v(e.key).slice(0,24),title:s,status:r,order:e.order??t?.order,confidence:Math.max(e.confidence,t?.confidence??0),updatedAt:e.occurredAt,updatedBy:{agent:e.agent,nativeSessionId:e.nativeSessionId,eventId:e.eventId}}}async function Ar(t,e){let n=`projects/${t.id}/work/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}async function ae(t,e){let r=(await Ar(t,e)).flatMap(f=>f.observations).sort((f,x)=>{let Fe=f.occurredAt.localeCompare(x.occurredAt);if(Fe!==0)return Fe;let Ke=f.sequence-x.sequence;return Ke!==0?Ke:f.id.localeCompare(x.id)}),s=new Map,o=new Map,i,l,c,a=[],p=[],u=[],m=[],d=[],S=[];for(let f of r)switch(f.kind){case"goal":i=f.text;break;case"plan":l=f.text;break;case"phase":s.set(f.key,vt(s.get(f.key),f));break;case"task":o.set(f.key,vt(o.get(f.key),f));break;case"decision":a.push(f.text);break;case"blocker":p.push(f.text);break;case"warning":u.push(f.text);break;case"next_action":m.push(f.text);break;case"file":d.push(f.text);break;case"test":S.push(f.text);break;case"session":c={agent:f.agent,nativeSessionId:f.nativeSessionId,sessionKey:f.sessionKey,updatedAt:f.occurredAt};break}let y=Array.from(s.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),g=Array.from(o.values()).sort((f,x)=>(f.order??Number.MAX_SAFE_INTEGER)-(x.order??Number.MAX_SAFE_INTEGER)),h=y.find(f=>f.status==="in_progress")??y.find(f=>f.status==="blocked")??y.find(f=>f.status==="pending"),w=g.find(f=>f.status==="in_progress")??g.find(f=>f.status==="blocked")??g.find(f=>f.status==="pending"),T=F([...m,...w?[w.title]:[],...!w&&h?[h.title]:[],...g.filter(f=>f.status==="pending").slice(0,5).map(f=>f.title)],8),$=F([...p,...y.filter(f=>f.status==="blocked").map(f=>f.title),...g.filter(f=>f.status==="blocked").map(f=>f.title)],20),C={version:1,projectId:t.id,projectName:t.name,goal:i,plan:l,phases:y,tasks:g,decisions:F(a,20),blockers:$,warnings:F(u,20),nextActions:T,filesTouched:F(d,30),tests:F(S,20),currentPhase:h,currentTask:w,progress:{phasesTotal:y.length,phasesCompleted:y.filter(f=>f.status==="completed").length,tasksTotal:g.length,tasksCompleted:g.filter(f=>f.status==="completed").length,blocked:y.filter(f=>f.status==="blocked").length+g.filter(f=>f.status==="blocked").length},lastSession:c,updatedAt:r.length?r[r.length-1].occurredAt:new Date().toISOString()},A=St(t.rootPath,".toolnet","work");return Cr(A,{recursive:!0}),E(St(A,"current.json"),C),await e.put(`projects/${t.id}/work/current.json`,JSON.stringify(C,null,2)+`
17
17
  `,"application/json"),C}async function ce(t,e){let n=await e.getText(`projects/${t.id}/work/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Fr(t,e){if(!_r(t))return{events:[],nextOffset:e};let n=Dr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=n-r,o=Buffer.alloc(s),i=$r(t,"r");try{Lr(i,o,0,s,r)}finally{Nr(i)}let l=o.toString("utf8"),c=l.lastIndexOf(`
18
18
  `);if(c<0)return{events:[],nextOffset:r};let a=l.slice(0,c+1);return{events:a.split(`
19
- `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ue=class{constructor(e){this.options=e;this.journal=new ie(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Fr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=yt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ae(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Hr,existsSync as Yr,openSync as Gr,readSync as Xr,statSync as Qr}from"node:fs";var Kr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function K(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ce(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Ce(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Kr.has(r)||["data","payload","parts","messages"].includes(r))&&Ce(s,e,n+1)}}function O(t,e,n,r,s,o=.95){let i=K(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return K(t.slice(r.length+1))}return null}function Br(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Wr(t){return K(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function bt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Ce(o.data,i);for(let l of i){let c={type:"project"},a=null;for(let p of l.split(/\r?\n/u)){let u=K(p);if(!u){a=null;continue}let m=u.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let x=Number(m[1]);c={type:"phase",key:`phase:${x}`,order:x,title:K(m[2]??"")},a=null;continue}let d=u.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let x=Number(d[1]);c={type:"task",key:`task:${x}`,order:x,title:K(d[2]??"")},a=null;continue}let S=P(u,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(O(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let h=P(u,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(h){s(O(t,o,c.type==="phase"?"phase_objective":"objective",h,c,.98)),a=null;continue}let g=P(u,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(O(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let y=P(u,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(y){s(O(t,o,"desired_outcome",y,{type:"project"},.98)),a=null;continue}let w=P(u,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(w){s(O(t,o,"plan_rationale",w,{type:"project"},.98)),a=null;continue}let T=P(u,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(O(t,o,"phase_deliverable",T,c,.97)),a=null;continue}let $=P(u,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if($){s(O(t,o,"acceptance_criterion",$,c,.98)),a="acceptance_criterion";continue}let C=P(u,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(O(t,o,"dependency",C,c,.97)),a="dependency";continue}let A=P(u,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(A){s(O(t,o,"open_question",A,c,.95)),a="open_question";continue}let f=P(u,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(O(t,o,"constraint",f,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(u)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(u)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(u)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(u)){a="constraint";continue}if(a&&Br(p)){s(O(t,o,a,Wr(p),c,.96));continue}a=null}}}return n}function kt(t){return String(t).padStart(12,"0")}var le=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(c=>c.id).sort().join("|")).slice(0,16),l=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${kt(r)}-${kt(s)}-${i}.json`].join("/");return await this.storage.exists(l)||await this.storage.put(l,JSON.stringify(o,null,2)+`
20
- `,"application/json"),l}};import{mkdirSync as zr}from"node:fs";import{join as wt}from"node:path";function qr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Jr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function R(t,e){return Jr(e,t)?e:t}function M(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Vr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}function Ur(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function jt(t,e){let r=(await Vr(t,e)).flatMap(h=>h.observations).sort((h,g)=>{let y=h.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return y!==0?y:h.evidence.sessionKey===g.evidence.sessionKey?h.evidence.sequence-g.evidence.sequence:h.id.localeCompare(g.id)}),s,o,i,l,c,a=new Map,p=[],u=[],m=[];for(let h of r){let g=qr(h);if(h.scope==="phase"&&h.scopeKey){let y=a.get(h.scopeKey)??Ur(h);switch(h.kind){case"phase_objective":y.objective=R(y.objective,g);break;case"phase_why":y.why=R(y.why,g);break;case"phase_deliverable":y.deliverable=R(y.deliverable,g);break;case"acceptance_criterion":y.acceptanceCriteria.push(g);break;case"dependency":y.dependencies.push(g);break;case"open_question":y.openQuestions.push(g);break;case"constraint":y.constraints.push(g);break;case"note":y.notes.push(g);break}a.set(y.key,y);continue}switch(h.kind){case"mission":s=R(s,g);break;case"objective":o=R(o,g);break;case"why":i=R(i,g);break;case"desired_outcome":l=R(l,g);break;case"plan_rationale":c=R(c,g);break;case"open_question":p.push(g);break;case"constraint":u.push(g);break;case"note":m.push(g);break}}for(let h of a.values())h.acceptanceCriteria=M(h.acceptanceCriteria,20),h.dependencies=M(h.dependencies,15),h.openQuestions=M(h.openQuestions,15),h.constraints=M(h.constraints,15),h.notes=M(h.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:l,planRationale:c,phases:Array.from(a.values()).sort((h,g)=>h.order-g.order),openQuestions:M(p,20),constraints:M(u,20),notes:M(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=wt(t.rootPath,".toolnet","work");return zr(S,{recursive:!0}),I(wt(S,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
19
+ `).filter(Boolean).flatMap(u=>{try{return[JSON.parse(u)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(a,"utf8")}}var ue=class{constructor(e){this.options=e;this.journal=new ie(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.continuity.offset"]??0),r=Fr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=ht(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await ae(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.continuity.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{closeSync as Hr,existsSync as Yr,openSync as Gr,readSync as Xr,statSync as Qr}from"node:fs";var Kr=new Set(["content","text","message","prompt","summary","description","title","reason","last_assistant_message","lastAssistantMessage"]);function K(t){return t.normalize("NFKC").replace(/\s+/g," ").replace(/^[\s>*#•-]+/u,"").trim()}function Ce(t,e,n=0){if(!(n>6)){if(typeof t=="string"){e.push(t);return}if(Array.isArray(t)){for(let r of t.slice(0,50))Ce(r,e,n+1);return}if(!(!t||typeof t!="object"))for(let[r,s]of Object.entries(t))(Kr.has(r)||["data","payload","parts","messages"].includes(r))&&Ce(s,e,n+1)}}function O(t,e,n,r,s,o=.95){let i=K(r);return{version:1,id:v([t.projectId,n,s.type,s.key??"",i.toLowerCase(),e.id].join("|")).slice(0,32),projectId:t.projectId,kind:n,value:i,scope:s.type,scopeKey:s.key,scopeOrder:s.order,confidence:o,evidence:{agent:t.agent,nativeSessionId:t.nativeSessionId,sessionKey:t.sessionKey,eventId:e.id,sourceEventId:e.sourceEventId,sequence:e.sequence,occurredAt:e.timestamp}}}function P(t,e){let n=t.toLowerCase();for(let r of e){let s=r.toLowerCase();if(n.startsWith(`${s}:`)||n.startsWith(`${s} -`)||n.startsWith(`${s} \u2014`))return K(t.slice(r.length+1))}return null}function Br(t){let e=t.trimStart();return e.startsWith("- ")||e.startsWith("* ")||/^\d+[.)]\s+/u.test(e)}function Wr(t){return K(t.trim().replace(/^[-*]\s+/u,"").replace(/^\d+[.)]\s+/u,""))}function bt(t,e){let n=[],r=new Set;function s(o){!o.value||o.value.length<3||r.has(o.id)||(r.add(o.id),n.push(o))}for(let o of e){let i=[];Ce(o.data,i);for(let l of i){let c={type:"project"},a=null;for(let p of l.split(/\r?\n/u)){let u=K(p);if(!u){a=null;continue}let m=u.match(/^(?:phase|giai đoạn|giai doan|stage)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(m){let x=Number(m[1]);c={type:"phase",key:`phase:${x}`,order:x,title:K(m[2]??"")},a=null;continue}let d=u.match(/^(?:todo|task|việc)\s*(\d+)\s*(?:[:\-–—]\s*)?(.*)$/iu);if(d){let x=Number(d[1]);c={type:"task",key:`task:${x}`,order:x,title:K(d[2]??"")},a=null;continue}let S=P(u,["mission","s\u1EE9 m\u1EC7nh","m\u1EE5c ti\xEAu t\u1ED5ng th\u1EC3","m\u1EE5c ti\xEAu project","project goal"]);if(S){s(O(t,o,"mission",S,{type:"project"},.99)),a=null;continue}let y=P(u,["current objective","active objective","m\u1EE5c ti\xEAu hi\u1EC7n t\u1EA1i","objective","m\u1EE5c ti\xEAu","m\u1EE5c \u0111\xEDch"]);if(y){s(O(t,o,c.type==="phase"?"phase_objective":"objective",y,c,.98)),a=null;continue}let g=P(u,["why","why this","why this phase","reason","rationale","v\xEC sao","l\xFD do","t\u1EA1i sao","\xFD ngh\u0129a"]);if(g){s(O(t,o,c.type==="phase"?"phase_why":"why",g,c,.98)),a=null;continue}let h=P(u,["desired outcome","final outcome","k\u1EBFt qu\u1EA3 cu\u1ED1i","k\u1EBFt qu\u1EA3 mong mu\u1ED1n","m\u1EE5c ti\xEAu cu\u1ED1i"]);if(h){s(O(t,o,"desired_outcome",h,{type:"project"},.98)),a=null;continue}let w=P(u,["plan rationale","approach rationale","why this approach","t\u1EA1i sao ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn h\u01B0\u1EDBng n\xE0y","l\xFD do ch\u1ECDn ki\u1EBFn tr\xFAc"]);if(w){s(O(t,o,"plan_rationale",w,{type:"project"},.98)),a=null;continue}let T=P(u,["deliverable","output","k\u1EBFt qu\u1EA3 c\u1EA7n \u0111\u1EA1t","ph\u1EA3i t\u1EA1o ra","\u0111\u1EA7u ra"]);if(T){s(O(t,o,"phase_deliverable",T,c,.97)),a=null;continue}let $=P(u,["acceptance criteria","definition of done","done khi","ho\xE0n th\xE0nh khi","ti\xEAu ch\xED ho\xE0n th\xE0nh"]);if($){s(O(t,o,"acceptance_criterion",$,c,.98)),a="acceptance_criterion";continue}let C=P(u,["depends on","dependency","dependencies","ph\u1EE5 thu\u1ED9c","c\u1EA7n c\xF3 tr\u01B0\u1EDBc"]);if(C){s(O(t,o,"dependency",C,c,.97)),a="dependency";continue}let A=P(u,["open question","open questions","c\xE2u h\u1ECFi m\u1EDF","ch\u01B0a quy\u1EBFt \u0111\u1ECBnh","ch\u01B0a r\xF5"]);if(A){s(O(t,o,"open_question",A,c,.95)),a="open_question";continue}let f=P(u,["constraint","constraints","r\xE0ng bu\u1ED9c","gi\u1EDBi h\u1EA1n"]);if(f){s(O(t,o,"constraint",f,c,.97)),a="constraint";continue}if(/^(?:acceptance criteria|definition of done|done khi|tiêu chí hoàn thành)\s*:?\s*$/iu.test(u)){a="acceptance_criterion";continue}if(/^(?:dependencies|dependency|phụ thuộc)\s*:?\s*$/iu.test(u)){a="dependency";continue}if(/^(?:open questions|open question|câu hỏi mở)\s*:?\s*$/iu.test(u)){a="open_question";continue}if(/^(?:constraints|constraint|ràng buộc)\s*:?\s*$/iu.test(u)){a="constraint";continue}if(a&&Br(p)){s(O(t,o,a,Wr(p),c,.96));continue}a=null}}}return n}function kt(t){return String(t).padStart(12,"0")}var le=class{constructor(e){this.storage=e}storage;async write(e,n){if(n.length===0)return null;let r=Math.min(...n.map(c=>c.evidence.sequence)),s=Math.max(...n.map(c=>c.evidence.sequence)),o={version:1,projectId:e.projectId,agent:e.agent,nativeSessionId:e.nativeSessionId,sessionKey:e.sessionKey,firstSequence:r,lastSequence:s,createdAt:new Date().toISOString(),observations:n},i=v(n.map(c=>c.id).sort().join("|")).slice(0,16),l=[`projects/${e.projectId}`,"work","semantic","observations",e.agent,e.nativeSessionId,`${kt(r)}-${kt(s)}-${i}.json`].join("/");return await this.storage.exists(l)||await this.storage.put(l,JSON.stringify(o,null,2)+`
20
+ `,"application/json"),l}};import{mkdirSync as zr}from"node:fs";import{join as wt}from"node:path";function qr(t){return{value:t.value,confidence:t.confidence,evidence:t.evidence}}function Jr(t,e){if(!e)return!0;let n=t.evidence.occurredAt.localeCompare(e.evidence.occurredAt);return n!==0?n>0:t.evidence.sessionKey===e.evidence.sessionKey?t.evidence.sequence>=e.evidence.sequence:t.confidence>=e.confidence}function R(t,e){return Jr(e,t)?e:t}function M(t,e=30){let n=new Set,r=[];for(let s of t){let o=s.value.normalize("NFKC").toLowerCase().replace(/\s+/g," ").trim();!o||n.has(o)||(n.add(o),r.push(s))}return r.slice(-e)}async function Vr(t,e){let n=`projects/${t.id}/work/semantic/observations/`,r=await e.list(n),s=[];for(let o of r.filter(i=>i.key.endsWith(".json")).sort((i,l)=>i.key.localeCompare(l.key))){let i=await e.getText(o.key);if(i)try{let l=JSON.parse(i);l.version===1&&Array.isArray(l.observations)&&s.push(l)}catch{}}return s}function Ur(t){return{key:t.scopeKey??`phase:${t.scopeOrder??0}`,order:t.scopeOrder??0,acceptanceCriteria:[],dependencies:[],openQuestions:[],constraints:[],notes:[]}}async function jt(t,e){let r=(await Vr(t,e)).flatMap(y=>y.observations).sort((y,g)=>{let h=y.evidence.occurredAt.localeCompare(g.evidence.occurredAt);return h!==0?h:y.evidence.sessionKey===g.evidence.sessionKey?y.evidence.sequence-g.evidence.sequence:y.id.localeCompare(g.id)}),s,o,i,l,c,a=new Map,p=[],u=[],m=[];for(let y of r){let g=qr(y);if(y.scope==="phase"&&y.scopeKey){let h=a.get(y.scopeKey)??Ur(y);switch(y.kind){case"phase_objective":h.objective=R(h.objective,g);break;case"phase_why":h.why=R(h.why,g);break;case"phase_deliverable":h.deliverable=R(h.deliverable,g);break;case"acceptance_criterion":h.acceptanceCriteria.push(g);break;case"dependency":h.dependencies.push(g);break;case"open_question":h.openQuestions.push(g);break;case"constraint":h.constraints.push(g);break;case"note":h.notes.push(g);break}a.set(h.key,h);continue}switch(y.kind){case"mission":s=R(s,g);break;case"objective":o=R(o,g);break;case"why":i=R(i,g);break;case"desired_outcome":l=R(l,g);break;case"plan_rationale":c=R(c,g);break;case"open_question":p.push(g);break;case"constraint":u.push(g);break;case"note":m.push(g);break}}for(let y of a.values())y.acceptanceCriteria=M(y.acceptanceCriteria,20),y.dependencies=M(y.dependencies,15),y.openQuestions=M(y.openQuestions,15),y.constraints=M(y.constraints,15),y.notes=M(y.notes,20);let d={version:1,projectId:t.id,projectName:t.name,mission:s,activeObjective:o,why:i,desiredOutcome:l,planRationale:c,phases:Array.from(a.values()).sort((y,g)=>y.order-g.order),openQuestions:M(p,20),constraints:M(u,20),notes:M(m,20),updatedAt:r.length?r[r.length-1].evidence.occurredAt:new Date().toISOString()},S=wt(t.rootPath,".toolnet","work");return zr(S,{recursive:!0}),E(wt(S,"semantic-current.json"),d),await e.put(`projects/${t.id}/work/semantic/current.json`,JSON.stringify(d,null,2)+`
21
21
  `,"application/json"),d}async function xt(t,e){let n=await e.getText(`projects/${t.id}/work/semantic/current.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Zr(t,e){if(!Yr(t))return{events:[],nextOffset:e};let n=Qr(t).size,r=Number.isFinite(e)?Math.max(0,e):0;if(r>n&&(r=0),r===n)return{events:[],nextOffset:n};let s=Buffer.alloc(n-r),o=Gr(t,"r");try{Xr(o,s,0,s.length,r)}finally{Hr(o)}let i=s.toString("utf8"),l=i.lastIndexOf(`
22
22
  `);if(l<0)return{events:[],nextOffset:r};let c=i.slice(0,l+1);return{events:c.split(`
23
- `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var de=class{constructor(e){this.options=e;this.journal=new le(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Zr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=bt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await jt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as us}from"node:fs";import{join as Re}from"node:path";import{existsSync as Ot,mkdirSync as es,readFileSync as ts,statSync as It,writeFileSync as ns}from"node:fs";import{dirname as rs,join as ss}from"node:path";var Et=64*1024,os=`# ToolNet Project Operating Manual
23
+ `).filter(Boolean).flatMap(a=>{try{return[JSON.parse(a)]}catch{return[]}}),nextOffset:r+Buffer.byteLength(c,"utf8")}}var de=class{constructor(e){this.options=e;this.journal=new le(e.storage)}options;journal;async learnNew(){let e=this.options.wal.loadState(),n=Number(e.sourceCursors["work.semantic.offset"]??0),r=Zr(this.options.wal.eventsFile,Number.isFinite(n)?n:0);if(r.events.length===0)return{scannedEvents:0,observations:0,journalWritten:!1,reconciled:!1,nextOffset:r.nextOffset};let s=bt(this.options.identity,r.events),o=!1,i=!1;return s.length>0&&(o=!!await this.journal.write(this.options.identity,s),o&&(await jt(this.options.project,this.options.storage),i=!0)),this.options.wal.setSourceCursor("work.semantic.offset",r.nextOffset),{scannedEvents:r.events.length,observations:s.length,journalWritten:o,reconciled:i,nextOffset:r.nextOffset}}};import{mkdirSync as us}from"node:fs";import{join as Re}from"node:path";import{existsSync as Ot,mkdirSync as es,readFileSync as ts,statSync as Et,writeFileSync as ns}from"node:fs";import{dirname as rs,join as ss}from"node:path";var It=64*1024,os=`# ToolNet Project Operating Manual
24
24
 
25
25
  This file contains persistent instructions for AI agents working on this project.
26
26
 
@@ -63,9 +63,9 @@ Things an AI agent should always remember.
63
63
  <!--
64
64
  - [advisory] Prefer small focused files.
65
65
  -->
66
- `;function pe(t){return ss(t.rootPath,".toolnet","PROJECT.md")}function is(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function as(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=is(s[2]);if(!i)continue;let l=`${o}:${i.toLowerCase()}`;n.has(l)||(n.add(l),e.push({id:v(l).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function cs(t){let e=pe(t);return Ot(e)||(es(rs(e),{recursive:!0}),ns(e,os,{encoding:"utf8",mode:384})),e}function fe(t,e=!1){let n=e?cs(t):pe(t);if(!Ot(n))return null;if(It(n).size>Et)throw new Error(`PROJECT.md exceeds ${Et} bytes`);let s=ts(n,"utf8");return{path:n,content:s,digest:v(s),rules:as(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(It(n).mtimeMs).toISOString()}}function ls(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function ds(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var me=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ce(this.options.project,this.options.storage);if(r||(r=await ae(this.options.project,this.options.storage)),!ds(r))return null;let s=fe(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=v(JSON.stringify(ls(r))),l=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),c=new Date().toISOString(),a={version:1,id:l,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:c,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},p=`projects/${this.options.project.id}/work/handoffs/${l}.json`;await this.options.storage.exists(p)||await this.options.storage.put(p,JSON.stringify(a,null,2)+`
66
+ `;function pe(t){return ss(t.rootPath,".toolnet","PROJECT.md")}function is(t){return t.normalize("NFKC").replace(/\s+/g," ").trim()}function as(t){let e=[],n=new Set,r=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=r.exec(t);){let o=s[1].toLowerCase(),i=is(s[2]);if(!i)continue;let l=`${o}:${i.toLowerCase()}`;n.has(l)||(n.add(l),e.push({id:v(l).slice(0,24),mode:o,text:i,source:"manual"}))}return e}function cs(t){let e=pe(t);return Ot(e)||(es(rs(e),{recursive:!0}),ns(e,os,{encoding:"utf8",mode:384})),e}function fe(t,e=!1){let n=e?cs(t):pe(t);if(!Ot(n))return null;if(Et(n).size>It)throw new Error(`PROJECT.md exceeds ${It} bytes`);let s=ts(n,"utf8");return{path:n,content:s,digest:v(s),rules:as(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(Et(n).mtimeMs).toISOString()}}function ls(t){return{goal:t.goal,plan:t.plan,phases:t.phases.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),tasks:t.tasks.map(e=>({id:e.id,title:e.title,status:e.status,order:e.order})),decisions:t.decisions,blockers:t.blockers,warnings:t.warnings,nextActions:t.nextActions,filesTouched:t.filesTouched,tests:t.tests}}function ds(t){return t.phases.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.tasks.some(e=>e.status==="pending"||e.status==="in_progress"||e.status==="blocked")||t.nextActions.length>0||t.blockers.length>0}var me=class{constructor(e){this.options=e}options;async capture(e,n){let r=await ce(this.options.project,this.options.storage);if(r||(r=await ae(this.options.project,this.options.storage)),!ds(r))return null;let s=fe(this.options.project,!1),o=s?s.rules.filter(m=>m.mode==="enforce").map(m=>m.text):[],i=v(JSON.stringify(ls(r))),l=v([this.options.project.id,this.options.identity.sessionKey,i].join("|")).slice(0,24),c=new Date().toISOString(),a={version:1,id:l,projectId:this.options.project.id,projectName:this.options.project.name,createdAt:c,reason:e,sourceSession:{agent:this.options.identity.agent,nativeSessionId:this.options.identity.nativeSessionId,sessionKey:this.options.identity.sessionKey,sequence:n},goal:r.goal,plan:r.plan,progress:r.progress,currentPhase:r.currentPhase,currentTask:r.currentTask,incompletePhases:r.phases.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),incompleteTasks:r.tasks.filter(m=>m.status!=="completed"&&m.status!=="cancelled"),nextActions:r.nextActions.slice(0,10),blockers:r.blockers.slice(0,10),decisions:r.decisions.slice(-10),warnings:r.warnings.slice(-10),attention:[...o,...r.warnings].slice(0,20),filesTouched:r.filesTouched.slice(-20),tests:r.tests.slice(-15),stateDigest:i},p=`projects/${this.options.project.id}/work/handoffs/${l}.json`;await this.options.storage.exists(p)||await this.options.storage.put(p,JSON.stringify(a,null,2)+`
67
67
  `,"application/json"),await this.options.storage.put(`projects/${this.options.project.id}/work/handoff-latest.json`,JSON.stringify(a,null,2)+`
68
- `,"application/json");let u=Re(this.options.project.rootPath,".toolnet","work","handoffs");return us(u,{recursive:!0}),I(Re(u,`${l}.json`),a),I(Re(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function Pt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var ge=class{identity;wal;remote;sanitizer=new J;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=nt(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ne(this.identity),this.remote=new te(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new se({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ue({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new de({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new me({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};var ps=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],fs=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],ms=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function gs(t){let e=t.toLowerCase();return ms.some(n=>e.includes(n))}function ys(t){if(!t.trim())return!0;for(let e of ps)if(e.test(t))return!0;return gs(t),!1}function hs(t){let e=t;for(let n of fs)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Me(t){let e=t.trim();return e?ys(e)?{content:"",filtered:!0,reason:"noise"}:{content:hs(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function ye(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=Me(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=ye(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=Me(s);return o.filtered?null:o.content}return s&&typeof s=="object"?ye(s):s}).filter(s=>s!==null):e[n]=r;return e}function Tt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&Me(r).filtered)return!0}return!1}function he(t){return t?Math.ceil(t.length/3.5):0}function Se(t,e){if(!t)return"";if(he(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
68
+ `,"application/json");let u=Re(this.options.project.rootPath,".toolnet","work","handoffs");return us(u,{recursive:!0}),E(Re(u,`${l}.json`),a),E(Re(this.options.project.rootPath,".toolnet","work","handoff-latest.json"),a),a}};async function Pt(t,e){let n=await e.getText(`projects/${t.id}/work/handoff-latest.json`);if(!n)return null;try{return JSON.parse(n)}catch{return null}}var ge=class{identity;wal;remote;sanitizer=new J;learner;continuity;semantic;handoff;title;metadata;constructor(e){this.identity=nt(e.project,e.agent,e.nativeSessionId),this.title=e.title,this.metadata=this.sanitizer.sanitizeValue(e.metadata??{}),this.wal=new ne(this.identity),this.remote=new te(e.storage,e.maxEventsPerChunk??100,e.maxChunkBytes??512*1024),this.learner=new se({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.continuity=new ue({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.semantic=new de({project:e.project,storage:e.storage,identity:this.identity,wal:this.wal}),this.handoff=new me({project:e.project,storage:e.storage,identity:this.identity})}sanitizeEvent(e){let n=e.provenance?{...e.provenance,metadata:this.sanitizer.sanitizeValue(e.provenance.metadata)}:void 0;return{...e,data:this.sanitizer.sanitizeValue(e.data??{}),provenance:n}}start(e={}){let n=this.wal.loadState();return this.record({type:n.lastSequence===0?"session_start":"session_resume",data:e,provenance:{source:this.identity.agent}})}record(e){return this.wal.append([this.sanitizeEvent(e)])[0]}recordMany(e){return this.wal.append(e.map(n=>this.sanitizeEvent(n)))}setSourceCursor(e,n){this.wal.setSourceCursor(e,n)}async flush(){let e=this.wal.readPending(),n=this.wal.loadState(),r=await this.remote.append(this.identity,e.events,n.sourceCursors,{title:this.title,metadata:this.metadata});if(e.events.length>0){let s=e.events[e.events.length-1];this.wal.markRemote(s.sequence,e.endOffset)}if(process.env.TOOLNET_SESSION_LEARNING!=="0")try{await this.learner.learnNew()}catch{}if(process.env.TOOLNET_WORK_CONTINUITY!=="0")try{await this.continuity.learnNew()}catch{}if(process.env.TOOLNET_SEMANTIC_CONTINUITY!=="0")try{await this.semantic.learnNew()}catch{}if(process.env.TOOLNET_SMART_HANDOFF!=="0"&&e.events.length>0)try{let s=e.events[e.events.length-1],o=["session_idle","session_end","session_compact"].includes(s.type)?s.type:"checkpoint";await this.handoff.capture(o,s.sequence)}catch{}return r}async idle(e={}){return this.record({type:"session_idle",data:e,provenance:{source:this.identity.agent}}),this.flush()}async end(e={}){return this.record({type:"session_end",data:e,provenance:{source:this.identity.agent}}),this.flush()}status(){return this.wal.loadState()}recoverRemote(){return this.remote.recover(this.identity)}};var ps=[/^<SYSTEM MESSAGE>/i,/^<EPHEMERAL MESSAGE>/i,/^<system>/i,/^<ephemeral>/i,/^ManageTask:/i,/^Task \d+ status:/i,/^Task \d+ killed/i,/^Task \d+ loading/i,/^Thought for \d+ tokens/i,/^Prioritizing Tool Usage/i,/^Tool call:/i,/^Tool response:/i,/^npm notice/i,/^npm WARN/i,/^added \d+ packages/i,/^removed \d+ packages/i,/^up to date/i,/^\d+ packages are looking for funding/i,/^run `npm fund` for details/i,/^[\d.]+%/,/^\[={10,}\]/,/^Loading\.\.\./i,/^Processing\.\.\./i,/^bash-\d+\.\d+\$/,/^\$ /,/^\s*$/],fs=[/api[_-]?key[:\s=]+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/secret[:\s=]+[^\s]+/gi,/password[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/authorization:\s*[^\s]+/gi],ms=["decision","decided","rule","convention","architecture","pattern","fixed","resolved","implemented","created","updated","deleted","deployed","blocker","blocked","issue","bug","error","next","todo","action","requirement","must","should","important"];function gs(t){let e=t.toLowerCase();return ms.some(n=>e.includes(n))}function hs(t){if(!t.trim())return!0;for(let e of ps)if(e.test(t))return!0;return gs(t),!1}function ys(t){let e=t;for(let n of fs)e=e.replace(n,r=>{let s=r.split(/[:\s=]+/);return s.length>1?`${s[0]}: [REDACTED]`:"[REDACTED]"});return e}function Me(t){let e=t.trim();return e?hs(e)?{content:"",filtered:!0,reason:"noise"}:{content:ys(e),filtered:!1}:{content:"",filtered:!0,reason:"empty"}}function he(t){let e={};for(let[n,r]of Object.entries(t))if(typeof r=="string"){let s=Me(r);s.filtered||(e[n]=s.content)}else r&&typeof r=="object"&&!Array.isArray(r)?e[n]=he(r):Array.isArray(r)?e[n]=r.map(s=>{if(typeof s=="string"){let o=Me(s);return o.filtered?null:o.content}return s&&typeof s=="object"?he(s):s}).filter(s=>s!==null):e[n]=r;return e}function Tt(t){let e=typeof t.type=="string"?t.type.toLowerCase():"";if(e.includes("system")||e.includes("ephemeral")||e==="tool_call"&&!t.result)return!0;if(t.data&&typeof t.data=="object"){let n=t.data,r=typeof n.content=="string"?n.content:"";if(r&&Me(r).filtered)return!0}return!1}function ye(t){return t?Math.ceil(t.length/3.5):0}function Se(t,e){if(!t)return"";if(ye(t)<=e)return t;let r=Math.floor(e*3.5),s=t.slice(0,r),o=s.lastIndexOf("."),i=s.lastIndexOf(`
69
69
  `),l=Math.max(o,i);return l>r*.7?s.slice(0,l+1):s}function N(){let t=H(),e=process.env.TOOLNET_SESSION_SAVE||"summary",n=process.env.TOOLNET_RAW_TRANSCRIPT==="on"||e==="archive"||e==="full",r=process.env.TOOLNET_MEMORY_PROMOTION||"conservative",s=parseFloat(process.env.TOOLNET_PROMOTE_MIN_SCORE||"0.65"),o=parseInt(process.env.TOOLNET_SESSION_SUMMARY_MAX_TOKENS||"700",10),i=parseInt(process.env.TOOLNET_DURABLE_MEMORY_MAX_ITEMS_PER_SESSION||"10",10),l=n,c=process.env.TOOLNET_RAW_TRANSCRIPT_REMOTE==="on"||e==="full";return{sessionSave:e,rawTranscript:n,memoryPromotion:r,promoteMinScore:s,sessionSummaryMaxTokens:o,durableMemoryMaxItemsPerSession:i,archiveLocal:l,archiveRemote:c}}function Ct(t){return(t||N()).rawTranscript}function Rt(t){return(t||N()).durableMemoryMaxItemsPerSession}function Mt(t){return(t||N()).sessionSummaryMaxTokens}function At(t){return(t||N()).archiveRemote}function Ss(t){return t.replace(/\b[A-Za-z0-9_-]{20,}\b/g,"[REDACTED]").replace(/api[_-]?key[:\s=]+[^\s]+/gi,"api_key=[REDACTED]").replace(/token[:\s=]+[^\s]+/gi,"token=[REDACTED]").replace(/secret[:\s=]+[^\s]+/gi,"secret=[REDACTED]").replace(/password[:\s=]+[^\s]+/gi,"password=[REDACTED]")}function vs(t,e){let n=t.toLowerCase(),r=.5,s=["nh\u1EDB","remember","quy t\u1EAFc","rule","t\u1EEB gi\u1EDD","from now","kh\xF4ng \u0111\u01B0\u1EE3c","must not","lu\xF4n lu\xF4n","always","never","critical","important","blocker","deploy","production","architecture"];for(let i of s)n.includes(i)&&(r+=.15);e==="rule"||e==="architecture"||e==="blocker"?r+=.2:e==="decision"||e==="deploy"?r+=.15:(e==="fix"||e==="next_action")&&(r+=.1),t.length<20?r-=.3:t.length>500&&(r-=.1);let o=[/npm (notice|warn|ERR)/i,/\d+ packages? in \d+/i,/found \d+ vulnerabilities/i,/up to date/i,/added \d+ packages/i,/^(ok|done|success|error|warning)$/i];for(let i of o)i.test(t)&&(r-=.4);return Math.max(0,Math.min(1,r))}function bs(t,e){let n=[],r=new Set;for(let i of t){let l=i.split(`
70
70
  `).filter(c=>c.trim());for(let c of l){let a=c.trim();if(a.length<15)continue;let p=a.toLowerCase().replace(/\s+/g," ");if(r.has(p))continue;r.add(p);let u="decision";/\b(rule|quy tắc|policy|standard|convention)\b/i.test(a)||/\b(always|never|must|should|từ giờ|không được)\b/i.test(a)?u="rule":/\b(fix|fixed|bug|issue|error|lỗi)\b/i.test(a)?u="fix":/\b(blocker|blocked|stuck|cannot|không thể)\b/i.test(a)?u="blocker":/\b(next|todo|action|task|cần làm)\b/i.test(a)?u="next_action":/\b(deploy|release|publish|ship)\b/i.test(a)?u="deploy":/\b(architecture|design|structure|pattern)\b/i.test(a)?u="architecture":/\.(ts|js|py|go|rs|java|cpp|c|h)\b/i.test(a)&&(u="file");let m=vs(a,u);if(m<.3)continue;let d=Ss(a);n.push({category:u,text:d,importance:m,sourceSessionId:e})}}let s=N(),o=Rt(s);return n.sort((i,l)=>l.importance-i.importance).slice(0,o)}function ks(t){let e=N(),n=Mt(e),o=t.join(`
71
71
 
@@ -73,7 +73,7 @@ Things an AI agent should always remember.
73
73
  `).filter(i=>{let l=i.trim();return l.length>20&&!l.startsWith("npm")&&!l.startsWith("\u2713")&&!l.startsWith("Error:")}).slice(0,20).join(`
74
74
  `);return Se(o,n)}function Nt(t,e){let r=(Array.isArray(t)?t:t.split(`
75
75
 
76
- `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=bs(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),l=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),u=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:ks(r),decisions:o,projectRules:i,filesChanged:l,bugsFixed:c,commands:u,blockers:a,nextActions:p,durableFacts:s}}function Bt(){try{let e=js("opencode",["db","path"],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5e3}).trim();if(e)return e}catch{}if(process.env.OPENCODE_DB)return process.env.OPENCODE_DB;let t=process.env.XDG_DATA_HOME??_t(xs(),".local","share");return _t(t,"opencode","opencode.db")}function k(t){return typeof t=="string"?t:""}function _(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function Ae(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function B(t){let e=_(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function ve(t,e){if(!e)return!1;let n=$t(t),r=$t(e);if(n===r)return!0;let s=Es(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!Is(s)}function Lt(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function Dt(t){return JSON.stringify(t)}function Wt(t){if(!ws(t))throw new Error(`OpenCode database not found: ${t}`);let e=new Os(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function Ps(t,e){let n=t.prepare(`
76
+ `).filter(d=>d.trim())).map(d=>typeof d=="string"?d:JSON.stringify(d)).filter(d=>d.trim()),s=bs(r,e),o=s.filter(d=>d.category==="decision").map(d=>d.text),i=s.filter(d=>d.category==="rule").map(d=>d.text),l=s.filter(d=>d.category==="file").map(d=>d.text),c=s.filter(d=>d.category==="fix").map(d=>d.text),a=s.filter(d=>d.category==="blocker").map(d=>d.text),p=s.filter(d=>d.category==="next_action").map(d=>d.text),u=s.filter(d=>d.category==="deploy").map(d=>d.text);return{summary:ks(r),decisions:o,projectRules:i,filesChanged:l,bugsFixed:c,commands:u,blockers:a,nextActions:p,durableFacts:s}}function Bt(){try{let e=js("opencode",["db","path"],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5e3}).trim();if(e)return e}catch{}if(process.env.OPENCODE_DB)return process.env.OPENCODE_DB;let t=process.env.XDG_DATA_HOME??_t(xs(),".local","share");return _t(t,"opencode","opencode.db")}function k(t){return typeof t=="string"?t:""}function _(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(typeof t=="bigint")return Number(t);if(typeof t=="string"){let e=Number(t);if(Number.isFinite(e))return e}return 0}function Ae(t){if(t&&typeof t=="object"&&!Buffer.isBuffer(t))return t;if(typeof t!="string")return{};try{let e=JSON.parse(t);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{}}function B(t){let e=_(t);if(e<=0)return new Date().toISOString();e<1e11&&(e*=1e3);let n=new Date(e);return Number.isNaN(n.getTime())?new Date().toISOString():n.toISOString()}function ve(t,e){if(!e)return!1;let n=$t(t),r=$t(e);if(n===r)return!0;let s=Is(n,r);return s!==""&&s!==".."&&!s.startsWith(`..${process.platform==="win32"?"\\":"/"}`)&&!Es(s)}function Lt(t){if(!t)return{time:-1,id:""};try{let e=JSON.parse(t);return{time:typeof e.time=="number"?e.time:-1,id:typeof e.id=="string"?e.id:""}}catch{return{time:-1,id:""}}}function Dt(t){return JSON.stringify(t)}function Wt(t){if(!ws(t))throw new Error(`OpenCode database not found: ${t}`);let e=new Os(t,{readOnly:!0});return e.exec("PRAGMA query_only = ON"),e.exec("PRAGMA busy_timeout = 3000"),e}function Ps(t,e){let n=t.prepare(`
77
77
  SELECT *
78
78
  FROM "session"
79
79
  WHERE id = ?
@@ -127,7 +127,7 @@ Things an AI agent should always remember.
127
127
  `;return t.prepare(s).all(n,r.time,r.time,r.id)}function Kt(t,e){let n=t[t.length-1];return n?{time:_(n.__clock),id:k(n.id)}:e}function Ts(t,e){let n=Ae(e.data),r=k(n.role),s=_(e.__clock),o=k(e.id),i="message";return r==="user"?i="user_prompt":r==="assistant"&&(i="assistant_message"),{clock:s,order:0,event:{type:i,timestamp:B(s),role:r||void 0,sourceEventId:`message:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{messageId:o,...n},provenance:{source:"opencode",sourcePath:t,sourceTable:"message",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}function Cs(t){let e={...t},n=t.state&&typeof t.state=="object"&&!Array.isArray(t.state)?{...t.state}:void 0;if(n){let r=n.output;if(typeof r=="string"){let s=r.replace(/\r\n/g,`
128
128
  `),o=500;n.outputSummary=s.length<=o?s:`${s.slice(0,350)}
129
129
  ...[ToolNet truncated ${s.length-o} chars]...
130
- ${s.slice(-150)}`,delete n.output}else r!==void 0&&(n.outputSummary="[non-text tool output omitted]",delete n.output);if(n.input&&typeof n.input=="object"&&!Array.isArray(n.input)){let s={...n.input};for(let[o,i]of Object.entries(s))typeof i=="string"&&i.length>1e3&&(s[o]=`${i.slice(0,1e3)}...[ToolNet truncated]`);n.input=s}e.state=n}return e}function Rs(t,e){let n=Ae(e.data),r=k(n.type),s=_(e.__clock),o=k(e.id),i=k(e.message_id),l="message_part";return r==="tool"?l="tool_call":r==="snapshot"&&(l="artifact"),{clock:s,order:1,event:{type:l,timestamp:B(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...r==="tool"?Cs(n):n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function Ne(t){let e=t.dbPath??Bt(),n=Wt(e);try{let r=Ps(n,t.nativeSessionId);if(!zt(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${k(r.directory)||"unknown"}`].join(" "));let s=new ge({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:k(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:k(r.project_id)||void 0,directory:k(r.directory)||void 0}}),o=s.status(),i=Lt(o.sourceCursors["opencode.message"]),l=Lt(o.sourceCursors["opencode.part"]),c=Ft(n,"message",t.nativeSessionId,i),a=Ft(n,"part",t.nativeSessionId,l),p=[];if(o.lastSequence===0){let y=_(r.time_created);p.push({clock:y,order:-1,event:{type:"session_start",timestamp:B(y),sourceEventId:`session:${t.nativeSessionId}:created:${y}`,data:{title:k(r.title)||void 0,directory:k(r.directory)||void 0,openCodeProjectId:k(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...c.map(y=>Ts(e,y))),p.push(...a.map(y=>Rs(e,y)));let u=_(r.time_updated)||_(r.time_created);t.compacted&&p.push({clock:u,order:98,event:{type:"session_compact",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:compact:${u}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:u,order:99,event:{type:"error",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:error:${u}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:u,order:100,event:{type:"session_idle",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:idle:${u}`,data:{},provenance:{source:"opencode"}}}),p.sort((y,w)=>y.clock-w.clock||y.order-w.order);let m=p.filter(y=>!Tt(y.event.data)).map(y=>({...y,event:{...y.event,data:ye(y.event.data)}})),d=s.recordMany(m.map(y=>y.event)),S=Kt(c,i),h=Kt(a,l);if(s.setSourceCursor("opencode.message",Dt(S)),s.setSourceCursor("opencode.part",Dt(h)),t.idle&&m.length>0)try{let y=m.map(T=>JSON.stringify(T.event.data)),w=Nt(y,t.nativeSessionId);s.setSourceCursor("opencode.session.summary",w.summary),s.setSourceCursor("opencode.session.facts_count",w.durableFacts.length),Ct()&&!At()&&s.setSourceCursor("opencode.raw_transcript.archived","local")}catch{}let g=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:c.length,importedParts:a.length,recordedEvents:d.length,eventCount:g.eventCount,chunkCount:g.chunkCount,status:g.status}}finally{n.close()}}async function qt(t){let e=t.dbPath??Bt(),n=Wt(e),r=[];try{let o=n.prepare(`
130
+ ${s.slice(-150)}`,delete n.output}else r!==void 0&&(n.outputSummary="[non-text tool output omitted]",delete n.output);if(n.input&&typeof n.input=="object"&&!Array.isArray(n.input)){let s={...n.input};for(let[o,i]of Object.entries(s))typeof i=="string"&&i.length>1e3&&(s[o]=`${i.slice(0,1e3)}...[ToolNet truncated]`);n.input=s}e.state=n}return e}function Rs(t,e){let n=Ae(e.data),r=k(n.type),s=_(e.__clock),o=k(e.id),i=k(e.message_id),l="message_part";return r==="tool"?l="tool_call":r==="snapshot"&&(l="artifact"),{clock:s,order:1,event:{type:l,timestamp:B(s),sourceEventId:`part:${o}:${s}`,sourceSequence:`${s}:${o}`,data:{partId:o,messageId:i,...r==="tool"?Cs(n):n},provenance:{source:"opencode",sourcePath:t,sourceTable:"part",sourceRowId:o,sourceOffset:`${s}:${o}`}}}}async function Ne(t){let e=t.dbPath??Bt(),n=Wt(e);try{let r=Ps(n,t.nativeSessionId);if(!zt(n,r,t.project))throw new Error(["OpenCode session does not belong to current ToolNet project.",`Session: ${t.nativeSessionId}`,`Project: ${t.project.rootPath}`,`Session directory: ${k(r.directory)||"unknown"}`].join(" "));let s=new ge({project:t.project,storage:t.storage,agent:"opencode",nativeSessionId:t.nativeSessionId,title:k(r.title)||void 0,metadata:{source:"opencode.db",openCodeProjectId:k(r.project_id)||void 0,directory:k(r.directory)||void 0}}),o=s.status(),i=Lt(o.sourceCursors["opencode.message"]),l=Lt(o.sourceCursors["opencode.part"]),c=Ft(n,"message",t.nativeSessionId,i),a=Ft(n,"part",t.nativeSessionId,l),p=[];if(o.lastSequence===0){let h=_(r.time_created);p.push({clock:h,order:-1,event:{type:"session_start",timestamp:B(h),sourceEventId:`session:${t.nativeSessionId}:created:${h}`,data:{title:k(r.title)||void 0,directory:k(r.directory)||void 0,openCodeProjectId:k(r.project_id)||void 0},provenance:{source:"opencode",sourcePath:e,sourceTable:"session",sourceRowId:t.nativeSessionId}}})}p.push(...c.map(h=>Ts(e,h))),p.push(...a.map(h=>Rs(e,h)));let u=_(r.time_updated)||_(r.time_created);t.compacted&&p.push({clock:u,order:98,event:{type:"session_compact",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:compact:${u}`,data:{},provenance:{source:"opencode"}}}),t.error?p.push({clock:u,order:99,event:{type:"error",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:error:${u}`,data:{source:"session.error"},provenance:{source:"opencode"}}}):t.idle&&p.push({clock:u,order:100,event:{type:"session_idle",timestamp:B(u),sourceEventId:`session:${t.nativeSessionId}:idle:${u}`,data:{},provenance:{source:"opencode"}}}),p.sort((h,w)=>h.clock-w.clock||h.order-w.order);let m=p.filter(h=>!Tt(h.event.data)).map(h=>({...h,event:{...h.event,data:he(h.event.data)}})),d=s.recordMany(m.map(h=>h.event)),S=Kt(c,i),y=Kt(a,l);if(s.setSourceCursor("opencode.message",Dt(S)),s.setSourceCursor("opencode.part",Dt(y)),t.idle&&m.length>0)try{let h=m.map(T=>JSON.stringify(T.event.data)),w=Nt(h,t.nativeSessionId);s.setSourceCursor("opencode.session.summary",w.summary),s.setSourceCursor("opencode.session.facts_count",w.durableFacts.length),Ct()&&!At()&&s.setSourceCursor("opencode.raw_transcript.archived","local")}catch{}let g=await s.flush();return{nativeSessionId:t.nativeSessionId,importedMessages:c.length,importedParts:a.length,recordedEvents:d.length,eventCount:g.eventCount,chunkCount:g.chunkCount,status:g.status}}finally{n.close()}}async function qt(t){let e=t.dbPath??Bt(),n=Wt(e),r=[];try{let o=n.prepare(`
131
131
  SELECT *
132
132
  FROM "session"
133
133
  ORDER BY
@@ -177,6 +177,12 @@ Rules:
177
177
 
178
178
  - Never invent previous work.
179
179
  - Current repository evidence overrides stale memory.
180
+ - NEVER reconstruct previous work by reading ToolNet internal session files.
181
+ - NEVER read/list/search .toolnet/sessions/**, session state.json,
182
+ events.jsonl, or raw transcripts to discover previous-agent state.
183
+ - Do not search the filesystem for the implementation/schema of
184
+ memory_agent_ask. Invoke the MCP tool directly when deeper
185
+ continuity is required.
180
186
  - Do not dump raw transcripts or full memory.
181
187
  - After receiving the ToolNet answer, continue the task
182
188
  instead of asking the user to repeat known context.
@@ -835,10 +841,10 @@ export const ToolNetMemoryPlugin =
835
841
  `)),i=Math.max(0,e-o);if(i>=16){let l=Math.floor(i*3.2),c=b(r,l);c&&n.push(c)}break}return n.join(`
836
842
  `).trim()}async function Gt(t){let e=Math.max(256,Math.min(2e3,t.maxTokens??1e3)),n=fe(t.project,!1),r=n?.content??"";r||(r=await t.storage.getText(`projects/${t.project.id}/project/manual.md`)??"");let s=Ls(r),o=n?n.rules.filter(d=>d.mode==="enforce").map(d=>d.text):s.enforce,i=n?n.rules.filter(d=>d.mode==="advisory").map(d=>d.text):s.advisory,l=r?$s(r):[],c=await ce(t.project,t.storage),a=await xt(t.project,t.storage),p=await Pt(t.project,t.storage),u=[];if(u.push("[TOOLNET PROJECT CONTEXT]"),u.push(`Project: ${t.project.name}`),u.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),r&&u.push(`Full operating manual: ${pe(t.project)}`),o.length){u.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let d of o.slice(0,24))u.push(`- [ENFORCE] ${b(d,240)}`)}if(i.length){u.push("","PROJECT PREFERENCES");for(let d of i.slice(0,10))u.push(`- ${b(d,220)}`)}if(a&&(a.mission&&u.push("","MISSION",b(a.mission.value,420)),a.activeObjective&&u.push("","CURRENT OBJECTIVE",b(a.activeObjective.value,420)),a.why&&u.push("","WHY THIS WORK MATTERS",b(a.why.value,420)),a.desiredOutcome&&u.push("","DESIRED OUTCOME",b(a.desiredOutcome.value,420)),a.planRationale&&u.push("","WHY THIS APPROACH",b(a.planRationale.value,420))),c){if(u.push("","ACTIVE WORK"),c.goal&&u.push(`Goal: ${b(c.goal,320)}`),c.plan&&u.push(`Plan: ${b(c.plan,320)}`),u.push(`Progress: phases ${c.progress.phasesCompleted}/${c.progress.phasesTotal}; tasks ${c.progress.tasksCompleted}/${c.progress.tasksTotal}; blocked ${c.progress.blocked}`),c.currentPhase&&u.push(`Current phase: ${c.currentPhase.title} [${c.currentPhase.status}]`),c.currentPhase&&a){let d=a.phases.find(S=>S.order===c.currentPhase?.order);d&&(d.objective&&u.push(`Phase objective: ${b(d.objective.value,340)}`),d.why?u.push(`Why this phase: ${b(d.why.value,340)}`):u.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),d.deliverable&&u.push(`Deliverable: ${b(d.deliverable.value,340)}`),d.dependencies.length&&u.push(`Depends on: ${d.dependencies.slice(0,4).map(S=>b(S.value,180)).join("; ")}`),d.acceptanceCriteria.length&&(u.push("","DEFINITION OF DONE"),d.acceptanceCriteria.slice(0,6).forEach(S=>{u.push(`- ${b(S.value,260)}`)})),d.openQuestions.length&&(u.push("","OPEN QUESTIONS FOR CURRENT PHASE"),d.openQuestions.slice(0,4).forEach(S=>{u.push(`- ${b(S.value,260)}`)})))}c.currentTask&&u.push(`Current task: ${c.currentTask.title} [${c.currentTask.status}]`),c.nextActions.length&&(u.push("","NEXT ACTIONS"),c.nextActions.slice(0,6).forEach((d,S)=>{u.push(`${S+1}. ${b(d,260)}`)})),c.blockers.length&&(u.push("","BLOCKERS"),c.blockers.slice(0,5).forEach(d=>{u.push(`- ${b(d,260)}`)})),c.warnings.length&&(u.push("","ATTENTION"),c.warnings.slice(-5).forEach(d=>{u.push(`- ${b(d,260)}`)})),c.decisions.length&&(u.push("","RECENT DECISIONS"),c.decisions.slice(-5).forEach(d=>{u.push(`- ${b(d,260)}`)})),c.lastSession&&u.push("",`Last work session: ${c.lastSession.agent} / ${c.lastSession.nativeSessionId}`)}if(a&&a.openQuestions.length&&(u.push("","UNRESOLVED QUESTIONS"),a.openQuestions.slice(0,5).forEach(d=>{u.push(`- ${b(d.value,260)}`)})),p&&u.push(`Latest handoff: ${p.reason} / ${p.sourceSession.agent}`),l.length){u.push("","OPERATING NOTES");for(let d of l)u.push(`- ${d}`)}u.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let m=Ds(u,e);return{version:1,projectId:t.project.id,projectName:t.project.name,text:m,estimatedTokens:Le(m),maxTokens:e,hasManual:!!r,hasWorkState:!!c,hasHandoff:!!p,generatedAt:new Date().toISOString()}}function Ws(t){return Xt(t.rootPath,".toolnet","context","startup.md")}function zs(t){return Xt(t.rootPath,".toolnet","context","startup.json")}function qs(t,e){let n=Ws(t);Fs(Bs(n),{recursive:!0}),Ks(n,e.text.endsWith(`
837
843
  `)?e.text:e.text+`
838
- `,{encoding:"utf8",mode:384}),I(zs(t),e)}async function Qt(t,e,n=800){let s=(await Gt({project:t,storage:e,maxTokens:n})).text;he(s)>n&&(s=Se(s,n),s+=`
844
+ `,{encoding:"utf8",mode:384}),E(zs(t),e)}async function Qt(t,e,n=800){let s=(await Gt({project:t,storage:e,maxTokens:n})).text;ye(s)>n&&(s=Se(s,n),s+=`
839
845
 
840
846
  [Context trimmed by ToolNet Memory token budget]
841
- `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:he(s),generatedAt:new Date().toISOString()};return qs(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
847
+ `);let i={version:1,projectId:t.id,projectName:t.name,text:s,digest:v(s),estimatedTokens:ye(s),generatedAt:new Date().toISOString()};return qs(t,i),await e.put(`projects/${t.id}/context/startup.md`,i.text+`
842
848
  `,"text/markdown"),await e.put(`projects/${t.id}/context/startup.json`,JSON.stringify(i,null,2)+`
843
849
  `,"application/json"),i}function ke(t,e){let n=t.indexOf(e);if(!(n<0))return t[n+1]}function De(t,e){return t.includes(e)}function Js(t){let e=H(),n=Ge(He({provider:e.storage.provider,huggingface:e.storage.huggingface,localRoot:e.storage.localRoot}),{attempts:3});return new ee(n,t.id,t.name,t.remote??t.name)}async function Vs(){let[t="help",...e]=process.argv.slice(2);if(t==="install-plugin"){let i=Yt({binary:ke(e,"--bin")});console.log(`\u2705 OpenCode plugin installed: ${i}`),console.log("OpenCode will load it automatically on next start.");return}let n=ke(e,"--project")??process.cwd(),r=new G().detect(n),s=Js(r),o=ke(e,"--db");if(t==="sync"){let i=e.find(u=>!u.startsWith("--")&&u!==n&&u!==o);if(!i)throw new Error("Usage: session:opencode-sync <session-id>");let l=De(e,"--idle"),c=De(e,"--error"),a=De(e,"--compacted"),p=await Ne({project:r,storage:s,nativeSessionId:i,dbPath:o,idle:l,error:c,compacted:a});if(l||a||c)try{await Qt(r,s,800)}catch{}console.log(JSON.stringify(p,null,2));return}if(t==="recover"){let i=ke(e,"--limit"),l=i?Number(i):100,c=await qt({project:r,storage:s,dbPath:o,limit:Number.isFinite(l)?l:100});console.log(JSON.stringify({project:r.name,sessions:c.length,importedMessages:c.reduce((a,p)=>a+p.importedMessages,0),importedParts:c.reduce((a,p)=>a+p.importedParts,0)},null,2));return}console.log(`OpenCode Session Adapter
844
850