@gencode/agents 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,25 @@
1
1
  # @gencode/agents
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ff2729c: Add a batch_subagent_spawn tool that accepts multiple subagent tasks and runs them with a five-child concurrency limit.
8
+ - 80932da: Restrict subagent nesting depth from 3 to 2 and add depth-aware guardrails: system prompts now include a subagent constraint section discouraging deep nesting, and the subagent_spawn tool description warns subagents to prefer direct tool calls over spawning further subagents.
9
+
10
+ ### Patch Changes
11
+
12
+ - 80932da: Fix sub-subagent session directories being placed at the sessions root instead of nested inside the parent subagent's directory. Added `parentDir` field to `SessionPathOptions` so the session layer can resolve child paths relative to the spawning session's absolute directory, correctly nesting subagents at any depth.
13
+ - f96b5fd: Record successful agent file write and edit operations in per-session artifacts.json files with tool metadata, operation names, move sources, timestamps, and bounded content previews.
14
+ - 7e0ecf4: Stop truncating agent log message previews by default so full task and message text is preserved in logs.
15
+
3
16
  ## 0.3.1
4
17
 
5
18
  ### Patch Changes
6
19
 
20
+ - 5661a10: Temporarily omit effective custom agents from agent prompts and the subagent spawn tool contract.
21
+ - Persist assistant transcript entries as soon as a blocking `subagent_spawn` assistant message is complete, while still appending the corresponding `tool_result` entries after the subagents settle.
22
+ - b4687b0: Report subagent runs that return runner errors as failed instead of completed.
7
23
  - 4325f90: Store spawned subagent sessions under their parent session using the spawn tool call id as the child session id.
8
24
 
9
25
  ## 0.3.0
@@ -0,0 +1,71 @@
1
+ import{t as e}from"./rolldown-runtime-CNxR59P3.js";import{createRequire as t}from"node:module";import n from"node:fs/promises";import r,{basename as i}from"node:path";import a from"node:fs";import o,{randomUUID as s}from"node:crypto";const c=`sessions`,l=2e3,u=new Map;function d(e){let t=e?.trim()||c;if(!/^[A-Za-z0-9_-]+$/.test(t))throw Error(`Invalid session store name: ${e}. Must match /^[A-Za-z0-9_-]+$/`);return t}function f(e,t){let n=t.trim();if(!/^[A-Za-z0-9_-]+$/.test(n))throw Error(`Invalid ${e}: ${t}. Must match /^[A-Za-z0-9_-]+$/`);return n}function p(e,t){return r.join(e,`.aimax`,d(t?.storeName))}function m(e,t,n){let i=n?.subagent?f(`subagent session id`,t):t;if(n?.subagent){if(n.subagent.parentDir)return r.join(n.subagent.parentDir,`subagents`,i);let t=f(`parent session id`,n.subagent.parentSessionId);return r.join(p(e,n),t,`subagents`,i)}return r.join(p(e,n),i)}function h(e,t,n){return r.join(m(e,t,n),`transcript.jsonl`)}function g(e,t,n){return r.join(m(e,t,n),`artifacts.json`)}function _(e,t,n){return r.join(m(e,t,n),`session.json`)}function v(e,t,n){return r.join(m(e,t,n),`context.json`)}function y(e,t,n){return r.join(m(e,t,n),`session-memory.json`)}function ee(e,t,n){return r.join(m(e,t,n),`collapse-log.jsonl`)}function b(e,t,n){return r.join(m(e,t,n),`tool-results`)}function x(e,t,n){return r.join(m(e,t,n),`cron-executions.jsonl`)}const S={version:2,updatedAt:new Date(0).toISOString(),readStates:[],toolResults:[],compaction:{budgets:[],snips:[],collapseSpans:[],consecutiveAutocompactFailures:0}};async function te(e,t,i){let a=i?.sessionId??s(),o=m(e,a,i);await n.mkdir(o,{recursive:!0});let c=r.join(o,`.channel`);return await n.writeFile(c,t,`utf-8`),a}async function C(e,t,r){let i=m(e,t,r);await n.mkdir(i,{recursive:!0})}async function w(e,t,r){let i=h(e,t,r),a;try{a=await n.readFile(i,`utf-8`)}catch(e){if(e.code===`ENOENT`)return[];throw e}let o=[];for(let e of a.split(`
2
+ `)){let t=e.trim();if(t)try{o.push(JSON.parse(t))}catch{}}return o}async function ne(e,t,n,r){await C(e,t,r);let i=g(e,t,r);await oe(i,async()=>{let e=await T(i);await ae(i,{version:1,updatedAt:new Date().toISOString(),operations:[...e.operations,ie(n)]})})}async function re(e,t,n){return(await T(g(e,t,n))).operations}function ie(e){let t=e.content.length,n=t>l;return{...e,content:n?`${e.content.slice(0,Math.max(0,l-3))}...`:e.content,timestamp:new Date().toISOString(),truncated:n,originalChars:t}}async function T(e){let t;try{t=await n.readFile(e,`utf-8`)}catch(e){if(e.code===`ENOENT`)return E();throw e}try{let e=JSON.parse(t);return e.version!==1||!Array.isArray(e.operations)?E():{version:1,updatedAt:typeof e.updatedAt==`string`?e.updatedAt:new Date(0).toISOString(),operations:e.operations}}catch{return E()}}function E(){return{version:1,updatedAt:new Date(0).toISOString(),operations:[]}}async function ae(e,t){await n.mkdir(r.dirname(e),{recursive:!0});let i=`${e}.${process.pid}.${Date.now()}.tmp`;await n.writeFile(i,`${JSON.stringify(t,null,2)}\n`,`utf-8`),await n.rename(i,e)}async function oe(e,t){let n=(u.get(e)??Promise.resolve()).catch(()=>{}).then(t);u.set(e,n);try{await n}finally{u.get(e)===n&&u.delete(e)}}async function se(e,t,i,a){await C(e,t,a);let o=h(e,t,a),s=JSON.stringify(i)+`
3
+ `;await n.appendFile(o,s,`utf-8`);try{let{resolveMemoryProvider:t}=await import(`./provider-registry-CxtHsHdk.js`).then(e=>e.t),{createBuiltinMemoryProvider:n}=await Promise.resolve().then(()=>$),i=r.join(e,`.aimax`),s=t({providerId:a?.providerId,pluginId:a?.pluginId,dataDir:e,memoryDir:i,sessionStoreName:a?.storeName})?.provider??n({dataDir:e,memoryDir:i,sessionStoreName:a?.storeName});s.noteSessionUpdate&&s.noteSessionUpdate(o)}catch{}a?.onMemoryChanged&&await Promise.resolve(a.onMemoryChanged({reason:`transcript-append`,files:[r.join(d(a.storeName),t,`transcript.jsonl`).replace(/\\/g,`/`)],source:`sessions`,sessionId:t,providerId:a.providerId??a.pluginId,timestamp:new Date().toISOString()})).catch(()=>{})}async function ce(e,t,i,a){await C(e,t,a);let o=h(e,t,a),s=i(await w(e,t,a)),c=s.map(e=>JSON.stringify(e)).join(`
4
+ `);await n.writeFile(o,c.length>0?`${c}\n`:``,`utf-8`);try{let{resolveMemoryProvider:t}=await import(`./provider-registry-CxtHsHdk.js`).then(e=>e.t),{createBuiltinMemoryProvider:n}=await Promise.resolve().then(()=>$),i=r.join(e,`.aimax`),s=t({providerId:a?.providerId,pluginId:a?.pluginId,dataDir:e,memoryDir:i,sessionStoreName:a?.storeName})?.provider??n({dataDir:e,memoryDir:i,sessionStoreName:a?.storeName});s.noteSessionUpdate&&s.noteSessionUpdate(o)}catch{}return a?.onMemoryChanged&&await Promise.resolve(a.onMemoryChanged({reason:`transcript-rewrite`,files:[r.join(d(a.storeName),t,`transcript.jsonl`).replace(/\\/g,`/`)],source:`sessions`,sessionId:t,providerId:a.providerId??a.pluginId,timestamp:new Date().toISOString()})).catch(()=>{}),s}async function le(e,t,r,i){await C(e,t,i);let a=x(e,t,i),o=JSON.stringify(r)+`
5
+ `;await n.appendFile(a,o,`utf-8`)}async function ue(e,t,r){let i=x(e,t,r),a;try{a=await n.readFile(i,`utf-8`)}catch(e){if(e.code===`ENOENT`)return[];throw e}let o=[];for(let e of a.split(`
6
+ `)){let t=e.trim();if(t)try{o.push(JSON.parse(t))}catch{}}return o}async function D(e,t){let r=p(e,t);try{return(await n.readdir(r,{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name).sort()}catch(e){if(e.code===`ENOENT`)return[];throw e}}async function O(e,t,r){await C(e,t.id,r);let i=_(e,t.id,r);await n.writeFile(i,JSON.stringify(t,null,2),`utf-8`)}async function de(e,t,n,r){let i=await k(e,t,r);if(!i)return null;let a={...i,...n,id:i.id,createdAt:i.createdAt,updatedAt:new Date().toISOString()};return await O(e,a,r),a}async function k(e,t,i){let a=_(e,t,i);try{let o=await n.readFile(a,`utf-8`),s=JSON.parse(o);if(!s.channel){let a=r.join(m(e,t,i),`.channel`);try{s.channel=(await n.readFile(a,`utf-8`)).trim()}catch{s.channel=`WEB`}}return s}catch(e){if(e.code===`ENOENT`)return null;throw e}}async function fe(e,t,n){let r=await D(e,n),i=await Promise.all(r.map(async t=>{let r=await k(e,t,n);return{id:t,title:r?.title??t,channel:r?.channel??`WEB`,createdAt:r?.createdAt??``,updatedAt:r?.updatedAt??``}}));return t?i.filter(e=>e.channel===t):i}async function A(e,t,r){let i=v(e,t,r);try{let e=await n.readFile(i,`utf-8`),t=JSON.parse(e),r=typeof t.version==`number`?t.version:void 0;return r!==1&&r!==2?S:{version:2,updatedAt:typeof t.updatedAt==`string`?t.updatedAt:S.updatedAt,readStates:Array.isArray(t.readStates)?t.readStates:[],toolResults:Array.isArray(t.toolResults)?t.toolResults:[],compaction:{sessionMemory:t.compaction?.sessionMemory,modelUsage:t.compaction?.modelUsage,budgets:Array.isArray(t.compaction?.budgets)?t.compaction.budgets:[],snips:Array.isArray(t.compaction?.snips)?t.compaction.snips:[],collapseSpans:Array.isArray(t.compaction?.collapseSpans)?t.compaction.collapseSpans:[],consecutiveAutocompactFailures:typeof t.compaction?.consecutiveAutocompactFailures==`number`?t.compaction.consecutiveAutocompactFailures:0,lastCompactionAt:typeof t.compaction?.lastCompactionAt==`string`?t.compaction.lastCompactionAt:void 0,lastCompactionLayer:t.compaction?.lastCompactionLayer===`L1`||t.compaction?.lastCompactionLayer===`L2`||t.compaction?.lastCompactionLayer===`L3`||t.compaction?.lastCompactionLayer===`L4`||t.compaction?.lastCompactionLayer===`L5`||t.compaction?.lastCompactionLayer===`L6`?t.compaction.lastCompactionLayer:void 0}}}catch(e){if(e.code===`ENOENT`)return S;throw e}}async function pe(e,t,r){let i=m(e,t,r);try{return(await n.stat(i)).isDirectory()}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function j(e,t,n){let[r,i,a]=await Promise.all([k(e,t,n),w(e,t,n),A(e,t,n)]);return{id:t,metadata:r,transcriptPath:h(e,t,n),contextSnapshotPath:v(e,t,n),sessionMemoryPath:y(e,t,n),collapseLogPath:ee(e,t,n),toolResultsDir:b(e,t,n),transcriptEntryCount:i.length,readStateCount:a.readStates.length,toolResultRefCount:a.toolResults.length,transcriptEntries:i,context:a}}async function me(e,t,n){let r=await j(e,t,n);return{id:r.id,metadata:r.metadata,transcript:r.transcriptEntries,context:r.context,paths:{transcriptPath:r.transcriptPath,contextSnapshotPath:r.contextSnapshotPath,sessionMemoryPath:r.sessionMemoryPath,collapseLogPath:r.collapseLogPath,toolResultsDir:r.toolResultsDir}}}function M(e){return!!(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)}async function he(e){let t;try{t=await n.lstat(e)}catch(e){if(M(e))return{missing:!0};throw e}if(t.isSymbolicLink()||!t.isFile())throw Error(`path required`);return{missing:!1,stat:t}}function ge(e){try{a.mkdirSync(e,{recursive:!0})}catch{}return e}function _e(e){return e.trim().replace(/^[./]+/,``).replace(/\\/g,`/`)}function ve(e){let t=_e(e);return t?t===`MEMORY.md`||t===`memory.md`?!0:t.startsWith(`memory/`):!1}async function N(e,t){let i=await n.readdir(e,{withFileTypes:!0});for(let n of i){let i=r.join(e,n.name);if(!n.isSymbolicLink()){if(n.isDirectory()){await N(i,t);continue}n.isFile()&&n.name.endsWith(`.md`)&&t.push(i)}}}async function P(e){let t=[],i=r.join(e,`MEMORY.md`),a=r.join(e,`memory.md`),o=r.join(e,`memory`),s=async e=>{try{let r=await n.lstat(e);if(r.isSymbolicLink()||!r.isFile()||!e.endsWith(`.md`))return;t.push(e)}catch{}};await s(i),await s(a);try{let e=await n.lstat(o);!e.isSymbolicLink()&&e.isDirectory()&&await N(o,t)}catch{}if(t.length<=1)return t;let c=new Set,l=[];for(let e of t){let t=e;try{t=await n.realpath(e)}catch{}c.has(t)||(c.add(t),l.push(e))}return l}function F(e){return o.createHash(`sha256`).update(e).digest(`hex`)}async function ye(e,t){let i;try{i=await n.stat(e)}catch(e){if(M(e))return null;throw e}let a;try{a=await n.readFile(e,`utf-8`)}catch(e){if(M(e))return null;throw e}let o=F(a);return{path:r.relative(t,e).replace(/\\/g,`/`),absPath:e,mtimeMs:i.mtimeMs,size:i.size,hash:o}}function be(e,t){let n=e.split(`
7
+ `);if(n.length===0)return[];let r=Math.max(32,t.tokens*4),i=Math.max(0,t.overlap*4),a=[],o=[],s=0,c=()=>{if(o.length===0)return;let e=o[0],t=o[o.length-1];if(!e||!t)return;let n=o.map(e=>e.line).join(`
8
+ `),r=e.lineNo,i=t.lineNo;a.push({startLine:r,endLine:i,text:n,hash:F(n)})},l=()=>{if(i<=0||o.length===0){o=[],s=0;return}let e=0,t=[];for(let n=o.length-1;n>=0;--n){let r=o[n];if(r&&(e+=r.line.length+1,t.unshift(r),e>=i))break}o=t,s=t.reduce((e,t)=>e+t.line.length+1,0)};for(let e=0;e<n.length;e+=1){let t=n[e]??``,i=e+1,a=[];if(t.length===0)a.push(``);else for(let e=0;e<t.length;e+=r)a.push(t.slice(e,e+r));for(let e of a){let t=e.length+1;s+t>r&&o.length>0&&(c(),l()),o.push({line:e,lineNo:i}),s+=t}}return c(),a}function xe(e,t){if(!(!t||t.length===0))for(let n of e)n.startLine=t[n.startLine-1]??n.startLine,n.endLine=t[n.endLine-1]??n.endLine}function Se(e){try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function Ce(e,t){if(e.length===0||t.length===0)return 0;let n=Math.min(e.length,t.length),r=0,i=0,a=0;for(let o=0;o<n;o+=1){let n=e[o]??0,s=t[o]??0;r+=n*s,i+=n*n,a+=s*s}return i===0||a===0?0:r/(Math.sqrt(i)*Math.sqrt(a))}function we(e){return(e.toLowerCase().match(/[\p{L}\p{N}_]+/gu)??[]).filter(Boolean)}function Te(e){return o.createHash(`sha256`).update(e).digest().readUInt32BE(0)}function I(e,t=384){let n=Array(t).fill(0),r=we(e);if(r.length===0)return n;for(let e of r){let r=Te(e)%t;n[r]+=1}let i=Math.sqrt(n.reduce((e,t)=>e+t*t,0));if(i>0)for(let e=0;e<n.length;e+=1)n[e]=n[e]/i;return n}function L(e){let t=e?.model?.trim()||`mock-embedding-v1`,n=e?.dimensions??384;return{id:`external-mock`,model:t,embedQuery:async e=>I(e,n),embedBatch:async e=>e.map(e=>I(e,n))}}const R=new class{providers=new Map;byPluginId=new Map;register(e){this.providers.set(e.id,e),e.pluginId&&this.byPluginId.set(e.pluginId,e.id)}getById(e){return this.providers.get(e)}getByPluginId(e){let t=this.byPluginId.get(e);return t?this.providers.get(t):void 0}clear(){this.providers.clear(),this.byPluginId.clear()}};function Ee(e){let t=e.id?.trim()||e.pluginId;return R.register({id:t,pluginId:e.pluginId,create:e.create,config:e.config,rootDir:e.rootDir,source:e.source}),t}function z(e){let t=e.providerId?.trim(),n=e.pluginId?.trim(),r=(t?R.getById(t):void 0)??(n?R.getByPluginId(n):void 0);return r?{provider:r.create({dataDir:e.dataDir,memoryDir:e.memoryDir,pluginId:r.pluginId,config:r.config,rootDir:r.rootDir,source:r.source}),registration:r}:null}function De(){R.clear()}const B={enabled:!1,lambda:.7};function V(e){let t=e.toLowerCase().match(/[a-z0-9_]+/g)??[];return new Set(t)}function Oe(e,t){if(e.size===0&&t.size===0)return 1;if(e.size===0||t.size===0)return 0;let n=0,r=e.size<=t.size?e:t,i=e.size<=t.size?t:e;for(let e of r)i.has(e)&&n++;let a=e.size+t.size-n;return a===0?0:n/a}function ke(e,t,n){if(t.length===0)return 0;let r=0,i=n.get(e.id)??V(e.content);for(let e of t){let t=Oe(i,n.get(e.id)??V(e.content));t>r&&(r=t)}return r}function Ae(e,t,n){return n*e-(1-n)*t}function je(e,t={}){let{enabled:n=B.enabled,lambda:r=B.lambda}=t;if(!n||e.length<=1)return[...e];let i=Math.max(0,Math.min(1,r));if(i===1)return e.slice().sort((e,t)=>t.score-e.score);let a=new Map;for(let t of e)a.set(t.id,V(t.content));let o=Math.max(...e.map(e=>e.score)),s=Math.min(...e.map(e=>e.score)),c=o-s,l=e=>c===0?1:(e-s)/c,u=[],d=new Set(e);for(;d.size>0;){let e=null,t=-1/0;for(let n of d){let r=Ae(l(n.score),ke(n,u,a),i);(r>t||r===t&&n.score>(e?.score??-1/0))&&(t=r,e=n)}if(e)u.push(e),d.delete(e);else break}return u}function Me(e,t={}){if(e.length===0)return e;let n=new Map;return je(e.map((e,t)=>{let r=`${e.path}:${e.startLine}:${t}`;return n.set(r,e),{id:r,score:e.score,content:e.snippet}}),t).map(e=>n.get(e.id))}const H={enabled:!1,halfLifeDays:30},U=/(?:^|\/)(?:memory)\/(\d{4})-(\d{2})-(\d{2})\.md$/;function Ne(e){return!Number.isFinite(e)||e<=0?0:Math.LN2/e}function Pe(e){let t=Ne(e.halfLifeDays),n=Math.max(0,e.ageInDays);return t<=0||!Number.isFinite(n)?1:Math.exp(-t*n)}function Fe(e){return e.score*Pe(e)}function Ie(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``),n=U.exec(t);if(!n)return null;let r=Number(n[1]),i=Number(n[2]),a=Number(n[3]);if(!Number.isInteger(r)||!Number.isInteger(i)||!Number.isInteger(a))return null;let o=Date.UTC(r,i-1,a),s=new Date(o);return s.getUTCFullYear()!==r||s.getUTCMonth()!==i-1||s.getUTCDate()!==a?null:s}function Le(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``);return t===`MEMORY.md`||t===`memory.md`?!0:t.startsWith(`memory/`)?!U.test(t):!1}async function Re(e){let t=Ie(e.filePath);if(t)return t;if(e.source===`memory`&&Le(e.filePath)||!e.memoryRoot)return null;let i=r.isAbsolute(e.filePath)?e.filePath:r.resolve(e.memoryRoot,e.filePath);try{let e=await n.stat(i);return Number.isFinite(e.mtimeMs)?new Date(e.mtimeMs):null}catch{return null}}function ze(e,t){return Math.max(0,t-e.getTime())/864e5}async function Be(e){let t={...H,...e.temporalDecay};if(!t.enabled)return[...e.results];let n=e.nowMs??Date.now(),r=new Map;return Promise.all(e.results.map(async i=>{let a=`${i.source}:${i.path}`,o=r.get(a);o||(o=Re({filePath:i.path,source:i.source,memoryRoot:e.memoryRoot}),r.set(a,o));let s=await o;if(!s)return i;let c=Fe({score:i.score,ageInDays:ze(s,n),halfLifeDays:t.halfLifeDays});return{...i,score:c}}))}function Ve(e){let t=e.match(/[\p{L}\p{N}_]+/gu)?.map(e=>e.trim()).filter(Boolean)??[];return t.length===0?null:t.map(e=>`"${e.replaceAll(`"`,``)}"`).join(` AND `)}function He(e){return 1/(1+(Number.isFinite(e)?Math.max(0,e):999))}async function Ue(e){let t=new Map;for(let n of e.vector)t.set(n.id,{id:n.id,path:n.path,startLine:n.startLine,endLine:n.endLine,source:n.source,snippet:n.snippet,vectorScore:n.vectorScore,textScore:0});for(let n of e.keyword){let e=t.get(n.id);e?(e.textScore=n.textScore,n.snippet&&n.snippet.length>0&&(e.snippet=n.snippet)):t.set(n.id,{id:n.id,path:n.path,startLine:n.startLine,endLine:n.endLine,source:n.source,snippet:n.snippet,vectorScore:0,textScore:n.textScore})}let n=(await Be({results:Array.from(t.values()).map(t=>{let n=e.vectorWeight*t.vectorScore+e.textWeight*t.textScore;return{path:t.path,startLine:t.startLine,endLine:t.endLine,score:n,snippet:t.snippet,source:t.source}}),temporalDecay:{...H,...e.temporalDecay},memoryRoot:e.memoryRoot,nowMs:e.nowMs})).slice().sort((e,t)=>t.score-e.score),r={...B,...e.mmr};return r.enabled?Me(n,r):n}function We(e){e.db.exec(`
9
+ CREATE TABLE IF NOT EXISTS meta (
10
+ key TEXT PRIMARY KEY,
11
+ value TEXT NOT NULL
12
+ );
13
+ `),e.db.exec(`
14
+ CREATE TABLE IF NOT EXISTS files (
15
+ path TEXT PRIMARY KEY,
16
+ source TEXT NOT NULL DEFAULT 'memory',
17
+ hash TEXT NOT NULL,
18
+ mtime INTEGER NOT NULL,
19
+ size INTEGER NOT NULL
20
+ );
21
+ `),e.db.exec(`
22
+ CREATE TABLE IF NOT EXISTS chunks (
23
+ id TEXT PRIMARY KEY,
24
+ path TEXT NOT NULL,
25
+ source TEXT NOT NULL DEFAULT 'memory',
26
+ start_line INTEGER NOT NULL,
27
+ end_line INTEGER NOT NULL,
28
+ hash TEXT NOT NULL,
29
+ model TEXT NOT NULL,
30
+ text TEXT NOT NULL,
31
+ embedding TEXT NOT NULL,
32
+ updated_at INTEGER NOT NULL
33
+ );
34
+ `),e.db.exec(`
35
+ CREATE TABLE IF NOT EXISTS ${e.embeddingCacheTable} (
36
+ provider TEXT NOT NULL,
37
+ model TEXT NOT NULL,
38
+ provider_key TEXT NOT NULL,
39
+ hash TEXT NOT NULL,
40
+ embedding TEXT NOT NULL,
41
+ dims INTEGER,
42
+ updated_at INTEGER NOT NULL,
43
+ PRIMARY KEY (provider, model, provider_key, hash)
44
+ );
45
+ `),e.db.exec(`CREATE INDEX IF NOT EXISTS idx_embedding_cache_updated_at ON ${e.embeddingCacheTable}(updated_at);`);let t=!1,n;if(e.ftsEnabled)try{e.db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS ${e.ftsTable} USING fts5(\n text,\n id UNINDEXED,\n path UNINDEXED,\n source UNINDEXED,\n model UNINDEXED,\n start_line UNINDEXED,\n end_line UNINDEXED\n);`),t=!0}catch(e){let r=e instanceof Error?e.message:String(e);t=!1,n=r}return W(e.db,`files`,`source`,`TEXT NOT NULL DEFAULT 'memory'`),W(e.db,`chunks`,`source`,`TEXT NOT NULL DEFAULT 'memory'`),e.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);`),e.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`),{ftsAvailable:t,...n?{ftsError:n}:{}}}function W(e,t,n,r){e.prepare(`PRAGMA table_info(${t})`).all().some(e=>e.name===n)||e.exec(`ALTER TABLE ${t} ADD COLUMN ${n} ${r}`)}function G(e,t){return e.length<=t?e:e.slice(0,t)}const Ge=e=>Buffer.from(new Float32Array(e).buffer);async function Ke(e){return e.queryVec.length===0||e.limit<=0?[]:await e.ensureVectorReady(e.queryVec.length)?e.db.prepare(`SELECT c.id, c.path, c.start_line, c.end_line, c.text,
46
+ c.source,
47
+ vec_distance_cosine(v.embedding, ?) AS dist
48
+ FROM ${e.vectorTable} v\n JOIN chunks c ON c.id = v.id\n WHERE c.model = ?${e.sourceFilterVec.sql}\n ORDER BY dist ASC\n LIMIT ?`).all(Ge(e.queryVec),e.providerModel,...e.sourceFilterVec.params,e.limit).map(t=>({id:t.id,path:t.path,startLine:t.start_line,endLine:t.end_line,score:1-t.dist,snippet:G(t.text,e.snippetMaxChars),source:t.source})):qe({db:e.db,providerModel:e.providerModel,sourceFilter:e.sourceFilterChunks}).map(t=>({chunk:t,score:Ce(e.queryVec,t.embedding)})).filter(e=>Number.isFinite(e.score)).slice().sort((e,t)=>t.score-e.score).slice(0,e.limit).map(t=>({id:t.chunk.id,path:t.chunk.path,startLine:t.chunk.startLine,endLine:t.chunk.endLine,score:t.score,snippet:G(t.chunk.text,e.snippetMaxChars),source:t.chunk.source}))}function qe(e){return e.db.prepare(`SELECT id, path, start_line, end_line, text, embedding, source
49
+ FROM chunks
50
+ WHERE model = ?${e.sourceFilter.sql}`).all(e.providerModel,...e.sourceFilter.params).map(e=>({id:e.id,path:e.path,startLine:e.start_line,endLine:e.end_line,text:e.text,embedding:Se(e.embedding),source:e.source}))}async function Je(e){if(e.limit<=0)return[];let t=e.buildFtsQuery(e.query);if(!t)return[];let n=e.providerModel?` AND model = ?`:``,r=e.providerModel?[e.providerModel]:[];return e.db.prepare(`SELECT id, path, source, start_line, end_line, text,\n bm25(${e.ftsTable}) AS rank\n FROM ${e.ftsTable}\n WHERE ${e.ftsTable} MATCH ?${n}${e.sourceFilter.sql}\n ORDER BY rank ASC\n LIMIT ?`).all(t,...r,...e.sourceFilter.params,e.limit).map(t=>{let n=e.bm25RankToScore(t.rank);return{id:t.id,path:t.path,startLine:t.start_line,endLine:t.end_line,score:n,textScore:n,snippet:G(t.text,e.snippetMaxChars),source:t.source}})}const Ye=t(import.meta.url);function Xe(){try{return Ye(`node:sqlite`)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`SQLite support is unavailable in this Node runtime (missing node:sqlite). ${t}`,{cause:e})}}const K={chunkTokens:400,chunkOverlap:80,maxResults:6,minScore:.2,fallback:{enabled:!0},embedding:{},experimental:{sessionMemory:!1},sources:[`memory`],store:{sessionStoreName:void 0,vector:{enabled:!0}},hybrid:{enabled:!0,vectorWeight:.7,textWeight:.3,candidateMultiplier:4,mmr:{enabled:!1,lambda:.7},temporalDecay:{enabled:!1,halfLifeDays:30}},cache:{enabled:!0,maxEntries:5e4},sync:{onSessionStart:!0,onSearch:!0,watch:!0,watchDebounceMs:1500,sessions:{deltaBytes:1e5,deltaMessages:50}},citations:`auto`};async function Ze(e){try{let t=await import(`sqlite-vec`),n=e.extensionPath?.trim()?e.extensionPath.trim():void 0,r=n??t.getLoadablePath();return e.db.enableLoadExtension(!0),n?e.db.loadExtension(r):t.load(e.db),{ok:!0,extensionPath:r}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}function Qe(e,t,n){let i=p(e,{storeName:n});return r.relative(i,t).replace(/\\/g,`/`)}async function $e(e,t){let i=p(e,{storeName:t});try{let e=await n.readdir(i,{withFileTypes:!0}),t=[];for(let a of e){if(!a.isDirectory())continue;let e=r.join(i,a.name,`transcript.jsonl`);try{(await n.stat(e)).isFile()&&t.push(e)}catch{}}return t}catch(e){if(M(e))return[];throw e}}function et(e){return typeof e==`string`?e:Array.isArray(e)?e.map(e=>typeof e==`string`?e:e&&typeof e==`object`&&`text`in e?String(e.text??``):``).filter(Boolean).join(` `):e?String(e):``}async function tt(e,t,i){let a;try{a=await n.stat(t)}catch(e){if(M(e))return null;throw e}let o;try{o=await n.readFile(t,`utf-8`)}catch(e){if(M(e))return null;throw e}let s=[],c=[],l=o.split(`
51
+ `);for(let e=0;e<l.length;e+=1){let t=l[e]?.trim();if(t)try{let n=JSON.parse(t),r=n.role??`unknown`,i=et(n.content);if(!i)continue;let a=i.split(`
52
+ `);for(let t of a)s.push(`[${r}] ${t}`),c.push(e+1)}catch{}}let u=s.join(`
53
+ `),f=F(u);return{path:r.join(d(i),Qe(e,t,i)).replace(/\\/g,`/`),absPath:t,mtimeMs:a.mtimeMs,size:a.size,hash:f,content:u,lineMap:c}}const q=`chunks_vec`,J=`chunks_fts`,Y=`embedding_cache`,X=`memory_index_meta_v1`,Z=3e4;function nt(e,t,n){let r=t.split(`
54
+ `);for(let t of r){let n=t.match(/^##\s+(.+)$/);if(n?.[1])return`${e}#${n[1].trim()}`}return`${e}#L${n}`}const rt=new Map;function Q(e,t){let n={...e,...t,hybrid:{...e.hybrid,...t?.hybrid??{}},cache:{...e.cache,...t?.cache??{}},sync:{...e.sync,...t?.sync??{}},experimental:{...e.experimental,...t?.experimental??{}},sources:t?.sources??e.sources,embedding:{...e.embedding,...t?.embedding??{}},store:{...e.store,...t?.store??{},vector:{...e.store.vector,...t?.store?.vector??{}}}};return n.experimental.sessionMemory&&!n.sources.includes(`sessions`)&&(n.sources=[...n.sources,`sessions`]),n}var it=class e{dataDir;memoryRoot;storePath;config;sessionStoreName;provider;providerKey;embeddingProviderId;db;dirty=!0;ftsAvailable=!1;ftsError;vector={enabled:!0,available:null,extensionPath:void 0,loadError:void 0,dims:void 0};vectorReady=null;watchers=[];watchTimer=null;sessionWatchTimer=null;sessionsDirty=!1;sessionsDirtyFiles=new Set;sessionPendingFiles=new Set;searchFallbackOnly=!1;lastRebuildSummary;sessionDeltas=new Map;static get(t,n){let i=r.join(t,`.aimax`),a=Q(K,n),o=`${i}::${d(a.store.sessionStoreName)}`,s=rt.get(o);if(s)return n&&s.applyConfig(n),s;let c=new e(t,i,a);return rt.set(o,c),c}constructor(e,t,n){this.dataDir=e,this.memoryRoot=t,this.storePath=r.join(t,`.index.sqlite`),this.config=Q(K,n),this.sessionStoreName=d(this.config.store.sessionStoreName),this.provider=L(),this.providerKey=this.computeProviderKey(),this.applyEmbeddingProvider(),this.vector.enabled=this.config.store.vector.enabled,this.vector.extensionPath=this.config.store.vector.extensionPath,this.db=this.openDatabase(),this.ensureSchema(),this.ensureWatcher(),this.ensureSessionListener(),this.dirty=!0}applyConfig(e){this.config=Q(this.config,e),this.sessionStoreName=d(this.config.store.sessionStoreName),this.applyEmbeddingProvider(),this.vector.enabled=this.config.store.vector.enabled,this.vector.extensionPath=this.config.store.vector.extensionPath,this.ensureWatcher(),this.ensureSessionListener()}warmSession(){this.config.sync.onSessionStart&&this.sync({reason:`session-start`}).catch(()=>{})}noteSessionUpdate(e){this.scheduleSessionDirty(e)}status(){let e=this.buildSourceFilter(),t=this.db.prepare(`SELECT COUNT(*) as c FROM files WHERE 1=1${e.sql}`).get(...e.params),n=this.db.prepare(`SELECT COUNT(*) as c FROM chunks WHERE 1=1${e.sql}`).get(...e.params),r=(()=>{let t=Array.from(this.config.sources);if(t.length===0)return[];let n=new Map;for(let e of t)n.set(e,{files:0,chunks:0});let r=this.db.prepare(`SELECT source, COUNT(*) as c FROM files WHERE 1=1${e.sql} GROUP BY source`).all(...e.params);for(let e of r){let t=n.get(e.source)??{files:0,chunks:0};t.files=e.c??0,n.set(e.source,t)}let i=this.db.prepare(`SELECT source, COUNT(*) as c FROM chunks WHERE 1=1${e.sql} GROUP BY source`).all(...e.params);for(let e of i){let t=n.get(e.source)??{files:0,chunks:0};t.chunks=e.c??0,n.set(e.source,t)}return t.map(e=>Object.assign({source:e},n.get(e)))})(),i=this.provider?`hybrid`:`fts-only`,a=this.config.cache.enabled?this.db.prepare(`SELECT COUNT(*) as c FROM ${Y}`).get()?.c??0:void 0;return{backend:`builtin`,files:t?.c??0,chunks:n?.c??0,dirty:this.dirty||this.sessionsDirty,workspaceDir:this.memoryRoot,dbPath:this.storePath,provider:this.provider.id,model:this.provider.model,sources:Array.from(this.config.sources),sourceCounts:r,cache:this.config.cache.enabled?{enabled:!0,entries:a,maxEntries:this.config.cache.maxEntries}:{enabled:!1,maxEntries:this.config.cache.maxEntries},fts:{enabled:this.config.hybrid.enabled,available:this.ftsAvailable,error:this.ftsError,rows:this.getFtsRowCount()},vector:{enabled:this.vector.enabled,available:this.vector.available??void 0,extensionPath:this.vector.extensionPath,loadError:this.vector.loadError,dims:this.vector.dims},custom:{searchMode:i,fallbackActive:this.searchFallbackOnly,lastRebuildSummary:this.lastRebuildSummary}}}async probeEmbeddingAvailability(){try{return await this.provider.embedBatch([`ping`]),{ok:!0}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async probeVectorAvailability(){return this.vector.enabled?await this.ensureVectorReady():!1}async search(e){let t=e.trim();if(!t)return[];if(this.readMeta()?this.config.sync.onSearch&&(this.dirty||this.sessionsDirty)&&this.sync({reason:`search`}).catch(()=>{this.searchFallbackOnly=!0}):await this.sync({reason:`boot`}).catch(()=>{this.searchFallbackOnly=!0}),this.searchFallbackOnly)return this.decorateCitations(await this.fileScanSearch(t));let n=this.config.hybrid,r=Math.min(200,Math.max(1,Math.floor(this.config.maxResults*n.candidateMultiplier))),i=n.enabled&&this.ftsAvailable?await this.searchKeyword(t,r).catch(()=>[]):[],a=await this.provider.embedQuery(t).catch(()=>[]),o=a.some(e=>e!==0)?await this.searchVector(a,r).catch(()=>[]):[],s=[];if(!n.enabled||!this.ftsAvailable)s=o.filter(e=>e.score>=this.config.minScore).slice(0,this.config.maxResults);else{let e=await Ue({vector:o.map(e=>({id:`${e.path}:${e.startLine}:${e.endLine}:${e.source}`,path:e.path,startLine:e.startLine,endLine:e.endLine,source:e.source,snippet:e.snippet,vectorScore:e.score})),keyword:i.map(e=>({id:`${e.path}:${e.startLine}:${e.endLine}:${e.source}`,path:e.path,startLine:e.startLine,endLine:e.endLine,source:e.source,snippet:e.snippet,textScore:e.textScore})),vectorWeight:n.vectorWeight,textWeight:n.textWeight,mmr:n.mmr,temporalDecay:n.temporalDecay,memoryRoot:this.memoryRoot}),t=e.filter(e=>e.score>=this.config.minScore);if(t.length>0||i.length===0)s=t.slice(0,this.config.maxResults);else{let t=Math.min(this.config.minScore,n.textWeight);s=e.filter(e=>e.score>=t).slice(0,this.config.maxResults)}}return s.length>0?this.decorateCitations(this.decorateEntryIds(s)):this.config.fallback.enabled?(this.searchFallbackOnly=!0,this.decorateCitations(this.decorateEntryIds(await this.fileScanSearch(t)))):[]}async readFile(e){let{absPath:t,relPath:r}=this.resolveMemoryFilePath(e.relPath);if((await he(t)).missing)return{text:``,path:r};let i;try{i=await n.readFile(t,`utf-8`)}catch(e){if(M(e))return{text:``,path:r};throw e}if(!e.from&&!e.lines)return{text:i,path:r};let a=i.split(`
55
+ `),o=Math.max(1,e.from??1),s=Math.max(1,e.lines??a.length);return{text:a.slice(o-1,o-1+s).join(`
56
+ `),path:r}}async replaceFile(e){let{absPath:t}=this.resolveMemoryFilePath(e.relPath);await n.mkdir(r.dirname(t),{recursive:!0}),await n.writeFile(t,e.content,`utf-8`),this.dirty=!0,await this.syncAndPostCheck(`replace`)}async deleteFile(e){let{absPath:t}=this.resolveMemoryFilePath(e);try{await n.unlink(t)}catch(e){if(M(e))return;throw e}this.dirty=!0,await this.syncAndPostCheck(`delete`)}async appendToMemory(e){let t=this.memoryRoot;await n.mkdir(t,{recursive:!0});let i=r.join(t,`MEMORY.md`),a=e.endsWith(`
57
+ `)?e:`${e}\n`;await n.appendFile(i,a,`utf-8`),this.dirty=!0,await this.syncAndPostCheck(`append`)}openDatabase(){ge(r.dirname(this.storePath));let{DatabaseSync:e}=Xe();return new e(this.storePath,{allowExtension:this.vector.enabled})}ensureSchema(){let e=We({db:this.db,embeddingCacheTable:Y,ftsTable:J,ftsEnabled:this.config.hybrid.enabled});this.ftsAvailable=e.ftsAvailable,e.ftsError&&(this.ftsError=e.ftsError)}async ensureVectorReady(e){if(!this.vector.enabled)return!1;this.vectorReady||=this.withTimeout(this.loadVectorExtension(),Z,`sqlite-vec load timed out after ${Math.round(Z/1e3)}s`);let t=!1;try{t=await this.vectorReady||!1}catch(e){let t=e instanceof Error?e.message:String(e);return this.vector.available=!1,this.vector.loadError=t,this.vectorReady=null,!1}return t&&typeof e==`number`&&e>0&&this.ensureVectorTable(e),t}async loadVectorExtension(){if(this.vector.available!==null)return this.vector.available;if(!this.vector.enabled)return this.vector.available=!1,!1;try{let e=this.vector.extensionPath?.trim()?this.vector.extensionPath.trim():void 0,t=await Ze({db:this.db,extensionPath:e});if(!t.ok)throw Error(t.error??`unknown sqlite-vec load error`);return this.vector.extensionPath=t.extensionPath,this.vector.available=!0,!0}catch(e){let t=e instanceof Error?e.message:String(e);return this.vector.available=!1,this.vector.loadError=t,!1}}ensureVectorTable(e){this.vector.dims!==e&&(this.vector.dims&&this.vector.dims!==e&&this.dropVectorTable(),this.db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS ${q} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${e}]\n)`),this.vector.dims=e)}dropVectorTable(){try{this.db.exec(`DROP TABLE IF EXISTS ${q}`)}catch{}}async withTimeout(e,t,n){if(!Number.isFinite(t)||t<=0)return await e;let r=null,i=new Promise((e,i)=>{r=setTimeout(()=>i(Error(n)),t)});try{return await Promise.race([e,i])}finally{r&&clearTimeout(r)}}ensureWatcher(){if(!this.config.sync.watch||this.watchers.length>0)return;let e=[r.join(this.memoryRoot,`MEMORY.md`),r.join(this.memoryRoot,`memory.md`),r.join(this.memoryRoot,`memory`)],t=()=>{this.dirty=!0,this.scheduleWatchSync()};for(let n of e)try{let e=a.watch(n,{recursive:!1},t);e.on(`error`,()=>{try{e.close()}catch{}}),this.watchers.push(e)}catch{}}scheduleWatchSync(){this.config.sync.watch&&(this.watchTimer&&clearTimeout(this.watchTimer),this.watchTimer=setTimeout(()=>{this.watchTimer=null,this.sync({reason:`watch`}).catch(()=>{})},this.config.sync.watchDebounceMs))}ensureSessionListener(){if(!this.config.experimental.sessionMemory)return;let e=p(this.dataDir,{storeName:this.sessionStoreName});try{let t=a.watch(e,{recursive:!0},(t,n)=>{if(!n||!n.endsWith(`transcript.jsonl`))return;let i=r.join(e,n);this.scheduleSessionDirty(i)});this.watchers.push(t)}catch{}}scheduleSessionDirty(e){this.config.experimental.sessionMemory&&(this.sessionPendingFiles.add(e),!this.sessionWatchTimer&&(this.sessionWatchTimer=setTimeout(()=>{this.sessionWatchTimer=null,this.processSessionDeltaBatch().catch(()=>{})},5e3)))}async processSessionDeltaBatch(){if(this.sessionPendingFiles.size===0)return;let e=Array.from(this.sessionPendingFiles);this.sessionPendingFiles.clear();let t=!1;for(let n of e){let e=await this.updateSessionDelta(n);if(!e)continue;let r=e.deltaBytes,i=e.deltaMessages,a=r<=0?e.pendingBytes>0:e.pendingBytes>=r,o=i<=0?e.pendingMessages>0:e.pendingMessages>=i;!a&&!o||(this.sessionsDirtyFiles.add(n),this.sessionsDirty=!0,e.pendingBytes=r>0?Math.max(0,e.pendingBytes-r):0,e.pendingMessages=i>0?Math.max(0,e.pendingMessages-i):0,t=!0)}t&&this.sync({reason:`session-delta`}).catch(()=>{})}async updateSessionDelta(e){let t=this.config.sync.sessions;if(!t)return null;let r;try{r=await n.stat(e)}catch{return null}let i=r.size,a=this.sessionDeltas.get(e);a||(a={lastSize:0,pendingBytes:0,pendingMessages:0},this.sessionDeltas.set(e,a));let o=Math.max(0,i-a.lastSize);return o===0&&i===a.lastSize?{deltaBytes:t.deltaBytes,deltaMessages:t.deltaMessages,pendingBytes:a.pendingBytes,pendingMessages:a.pendingMessages}:(i<a.lastSize?(a.lastSize=i,a.pendingBytes+=i,t.deltaMessages>0&&(t.deltaBytes<=0||a.pendingBytes<t.deltaBytes)&&(a.pendingMessages+=await this.countNewlines(e,0,i))):(a.pendingBytes+=o,t.deltaMessages>0&&(t.deltaBytes<=0||a.pendingBytes<t.deltaBytes)&&(a.pendingMessages+=await this.countNewlines(e,a.lastSize,i)),a.lastSize=i),this.sessionDeltas.set(e,a),{deltaBytes:t.deltaBytes,deltaMessages:t.deltaMessages,pendingBytes:a.pendingBytes,pendingMessages:a.pendingMessages})}async countNewlines(e,t,r){if(r<=t)return 0;let i;try{i=await n.open(e,`r`)}catch{return 0}try{let e=t,n=0,a=Buffer.alloc(64*1024);for(;e<r;){let t=Math.min(a.length,r-e),{bytesRead:o}=await i.read(a,0,t,e);if(o<=0)break;for(let e=0;e<o;e+=1)a[e]===10&&(n+=1);e+=o}return n}finally{await i.close()}}computeProviderKey(){return F(JSON.stringify({provider:this.provider.id,model:this.provider.model}))}resolveMemoryFilePath(e){let t=e.trim();if(!t)throw Error(`path required`);let n=r.isAbsolute(t)?r.resolve(t):r.resolve(this.memoryRoot,t),i=r.relative(this.memoryRoot,n).replace(/\\/g,`/`);if(!(i.length>0&&!i.startsWith(`..`)&&!r.isAbsolute(i)&&ve(i))||!n.endsWith(`.md`))throw Error(`path required`);return{absPath:n,relPath:i}}applyEmbeddingProvider(){let e=this.config.embedding?.providerId?.trim();if(e){let t=z({providerId:e,dataDir:this.dataDir,memoryDir:this.memoryRoot});if(!t)throw Error(`Embedding provider not found: ${e}`);this.provider=t.provider,this.embeddingProviderId=e,this.providerKey=this.computeProviderKey(),this.dirty=!0;return}this.embeddingProviderId&&(this.provider=L(),this.embeddingProviderId=void 0,this.providerKey=this.computeProviderKey(),this.dirty=!0)}readMeta(){let e=this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(X);if(!e?.value)return null;try{return JSON.parse(e.value)}catch{return null}}writeMeta(e){let t=JSON.stringify(e);this.db.prepare(`INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(X,t)}loadEmbeddingCache(e){if(!this.config.cache.enabled||e.length===0)return new Map;let t=Array.from(new Set(e.filter(Boolean)));if(t.length===0)return new Map;let n=new Map,r=[this.provider.id,this.provider.model,this.providerKey];for(let e=0;e<t.length;e+=400){let i=t.slice(e,e+400),a=i.map(()=>`?`).join(`, `),o=this.db.prepare(`SELECT hash, embedding FROM ${Y}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${a})`).all(...r,...i);for(let e of o)n.set(e.hash,Se(e.embedding))}return n}upsertEmbeddingCache(e){if(!this.config.cache.enabled||e.length===0)return;let t=Date.now(),n=this.db.prepare(`INSERT INTO ${Y} (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(provider, model, provider_key, hash) DO UPDATE SET\n embedding=excluded.embedding,\n dims=excluded.dims,\n updated_at=excluded.updated_at`);for(let r of e){let e=r.embedding??[];n.run(this.provider.id,this.provider.model,this.providerKey,r.hash,JSON.stringify(e),e.length,t)}}async embedChunks(e){if(e.length===0)return[];let t=this.loadEmbeddingCache(e.map(e=>e.hash)),n=Array.from({length:e.length},()=>[]),r=[];for(let i=0;i<e.length;i+=1){let a=e[i],o=a?.hash?t.get(a.hash):void 0;o&&o.length>0?n[i]=o:a&&r.push({index:i,chunk:a})}if(r.length===0)return n;let i=await this.provider.embedBatch(r.map(e=>e.chunk.text)),a=[];for(let e=0;e<r.length;e+=1){let t=r[e],o=i[e]??[];n[t.index]=o,a.push({hash:t.chunk.hash,embedding:o})}return this.upsertEmbeddingCache(a),n}async indexFile(e,t){let r=be(t.content??await n.readFile(e.absPath,`utf-8`),{tokens:this.config.chunkTokens,overlap:this.config.chunkOverlap}).filter(e=>e.text.trim().length>0);t.source===`sessions`&&xe(r,t.lineMap);let i=await this.embedChunks(r),a=i.find(e=>e.length>0),o=a?await this.ensureVectorReady(a.length):!1,s=Date.now();if(o)try{this.db.prepare(`DELETE FROM ${q} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`).run(e.path,t.source)}catch{}if(this.ftsAvailable)try{this.db.prepare(`DELETE FROM ${J} WHERE path = ? AND source = ? AND model = ?`).run(e.path,t.source,this.provider.model)}catch{}this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(e.path,t.source);for(let n=0;n<r.length;n+=1){let a=r[n],c=i[n]??[],l=F(`${t.source}:${e.path}:${a.startLine}:${a.endLine}:${a.hash}:${this.provider.model}`);if(this.db.prepare(`INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)
58
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
59
+ ON CONFLICT(id) DO UPDATE SET
60
+ hash=excluded.hash,
61
+ model=excluded.model,
62
+ text=excluded.text,
63
+ embedding=excluded.embedding,
64
+ updated_at=excluded.updated_at`).run(l,e.path,t.source,a.startLine,a.endLine,a.hash,this.provider.model,a.text,JSON.stringify(c),s),o&&c.length>0){try{this.db.prepare(`DELETE FROM ${q} WHERE id = ?`).run(l)}catch{}this.db.prepare(`INSERT INTO ${q} (id, embedding) VALUES (?, ?)`).run(l,Buffer.from(new Float32Array(c).buffer))}this.ftsAvailable&&this.db.prepare(`INSERT INTO ${J} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`).run(a.text,l,e.path,t.source,this.provider.model,a.startLine,a.endLine)}this.db.prepare(`INSERT INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)
65
+ ON CONFLICT(path) DO UPDATE SET
66
+ source=excluded.source,
67
+ hash=excluded.hash,
68
+ mtime=excluded.mtime,
69
+ size=excluded.size`).run(e.path,t.source,e.hash,e.mtimeMs,e.size)}buildSourceFilter(){let e=this.config.sources;return e.length?{sql:` AND source IN (${e.map(()=>`?`).join(`, `)})`,params:e}:{sql:``,params:[]}}async searchVector(e,t){return await Ke({db:this.db,vectorTable:q,providerModel:this.provider.model,queryVec:e,limit:t,snippetMaxChars:700,ensureVectorReady:async e=>await this.ensureVectorReady(e),sourceFilterVec:this.buildSourceFilter(),sourceFilterChunks:this.buildSourceFilter()})}async searchKeyword(e,t){return this.ftsAvailable?await Je({db:this.db,ftsTable:J,providerModel:this.provider.model,query:e,limit:t,snippetMaxChars:700,sourceFilter:this.buildSourceFilter(),buildFtsQuery:e=>Ve(e),bm25RankToScore:He}):[]}resetIndex(){if(this.db.exec(`DELETE FROM files`),this.db.exec(`DELETE FROM chunks`),this.ftsAvailable)try{this.db.exec(`DELETE FROM ${J}`)}catch{}this.dropVectorTable(),this.vector.dims=void 0,this.sessionsDirtyFiles.clear()}async syncAndPostCheck(e){try{await this.sync({reason:`mutation-postcheck`})}catch{this.searchFallbackOnly=!0;return}this.searchFallbackOnly=!this.indexHasSearchableData()}indexHasSearchableData(){try{if((this.db.prepare(`SELECT COUNT(*) as c FROM chunks`).get()?.c??0)>0)return!0}catch{}try{if(a.readdirSync(this.memoryRoot).filter(e=>e.endsWith(`.md`)).length>0)return!1;let e=r.join(this.memoryRoot,`memory`);return a.existsSync(e)?a.readdirSync(e).filter(e=>e.endsWith(`.md`)).length===0:!0}catch{return!1}}async fileScanSearch(e){let t=e.trim().toLowerCase();if(!t)return[];let a=await P(this.memoryRoot),o=[];for(let e of a){let a=``;try{a=await n.readFile(e,`utf-8`)}catch{continue}let s=r.relative(this.memoryRoot,e).replace(/\\/g,`/`);s.startsWith(`memory/`);let c=a.split(`
70
+ `);for(let n=0;n<c.length;n+=1){let r=c[n]??``,a=r.toLowerCase();if(!a.includes(t))continue;let l=a===t?1:Math.max(.2,t.length/Math.max(r.length,t.length));o.push({path:s||i(e),startLine:n+1,endLine:n+1,score:Number(l.toFixed(4)),snippet:r.slice(0,700),source:`memory`})}}return o.sort((e,t)=>t.score-e.score||e.path.localeCompare(t.path)||e.startLine-t.startLine),o.slice(0,this.config.maxResults)}getFtsRowCount(){if(this.ftsAvailable)try{return this.db.prepare(`SELECT COUNT(*) as c FROM ${J}`).get()?.c??0}catch{return}}buildRebuildSummary(e){let t=this.db.prepare(`SELECT COUNT(*) as c FROM chunks`).get();return{reason:e.reason,memoryFilesIndexed:e.memoryFilesIndexed,sessionFilesIndexed:e.sessionFilesIndexed,staleMemoryFilesRemoved:e.staleMemoryFilesRemoved,staleSessionFilesRemoved:e.staleSessionFilesRemoved,chunks:t?.c??0,ftsRows:this.getFtsRowCount(),fallbackActive:this.searchFallbackOnly,needsFullReindex:e.needsFullReindex}}async rebuild(e=`manual-rebuild`){return this.resetIndex(),this.dirty=!0,this.sessionsDirty=!0,await this.sync({reason:e,forceFullReindex:!0}),this.lastRebuildSummary??this.buildRebuildSummary({reason:e,memoryFilesIndexed:0,sessionFilesIndexed:0,staleMemoryFilesRemoved:0,staleSessionFilesRemoved:0,needsFullReindex:!0})}async sync(e){let t=this.readMeta(),n=e?.forceFullReindex||!t||t.model!==this.provider.model||t.provider!==this.provider.id||t.providerKey!==this.providerKey||t.chunkTokens!==this.config.chunkTokens||t.chunkOverlap!==this.config.chunkOverlap||this.vector.available&&!t?.vectorDims;n&&this.resetIndex();let r=await P(this.memoryRoot),i=(await Promise.all(r.map(async e=>ye(e,this.memoryRoot)))).filter(e=>e!==null),a=new Set(i.map(e=>e.path)),o=0,s=i.map(e=>async()=>{let t=this.db.prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`).get(e.path,`memory`);!n&&t?.hash===e.hash||(await this.indexFile(e,{source:`memory`}),o+=1)});for(let e of s)await e();let c=0,l=this.db.prepare(`SELECT path FROM files WHERE source = ?`).all(`memory`);for(let e of l)if(!a.has(e.path)){this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(e.path,`memory`),c+=1;try{this.db.prepare(`DELETE FROM ${q} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`).run(e.path,`memory`)}catch{}if(this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(e.path,`memory`),this.ftsAvailable)try{this.db.prepare(`DELETE FROM ${J} WHERE path = ? AND source = ? AND model = ?`).run(e.path,`memory`,this.provider.model)}catch{}}let u={indexed:0,staleRemoved:0};this.config.experimental.sessionMemory&&(n||this.sessionsDirty)&&(u=await this.syncSessionFiles(n)),this.writeMeta({model:this.provider.model,provider:this.provider.id,providerKey:this.providerKey,chunkTokens:this.config.chunkTokens,chunkOverlap:this.config.chunkOverlap,...this.vector.available&&this.vector.dims?{vectorDims:this.vector.dims}:{}}),this.dirty=!1,this.searchFallbackOnly=!this.indexHasSearchableData(),this.lastRebuildSummary=this.buildRebuildSummary({reason:e?.reason??`sync`,memoryFilesIndexed:o,sessionFilesIndexed:u.indexed,staleMemoryFilesRemoved:c,staleSessionFilesRemoved:u.staleRemoved,needsFullReindex:!!n})}async syncSessionFiles(e){let t=await $e(this.dataDir,this.sessionStoreName),n=(await Promise.all(t.map(async e=>tt(this.dataDir,e,this.sessionStoreName)))).filter(e=>e!==null),r=new Set(n.map(e=>e.path)),i=e||this.sessionsDirtyFiles.size===0,a=0;for(let t of n){if(!i&&!this.sessionsDirtyFiles.has(t.absPath))continue;let n=this.db.prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`).get(t.path,`sessions`);if(!e&&n?.hash===t.hash){this.resetSessionDelta(t.absPath,t.size);continue}await this.indexFile(t,{source:`sessions`,content:t.content,lineMap:t.lineMap}),a+=1,this.resetSessionDelta(t.absPath,t.size)}let o=0,s=this.db.prepare(`SELECT path FROM files WHERE source = ?`).all(`sessions`);for(let e of s)if(!r.has(e.path)){this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(e.path,`sessions`),o+=1;try{this.db.prepare(`DELETE FROM ${q} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`).run(e.path,`sessions`)}catch{}if(this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(e.path,`sessions`),this.ftsAvailable)try{this.db.prepare(`DELETE FROM ${J} WHERE path = ? AND source = ? AND model = ?`).run(e.path,`sessions`,this.provider.model)}catch{}}return this.sessionsDirty=!1,this.sessionsDirtyFiles.clear(),{indexed:a,staleRemoved:o}}resetSessionDelta(e,t){let n=this.sessionDeltas.get(e);n&&(n.lastSize=t,n.pendingBytes=0,n.pendingMessages=0)}decorateCitations(e){return this.config.citations===`off`?e:e.map(e=>{let t=`Source: ${e.path}#L${e.startLine}-L${e.endLine}`;return this.config.citations===`on`?{...e,citation:t,snippet:`${e.snippet}\n\n${t}`}:{...e,citation:t}})}decorateEntryIds(e){return e.map(e=>{if(e.id)return e;let t=nt(e.path,e.snippet,e.startLine);return{...e,id:t}})}},$=e({createBuiltinMemoryProvider:()=>at});function at(e,t){let n=it.get(e.dataDir,t?.includeSessions?{experimental:{sessionMemory:!0},sources:[`memory`,`sessions`],store:{sessionStoreName:e.sessionStoreName,vector:{enabled:!0}}}:e.sessionStoreName?{store:{sessionStoreName:e.sessionStoreName,vector:{enabled:!0}}}:void 0),i=e.memoryDir;return{id:`builtin-memory`,name:`Builtin Memory Provider`,status:()=>n.status(),search:async(e,t)=>n.search(e),getLines:async(e,t,r)=>{let i=Math.max(1,r-t+1),a=await n.readFile({relPath:e,from:t,lines:i});return a.text?a.text.split(`
71
+ `):[]},listFiles:async()=>P(i),append:async e=>n.appendToMemory(e),updateFile:async(e,t)=>{await n.replaceFile({relPath:e,content:t})},deleteFile:async e=>{await n.deleteFile(e)},sync:async e=>{if(e===`cli-rebuild`){await n.rebuild(e);return}await n.sync({reason:e??`provider-sync`})},noteSessionUpdate:e=>{let t=r.isAbsolute(e)?e:r.resolve(e);n.noteSessionUpdate(t)}}}export{ce as A,re as C,w as D,k as E,p as F,b as I,h as L,m as M,pe as N,_ as O,y as P,de as R,D as S,A as T,x as _,De as a,j as b,c,le as d,se as f,te as g,v as h,Ee as i,O as j,d as k,l,ee as m,at as n,z as o,g as p,it as r,P as s,$ as t,ne as u,C as v,ue as w,fe as x,me as y};
package/dist/index.d.ts CHANGED
@@ -217,6 +217,12 @@ type SubagentContext = {
217
217
  type SessionPathScope = {
218
218
  subagent?: {
219
219
  parentSessionId: string;
220
+ /**
221
+ * Absolute filesystem path of the parent session's directory.
222
+ * Required for correctly nesting sub-subagents (depth ≥ 2).
223
+ * See SessionPathOptions.subagent.parentDir for details.
224
+ */
225
+ parentDir?: string;
220
226
  };
221
227
  };
222
228
  type AgentRunParamsBase = {
@@ -370,7 +376,7 @@ type SubagentRunRecord = {
370
376
  };
371
377
  //#endregion
372
378
  //#region src/subagent/registry.d.ts
373
- declare const MAX_SUBAGENT_DEPTH = 3;
379
+ declare const MAX_SUBAGENT_DEPTH = 2;
374
380
  declare const MAX_CHILDREN_PER_SESSION = 5;
375
381
  /**
376
382
  * In-memory registry for subagent runs scoped to a single parent runAgent call.
@@ -867,6 +873,13 @@ type SessionPathOptions = {
867
873
  storeName?: string;
868
874
  subagent?: {
869
875
  parentSessionId: string;
876
+ /**
877
+ * Absolute filesystem path of the parent session's directory.
878
+ * When set, the child path is resolved as `path.join(parentDir, "subagents", childSessionId)`
879
+ * rather than anchoring at `sessionsDir`. This is required for correctly nesting
880
+ * sub-subagents (depth ≥ 2) inside their parent subagent's own directory.
881
+ */
882
+ parentDir?: string;
870
883
  };
871
884
  };
872
885
  type SessionInspection = {
@@ -903,6 +916,23 @@ type CronExecutionRecord = {
903
916
  childSessionId?: string;
904
917
  createdAt: string;
905
918
  };
919
+ declare const MAX_ARTIFACT_CONTENT_CHARS = 2000;
920
+ type ArtifactOperationType = "write" | "edit" | "delete" | "move";
921
+ type ArtifactOperationName = "write_file" | "edit_file" | "patch_add" | "patch_update" | "patch_delete" | "patch_move";
922
+ type ArtifactOperationInput = {
923
+ type: ArtifactOperationType;
924
+ operation: ArtifactOperationName;
925
+ file: string;
926
+ sourceFile?: string;
927
+ content: string;
928
+ toolCallId: string;
929
+ toolName: string;
930
+ };
931
+ type ArtifactOperation = ArtifactOperationInput & {
932
+ timestamp: string;
933
+ truncated: boolean;
934
+ originalChars: number;
935
+ };
906
936
  /** Resolves the sessions directory path within a data directory */
907
937
  declare function normalizeSessionStoreName(storeName?: string): string;
908
938
  /** Resolves the sessions directory path within a data directory */
@@ -911,6 +941,8 @@ declare function sessionsDir(dataDir: string, options?: SessionPathOptions): str
911
941
  declare function sessionDir(dataDir: string, sessionId: string, options?: SessionPathOptions): string;
912
942
  /** Resolves the transcript file path for a session */
913
943
  declare function transcriptPath(dataDir: string, sessionId: string, options?: SessionPathOptions): string;
944
+ /** Resolves the artifact operation log path for a session */
945
+ declare function artifactsPath(dataDir: string, sessionId: string, options?: SessionPathOptions): string;
914
946
  /** Resolves the metadata file path for a session */
915
947
  declare function metadataPath(dataDir: string, sessionId: string, options?: SessionPathOptions): string;
916
948
  /** Resolves the persisted context snapshot path for a session */
@@ -928,6 +960,8 @@ declare function createSession(dataDir: string, channel: Channel, options?: Sess
928
960
  declare function ensureSession(dataDir: string, sessionId: string, options?: SessionPathOptions): Promise<void>;
929
961
  /** Loads all transcript entries from a session */
930
962
  declare function loadTranscript(dataDir: string, sessionId: string, options?: SessionPathOptions): Promise<TranscriptEntry[]>;
963
+ declare function appendArtifactOperation(dataDir: string, sessionId: string, operation: ArtifactOperationInput, options?: SessionPathOptions): Promise<void>;
964
+ declare function loadArtifactOperations(dataDir: string, sessionId: string, options?: SessionPathOptions): Promise<ArtifactOperation[]>;
931
965
  /** Appends a single entry to the transcript file */
932
966
  declare function appendTranscriptEntry(dataDir: string, sessionId: string, entry: TranscriptEntry, options?: SessionPathOptions & {
933
967
  providerId?: string;
@@ -1308,6 +1342,12 @@ type SystemPromptParams = {
1308
1342
  presetSystemPrompt?: string; /** Custom agent prompt body used for a named subagent. */
1309
1343
  activeAgentSystemPrompt?: string; /** Custom agents visible to the main agent for delegation decisions. */
1310
1344
  availableAgents?: AgentDefinition[];
1345
+ /**
1346
+ * Nesting depth of this agent run (0 = root, 1 = first-level subagent, …).
1347
+ * When > 0, an explicit constraint section is injected to discourage further
1348
+ * subagent spawning.
1349
+ */
1350
+ subagentDepth?: number;
1311
1351
  /**
1312
1352
  * Summary of prior conversation history produced by compaction.
1313
1353
  * When provided, it is appended to the system prompt so the agent
@@ -1455,6 +1495,30 @@ type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> ex
1455
1495
  type UnionToTuple<U, Acc extends unknown[] = [], R = UnionLast<U>> = [U] extends [never] ? Acc : UnionToTuple<Exclude<U, R>, [Extract<U, R>, ...Acc]>;
1456
1496
  type Assert<T, E> = T extends E ? T : never;
1457
1497
  type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
1498
+ type Ensure<T> = T extends infer U ? U : never;
1499
+ //#endregion
1500
+ //#region ../../node_modules/.pnpm/@sinclair+typebox@0.34.48/node_modules/@sinclair/typebox/build/cjs/type/array/array.d.ts
1501
+ interface ArrayOptions extends SchemaOptions {
1502
+ /** The minimum number of items in this array */
1503
+ minItems?: number;
1504
+ /** The maximum number of items in this array */
1505
+ maxItems?: number;
1506
+ /** Should this schema contain unique items */
1507
+ uniqueItems?: boolean;
1508
+ /** A schema for which some elements should match */
1509
+ contains?: TSchema;
1510
+ /** A minimum number of contains schema matches */
1511
+ minContains?: number;
1512
+ /** A maximum number of contains schema matches */
1513
+ maxContains?: number;
1514
+ }
1515
+ type ArrayStatic<T extends TSchema, P extends unknown[]> = Ensure<Static<T, P>[]>;
1516
+ interface TArray<T extends TSchema = TSchema> extends TSchema, ArrayOptions {
1517
+ [Kind]: 'Array';
1518
+ static: ArrayStatic<T, this['params']>;
1519
+ type: 'array';
1520
+ items: T;
1521
+ }
1458
1522
  //#endregion
1459
1523
  //#region ../../node_modules/.pnpm/@sinclair+typebox@0.34.48/node_modules/@sinclair/typebox/build/cjs/type/schema/schema.d.ts
1460
1524
  interface SchemaOptions {
@@ -1683,6 +1747,7 @@ declare function createProcessTool(options: ProcessToolOptions): AgentTool<typeo
1683
1747
  declare function createBashTool(workspaceDir: string): AgentTool;
1684
1748
  //#endregion
1685
1749
  //#region src/tools/files.d.ts
1750
+ type ArtifactRecorder = (operation: ArtifactOperationInput) => Promise<void>;
1686
1751
  declare const readFileSchema: TObject<{
1687
1752
  path: TString;
1688
1753
  offset: TOptional<TNumber>;
@@ -1698,7 +1763,7 @@ declare const writeFileSchema: TObject<{
1698
1763
  path: TString;
1699
1764
  content: TString;
1700
1765
  }>;
1701
- declare function createWriteFileTool(workspaceDir: string, contextManager?: ContextManager): AgentTool<typeof writeFileSchema, {
1766
+ declare function createWriteFileTool(workspaceDir: string, contextManager?: ContextManager, artifactRecorder?: ArtifactRecorder): AgentTool<typeof writeFileSchema, {
1702
1767
  path: string;
1703
1768
  }>;
1704
1769
  declare const editFileSchema: TObject<{
@@ -1706,7 +1771,7 @@ declare const editFileSchema: TObject<{
1706
1771
  old_string: TString;
1707
1772
  new_string: TString;
1708
1773
  }>;
1709
- declare function createEditFileTool(workspaceDir: string, contextManager?: ContextManager): AgentTool<typeof editFileSchema, {
1774
+ declare function createEditFileTool(workspaceDir: string, contextManager?: ContextManager, artifactRecorder?: ArtifactRecorder): AgentTool<typeof editFileSchema, {
1710
1775
  path: string;
1711
1776
  occurrences: number;
1712
1777
  }>;
@@ -1732,6 +1797,7 @@ declare const applyPatchSchema: TObject<{
1732
1797
  type ApplyPatchToolOptions = {
1733
1798
  sessionId?: string;
1734
1799
  hitlResume?: AgentRunParams["hitlResume"];
1800
+ artifactRecorder?: (operation: ArtifactOperationInput) => Promise<void>;
1735
1801
  };
1736
1802
  declare function createApplyPatchTool(workspaceDir: string, options?: ApplyPatchToolOptions): AgentTool<typeof applyPatchSchema, ApplyPatchDetails>;
1737
1803
  //#endregion
@@ -1806,10 +1872,16 @@ type ImageResult = {
1806
1872
  declare function createImageTool(): AgentTool<typeof imageSchema, ImageResult>;
1807
1873
  //#endregion
1808
1874
  //#region src/tools/subagent-spawn.d.ts
1875
+ declare const spawnTaskSchema: TObject<{
1876
+ task: TString;
1877
+ label: TOptional<TString>;
1878
+ }>;
1809
1879
  declare const spawnSchema: TObject<{
1810
1880
  task: TString;
1811
1881
  label: TOptional<TString>;
1812
- agent: TOptional<TString>;
1882
+ }>;
1883
+ declare const batchSpawnSchema: TObject<{
1884
+ tasks: TArray<typeof spawnTaskSchema>;
1813
1885
  }>;
1814
1886
  type SpawnResult = {
1815
1887
  status: "done";
@@ -1830,6 +1902,16 @@ type SpawnResult = {
1830
1902
  runId: string;
1831
1903
  error: string;
1832
1904
  };
1905
+ type BatchSpawnItemResult = SpawnResult & {
1906
+ index: number;
1907
+ task: string;
1908
+ label?: string;
1909
+ };
1910
+ type BatchSpawnResult = {
1911
+ status: "done" | "partial_error" | "error";
1912
+ results: BatchSpawnItemResult[];
1913
+ };
1914
+ type InheritedRunParams = Pick<AgentRunParams, "plugins" | "skillsLoadPaths" | "memory" | "messaging" | "historyLimit" | "onProgress" | "messageId" | "sessionStoreName" | "agentPolicy">;
1833
1915
  /** Formats the announce message injected into the parent session when a subagent completes. */
1834
1916
  declare function buildSubagentAnnounceMessage(params: {
1835
1917
  task: string;
@@ -1843,6 +1925,8 @@ declare function buildSubagentAnnounceMessage(params: {
1843
1925
  *
1844
1926
  * @param registry The parent session's subagent registry.
1845
1927
  * @param parentSessionId Session ID of the agent doing the spawning.
1928
+ * @param parentSessionDir Absolute filesystem path of the spawning session's directory.
1929
+ * Used to correctly nest child session directories under the parent.
1846
1930
  * @param depth Current nesting depth of the spawning agent (child will be depth+1).
1847
1931
  * @param dataDir User data directory (shared between parent and child).
1848
1932
  * @param channel Channel inherited from the parent session.
@@ -1850,7 +1934,8 @@ declare function buildSubagentAnnounceMessage(params: {
1850
1934
  * @param loopDetection Tool-loop detection config inherited from the parent.
1851
1935
  * @param spawnFn Function that actually runs a child agent (injected to avoid circular imports).
1852
1936
  */
1853
- declare function createSubagentSpawnTool(registry: SubagentRegistry, parentSessionId: string, depth: number, dataDir: string, channel: AgentRunParams["channel"], llm: AgentRunParams["llm"], loopDetection: ToolLoopDetectionConfig | undefined, inheritedRunParams: Pick<AgentRunParams, "plugins" | "skillsLoadPaths" | "memory" | "messaging" | "historyLimit" | "onProgress" | "messageId" | "sessionStoreName" | "agentPolicy">, spawnFn: (params: AgentRunParams) => Promise<AgentRunResult>): AgentTool<typeof spawnSchema, SpawnResult>;
1937
+ declare function createSubagentSpawnTool(registry: SubagentRegistry, parentSessionId: string, parentSessionDir: string, depth: number, dataDir: string, channel: AgentRunParams["channel"], llm: AgentRunParams["llm"], loopDetection: ToolLoopDetectionConfig | undefined, inheritedRunParams: InheritedRunParams, spawnFn: (params: AgentRunParams) => Promise<AgentRunResult>): AgentTool<typeof spawnSchema, SpawnResult>;
1938
+ declare function createBatchSubagentSpawnTool(registry: SubagentRegistry, parentSessionId: string, parentSessionDir: string, depth: number, dataDir: string, channel: AgentRunParams["channel"], llm: AgentRunParams["llm"], loopDetection: ToolLoopDetectionConfig | undefined, inheritedRunParams: InheritedRunParams, spawnFn: (params: AgentRunParams) => Promise<AgentRunResult>): AgentTool<typeof batchSpawnSchema, BatchSpawnResult>;
1854
1939
  //#endregion
1855
1940
  //#region src/tools/subagents.d.ts
1856
1941
  declare const ACTIONS: readonly ["list", "kill"];
@@ -1957,6 +2042,18 @@ declare function isUiToolPauseSignal(error: unknown): error is UiToolPauseSignal
1957
2042
  /** Optional context for enabling subagent tools */
1958
2043
  type SubagentToolsContext = {
1959
2044
  sessionId: string;
2045
+ /**
2046
+ * Runtime-local session id for artifacts and other tool side files.
2047
+ * Usually the same as `sessionId`; in subagent runs, `sessionId` may point
2048
+ * to the parent interaction session while this remains the child run session.
2049
+ */
2050
+ currentSessionId?: string;
2051
+ /**
2052
+ * Absolute filesystem path of the current (spawning) session's directory.
2053
+ * Passed to createSubagentSpawnTool so it can correctly nest child sessions
2054
+ * under the parent's directory at any depth.
2055
+ */
2056
+ currentSessionDir: string;
1960
2057
  registry: SubagentRegistry;
1961
2058
  parentSessionId: string; /** Depth of the current agent (root = 0) */
1962
2059
  depth: number;
@@ -2432,4 +2529,4 @@ declare function formatClarifyResolution(resolution: HitlResolution): string;
2432
2529
  declare function formatReviewResolution(resolution: HitlResolution): string;
2433
2530
  declare function buildResumeNarration(resolution: HitlResolution, kind: string): string;
2434
2531
  //#endregion
2435
- export { AgentBinding, AgentConfig, type AgentConfigSource, type AgentCustomProgressEvent, type AgentDefinition, type AgentDirectoryCandidate, AgentModelConfig, type AgentProgressEvent, type AgentRunParams, type AgentRunResult, type AgentRuntimePolicy, type AgentScanOptions, AgentsConfig, BOOTSTRAP_FILE_NAMES, BOOTSTRAP_MAX_CHARS, BOOTSTRAP_TOTAL_MAX_CHARS, type BootstrapContextFile, type BootstrapEnsureResult, type BootstrapFile, type BootstrapMountResult, type BootstrapMountStatus, type CallbackEventPayload, type CallbackPayload, type Channel, type ContextManager, type CronExecutionRecord, DEFAULT_SESSION_STORE_NAME, type EmbeddingProvider, type EmbeddingProviderContext, type EmbeddingProviderFactory, type EmbeddingProviderRegistration, HITL_MESSAGES, type HitlPauseContext, HitlPauseSignal, type HitlToolContext, MAX_CHILDREN_PER_SESSION, MAX_SUBAGENT_DEPTH, type MemoryCallOptions, type MemoryChangeSource, type MemoryChangedEvent, type MemoryChangedHandler, MemoryIndexManager, type MemoryProvider, type MemoryProviderContext, type MemoryProviderFactory, type MemoryProviderRegistration, type MemoryProviderStatus, type MemoryRebuildSummary, type MemorySearchOptions, type MemorySearchResult, type NormalizedPluginsConfig, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PersistedSubagentRunRecord, type PersistedToolResult, type PluginApi, type PluginCandidate, type PluginConfigUiHint, type PluginCustomProgressInput, type PluginDiagnostic, type PluginDiscoveryOptions, type PluginDiscoveryResult, type PluginEntryConfig, type PluginExecutionRuntime, type PluginHookAfterCompactionEvent, type PluginHookAfterPromptBuildEvent, type PluginHookAfterToolCallEvent, type PluginHookAgentContext, type PluginHookAgentEndEvent, type PluginHookAssistantMessageEndEvent, type PluginHookBeforeCompactionEvent, type PluginHookBeforeCompactionResult, type PluginHookBeforeModelResolveEvent, type PluginHookBeforeModelResolveResult, type PluginHookBeforePromptBuildEvent, type PluginHookBeforePromptBuildResult, type PluginHookBeforeToolCallEvent, type PluginHookBeforeToolCallResult, type PluginHookDreamGateEvent, type PluginHookDreamGateResult, type PluginHookHandlerMap, type PluginHookLlmInputEvent, type PluginHookLlmOutputEvent, type PluginHookMemoryChangedEvent, type PluginHookName, PluginHookRegistry, type PluginHookSessionEndEvent, type PluginHookSessionResetEvent, type PluginHookSessionStartEvent, type PluginKind, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRegistry, type PluginOrigin, type PluginProgressEmitter, type PluginRecord, type PluginRegistry, type PluginRuntime, type PluginRuntimeContext, type PluginSystem, type PluginSystemOptions, type PluginToolOptions, PluginToolRegistry, type PluginUiToolDescriptor, type PluginUiToolOptions, type PluginsConfig, type PluginsConfigValidationResult, type RegisteredPluginTool, type ResumeOptions, type ResumeValidationResult, type RunResultPayload, SYSTEM_AGENTS_DIR, type SessionContextStore, type SessionExport, type SessionInspection, type SessionMetadata, type SessionMetadataUpdate, type SessionSummary, type Skill, type SkillDirectory, type SkillViewResult, type SlashCommandList, type SubagentContext, SubagentRegistry, type SubagentRunRecord, type SubagentStatus, type SubagentToolsContext, type SystemPromptParams, type ToolLoopDetectionConfig, type TranscriptEntry, type UiToolInputSchema, type UiToolOptions, UiToolPauseSignal, addAgent, addBinding, agentDirCandidates, aimaxDir, appendCronExecutionRecord, appendRecentToMemory, appendToMemory, appendTranscriptEntry, approvalSummaryFromResolution, bootstrapMountLayout, buildAgentDelegationPrompt, buildAgentTaskPrompt, buildBootstrapContextFiles, buildResumeNarration, buildSkillsPrompt, buildSubagentAnnounceMessage, buildSystemPrompt, cleanupOldSubagentRecords, clearPendingHitl, clearPendingUiTool, collapseLogPath, contextSnapshotPath, createAgentTools, createApplyPatchTool, createBashTool, createBuiltinMemoryProvider, createContextManager, createEditFileTool, createExecTool, createImageTool, createListDirTool, createMemoryAppendTool, createMemoryForgetTool, createMemoryGetTool, createMemoryListTool, createMemoryLogTool, createMemorySearchTool, createMemoryUpdateTool, createMemoryWriteTool, createPendingHitl, createPendingUiTool, createPluginProgressEmitter, createPluginRuntime, createProcessTool, createReadFileTool, createSession, createSessionContextStore, createSessionSearchTool, createSkillListTool, createSkillLoadTool, createSubagentSpawnTool, createSubagentsTool, createUiTool, createWriteFileTool, cronExecutionsPath, defaultUiToolInputSchema, deleteMemoryFile, discoverAIMaxPlugins, ensureBootstrapMountLayout, ensureSession, exportSession, filterSkillsForAgent, filterToolsForAgent, findAgentDefinition, findSkillByName, formatApprovalResolution, formatClarifyResolution, formatReviewResolution, generateSessionTitle, getAgentConfig, getMemoryLines, hasBootstrapSentinel, hitlHistoryPath, initializePluginSystem, inspectBootstrapMountLayout, inspectSession, isBootstrapMountLayoutReady, isHitlPauseSignal, isUiToolPauseSignal, listAgents, listAvailableSlashCommands, listBindings, listMemoryFiles, listSessionSummaries, listSessions, listSubagentRunsFromDisk, loadAgentDefinitionsFromDir, loadAgentsConfig, loadBootstrapFiles, loadCronExecutionRecords, readPendingHitl as loadPendingHitl, readPendingHitl, readPendingUiTool as loadPendingUiTool, readPendingUiTool, loadPluginManifest, loadPluginManifestRegistry, loadPlugins, loadSessionContextSnapshot, loadSessionMetadata, loadSkillView, loadSkills, loadSkillsFromDirs, loadSkillsWithPluginDirs, loadSubagentRegistryFromDisk, loadTranscript, memoryDir, metadataPath, normalizeAgentId, normalizePluginsConfig, normalizeSessionStoreName, parseAgentDefinition, pendingHitlPath, pendingUiToolPath, primaryMemoryPath, readHitlHistory, readMemoryFile, readPrimaryMemory, registerEmbeddingProvider, registerMemoryProvider, removeAgent, removeBindings, replaceMemoryFile, resetEmbeddingProviderRegistryForTests, resetMemoryProviderRegistryForTests, resolveAgentDir, resolveAgentIdByBinding, resolveAgentsConfigPath, resolveDefaultAgentId, resolveEmbeddingProvider, resolveHitlRequest, resolveHitlRequest as resolvePendingHitl, resolveMemoryProvider, resolveModelFallbacks, resolveModelString, resolvePendingUiTool, resolvePluginManifestPath, rewriteTranscript, runAgent, saveAgentsConfig, saveSessionMetadata, saveSubagentRegistryToDisk, scanAgentDefinitions, searchMemory, sessionDir, sessionMemoryPath, sessionsDir, skillsDir, toolResultsDir, transcriptPath, transitionHitlStatus, updateAgentIdentity, updateSessionMetadata, validatePluginsConfig, validateResume, wrapToolsWithHooks };
2532
+ export { AgentBinding, AgentConfig, type AgentConfigSource, type AgentCustomProgressEvent, type AgentDefinition, type AgentDirectoryCandidate, AgentModelConfig, type AgentProgressEvent, type AgentRunParams, type AgentRunResult, type AgentRuntimePolicy, type AgentScanOptions, AgentsConfig, type ArtifactOperation, type ArtifactOperationInput, type ArtifactOperationName, type ArtifactOperationType, BOOTSTRAP_FILE_NAMES, BOOTSTRAP_MAX_CHARS, BOOTSTRAP_TOTAL_MAX_CHARS, type BootstrapContextFile, type BootstrapEnsureResult, type BootstrapFile, type BootstrapMountResult, type BootstrapMountStatus, type CallbackEventPayload, type CallbackPayload, type Channel, type ContextManager, type CronExecutionRecord, DEFAULT_SESSION_STORE_NAME, type EmbeddingProvider, type EmbeddingProviderContext, type EmbeddingProviderFactory, type EmbeddingProviderRegistration, HITL_MESSAGES, type HitlPauseContext, HitlPauseSignal, type HitlToolContext, MAX_ARTIFACT_CONTENT_CHARS, MAX_CHILDREN_PER_SESSION, MAX_SUBAGENT_DEPTH, type MemoryCallOptions, type MemoryChangeSource, type MemoryChangedEvent, type MemoryChangedHandler, MemoryIndexManager, type MemoryProvider, type MemoryProviderContext, type MemoryProviderFactory, type MemoryProviderRegistration, type MemoryProviderStatus, type MemoryRebuildSummary, type MemorySearchOptions, type MemorySearchResult, type NormalizedPluginsConfig, PLUGIN_MANIFEST_FILENAME, PLUGIN_MANIFEST_FILENAMES, type PersistedSubagentRunRecord, type PersistedToolResult, type PluginApi, type PluginCandidate, type PluginConfigUiHint, type PluginCustomProgressInput, type PluginDiagnostic, type PluginDiscoveryOptions, type PluginDiscoveryResult, type PluginEntryConfig, type PluginExecutionRuntime, type PluginHookAfterCompactionEvent, type PluginHookAfterPromptBuildEvent, type PluginHookAfterToolCallEvent, type PluginHookAgentContext, type PluginHookAgentEndEvent, type PluginHookAssistantMessageEndEvent, type PluginHookBeforeCompactionEvent, type PluginHookBeforeCompactionResult, type PluginHookBeforeModelResolveEvent, type PluginHookBeforeModelResolveResult, type PluginHookBeforePromptBuildEvent, type PluginHookBeforePromptBuildResult, type PluginHookBeforeToolCallEvent, type PluginHookBeforeToolCallResult, type PluginHookDreamGateEvent, type PluginHookDreamGateResult, type PluginHookHandlerMap, type PluginHookLlmInputEvent, type PluginHookLlmOutputEvent, type PluginHookMemoryChangedEvent, type PluginHookName, PluginHookRegistry, type PluginHookSessionEndEvent, type PluginHookSessionResetEvent, type PluginHookSessionStartEvent, type PluginKind, type PluginManifest, type PluginManifestLoadResult, type PluginManifestRegistry, type PluginOrigin, type PluginProgressEmitter, type PluginRecord, type PluginRegistry, type PluginRuntime, type PluginRuntimeContext, type PluginSystem, type PluginSystemOptions, type PluginToolOptions, PluginToolRegistry, type PluginUiToolDescriptor, type PluginUiToolOptions, type PluginsConfig, type PluginsConfigValidationResult, type RegisteredPluginTool, type ResumeOptions, type ResumeValidationResult, type RunResultPayload, SYSTEM_AGENTS_DIR, type SessionContextStore, type SessionExport, type SessionInspection, type SessionMetadata, type SessionMetadataUpdate, type SessionSummary, type Skill, type SkillDirectory, type SkillViewResult, type SlashCommandList, type SubagentContext, SubagentRegistry, type SubagentRunRecord, type SubagentStatus, type SubagentToolsContext, type SystemPromptParams, type ToolLoopDetectionConfig, type TranscriptEntry, type UiToolInputSchema, type UiToolOptions, UiToolPauseSignal, addAgent, addBinding, agentDirCandidates, aimaxDir, appendArtifactOperation, appendCronExecutionRecord, appendRecentToMemory, appendToMemory, appendTranscriptEntry, approvalSummaryFromResolution, artifactsPath, bootstrapMountLayout, buildAgentDelegationPrompt, buildAgentTaskPrompt, buildBootstrapContextFiles, buildResumeNarration, buildSkillsPrompt, buildSubagentAnnounceMessage, buildSystemPrompt, cleanupOldSubagentRecords, clearPendingHitl, clearPendingUiTool, collapseLogPath, contextSnapshotPath, createAgentTools, createApplyPatchTool, createBashTool, createBatchSubagentSpawnTool, createBuiltinMemoryProvider, createContextManager, createEditFileTool, createExecTool, createImageTool, createListDirTool, createMemoryAppendTool, createMemoryForgetTool, createMemoryGetTool, createMemoryListTool, createMemoryLogTool, createMemorySearchTool, createMemoryUpdateTool, createMemoryWriteTool, createPendingHitl, createPendingUiTool, createPluginProgressEmitter, createPluginRuntime, createProcessTool, createReadFileTool, createSession, createSessionContextStore, createSessionSearchTool, createSkillListTool, createSkillLoadTool, createSubagentSpawnTool, createSubagentsTool, createUiTool, createWriteFileTool, cronExecutionsPath, defaultUiToolInputSchema, deleteMemoryFile, discoverAIMaxPlugins, ensureBootstrapMountLayout, ensureSession, exportSession, filterSkillsForAgent, filterToolsForAgent, findAgentDefinition, findSkillByName, formatApprovalResolution, formatClarifyResolution, formatReviewResolution, generateSessionTitle, getAgentConfig, getMemoryLines, hasBootstrapSentinel, hitlHistoryPath, initializePluginSystem, inspectBootstrapMountLayout, inspectSession, isBootstrapMountLayoutReady, isHitlPauseSignal, isUiToolPauseSignal, listAgents, listAvailableSlashCommands, listBindings, listMemoryFiles, listSessionSummaries, listSessions, listSubagentRunsFromDisk, loadAgentDefinitionsFromDir, loadAgentsConfig, loadArtifactOperations, loadBootstrapFiles, loadCronExecutionRecords, readPendingHitl as loadPendingHitl, readPendingHitl, readPendingUiTool as loadPendingUiTool, readPendingUiTool, loadPluginManifest, loadPluginManifestRegistry, loadPlugins, loadSessionContextSnapshot, loadSessionMetadata, loadSkillView, loadSkills, loadSkillsFromDirs, loadSkillsWithPluginDirs, loadSubagentRegistryFromDisk, loadTranscript, memoryDir, metadataPath, normalizeAgentId, normalizePluginsConfig, normalizeSessionStoreName, parseAgentDefinition, pendingHitlPath, pendingUiToolPath, primaryMemoryPath, readHitlHistory, readMemoryFile, readPrimaryMemory, registerEmbeddingProvider, registerMemoryProvider, removeAgent, removeBindings, replaceMemoryFile, resetEmbeddingProviderRegistryForTests, resetMemoryProviderRegistryForTests, resolveAgentDir, resolveAgentIdByBinding, resolveAgentsConfigPath, resolveDefaultAgentId, resolveEmbeddingProvider, resolveHitlRequest, resolveHitlRequest as resolvePendingHitl, resolveMemoryProvider, resolveModelFallbacks, resolveModelString, resolvePendingUiTool, resolvePluginManifestPath, rewriteTranscript, runAgent, saveAgentsConfig, saveSessionMetadata, saveSubagentRegistryToDisk, scanAgentDefinitions, searchMemory, sessionDir, sessionMemoryPath, sessionsDir, skillsDir, toolResultsDir, transcriptPath, transitionHitlStatus, updateAgentIdentity, updateSessionMetadata, validatePluginsConfig, validateResume, wrapToolsWithHooks };