toolnet-memory 0.2.9 → 0.2.11

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,8 +1,8 @@
1
- import{existsSync as oe,readFileSync as se}from"node:fs";import{homedir as ie}from"node:os";import{join as ae}from"node:path";function ce(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
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 pe(){let r=process.env.TOOLNET_GLOBAL_ENV??ae(ie(),".config","toolnet-memory",".env");if(!oe(r))return;let e=se(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let o=n.indexOf("=");if(o<=0)continue;let a=n.slice(0,o).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(a)&&process.env[a]===void 0&&(process.env[a]=ce(n.slice(o+1)))}}pe();function v(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function y(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function N(){return{memory:{autoCapture:v(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:v(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:v(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:v(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:y(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:y(process.env.MEMORY_RERANK_TOP,10),finalContext:y(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:y(process.env.MEMORY_TOKEN_BUDGET,2e3)},storage:{provider:process.env.MEMORY_STORAGE_PROVIDER??"huggingface",huggingface:{namespace:process.env.HF_NAMESPACE,bucket:process.env.HF_BUCKET,accessKeyId:process.env.HF_S3_ACCESS_KEY_ID,secretAccessKey:process.env.HF_S3_SECRET_ACCESS_KEY},localRoot:process.env.MEMORY_LOCAL_STORAGE_PATH},cache:{maxMb:y(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as ue}from"node:crypto";import{existsSync as I,mkdirSync as le,readFileSync as de,renameSync as me,writeFileSync as fe}from"node:fs";import{basename as ge,dirname as k,join as x,parse as _,resolve as S}from"node:path";var W=".toolnet",he="project.json";function ye(r){return ue("sha256").update(r).digest("hex").slice(0,16)}function A(r){return x(r,W,he)}function Se(r){return I(A(r))}function je(r,e){let t=S(r),n=_(t).root;for(;;){if(Se(t))return t;if(t===n||e&&t===S(e))break;let o=k(t);if(o===t)break;t=o}return null}function ve(r){let e=S(r),t=_(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(a=>I(x(e,a))))return e;if(e===t)break;let o=k(e);if(o===e)break;e=o}return S(r)}function ke(r){let e;try{e=JSON.parse(de(r,"utf8"))}catch(o){throw new Error(`Invalid ToolNet project manifest: ${r}: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:k(k(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function C(r,e){let t=x(r,W);le(t,{recursive:!0});let n=A(r),o=`${n}.tmp-${process.pid}`;fe(o,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384}),me(o,n)}function $(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var w=class{detect(e=process.cwd()){let t=S(e),n=ve(t),a=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>I(x(n,f))),c=je(t,a?n:void 0);if(c){let f=A(c),s=ke(f);return s.rootPath!==c&&(s.rootPath=c,s.updatedAt=new Date().toISOString(),C(c,s)),$(s,c)}let l=new Date().toISOString(),i=ge(n),u={version:1,id:ye(n),name:i,remote:i,rootPath:n,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return C(n,u),$(u,n)}};import{homedir as We}from"node:os";import{join as Be}from"node:path";import{DeleteObjectCommand as we,GetObjectCommand as xe,HeadObjectCommand as be,ListObjectsV2Command as Pe,PutObjectCommand as Oe,S3Client as Ie}from"@aws-sdk/client-s3";import{getSignedUrl as Ae}from"@aws-sdk/s3-request-presigner";var b=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ie({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let o=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Oe({Bucket:this.bucket,Key:e,Body:o,ContentType:n}))}async get(e){let t=await Ae(this.client,new xe({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new be({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new we({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let o=await this.client.send(new Pe({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let a of o.Contents??[])a.Key&&t.push({key:a.Key,size:a.Size,updatedAt:a.LastModified?.toISOString()});n=o.IsTruncated?o.NextContinuationToken:void 0}while(n);return t}};import{access as B,mkdir as Me,readFile as Te,readdir as Ee,rm as Re,stat as D,writeFile as Ne}from"node:fs/promises";import{dirname as Ce,join as $e,relative as L,resolve as _e}from"node:path";var j=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return _e(this.root,t)}async put(e,t){let n=this.path(e);await Me(Ce(n),{recursive:!0}),await Ne(n,t)}async get(e){try{return await Te(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await B(this.path(e)),!0}catch{return!1}}async delete(e){await Re(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await B(t)}catch{return n}let o=async c=>{let l=await Ee(c,{withFileTypes:!0});for(let i of l){let u=$e(c,i.name);if(i.isDirectory()){await o(u);continue}let f=await D(u);n.push({key:L(this.root,u),size:f.size,updatedAt:f.mtime.toISOString()})}},a=await D(t);return a.isDirectory()?await o(t):n.push({key:L(this.root,t),size:a.size,updatedAt:a.mtime.toISOString()}),n}};function K(r){let e=r.localRoot??Be(We(),".toolnet-memory","storage");if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new b({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):(console.warn("[storage] Hugging Face credentials missing. Using local fallback."),new j(e))}return new j(e)}function De(r){return new Promise(e=>setTimeout(e,r))}async function z(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,o=e.maxDelayMs??2e3,a;for(let c=1;c<=t;c++)try{return await r()}catch(l){if(a=l,c>=t)break;let i=Math.min(o,n*2**(c-1)),u=Math.floor(Math.random()*Math.max(1,i*.2));await De(i+u)}throw a}var Le=new Set(["put","get","getText","delete","list"]);function F(r,e={}){return new Proxy(r,{get(t,n){let o=Reflect.get(t,n,t);return typeof o!="function"?o:Le.has(n)?(...a)=>z(()=>Promise.resolve(o.apply(t,a)),e):o.bind(t)}})}function V(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function J(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let o=e.match(/^(projects\/[^/]+\/)memories\/(.+)$/);return o?`${o[1]}memory/records/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)vectors\/(.+)$/),o?`${o[1]}memory/vectors/${o[2]}`:(o=e.match(/^(projects\/[^/]+\/)graph\/(.+)$/),o?`${o[1]}code/graph/${o[2]}`:e))}var P=class{constructor(e,t,n,o){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=V(o??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,o=await this.provider.getText(e);if(o){let c;try{c=JSON.parse(o)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof c.id=="string"&&c.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${c.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof c.createdAt=="string"&&(n=c.createdAt)}let a={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(a,null,2)+`
4
- `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=J(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Ke}from"node:crypto";import{dirname as ze}from"node:path";import{mkdirSync as Fe,readFileSync as on,renameSync as Ve,writeFileSync as Je}from"node:fs";function m(r){return Ke("sha256").update(r).digest("hex")}function h(r,e){Fe(ze(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;Je(t,JSON.stringify(e,null,2)+`
5
- `,{encoding:"utf8",mode:384}),Ve(t,r)}async function M(r,e){let t=await e.getText(`projects/${r.id}/work/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}import{existsSync as U,mkdirSync as He,readFileSync as Ue,statSync as q,writeFileSync as Ye}from"node:fs";import{dirname as Ge,join as Qe}from"node:path";var H=64*1024,Xe=`# ToolNet Project Operating Manual
1
+ import{existsSync as ie,readFileSync as ae}from"node:fs";import{homedir as ce}from"node:os";import{join as ue}from"node:path";function pe(r){let e=r.trim();return e.length>=2&&e.startsWith('"')&&e.endsWith('"')?(e=e.slice(1,-1),e.replace(/\\n/g,`
2
+ `).replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\")):e.length>=2&&e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function le(){let r=process.env.TOOLNET_GLOBAL_ENV??ue(ce(),".config","toolnet-memory",".env");if(!ie(r))return;let e=ae(r,"utf8");for(let t of e.split(/\r?\n/)){let n=t.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7));let s=n.indexOf("=");if(s<=0)continue;let i=n.slice(0,s).trim();/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)&&process.env[i]===void 0&&(process.env[i]=pe(n.slice(s+1)))}}le();function y(r,e){return r===void 0?e:["1","true","yes","on"].includes(r.toLowerCase())}function S(r,e){if(!r)return e;let t=Number(r);return Number.isFinite(t)?t:e}function $(){return{memory:{autoCapture:y(process.env.MEMORY_AUTO_CAPTURE,!0),autoRetrieve:y(process.env.MEMORY_AUTO_RETRIEVE,!0),autoSummarize:y(process.env.MEMORY_AUTO_SUMMARIZE,!0),autoSync:y(process.env.MEMORY_AUTO_SYNC,!0)},retrieval:{maxCandidates:S(process.env.MEMORY_MAX_CANDIDATES,50),rerankTop:S(process.env.MEMORY_RERANK_TOP,10),finalContext:S(process.env.MEMORY_FINAL_CONTEXT,5),tokenBudget:S(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:y(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:S(process.env.MEMORY_LOCAL_CACHE_MB,200)}}}import{createHash as de}from"node:crypto";import{existsSync as A,mkdirSync as me,readFileSync as fe,renameSync as ge,writeFileSync as he}from"node:fs";import{basename as ye,dirname as b,join as x,parse as W,resolve as j}from"node:path";var B=".toolnet",Se="project.json";function je(r){return de("sha256").update(r).digest("hex").slice(0,16)}function E(r){return x(r,B,Se)}function ke(r){return A(E(r))}function ve(r,e){let t=j(r),n=W(t).root;for(;;){if(ke(t))return t;if(t===n||e&&t===j(e))break;let s=b(t);if(s===t)break;t=s}return null}function be(r){let e=j(r),t=W(e).root,n=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"];for(;;){if(n.some(i=>A(x(e,i))))return e;if(e===t)break;let s=b(e);if(s===e)break;e=s}return j(r)}function we(r){let e;try{e=JSON.parse(fe(r,"utf8"))}catch(s){throw new Error(`Invalid ToolNet project manifest: ${r}: ${s instanceof Error?s.message:String(s)}`)}if(!e||typeof e!="object")throw new Error(`Invalid ToolNet project manifest: ${r}`);let t=e;if(typeof t.id!="string"||!t.id.trim())throw new Error(`ToolNet project manifest is missing id: ${r}`);if(typeof t.name!="string"||!t.name.trim())throw new Error(`ToolNet project manifest is missing name: ${r}`);let n=new Date().toISOString();return{version:1,id:t.id,name:t.name,remote:typeof t.remote=="string"&&t.remote.trim()?t.remote:t.name,rootPath:typeof t.rootPath=="string"?t.rootPath:b(b(r)),createdAt:typeof t.createdAt=="string"?t.createdAt:n,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:n,graphVersion:typeof t.graphVersion=="number"?t.graphVersion:0,memoryVersion:typeof t.memoryVersion=="number"?t.memoryVersion:0,metadata:t.metadata&&typeof t.metadata=="object"?t.metadata:void 0}}function _(r,e){let t=x(r,B);me(t,{recursive:!0});let n=E(r),s=`${n}.tmp-${process.pid}`;he(s,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384}),ge(s,n)}function K(r,e){return{id:r.id,name:r.name,remote:r.remote,rootPath:e,createdAt:r.createdAt,updatedAt:r.updatedAt,graphVersion:r.graphVersion,memoryVersion:r.memoryVersion,metadata:r.metadata}}var w=class{detect(e=process.cwd()){let t=j(e),n=be(t),i=[".git","package.json","pyproject.toml","Cargo.toml","go.mod","composer.json"].some(f=>A(x(n,f))),c=ve(t,i?n:void 0);if(c){let f=E(c),o=we(f);return o.rootPath!==c&&(o.rootPath=c,o.updatedAt=new Date().toISOString(),_(c,o)),K(o,c)}let l=new Date().toISOString(),a=ye(n),p={version:1,id:je(n),name:a,remote:a,rootPath:n,createdAt:l,updatedAt:l,graphVersion:0,memoryVersion:0};return _(n,p),K(p,n)}};import{homedir as Ue}from"node:os";import{join as qe}from"node:path";import{DeleteObjectCommand as xe,GetObjectCommand as Pe,HeadObjectCommand as Oe,ListObjectsV2Command as Ie,PutObjectCommand as Ae,S3Client as Ee}from"@aws-sdk/client-s3";import{getSignedUrl as Te}from"@aws-sdk/s3-request-presigner";var P=class{name="huggingface";client;bucket;constructor(e){this.bucket=e.bucket,this.client=new Ee({region:"us-east-1",endpoint:`https://s3.hf.co/${e.namespace}`,forcePathStyle:!0,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ae({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Te(this.client,new Pe({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`HF download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Oe({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new xe({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new Ie({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};import{access as D,mkdir as Me,readFile as Re,readdir as Ce,rm as Ne,stat as L,writeFile as $e}from"node:fs/promises";import{dirname as _e,join as Ke,relative as z,resolve as We}from"node:path";var k=class{constructor(e){this.root=e}root;name="local";path(e){let t=e.replace(/^\/+/,"");return We(this.root,t)}async put(e,t){let n=this.path(e);await Me(_e(n),{recursive:!0}),await $e(n,t)}async get(e){try{return await Re(this.path(e))}catch(t){if(typeof t=="object"&&t!==null&&"code"in t&&t.code==="ENOENT")return null;throw t}}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await D(this.path(e)),!0}catch{return!1}}async delete(e){await Ne(this.path(e),{force:!0})}async list(e=""){let t=this.path(e),n=[];try{await D(t)}catch{return n}let s=async c=>{let l=await Ce(c,{withFileTypes:!0});for(let a of l){let p=Ke(c,a.name);if(a.isDirectory()){await s(p);continue}let f=await L(p);n.push({key:z(this.root,p),size:f.size,updatedAt:f.mtime.toISOString()})}},i=await L(t);return i.isDirectory()?await s(t):n.push({key:z(this.root,t),size:i.size,updatedAt:i.mtime.toISOString()}),n}};import{DeleteObjectCommand as Be,GetObjectCommand as De,HeadObjectCommand as Le,ListObjectsV2Command as ze,PutObjectCommand as Ve,S3Client as Fe}from"@aws-sdk/client-s3";import{getSignedUrl as Je}from"@aws-sdk/s3-request-presigner";var v=class{name;client;bucket;constructor(e){this.name=e.name??"s3",this.bucket=e.bucket,this.client=new Fe({region:e.region??"us-east-1",endpoint:e.endpoint||void 0,forcePathStyle:e.forcePathStyle??!1,requestChecksumCalculation:"WHEN_REQUIRED",responseChecksumValidation:"WHEN_REQUIRED",credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey}})}async put(e,t,n="application/octet-stream"){let s=typeof t=="string"?Buffer.from(t,"utf8"):t;await this.client.send(new Ve({Bucket:this.bucket,Key:e,Body:s,ContentType:n}))}async get(e){let t=await Je(this.client,new De({Bucket:this.bucket,Key:e}),{expiresIn:60}),n=await fetch(t,{redirect:"follow"});if(n.status===404)return null;if(!n.ok)throw new Error(`${this.name} download failed: ${n.status} ${n.statusText}`);return new Uint8Array(await n.arrayBuffer())}async getText(e){let t=await this.get(e);return t?Buffer.from(t).toString("utf8"):null}async exists(e){try{return await this.client.send(new Le({Bucket:this.bucket,Key:e})),!0}catch(t){if(typeof t=="object"&&t!==null&&"$metadata"in t&&t.$metadata?.httpStatusCode===404)return!1;throw t}}async delete(e){await this.client.send(new Be({Bucket:this.bucket,Key:e}))}async list(e=""){let t=[],n;do{let s=await this.client.send(new ze({Bucket:this.bucket,Prefix:e||void 0,ContinuationToken:n}));for(let i of s.Contents??[])i.Key&&t.push({key:i.Key,size:i.Size,updatedAt:i.LastModified?.toISOString()});n=s.IsTruncated?s.NextContinuationToken:void 0}while(n);return t}};function T(r,e){return console.warn(e),new k(r)}function V(r){let e=r.localRoot??qe(Ue(),".toolnet-memory","storage");if(r.provider==="r2"){let t=r.r2;return t?.accountId&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new v({name:"r2",endpoint:`https://${t.accountId}.r2.cloudflarestorage.com`,region:"auto",bucket:t.bucket,forcePathStyle:!0,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Cloudflare R2 credentials missing. Using local fallback.")}if(r.provider==="s3"){let t=r.s3;return t?.bucket&&t.accessKeyId&&t.secretAccessKey?new v({name:"s3",endpoint:t.endpoint,region:t.region??"us-east-1",bucket:t.bucket,forcePathStyle:t.forcePathStyle??!1,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] S3 credentials missing. Using local fallback.")}if(r.provider==="huggingface"){let t=r.huggingface;return t?.namespace&&t.bucket&&t.accessKeyId&&t.secretAccessKey?new P({namespace:t.namespace,bucket:t.bucket,accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey}):T(e,"[storage] Hugging Face credentials missing. Using local fallback.")}return new k(e)}function He(r){return new Promise(e=>setTimeout(e,r))}async function F(r,e={}){let t=Math.max(1,e.attempts??3),n=e.baseDelayMs??150,s=e.maxDelayMs??2e3,i;for(let c=1;c<=t;c++)try{return await r()}catch(l){if(i=l,c>=t)break;let a=Math.min(s,n*2**(c-1)),p=Math.floor(Math.random()*Math.max(1,a*.2));await He(a+p)}throw i}var Ye=new Set(["put","get","getText","delete","list"]);function J(r,e={}){return new Proxy(r,{get(t,n){let s=Reflect.get(t,n,t);return typeof s!="function"?s:Ye.has(n)?(...i)=>F(()=>Promise.resolve(s.apply(t,i)),e):s.bind(t)}})}function U(r){let e=r.trim().replace(/\s+/g,"_").replace(/[^A-Za-z0-9._-]/g,"_").replace(/_+/g,"_").replace(/^\.+|\.+$/g,"").slice(0,100);if(!e||e==="."||e==="..")throw new Error("Invalid project storage folder");return e}function q(r){let e=r.replace(/^\/+/,"");if(e.startsWith("memories/"))return"memory/records/"+e.slice(9);if(e.startsWith("vectors/"))return"memory/vectors/"+e.slice(8);if(e.startsWith("graph/"))return"code/graph/"+e.slice(6);let t=e.match(/^(snapshots\/[^/]+\/)memories\/(.+)$/);if(t)return`${t[1]}memory/records/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)vectors\/(.+)$/),t)return`${t[1]}memory/vectors/${t[2]}`;if(t=e.match(/^(snapshots\/[^/]+\/)graph\/(.+)$/),t)return`${t[1]}code/graph/${t[2]}`;let n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)memories\/(.+)$/);if(n)return`${n[1]}memory/records/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)vectors\/(.+)$/),n)return`${n[1]}memory/vectors/${n[2]}`;if(n=e.match(/^(projects\/[^/]+\/snapshots\/[^/]+\/)graph\/(.+)$/),n)return`${n[1]}code/graph/${n[2]}`;let 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 O=class{constructor(e,t,n,s){this.provider=e;this.name=e.name,this.projectId=t,this.projectName=n,this.folder=U(s??n),this.sourcePrefix=`projects/${t}`,this.targetPrefix=`projects/${this.folder}`}provider;name;folder;sourcePrefix;targetPrefix;projectId;projectName;registryPromise;async registerProject(){let e=`${this.targetPrefix}/project.json`,t=new Date().toISOString(),n=t,s=await this.provider.getText(e);if(s){let c;try{c=JSON.parse(s)}catch(l){throw new Error(`Invalid remote ToolNet project manifest at ${e}: ${l instanceof Error?l.message:String(l)}`)}if(typeof c.id=="string"&&c.id!==this.projectId)throw new Error(["ToolNet remote project namespace collision.",`Remote folder: ${this.targetPrefix}`,`Existing project id: ${c.id}`,`Current project id: ${this.projectId}`,"Refusing to mix data from two projects."].join(" "));typeof c.createdAt=="string"&&(n=c.createdAt)}let i={version:1,id:this.projectId,name:this.projectName,remote:this.folder,createdAt:n,updatedAt:t};await this.provider.put(e,JSON.stringify(i,null,2)+`
4
+ `,"application/json")}async ensureRegistered(){return this.registryPromise||(this.registryPromise=this.registerProject()),this.registryPromise}key(e){if(e=q(e),e===this.sourcePrefix)return this.targetPrefix;if(e.startsWith(`${this.sourcePrefix}/`))return this.targetPrefix+e.slice(this.sourcePrefix.length);if(e===this.targetPrefix||e.startsWith(`${this.targetPrefix}/`))return e;if(e.startsWith("projects/"))throw new Error(["Cross-project storage access denied.",`Current project: ${this.targetPrefix}`,`Requested key: ${e}`].join(" "));return e}async put(e,t,n){return await this.ensureRegistered(),this.provider.put(this.key(e),t,n)}async get(e){return await this.ensureRegistered(),this.provider.get(this.key(e))}async getText(e){return await this.ensureRegistered(),this.provider.getText(this.key(e))}async delete(e){return await this.ensureRegistered(),this.provider.delete(this.key(e))}async exists(e){return await this.ensureRegistered(),this.provider.exists(this.key(e))}async list(e){return await this.ensureRegistered(),this.provider.list(this.key(e))}};import{createHash as Ge}from"node:crypto";import{dirname as Qe}from"node:path";import{mkdirSync as Xe,readFileSync as vn,renameSync as Ze,writeFileSync as et}from"node:fs";function m(r){return Ge("sha256").update(r).digest("hex")}function h(r,e){Xe(Qe(r),{recursive:!0});let t=`${r}.${process.pid}.tmp`;et(t,JSON.stringify(e,null,2)+`
5
+ `,{encoding:"utf8",mode:384}),Ze(t,r)}async function M(r,e){let t=await e.getText(`projects/${r.id}/work/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}import{existsSync as G,mkdirSync as rt,readFileSync as nt,statSync as H,writeFileSync as st}from"node:fs";import{dirname as ot,join as it}from"node:path";var Y=64*1024,at=`# ToolNet Project Operating Manual
6
6
 
7
7
  This file contains persistent instructions for AI agents working on this project.
8
8
 
@@ -45,11 +45,11 @@ Things an AI agent should always remember.
45
45
  <!--
46
46
  - [advisory] Prefer small focused files.
47
47
  -->
48
- `;function O(r){return Qe(r.rootPath,".toolnet","PROJECT.md")}function Ze(r){return r.normalize("NFKC").replace(/\s+/g," ").trim()}function et(r){let e=[],t=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,o;for(;o=n.exec(r);){let a=o[1].toLowerCase(),c=Ze(o[2]);if(!c)continue;let l=`${a}:${c.toLowerCase()}`;t.has(l)||(t.add(l),e.push({id:m(l).slice(0,24),mode:a,text:c,source:"manual"}))}return e}function tt(r){let e=O(r);return U(e)||(He(Ge(e),{recursive:!0}),Ye(e,Xe,{encoding:"utf8",mode:384})),e}function T(r,e=!1){let t=e?tt(r):O(r);if(!U(t))return null;if(q(t).size>H)throw new Error(`PROJECT.md exceeds ${H} bytes`);let o=Ue(t,"utf8");return{path:t,content:o,digest:m(o),rules:et(o),bytes:Buffer.byteLength(o,"utf8"),updatedAt:new Date(q(t).mtimeMs).toISOString()}}async function Y(r,e){let t=await e.getText(`projects/${r.id}/work/handoff-latest.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function G(r,e){let t=await e.getText(`projects/${r.id}/work/semantic/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}function E(r){if(!r)return 0;let e=Array.from(r).length,t=r.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,t*1.3))}function d(r,e){let t=r.replace(/\s+/g," ").trim();return t.length<=e?t:t.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function rt(r){let e=[],t=!1;for(let n of r.split(/\r?\n/u)){let o=n.trim();if(o.includes("<!--")&&(t=!0),t){o.includes("-->")&&(t=!1);continue}let a=o.toLowerCase();if(!(!o||o.startsWith("#")||o==="```"||a.startsWith("- [enforce]")||a.startsWith("* [enforce]")||a.startsWith("- [advisory]")||a.startsWith("* [advisory]"))&&(o=o.replace(/^[-*]\s+/u,""),o&&e.push(d(o,280)),e.length>=16))break}return e}function nt(r){let e=[],t=[];for(let n of r.split(/\\r?\\n/u)){let o=n.trim(),a=o.toLowerCase(),l=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(u=>a.startsWith(u));if(!l)continue;let i=o.slice(l.length).trim();i&&(l.includes("enforce")?e.push(i):t.push(i))}return{enforce:e,advisory:t}}function ot(r,e){let t=[];for(let n of r){let o=[...t,n].join(`
49
- `);if(E(o)<=e){t.push(n);continue}let a=E(t.join(`
50
- `)),c=Math.max(0,e-a);if(c>=16){let l=Math.floor(c*3.2),i=d(n,l);i&&t.push(i)}break}return t.join(`
51
- `).trim()}async function Q(r){let e=Math.max(256,Math.min(2e3,r.maxTokens??1e3)),t=T(r.project,!1),n=t?.content??"";n||(n=await r.storage.getText(`projects/${r.project.id}/project/manual.md`)??"");let o=nt(n),a=t?t.rules.filter(p=>p.mode==="enforce").map(p=>p.text):o.enforce,c=t?t.rules.filter(p=>p.mode==="advisory").map(p=>p.text):o.advisory,l=n?rt(n):[],i=await M(r.project,r.storage),u=await G(r.project,r.storage),f=await Y(r.project,r.storage),s=[];if(s.push("[TOOLNET PROJECT CONTEXT]"),s.push(`Project: ${r.project.name}`),s.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&s.push(`Full operating manual: ${O(r.project)}`),a.length){s.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let p of a.slice(0,24))s.push(`- [ENFORCE] ${d(p,240)}`)}if(c.length){s.push("","PROJECT PREFERENCES");for(let p of c.slice(0,10))s.push(`- ${d(p,220)}`)}if(u&&(u.mission&&s.push("","MISSION",d(u.mission.value,420)),u.activeObjective&&s.push("","CURRENT OBJECTIVE",d(u.activeObjective.value,420)),u.why&&s.push("","WHY THIS WORK MATTERS",d(u.why.value,420)),u.desiredOutcome&&s.push("","DESIRED OUTCOME",d(u.desiredOutcome.value,420)),u.planRationale&&s.push("","WHY THIS APPROACH",d(u.planRationale.value,420))),i){if(s.push("","ACTIVE WORK"),i.goal&&s.push(`Goal: ${d(i.goal,320)}`),i.plan&&s.push(`Plan: ${d(i.plan,320)}`),s.push(`Progress: phases ${i.progress.phasesCompleted}/${i.progress.phasesTotal}; tasks ${i.progress.tasksCompleted}/${i.progress.tasksTotal}; blocked ${i.progress.blocked}`),i.currentPhase&&s.push(`Current phase: ${i.currentPhase.title} [${i.currentPhase.status}]`),i.currentPhase&&u){let p=u.phases.find(g=>g.order===i.currentPhase?.order);p&&(p.objective&&s.push(`Phase objective: ${d(p.objective.value,340)}`),p.why?s.push(`Why this phase: ${d(p.why.value,340)}`):s.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),p.deliverable&&s.push(`Deliverable: ${d(p.deliverable.value,340)}`),p.dependencies.length&&s.push(`Depends on: ${p.dependencies.slice(0,4).map(g=>d(g.value,180)).join("; ")}`),p.acceptanceCriteria.length&&(s.push("","DEFINITION OF DONE"),p.acceptanceCriteria.slice(0,6).forEach(g=>{s.push(`- ${d(g.value,260)}`)})),p.openQuestions.length&&(s.push("","OPEN QUESTIONS FOR CURRENT PHASE"),p.openQuestions.slice(0,4).forEach(g=>{s.push(`- ${d(g.value,260)}`)})))}i.currentTask&&s.push(`Current task: ${i.currentTask.title} [${i.currentTask.status}]`),i.nextActions.length&&(s.push("","NEXT ACTIONS"),i.nextActions.slice(0,6).forEach((p,g)=>{s.push(`${g+1}. ${d(p,260)}`)})),i.blockers.length&&(s.push("","BLOCKERS"),i.blockers.slice(0,5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.warnings.length&&(s.push("","ATTENTION"),i.warnings.slice(-5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.decisions.length&&(s.push("","RECENT DECISIONS"),i.decisions.slice(-5).forEach(p=>{s.push(`- ${d(p,260)}`)})),i.lastSession&&s.push("",`Last work session: ${i.lastSession.agent} / ${i.lastSession.nativeSessionId}`)}if(u&&u.openQuestions.length&&(s.push("","UNRESOLVED QUESTIONS"),u.openQuestions.slice(0,5).forEach(p=>{s.push(`- ${d(p.value,260)}`)})),f&&s.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),l.length){s.push("","OPERATING NOTES");for(let p of l)s.push(`- ${p}`)}s.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let R=ot(s,e);return{version:1,projectId:r.project.id,projectName:r.project.name,text:R,estimatedTokens:E(R),maxTokens:e,hasManual:!!n,hasWorkState:!!i,hasHandoff:!!f,generatedAt:new Date().toISOString()}}import{existsSync as st,mkdirSync as it,readFileSync as at,writeFileSync as ct}from"node:fs";import{dirname as pt,join as X}from"node:path";function Z(r){return X(r.rootPath,".toolnet","context","startup.md")}function ut(r){return X(r.rootPath,".toolnet","context","startup.json")}function ee(r,e){let t=Z(r);it(pt(t),{recursive:!0}),ct(t,e.text.endsWith(`
48
+ `;function I(r){return it(r.rootPath,".toolnet","PROJECT.md")}function ct(r){return r.normalize("NFKC").replace(/\s+/g," ").trim()}function ut(r){let e=[],t=new Set,n=/^\s*[-*]\s+\[(enforce|advisory)\]\s+(.+?)\s*$/gimu,s;for(;s=n.exec(r);){let i=s[1].toLowerCase(),c=ct(s[2]);if(!c)continue;let l=`${i}:${c.toLowerCase()}`;t.has(l)||(t.add(l),e.push({id:m(l).slice(0,24),mode:i,text:c,source:"manual"}))}return e}function pt(r){let e=I(r);return G(e)||(rt(ot(e),{recursive:!0}),st(e,at,{encoding:"utf8",mode:384})),e}function R(r,e=!1){let t=e?pt(r):I(r);if(!G(t))return null;if(H(t).size>Y)throw new Error(`PROJECT.md exceeds ${Y} bytes`);let s=nt(t,"utf8");return{path:t,content:s,digest:m(s),rules:ut(s),bytes:Buffer.byteLength(s,"utf8"),updatedAt:new Date(H(t).mtimeMs).toISOString()}}async function Q(r,e){let t=await e.getText(`projects/${r.id}/work/handoff-latest.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}async function X(r,e){let t=await e.getText(`projects/${r.id}/work/semantic/current.json`);if(!t)return null;try{return JSON.parse(t)}catch{return null}}function C(r){if(!r)return 0;let e=Array.from(r).length,t=r.trim().split(/\s+/u).filter(Boolean).length;return Math.ceil(Math.max(e/3.5,t*1.3))}function d(r,e){let t=r.replace(/\s+/g," ").trim();return t.length<=e?t:t.slice(0,Math.max(0,e-1)).trimEnd()+"\u2026"}function lt(r){let e=[],t=!1;for(let n of r.split(/\r?\n/u)){let s=n.trim();if(s.includes("<!--")&&(t=!0),t){s.includes("-->")&&(t=!1);continue}let i=s.toLowerCase();if(!(!s||s.startsWith("#")||s==="```"||i.startsWith("- [enforce]")||i.startsWith("* [enforce]")||i.startsWith("- [advisory]")||i.startsWith("* [advisory]"))&&(s=s.replace(/^[-*]\s+/u,""),s&&e.push(d(s,280)),e.length>=16))break}return e}function dt(r){let e=[],t=[];for(let n of r.split(/\\r?\\n/u)){let s=n.trim(),i=s.toLowerCase(),l=["- [enforce]","* [enforce]","- [advisory]","* [advisory]"].find(p=>i.startsWith(p));if(!l)continue;let a=s.slice(l.length).trim();a&&(l.includes("enforce")?e.push(a):t.push(a))}return{enforce:e,advisory:t}}function mt(r,e){let t=[];for(let n of r){let s=[...t,n].join(`
49
+ `);if(C(s)<=e){t.push(n);continue}let i=C(t.join(`
50
+ `)),c=Math.max(0,e-i);if(c>=16){let l=Math.floor(c*3.2),a=d(n,l);a&&t.push(a)}break}return t.join(`
51
+ `).trim()}async function Z(r){let e=Math.max(256,Math.min(2e3,r.maxTokens??1e3)),t=R(r.project,!1),n=t?.content??"";n||(n=await r.storage.getText(`projects/${r.project.id}/project/manual.md`)??"");let s=dt(n),i=t?t.rules.filter(u=>u.mode==="enforce").map(u=>u.text):s.enforce,c=t?t.rules.filter(u=>u.mode==="advisory").map(u=>u.text):s.advisory,l=n?lt(n):[],a=await M(r.project,r.storage),p=await X(r.project,r.storage),f=await Q(r.project,r.storage),o=[];if(o.push("[TOOLNET PROJECT CONTEXT]"),o.push(`Project: ${r.project.name}`),o.push("Continue existing project state. Do not restart completed work unless evidence shows it is necessary."),n&&o.push(`Full operating manual: ${I(r.project)}`),i.length){o.push("","PROJECT RULES \u2014 MUST FOLLOW");for(let u of i.slice(0,24))o.push(`- [ENFORCE] ${d(u,240)}`)}if(c.length){o.push("","PROJECT PREFERENCES");for(let u of c.slice(0,10))o.push(`- ${d(u,220)}`)}if(p&&(p.mission&&o.push("","MISSION",d(p.mission.value,420)),p.activeObjective&&o.push("","CURRENT OBJECTIVE",d(p.activeObjective.value,420)),p.why&&o.push("","WHY THIS WORK MATTERS",d(p.why.value,420)),p.desiredOutcome&&o.push("","DESIRED OUTCOME",d(p.desiredOutcome.value,420)),p.planRationale&&o.push("","WHY THIS APPROACH",d(p.planRationale.value,420))),a){if(o.push("","ACTIVE WORK"),a.goal&&o.push(`Goal: ${d(a.goal,320)}`),a.plan&&o.push(`Plan: ${d(a.plan,320)}`),o.push(`Progress: phases ${a.progress.phasesCompleted}/${a.progress.phasesTotal}; tasks ${a.progress.tasksCompleted}/${a.progress.tasksTotal}; blocked ${a.progress.blocked}`),a.currentPhase&&o.push(`Current phase: ${a.currentPhase.title} [${a.currentPhase.status}]`),a.currentPhase&&p){let u=p.phases.find(g=>g.order===a.currentPhase?.order);u&&(u.objective&&o.push(`Phase objective: ${d(u.objective.value,340)}`),u.why?o.push(`Why this phase: ${d(u.why.value,340)}`):o.push("Why this phase: not explicitly recorded. Inspect existing implementation before assuming intent."),u.deliverable&&o.push(`Deliverable: ${d(u.deliverable.value,340)}`),u.dependencies.length&&o.push(`Depends on: ${u.dependencies.slice(0,4).map(g=>d(g.value,180)).join("; ")}`),u.acceptanceCriteria.length&&(o.push("","DEFINITION OF DONE"),u.acceptanceCriteria.slice(0,6).forEach(g=>{o.push(`- ${d(g.value,260)}`)})),u.openQuestions.length&&(o.push("","OPEN QUESTIONS FOR CURRENT PHASE"),u.openQuestions.slice(0,4).forEach(g=>{o.push(`- ${d(g.value,260)}`)})))}a.currentTask&&o.push(`Current task: ${a.currentTask.title} [${a.currentTask.status}]`),a.nextActions.length&&(o.push("","NEXT ACTIONS"),a.nextActions.slice(0,6).forEach((u,g)=>{o.push(`${g+1}. ${d(u,260)}`)})),a.blockers.length&&(o.push("","BLOCKERS"),a.blockers.slice(0,5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.warnings.length&&(o.push("","ATTENTION"),a.warnings.slice(-5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.decisions.length&&(o.push("","RECENT DECISIONS"),a.decisions.slice(-5).forEach(u=>{o.push(`- ${d(u,260)}`)})),a.lastSession&&o.push("",`Last work session: ${a.lastSession.agent} / ${a.lastSession.nativeSessionId}`)}if(p&&p.openQuestions.length&&(o.push("","UNRESOLVED QUESTIONS"),p.openQuestions.slice(0,5).forEach(u=>{o.push(`- ${d(u.value,260)}`)})),f&&o.push(`Latest handoff: ${f.reason} / ${f.sourceSession.agent}`),l.length){o.push("","OPERATING NOTES");for(let u of l)o.push(`- ${u}`)}o.push("","Before changing anything: verify the current repository state and continue from the active phase/task above.");let N=mt(o,e);return{version:1,projectId:r.project.id,projectName:r.project.name,text:N,estimatedTokens:C(N),maxTokens:e,hasManual:!!n,hasWorkState:!!a,hasHandoff:!!f,generatedAt:new Date().toISOString()}}import{existsSync as ft,mkdirSync as gt,readFileSync as ht,writeFileSync as yt}from"node:fs";import{dirname as St,join as ee}from"node:path";function te(r){return ee(r.rootPath,".toolnet","context","startup.md")}function jt(r){return ee(r.rootPath,".toolnet","context","startup.json")}function re(r,e){let t=te(r);gt(St(t),{recursive:!0}),yt(t,e.text.endsWith(`
52
52
  `)?e.text:e.text+`
53
- `,{encoding:"utf8",mode:384}),h(ut(r),e)}async function lt(r,e,t=900){let n=await Q({project:r,storage:e,maxTokens:t}),o={version:1,projectId:r.id,projectName:r.name,text:n.text,digest:m(n.text),estimatedTokens:n.estimatedTokens,generatedAt:new Date().toISOString()};return ee(r,o),await e.put(`projects/${r.id}/context/startup.md`,o.text+`
54
- `,"text/markdown"),await e.put(`projects/${r.id}/context/startup.json`,JSON.stringify(o,null,2)+`
55
- `,"application/json"),o}async function te(r,e,t=900){try{let o=await e.getText(`projects/${r.id}/context/startup.md`);if(o&&o.trim()){let a=o.trim(),c={version:1,projectId:r.id,projectName:r.name,text:a,digest:m(a),estimatedTokens:Math.ceil(a.length/3.5),generatedAt:new Date().toISOString()};return ee(r,c),c}}catch{}let n=Z(r);if(st(n))try{let o=at(n,"utf8").trim();if(o)return{version:1,projectId:r.id,projectName:r.name,text:o,digest:m(o),estimatedTokens:Math.ceil(o.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await lt(r,e,t)}catch{return null}}async function re(r){let e=await te(r.project,r.storage,900);return e?.text?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:e.text}}:{}}import{existsSync as dt}from"node:fs";import{dirname as mt,join as ft,parse as gt,resolve as ht}from"node:path";function ne(r){let e=ht(r),t=gt(e).root;for(;;){if(dt(ft(e,".toolnet","project.json")))return new w().detect(e);if(e===t)break;let n=mt(e);if(n===e)break;e=n}return null}async function yt(){let r="";for await(let e of process.stdin)r+=e.toString();if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}async function St(){let r=await yt();if(r.hook_event_name!=="SessionStart"){process.stdout.write("{}");return}let e=typeof r.cwd=="string"?r.cwd:"";if(!e){process.stdout.write("{}");return}let t=ne(e);if(!t){process.stdout.write("{}");return}try{let n=N(),o=F(K({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:2}),a=new P(o,t.id,t.name,t.remote??t.name),c=await re({project:t,storage:a});process.stdout.write(JSON.stringify(c))}catch{process.stdout.write("{}")}}St().catch(()=>{process.stdout.write("{}"),process.exitCode=0});
53
+ `,{encoding:"utf8",mode:384}),h(jt(r),e)}async function kt(r,e,t=900){let n=await Z({project:r,storage:e,maxTokens:t}),s={version:1,projectId:r.id,projectName:r.name,text:n.text,digest:m(n.text),estimatedTokens:n.estimatedTokens,generatedAt:new Date().toISOString()};return re(r,s),await e.put(`projects/${r.id}/context/startup.md`,s.text+`
54
+ `,"text/markdown"),await e.put(`projects/${r.id}/context/startup.json`,JSON.stringify(s,null,2)+`
55
+ `,"application/json"),s}async function ne(r,e,t=900){try{let s=await e.getText(`projects/${r.id}/context/startup.md`);if(s&&s.trim()){let i=s.trim(),c={version:1,projectId:r.id,projectName:r.name,text:i,digest:m(i),estimatedTokens:Math.ceil(i.length/3.5),generatedAt:new Date().toISOString()};return re(r,c),c}}catch{}let n=te(r);if(ft(n))try{let s=ht(n,"utf8").trim();if(s)return{version:1,projectId:r.id,projectName:r.name,text:s,digest:m(s),estimatedTokens:Math.ceil(s.length/3.5),generatedAt:new Date().toISOString()}}catch{}try{return await kt(r,e,t)}catch{return null}}async function se(r){let e=await ne(r.project,r.storage,900);return e?.text?{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:e.text}}:{}}import{existsSync as vt}from"node:fs";import{dirname as bt,join as wt,parse as xt,resolve as Pt}from"node:path";function oe(r){let e=Pt(r),t=xt(e).root;for(;;){if(vt(wt(e,".toolnet","project.json")))return new w().detect(e);if(e===t)break;let n=bt(e);if(n===e)break;e=n}return null}async function Ot(){let r="";for await(let e of process.stdin)r+=e.toString();if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}async function It(){let r=await Ot();if(r.hook_event_name!=="SessionStart"){process.stdout.write("{}");return}let e=typeof r.cwd=="string"?r.cwd:"";if(!e){process.stdout.write("{}");return}let t=oe(e);if(!t){process.stdout.write("{}");return}try{let n=$(),s=J(V({provider:n.storage.provider,huggingface:n.storage.huggingface,localRoot:n.storage.localRoot}),{attempts:2}),i=new O(s,t.id,t.name,t.remote??t.name),c=await se({project:t,storage:i});process.stdout.write(JSON.stringify(c))}catch{process.stdout.write("{}")}}It().catch(()=>{process.stdout.write("{}"),process.exitCode=0});