@gencode/agents 0.5.0 → 0.6.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,5 +1,36 @@
1
1
  # @gencode/agents
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c0283fc: ### Auto-Skills Runtime and Review Workflow
8
+
9
+ Added the learned auto-skills runtime and CLI controls.
10
+
11
+ - Added `.aimax/auto-skills` storage support with `categories.json`, single-level category slugs, `SKILL.md` entrypoints, generated `metadata.json`, archived/active status handling, and `.reviews/run-log.jsonl` audit records for completed review-agent runs.
12
+ - Added `AutoSkillsLoader` APIs to list categories, list active learned skills by category, search compact skill metadata, view a selected `SKILL.md`, and load bounded resource files inside an auto-skill directory.
13
+ - Added manifest-based in-memory and prompt snapshot caching for auto-skill indexes, with cache invalidation after category, create, update, and archive writes.
14
+ - Added main-agent read tools: `auto_skill_categories`, `auto_skill_list`, `auto_skill_search`, and `auto_skill_view`; these are hidden when `autoSkills.load.enabled` is false.
15
+ - Added a system-prompt auto-skills section that routes the main agent from categories to list/view/search while preferring curated, user, and plugin skills when both apply.
16
+ - Added the restricted `auto_skill_manage` tool for internal review-agent use only, supporting `create_category`, `create`, `update`, and `archive` actions with structured success/error payloads.
17
+ - Added public/internal agent visibility, keeping `visibility: internal` definitions out of public custom-agent delegation and `subagent_spawn` selection while still allowing explicit internal orchestration to resolve them by name.
18
+ - Added post-run auto-skill review lifecycle modes: `off`, `gate`, `dry_run`, and `write`, replacing legacy score thresholds with configurable scope-based gates for the full session, current run, and post-review window.
19
+ - Added per-session auto-skill review state with `maxReviewsPerSession`, attempted/completed/failed timestamps, and a reviewed-transcript cursor so repeat reviews focus on newly accumulated work.
20
+ - Added pre-gate skips for subagents, cron runs, run errors, HITL pauses, pending UI tools, gate misses, and sessions that already reached their review cap.
21
+ - Added compact review packets with session/current-run/review-window ranges, stats, tool stats, loaded/viewed skills, failed tool summaries, active categories, review state, and evidence file locations.
22
+ - Added the review-only `auto_skill_review_context_view` tool so the internal curator can read bounded review-window, current-run, recent-conversation, explicit transcript-range, or referenced tool-result evidence.
23
+ - Added silent internal curator integration for dry-run and write review modes, including diagnostic timing events, sanitized tool-result diagnostics, sanitized write-tool arguments, durable-write summaries parsed from `auto_skill_manage` results, and completed/failed review run logs.
24
+ - Added the named internal `auto-skill-reviewer` agent for review orchestration, applying its prompt, init prompt, model override, and tool restrictions to silent review turns; review runs now skip with diagnostics when that internal agent is not configured.
25
+ - Added `--system-agents-dir` and `AIMAX_SYSTEM_AGENTS_DIR` controls for `run` and `resume`, including absolute-path validation, CLI-over-env precedence, start-log reporting, and propagation through direct runs, HITL resumes, UI tool resumes, and run-dispatched resume flows.
26
+ - Added CLI controls for `run` and `resume`: `--auto-skills-load-enabled`, `--auto-skills-review-mode`, `AIMAX_AUTO_SKILLS_LOAD_ENABLED`, and `AIMAX_AUTO_SKILLS_REVIEW_MODE`, including validation, option-overrides-env precedence, and propagation through direct runs, resumed HITL runs, UI tool resumes, and run-dispatched resume flows; when these controls are unset, the agents layer defaults to `load.enabled=false` and `review.mode=write`.
27
+ - Exported auto-skills loader helpers, review gate/state helpers, public types, and read-tool factories from the package entrypoints.
28
+
29
+ ### Patch Changes
30
+
31
+ - 18e17e4: Relax Microcompact staleness handling so tool results stay inline for the last 48 hours and remain protected within the most recent three user turns.
32
+ - c39239c: Use AES-GCM session encryption with CLI-supplied key rotation support so session files no longer rely on reversible encoding alone.
33
+
3
34
  ## 0.5.0
4
35
 
5
36
  ### Minor Changes
@@ -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,{createCipheriv as o,createDecipheriv as s,createHash as c,randomBytes as l,randomUUID as u}from"node:crypto";import d from"node:fs";const f=`amxsec1`,ee=`aes-256-gcm`,p=`aimax-session-default-key-v1`;let m=h();function te(e){return e.toString(`base64`).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/g,``)}function ne(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`),n=t.length%4==0?``:`=`.repeat(4-t.length%4);return Buffer.from(`${t}${n}`,`base64`)}function re(e){let t=e.trim();if(!t)throw Error(`Session encryption key must not be empty`);return t}function ie(e){return c(`sha256`).update(e,`utf8`).digest(`hex`).slice(0,16)}function ae(e){return c(`sha256`).update(e,`utf8`).digest()}function oe(e){return e??m}function se(e){let t=oe(e),n=t.keys.find(e=>e.keyId===t.primaryKeyId);if(!n)throw Error(`Missing primary session encryption key: ${t.primaryKeyId}`);return n}function ce(e,t){let n=oe(t).keys.find(t=>t.keyId===e);if(!n)throw Error(`Missing session decryption key for keyId=${e}`);return n}function le(e){let t=e.split(`.`);if(t.length!==4||t[0]!==f)throw Error(`Invalid encrypted session payload envelope`);let[,n,r,i]=t,a=ne(r),o=ne(i);if(a.length!==12)throw Error(`Invalid encrypted session payload iv length: ${a.length}`);if(o.length<16)throw Error(`Invalid encrypted session payload body`);return{keyId:n,iv:a,cipherWithTag:o}}function h(e=p,t=[]){let n=new Map,r=e=>{let t=re(e),r={keyId:ie(t),secret:t};return n.has(r.keyId)||n.set(r.keyId,r),r};r(p);let i=r(e);for(let e of t)r(e);return{primaryKeyId:i.keyId,keys:[...n.values()]}}function ue(e){m=e??h()}function de(){return m}function g(e,t){let n=se(t),r=l(12),i=o(ee,ae(n.secret),r),a=Buffer.concat([i.update(Buffer.from(e,`utf8`)),i.final()]),s=Buffer.concat([a,i.getAuthTag()]);return`${f}.${n.keyId}.${te(r)}.${te(s)}`}function _(e,t){if(!v(e))return e;let{keyId:n,iv:r,cipherWithTag:i}=le(e),a=ce(n,t),o=i.subarray(0,i.length-16),c=i.subarray(i.length-16),l=s(ee,ae(a.secret),r);return l.setAuthTag(c),Buffer.concat([l.update(o),l.final()]).toString(`utf8`)}function v(e){return e.startsWith(`${f}.`)}async function y(e,t){try{return _(await n.readFile(e,`utf-8`),t)}catch(e){if(e.code===`ENOENT`)return null;throw e}}async function b(e,t,r,i){let a=r?g(t,i):t;await n.writeFile(e,a,`utf-8`)}async function x(e,t,r,i){if(!r){await n.appendFile(e,t,`utf-8`);return}let a=await y(e,i);await b(e,a?a+t:t,!0,i)}async function fe(e,t,r,i){let a=r?g(t,i):t,o=`${e}.${process.pid}.${Date.now()}.tmp`;await n.writeFile(o,a,`utf-8`),await n.rename(o,e)}async function pe(e,t){return y(e,t)}const me=`sessions`,S=2e3,C=new Map;function w(e){let t=e?.trim()||me;if(!/^[A-Za-z0-9_-]+$/.test(t))throw Error(`Invalid session store name: ${e}. Must match /^[A-Za-z0-9_-]+$/`);return t}function T(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 E(e,t){return r.join(e,`.aimax`,w(t?.storeName))}function D(e,t,n){let i=n?.subagent?T(`subagent session id`,t):t;if(n?.subagent){if(n.subagent.parentDir)return r.join(n.subagent.parentDir,`subagents`,i);let t=T(`parent session id`,n.subagent.parentSessionId);return r.join(E(e,n),t,`subagents`,i)}return r.join(E(e,n),i)}function O(e,t,n){return r.join(D(e,t,n),`transcript.jsonl`)}function k(e,t,n){return r.join(D(e,t,n),`artifacts.json`)}function A(e,t,n){return r.join(D(e,t,n),`session.json`)}function j(e,t,n){return r.join(D(e,t,n),`context.json`)}function he(e,t,n){return r.join(D(e,t,n),`session-memory.json`)}function ge(e,t,n){return r.join(D(e,t,n),`collapse-log.jsonl`)}function _e(e,t,n){return r.join(D(e,t,n),`tool-results`)}function M(e,t,n){return r.join(D(e,t,n),`cron-executions.jsonl`)}const N={version:2,updatedAt:new Date(0).toISOString(),readStates:[],toolResults:[],compaction:{budgets:[],snips:[],collapseSpans:[],consecutiveAutocompactFailures:0}};async function ve(e,t,i){let a=i?.sessionId??u(),o=D(e,a,i);await n.mkdir(o,{recursive:!0});let s=r.join(o,`.channel`);return await n.writeFile(s,t,`utf-8`),a}async function P(e,t,r){let i=D(e,t,r);await n.mkdir(i,{recursive:!0})}async function F(e,t,n){let r=await y(O(e,t,n),n?.sessionEncryption);if(r===null)return[];let i=[];for(let e of r.split(`
2
+ `)){let t=e.trim();if(t)try{i.push(JSON.parse(t))}catch{}}return i}async function ye(e,t,n,r){await P(e,t,r);let i=k(e,t,r),a=r?.encryptSessions??!1;await we(i,async()=>{let e=await Se(i,r?.sessionEncryption);await Ce(i,{version:1,updatedAt:new Date().toISOString(),operations:[...e.operations,xe(n)]},a,r?.sessionEncryption)})}async function be(e,t,n){return(await Se(k(e,t,n),n?.sessionEncryption)).operations}function xe(e){let t=e.content.length,n=t>S;return{...e,content:n?`${e.content.slice(0,Math.max(0,S-3))}...`:e.content,timestamp:new Date().toISOString(),truncated:n,originalChars:t}}async function Se(e,t){let n=await y(e,t);if(n===null)return I();try{let e=JSON.parse(n);return e.version!==1||!Array.isArray(e.operations)?I():{version:1,updatedAt:typeof e.updatedAt==`string`?e.updatedAt:new Date(0).toISOString(),operations:e.operations}}catch{return I()}}function I(){return{version:1,updatedAt:new Date(0).toISOString(),operations:[]}}async function Ce(e,t,i,a){await n.mkdir(r.dirname(e),{recursive:!0}),await fe(e,`${JSON.stringify(t,null,2)}\n`,i,a)}async function we(e,t){let n=(C.get(e)??Promise.resolve()).catch(()=>{}).then(t);C.set(e,n);try{await n}finally{C.get(e)===n&&C.delete(e)}}async function Te(e,t,n,i){await P(e,t,i);let a=O(e,t,i);await x(a,JSON.stringify(n)+`
3
+ `,i?.encryptSessions??!1,i?.sessionEncryption);try{let{resolveMemoryProvider:t}=await import(`./provider-registry-CxtHsHdk.js`).then(e=>e.t),{createBuiltinMemoryProvider:n}=await Promise.resolve().then(()=>$),o=r.join(e,`.aimax`),s=t({providerId:i?.providerId,pluginId:i?.pluginId,dataDir:e,memoryDir:o,sessionStoreName:i?.storeName})?.provider??n({dataDir:e,memoryDir:o,sessionStoreName:i?.storeName});s.noteSessionUpdate&&s.noteSessionUpdate(a)}catch{}i?.onMemoryChanged&&await Promise.resolve(i.onMemoryChanged({reason:`transcript-append`,files:[r.join(w(i.storeName),t,`transcript.jsonl`).replace(/\\/g,`/`)],source:`sessions`,sessionId:t,providerId:i.providerId??i.pluginId,timestamp:new Date().toISOString()})).catch(()=>{})}async function Ee(e,t,n,i){await P(e,t,i);let a=O(e,t,i),o=n(await F(e,t,i)),s=o.map(e=>JSON.stringify(e)).join(`
4
+ `),c=i?.encryptSessions??!1;await b(a,s.length>0?`${s}\n`:``,c,i?.sessionEncryption);try{let{resolveMemoryProvider:t}=await import(`./provider-registry-CxtHsHdk.js`).then(e=>e.t),{createBuiltinMemoryProvider:n}=await Promise.resolve().then(()=>$),o=r.join(e,`.aimax`),s=t({providerId:i?.providerId,pluginId:i?.pluginId,dataDir:e,memoryDir:o,sessionStoreName:i?.storeName})?.provider??n({dataDir:e,memoryDir:o,sessionStoreName:i?.storeName});s.noteSessionUpdate&&s.noteSessionUpdate(a)}catch{}return i?.onMemoryChanged&&await Promise.resolve(i.onMemoryChanged({reason:`transcript-rewrite`,files:[r.join(w(i.storeName),t,`transcript.jsonl`).replace(/\\/g,`/`)],source:`sessions`,sessionId:t,providerId:i.providerId??i.pluginId,timestamp:new Date().toISOString()})).catch(()=>{}),o}async function De(e,t,n,r){await P(e,t,r),await x(M(e,t,r),JSON.stringify(n)+`
5
+ `,r?.encryptSessions??!1,r?.sessionEncryption)}async function Oe(e,t,n){let r=await y(M(e,t,n),n?.sessionEncryption);if(r===null)return[];let i=[];for(let e of r.split(`
6
+ `)){let t=e.trim();if(t)try{i.push(JSON.parse(t))}catch{}}return i}async function ke(e,t){let r=E(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 L(e,t,n){await P(e,t.id,n);let r=A(e,t.id,n),i=n?.encryptSessions??!1;await b(r,JSON.stringify(t,null,2),i,n?.sessionEncryption)}async function Ae(e,t,n,r){let i=await R(e,t,r);if(!i)return null;let a={...i,...n,id:i.id,createdAt:i.createdAt,updatedAt:new Date().toISOString()};return await L(e,a,r),a}async function R(e,t,i){let a=await y(A(e,t,i),i?.sessionEncryption);if(a===null)return null;try{let o=JSON.parse(a);if(!o.channel){let a=r.join(D(e,t,i),`.channel`);try{o.channel=(await n.readFile(a,`utf-8`)).trim()}catch{o.channel=`WEB`}}return o}catch{return null}}async function je(e,t,n){let r=await ke(e,n),i=await Promise.all(r.map(async t=>{let r=await R(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 z(e,t,n){let r=await y(j(e,t,n),n?.sessionEncryption);if(r===null)return N;try{let e=JSON.parse(r),t=typeof e.version==`number`?e.version:void 0;return t!==1&&t!==2?N:{version:2,updatedAt:typeof e.updatedAt==`string`?e.updatedAt:N.updatedAt,readStates:Array.isArray(e.readStates)?e.readStates:[],toolResults:Array.isArray(e.toolResults)?e.toolResults:[],compaction:{sessionMemory:e.compaction?.sessionMemory,modelUsage:e.compaction?.modelUsage,budgets:Array.isArray(e.compaction?.budgets)?e.compaction.budgets:[],snips:Array.isArray(e.compaction?.snips)?e.compaction.snips:[],collapseSpans:Array.isArray(e.compaction?.collapseSpans)?e.compaction.collapseSpans:[],consecutiveAutocompactFailures:typeof e.compaction?.consecutiveAutocompactFailures==`number`?e.compaction.consecutiveAutocompactFailures:0,lastCompactionAt:typeof e.compaction?.lastCompactionAt==`string`?e.compaction.lastCompactionAt:void 0,lastCompactionLayer:e.compaction?.lastCompactionLayer===`L1`||e.compaction?.lastCompactionLayer===`L2`||e.compaction?.lastCompactionLayer===`L3`||e.compaction?.lastCompactionLayer===`L4`||e.compaction?.lastCompactionLayer===`L5`||e.compaction?.lastCompactionLayer===`L6`?e.compaction.lastCompactionLayer:void 0}}}catch{return N}}async function Me(e,t,r){let i=D(e,t,r);try{return(await n.stat(i)).isDirectory()}catch(e){if(e.code===`ENOENT`)return!1;throw e}}async function B(e,t,n){let[r,i,a]=await Promise.all([R(e,t,n),F(e,t,n),z(e,t,n)]);return{id:t,metadata:r,transcriptPath:O(e,t,n),contextSnapshotPath:j(e,t,n),sessionMemoryPath:he(e,t,n),collapseLogPath:ge(e,t,n),toolResultsDir:_e(e,t,n),transcriptEntryCount:i.length,readStateCount:a.readStates.length,toolResultRefCount:a.toolResults.length,transcriptEntries:i,context:a}}async function Ne(e,t,n){let r=await B(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 V(e){return!!(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)}async function Pe(e){let t;try{t=await n.lstat(e)}catch(e){if(V(e))return{missing:!0};throw e}if(t.isSymbolicLink()||!t.isFile())throw Error(`path required`);return{missing:!1,stat:t}}function Fe(e){try{d.mkdirSync(e,{recursive:!0})}catch{}return e}function Ie(e){return e.trim().replace(/^[./]+/,``).replace(/\\/g,`/`)}function Le(e){let t=Ie(e);return t?t===`MEMORY.md`||t===`memory.md`?!0:t.startsWith(`memory/`):!1}async function H(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 H(i,t);continue}n.isFile()&&n.name.endsWith(`.md`)&&t.push(i)}}}async function U(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 H(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 W(e){return a.createHash(`sha256`).update(e).digest(`hex`)}async function Re(e,t){let i;try{i=await n.stat(e)}catch(e){if(V(e))return null;throw e}let a;try{a=await n.readFile(e,`utf-8`)}catch(e){if(V(e))return null;throw e}let o=W(a);return{path:r.relative(t,e).replace(/\\/g,`/`),absPath:e,mtimeMs:i.mtimeMs,size:i.size,hash:o}}function ze(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:W(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 Be(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 Ve(e){try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function He(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 Ue(e){return(e.toLowerCase().match(/[\p{L}\p{N}_]+/gu)??[]).filter(Boolean)}function We(e){return a.createHash(`sha256`).update(e).digest().readUInt32BE(0)}function Ge(e,t=384){let n=Array(t).fill(0),r=Ue(e);if(r.length===0)return n;for(let e of r){let r=We(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 Ke(e){let t=e?.model?.trim()||`mock-embedding-v1`,n=e?.dimensions??384;return{id:`external-mock`,model:t,embedQuery:async e=>Ge(e,n),embedBatch:async e=>e.map(e=>Ge(e,n))}}const G=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 qe(e){let t=e.id?.trim()||e.pluginId;return G.register({id:t,pluginId:e.pluginId,create:e.create,config:e.config,rootDir:e.rootDir,source:e.source}),t}function Je(e){let t=e.providerId?.trim(),n=e.pluginId?.trim(),r=(t?G.getById(t):void 0)??(n?G.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 Ye(){G.clear()}const K={enabled:!1,lambda:.7};function q(e){let t=e.toLowerCase().match(/[a-z0-9_]+/g)??[];return new Set(t)}function Xe(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 Ze(e,t,n){if(t.length===0)return 0;let r=0,i=n.get(e.id)??q(e.content);for(let e of t){let t=Xe(i,n.get(e.id)??q(e.content));t>r&&(r=t)}return r}function Qe(e,t,n){return n*e-(1-n)*t}function $e(e,t={}){let{enabled:n=K.enabled,lambda:r=K.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,q(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=Qe(l(n.score),Ze(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 et(e,t={}){if(e.length===0)return e;let n=new Map;return $e(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 tt={enabled:!1,halfLifeDays:30},nt=/(?:^|\/)(?:memory)\/(\d{4})-(\d{2})-(\d{2})\.md$/;function rt(e){return!Number.isFinite(e)||e<=0?0:Math.LN2/e}function it(e){let t=rt(e.halfLifeDays),n=Math.max(0,e.ageInDays);return t<=0||!Number.isFinite(n)?1:Math.exp(-t*n)}function at(e){return e.score*it(e)}function ot(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``),n=nt.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 st(e){let t=e.replaceAll(`\\`,`/`).replace(/^\.\//,``);return t===`MEMORY.md`||t===`memory.md`?!0:t.startsWith(`memory/`)?!nt.test(t):!1}async function ct(e){let t=ot(e.filePath);if(t)return t;if(e.source===`memory`&&st(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 lt(e,t){return Math.max(0,t-e.getTime())/864e5}async function ut(e){let t={...tt,...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=ct({filePath:i.path,source:i.source,memoryRoot:e.memoryRoot}),r.set(a,o));let s=await o;if(!s)return i;let c=at({score:i.score,ageInDays:lt(s,n),halfLifeDays:t.halfLifeDays});return{...i,score:c}}))}function dt(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 ft(e){return 1/(1+(Number.isFinite(e)?Math.max(0,e):999))}async function pt(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 ut({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:{...tt,...e.temporalDecay},memoryRoot:e.memoryRoot,nowMs:e.nowMs})).slice().sort((e,t)=>t.score-e.score),r={...K,...e.mmr};return r.enabled?et(n,r):n}function mt(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 ht(e.db,`files`,`source`,`TEXT NOT NULL DEFAULT 'memory'`),ht(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 ht(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 J(e,t){return e.length<=t?e:e.slice(0,t)}const gt=e=>Buffer.from(new Float32Array(e).buffer);async function _t(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(gt(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:J(t.text,e.snippetMaxChars),source:t.source})):vt({db:e.db,providerModel:e.providerModel,sourceFilter:e.sourceFilterChunks}).map(t=>({chunk:t,score:He(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:J(t.chunk.text,e.snippetMaxChars),source:t.chunk.source}))}function vt(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:Ve(e.embedding),source:e.source}))}async function yt(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:J(t.text,e.snippetMaxChars),source:t.source}})}const bt=t(import.meta.url);function xt(){try{return bt(`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 St={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 Ct(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 wt(e,t,n){let i=E(e,{storeName:n});return r.relative(i,t).replace(/\\/g,`/`)}async function Tt(e,t){let i=E(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(V(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 Dt(e,t,i){let a;try{a=await n.stat(t)}catch(e){if(V(e))return null;throw e}let o;try{let e=await y(t);if(e===null)return null;o=e}catch(e){if(V(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
+ `),d=W(u);return{path:r.join(w(i),wt(e,t,i)).replace(/\\/g,`/`),absPath:t,mtimeMs:a.mtimeMs,size:a.size,hash:d,content:u,lineMap:c}}const Y=`chunks_vec`,X=`chunks_fts`,Z=`embedding_cache`,Ot=`memory_index_meta_v1`,kt=3e4;function At(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 jt=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 Mt=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(St,n),o=`${i}::${w(a.store.sessionStoreName)}`,s=jt.get(o);if(s)return n&&s.applyConfig(n),s;let c=new e(t,i,a);return jt.set(o,c),c}constructor(e,t,n){this.dataDir=e,this.memoryRoot=t,this.storePath=r.join(t,`.index.sqlite`),this.config=Q(St,n),this.sessionStoreName=w(this.config.store.sessionStoreName),this.provider=Ke(),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=w(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 ${Z}`).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 pt({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 Pe(t)).missing)return{text:``,path:r};let i;try{i=await n.readFile(t,`utf-8`)}catch(e){if(V(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(V(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(){Fe(r.dirname(this.storePath));let{DatabaseSync:e}=xt();return new e(this.storePath,{allowExtension:this.vector.enabled})}ensureSchema(){let e=mt({db:this.db,embeddingCacheTable:Z,ftsTable:X,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(),kt,`sqlite-vec load timed out after ${Math.round(kt/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 Ct({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 ${Y} 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 ${Y}`)}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=d.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=E(this.dataDir,{storeName:this.sessionStoreName});try{let t=d.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 W(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)&&Le(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=Je({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=Ke(),this.embeddingProviderId=void 0,this.providerKey=this.computeProviderKey(),this.dirty=!0)}readMeta(){let e=this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(Ot);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(Ot,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 ${Z}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${a})`).all(...r,...i);for(let e of o)n.set(e.hash,Ve(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 ${Z} (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=ze(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`&&Be(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 ${Y} 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 ${X} 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=W(`${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 ${Y} WHERE id = ?`).run(l)}catch{}this.db.prepare(`INSERT INTO ${Y} (id, embedding) VALUES (?, ?)`).run(l,Buffer.from(new Float32Array(c).buffer))}this.ftsAvailable&&this.db.prepare(`INSERT INTO ${X} (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 _t({db:this.db,vectorTable:Y,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 yt({db:this.db,ftsTable:X,providerModel:this.provider.model,query:e,limit:t,snippetMaxChars:700,sourceFilter:this.buildSourceFilter(),buildFtsQuery:e=>dt(e),bm25RankToScore:ft}):[]}resetIndex(){if(this.db.exec(`DELETE FROM files`),this.db.exec(`DELETE FROM chunks`),this.ftsAvailable)try{this.db.exec(`DELETE FROM ${X}`)}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(d.readdirSync(this.memoryRoot).filter(e=>e.endsWith(`.md`)).length>0)return!1;let e=r.join(this.memoryRoot,`memory`);return d.existsSync(e)?d.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 U(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 ${X}`).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 U(this.memoryRoot),i=(await Promise.all(r.map(async e=>Re(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 ${Y} 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 ${X} 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 Tt(this.dataDir,this.sessionStoreName),n=(await Promise.all(t.map(async e=>Dt(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 ${Y} 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 ${X} 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=At(e.path,e.snippet,e.startLine);return{...e,id:t}})}},$=e({createBuiltinMemoryProvider:()=>Nt});function Nt(e,t){let n=Mt.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()=>U(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{Ee as A,x as B,be as C,F as D,R as E,E as F,de as G,h as H,_e as I,pe as J,v as K,O as L,D as M,Me as N,A as O,he as P,Ae as R,ke as S,z as T,_ as U,fe as V,g as W,b as X,ue as Y,M as _,Ye as a,B as b,me as c,De as d,Te as f,ve as g,j as h,qe as i,L as j,w as k,S as l,ge as m,Nt as n,Je as o,k as p,y as q,Mt as r,U as s,$ as t,ye as u,P as v,Oe as w,je as x,Ne as y,p as z};