@asaidimu/utils-workspace 1.0.0 → 2.0.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/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t,s=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,a=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,c=(e,t,c)=>(c=null!=e?s(a(e)):{},((e,t,s,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))i.call(e,c)||c===s||n(e,c,{get:()=>t[c],enumerable:!(a=r(t,c))||a.enumerable});return e})(e&&e.__esModule?c:n(c,"default",{value:e,enumerable:!0}),e)),d=(e={"node_modules/@asaidimu/events/index.js"(e,t){var s,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var s in t)n(e,s,{get:t[s],enumerable:!0})})(i,{createEventBus:()=>c}),t.exports=(s=i,((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===s||n(e,c,{get:()=>t[c],enumerable:!(i=r(t,c))||i.enumerable});return e})(n({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],n=0,r=0;const o=new Map,a=new Map;let i=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?i=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,r+=t,o.set(e,(o.get(e)||0)+1)},d=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(s)))}catch(n){e.errorHandler({...n,eventName:t,payload:s})}c(t,performance.now()-n)}))},l=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(d,e.batchDelay)}})(),u=e=>{const s=t.get(e);s?a.set(e,Array.from(s)):a.delete(e)};return i&&(i.onmessage=e=>{const{name:t,payload:s}=e.data;(a.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(s),u(e),()=>{n.delete(s),0===n.size?(t.delete(e),a.delete(e)):u(e)}},emit:({name:t,payload:n})=>{if(e.async)return s.push({name:t,payload:n}),s.length>=e.batchSize?d():l(),void(i&&i.postMessage({name:t,payload:n}));const r=performance.now();try{(a.get(t)||[]).forEach((e=>e(n))),i&&i.postMessage({name:t,payload:n})}catch(s){e.errorHandler({...s,eventName:t,payload:n})}c(t,performance.now()-r)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:n>0?r/n:0}),clear:()=>{t.clear(),a.clear(),s=[],n=0,r=0,o.clear(),i&&(i.close(),i=null)}}}}},function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports});function l(e){return{ok:!0,value:e}}function u(e){return{ok:!1,error:e}}c(d());var p=Symbol.for("delete"),h=e=>Array.isArray(e)?[...e]:{...e};function f(){return p}c(d()),c(d()),c(d()),c(d()),c(d()),c(d());var m=function(e){const t=e?.deleteMarker||p;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const n={};for(const[r,o]of Object.entries(e))if(o!==t)if("object"==typeof o&&null!==o){const e=s(o);void 0!==e&&(n[r]=e)}else n[r]=o;return n}return e===t?void 0:e}return function(e,n){if("object"!=typeof e||null===e)return"object"==typeof n&&null!==n?s(n):n===t?{}:n;if("object"!=typeof n||null===n)return e;const r=h(e),o=[{target:r,source:n}];for(;o.length>0;){const{target:e,source:s}=o.pop();for(const n of Object.keys(s)){const r=s[n];if(r!==t)if(Array.isArray(r))e[n]=r;else if("object"==typeof r&&null!==r){const t=n in e&&"object"==typeof e[n]&&null!==e[n]?e[n]:{};e[n]=h(t),o.push({target:e[n],source:r})}else e[n]=r;else delete e[n]}}return r}}({deleteMarker:p}),y="roles",w="preferences",b="context",g="turns",S="session_heads",x="index_state",v="singleton";function T(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function k(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}var O="blob_bytes",C="blob_records";function j(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function I(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}async function N(e){const t=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(t)).map((e=>e.toString(16).padStart(2,"0"))).join("")}function B(e){return{sha256:e.sha256,mediaType:e.mediaType,sizeBytes:e.sizeBytes,filename:e.filename,refCount:e.refCount,createdAt:e.createdAt,lastUsedAt:e.lastUsedAt}}var D={roles:1/0,preferences:50,contextEntries:20,transcriptWindows:3},P=10,R=3e4,A=class{map=new Map;max;constructor(e){this.max=e}get(e){if(!this.map.has(e))return;const t=this.map.get(e);return this.map.delete(e),this.map.set(e,t),t}set(e,t){if(this.map.has(e)&&this.map.delete(e),this.map.set(e,t),this.map.size>this.max){const e=this.map.keys().next().value;void 0!==e&&this.map.delete(e)}}has(e){return this.map.has(e)}delete(e){this.map.delete(e)}},E=class{roles;preferences;contexts;transcriptWindows;pinnedRoles=new Map;pinnedPreferences=new Map;pinnedContexts=new Map;pinnedTranscriptWindows=new Map;constructor(e){this.roles=new A(e.roles),this.preferences=new A(e.preferences),this.contexts=new A(e.contextEntries),this.transcriptWindows=new A(e.transcriptWindows)}getRole(e){return this.pinnedRoles.get(e)??this.roles.get(e)}setRole(e,t=!1){t?(this.pinnedRoles.set(e.name,e),this.roles.delete(e.name)):this.pinnedRoles.has(e.name)?this.pinnedRoles.set(e.name,e):this.roles.set(e.name,e)}deleteRole(e){this.pinnedRoles.delete(e),this.roles.delete(e)}unpinRole(e){const t=this.pinnedRoles.get(e);t&&(this.pinnedRoles.delete(e),this.roles.set(e,t))}getPreference(e){return this.pinnedPreferences.get(e)??this.preferences.get(e)}setPreference(e,t=!1){t?(this.pinnedPreferences.set(e.id,e),this.preferences.delete(e.id)):this.pinnedPreferences.has(e.id)?this.pinnedPreferences.set(e.id,e):this.preferences.set(e.id,e)}unpinPreference(e){const t=this.pinnedPreferences.get(e);t&&(this.pinnedPreferences.delete(e),this.preferences.set(e,t))}deletePreference(e){this.pinnedPreferences.delete(e),this.preferences.delete(e)}getContext(e){return this.pinnedContexts.get(e)??this.contexts.get(e)}setContext(e,t=!1){t?(this.pinnedContexts.set(e.key,e),this.contexts.delete(e.key)):this.contexts.set(e.key,e)}unpinContext(e){const t=this.pinnedContexts.get(e);t&&(this.pinnedContexts.delete(e),this.contexts.set(e,t))}invalidateContext(e){this.contexts.delete(e),this.pinnedContexts.delete(e)}getTranscriptWindow(e){return this.pinnedTranscriptWindows.get(e)??this.transcriptWindows.get(e)}setTranscriptWindow(e,t=!1){t?(this.pinnedTranscriptWindows.set(e.sessionId,e),this.transcriptWindows.delete(e.sessionId)):this.transcriptWindows.set(e.sessionId,e)}unpinTranscriptWindow(e){const t=this.pinnedTranscriptWindows.get(e);t&&(this.pinnedTranscriptWindows.delete(e),this.transcriptWindows.set(e,t))}invalidateTranscriptWindow(e){this.transcriptWindows.delete(e),this.pinnedTranscriptWindows.delete(e)}},_=class{sessionId;dirtyBuffer=[];flushTimer=null;flushConfig;onFlush;flushChain=Promise.resolve();constructor(e,t,s){this.sessionId=e,this.flushConfig=t,this.onFlush=s,this.startTimer()}startTimer(){this.flushTimer=setInterval((()=>{this.flushChain=this.flushChain.then((()=>this.doFlush()))}),this.flushConfig.flushIntervalMs)}async record(e){this.dirtyBuffer.push(e),this.dirtyBuffer.length>=this.flushConfig.maxBufferSize&&await this.flush()}getDirtyBuffer(){return this.dirtyBuffer}async flush(){return this.flushChain=this.flushChain.then((()=>this.doFlush())),this.flushChain}async doFlush(){if(0===this.dirtyBuffer.length)return;const e=this.dirtyBuffer.splice(0,this.dirtyBuffer.length);await this.onFlush(this.sessionId,e)}async deactivate(){null!==this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush()}};function $(e,t){return e.preferences.length>0?e.preferences:t.preferences}function F(e,t){return e.filter((e=>0===e.topics.length||e.topics.some((e=>t.includes(e)))))}function M(e,t){switch(t.type){case"workspace:create":{const{id:e,settings:s,project:n}=t.payload;return l({workspace:{id:e,settings:s,project:n,indexes:{sessions:{},roles:{},preferences:{},context:{},topics:{}}}})}case"role:add":{const s=t.payload;if(e.roles[s.name])return u({code:"DUPLICATE_KEY",resource:"role",key:s.name});const n={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return l({roles:{[s.name]:n},workspace:{indexes:{roles:{[s.name]:n}}}})}case"preference:add":{const s=t.payload,n={id:s.id,topics:s.topics,timestamp:s.timestamp,snippet:s.content.substring(0,100)},r={};return s.topics.forEach((n=>{const o=e.workspace.indexes.topics[n];r[n]={topic:n,contextKeys:o?.contextKeys||[],preferences:[...o?.preferences||[],s.id],metadata:{created:o?.metadata?.created||t.timestamp,updated:t.timestamp,entries:o?.metadata?.entries||0}}})),l({preferences:{[s.id]:n},workspace:{indexes:{preferences:{[s.id]:n},topics:r}}})}case"context:add":{const s=t.payload;if(e.context[s.key])return u({code:"DUPLICATE_KEY",resource:"context",key:s.key});const n={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"string"==typeof s.content?s.content.substring(0,200):JSON.stringify(s.content).substring(0,200),metadata:s.metadata},r={};return s.topics.forEach((n=>{const o=e.workspace.indexes.topics[n],a=o?.contextKeys||[],i=a.includes(s.key)?a:[...a,s.key];r[n]={topic:n,contextKeys:i,metadata:{updated:t.timestamp,entries:i.length}}})),l({context:{[s.key]:n},workspace:{indexes:{context:{[s.key]:n},topics:r}}})}case"session:create":{const{id:s,label:n,role:r,topics:o,preferences:a=[]}=t.payload;if(e.sessions[s])return u({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[r])return u({code:"NOT_FOUND",resource:"role",id:r});const i={id:s,label:n,role:r,topics:o,preferences:a,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null};return l({sessions:{[s]:i},workspace:{indexes:{sessions:{[s]:{id:s,label:n,role:r,topics:o,created:t.timestamp,updated:t.timestamp,turns:0}}}}})}case"turn:add":{const{sessionId:s,turn:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n.id,version:n.version},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{turns:(e.workspace.indexes.sessions[s]?.turns??0)+1,updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:n,newVersion:r}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n,version:r},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n.id,version:n.version},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:role:switch":{const{sessionId:s,role:n}=t.payload;return e.sessions[s]?e.roles[n]?l({sessions:{[s]:{role:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{role:n,updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"role",id:n}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:n}=t.payload,r=e.sessions[s];if(!r)return u({code:"NOT_FOUND",resource:"session",id:s});const o=Array.from(new Set([...r.topics,...n]));return l({sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{topics:o,updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{preferences:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:n,label:r,role:o,topics:a}=t.payload,i=e.sessions[s];if(!i)return u({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[n])return u({code:"DUPLICATE_KEY",resource:"session",key:n});const c=o??i.role;if(!e.roles[c])return u({code:"NOT_FOUND",resource:"role",id:c});const d=a??[...i.topics],p={id:n,label:r,role:c,topics:d,preferences:[...i.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:i.flushedTurnCount,head:i.head};return l({sessions:{[n]:p},workspace:{indexes:{sessions:{[n]:{id:n,label:r,role:c,topics:d,created:t.timestamp,updated:t.timestamp,turns:i.flushedTurnCount}}}}})}case"role:update":{const{name:s,...n}=t.payload;if(!e.roles[s])return u({code:"NOT_FOUND",resource:"role",id:s});const r=e.roles[s],o={...r,...n,preferences:n.preferences?.length??r.preferences};return l({roles:{[s]:o},workspace:{indexes:{roles:{[s]:o}}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return u({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?u({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):l({roles:{[s]:f()},workspace:{indexes:{roles:{[s]:f()}}}})}case"preference:update":{const{id:s,...n}=t.payload;if(!e.preferences[s])return u({code:"NOT_FOUND",resource:"preference",id:s});const r=e.preferences[s],o={...r,...n,snippet:n.content?n.content.substring(0,100):r.snippet},a={};return n.topics&&(r.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(a[t]={preferences:n.preferences.filter((e=>e!==s))})})),n.topics.forEach((n=>{const r=e.workspace.indexes.topics[n]||{topic:n,contextKeys:[],preferences:[],metadata:{created:t.timestamp,updated:t.timestamp,entries:0}};a[n]={...r,preferences:[...new Set([...r.preferences,s])],metadata:{updated:t.timestamp}}}))),l({preferences:{[s]:o},workspace:{indexes:{preferences:{[s]:o},topics:a}}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return u({code:"NOT_FOUND",resource:"preference",id:s});const n=e.preferences[s],r={};return n.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(r[t]={preferences:n.preferences.filter((e=>e!==s))})})),l({preferences:{[s]:f()},workspace:{indexes:{preferences:{[s]:f()},topics:r}}})}case"context:update":{const{key:s,...n}=t.payload;if(!e.context[s])return u({code:"NOT_FOUND",resource:"context",id:s});const r=e.context[s],o={...r,...n,preview:n.content?"string"==typeof n.content?n.content.substring(0,200):JSON.stringify(n.content).substring(0,200):r.preview},a={};return n.topics&&(r.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(a[t]={contextKeys:n.contextKeys.filter((e=>e!==s))})})),n.topics.forEach((n=>{const r=e.workspace.indexes.topics[n]||{contextKeys:[]},o=r.contextKeys.includes(s)?r.contextKeys:[...r.contextKeys,s];a[n]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),l({context:{[s]:o},workspace:{indexes:{context:{[s]:o},topics:a}}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return u({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],r={};return n.topics.forEach((n=>{const o=e.workspace.indexes.topics[n];o&&(r[n]={contextKeys:o.contextKeys.filter((e=>e!==s)),metadata:{updated:t.timestamp,entries:o.contextKeys.length-1}})})),l({context:{[s]:f()},workspace:{indexes:{context:{[s]:f()},topics:r}}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?l({sessions:{[s]:f()},workspace:{indexes:{sessions:{[s]:f()}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}default:return l({})}}function U(e){return Math.ceil(e.length/4)}function W(e,t){return(t??U)(e)}function z(e,t){return Math.ceil(e/1024*t)}function H(e,t,s,n){return V(e,t).reduce(((e,t)=>e+function(e,t,s){switch(e.type){case"text":return W(e.text,t);case"image":case"document":return z(e.blob.data?.byteLength??0,s);case"tool_use":return W(JSON.stringify(e.input),t);case"tool_result":return W("string"==typeof e.content?e.content:JSON.stringify(e.content),t);case"thinking":return W(e.thinking,t);default:return 0}}(t,s,n)),0)}function K(e){return new Set(e.toLowerCase().replace(/[^\w\s]/g," ").split(/\s+/).filter((e=>e.length>2)))}function L(e,t){const s=(Date.now()-new Date(e).getTime())/864e5;return Math.pow(.5,s/t)}function V(e,t){return e.blocks.map((e=>{if("image"===e.type){const s=t.get(e.blob.sha256);if(s)return{...e,blob:s}}if("document"===e.type){const s=t.get(e.blob.sha256);if(s)return{...e,blob:s}}return e}))}function J(e){return"object"==typeof e&&null!==e?JSON.stringify(e):String(e)}exports.BlobStore=class{backend;config;recordCache=new Map;onRegistryChanged;constructor(e,t={}){this.backend=e,this.config={eagerEviction:t.eagerEviction??!1}}async init(){const e=await this.backend.listRecords();for(const t of e)this.recordCache.set(t.sha256,t)}async register(e,t,s){try{const n=await N(e),r=(new Date).toISOString(),o=this.recordCache.get(n);if(o){const e={...o,refCount:o.refCount+1,lastUsedAt:r};await this.backend.saveRecord(e),this.recordCache.set(n,e),this.onRegistryChanged?.(n,B(e))}else{const o={sha256:n,mediaType:t,sizeBytes:e.byteLength,filename:s,refCount:1,remoteIds:{},createdAt:r,lastUsedAt:r};"registerBlob"in this.backend&&"function"==typeof this.backend.registerBlob?await this.backend.registerBlob(o,e):(await this.backend.storeBytes(n,e),await this.backend.saveRecord(o)),this.recordCache.set(n,o),this.onRegistryChanged?.(n,B(o))}const a=this.recordCache.get(n);return l({sha256:n,mediaType:t,sizeBytes:a.sizeBytes,filename:a.filename})}catch(e){return u({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return u({code:"NOT_FOUND",resource:"blob",id:e});const s={...t,refCount:t.refCount+1,lastUsedAt:(new Date).toISOString()};return await this.backend.saveRecord(s),this.recordCache.set(e,s),this.onRegistryChanged?.(e,B(s)),l(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return u({code:"NOT_FOUND",resource:"blob",id:e});const s=Math.max(0,t.refCount-1),n={...t,refCount:s,lastUsedAt:(new Date).toISOString()};return 0===s&&this.config.eagerEviction?(await this.backend.deleteBytes(e),await this.backend.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null)):(await this.backend.saveRecord(n),this.recordCache.set(e,n),this.onRegistryChanged?.(e,B(n))),l(void 0)}async recordRemoteId(e,t,s){const n=this.recordCache.get(e);if(!n)return u({code:"NOT_FOUND",resource:"blob",id:e});if(n.remoteIds[t]===s)return l(void 0);const r={...n,remoteIds:{...n.remoteIds,[t]:s}};return await this.backend.saveRecord(r),this.recordCache.set(e,r),l(void 0)}getRemoteId(e,t){return this.recordCache.get(e)?.remoteIds[t]??null}async resolveRef(e,t){try{if(t){const s=this.getRemoteId(e.sha256,t);if(s)return l({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.backend.loadBytes(e.sha256);return s?l({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):u({code:"BLOB_ERROR",reason:`Blob bytes not found locally for sha256=${e.sha256}. The blob may have been evicted. Re-register it before resolving.`})}catch(e){return u({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async resolveRefs(e,t){const s=function(e){const t=new Set,s=[];for(const n of e)t.has(n.sha256)||(t.add(n.sha256),s.push(n));return s}(e),n=await Promise.all(s.map((async e=>({ref:e,result:await this.resolveRef(e,t)})))),r=new Map,o=[];for(const{ref:e,result:t}of n)t.ok?r.set(e.sha256,t.value):o.push({ref:e,error:t.error});return{resolved:r,errors:o}}async gc(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((async e=>{await this.backend.deleteBytes(e.sha256)}))),e.length}async purge(e){return this.recordCache.has(e)?(await this.backend.deleteBytes(e),await this.backend.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null),l(void 0)):u({code:"NOT_FOUND",resource:"blob",id:e})}getRecord(e){return this.recordCache.get(e)??null}getSummary(e){const t=this.recordCache.get(e);return t?B(t):null}getAllSummaries(){const e={};for(const[t,s]of this.recordCache)e[t]=B(s);return e}},exports.ContentStore=class{storage;cache;config;activeSession=null;pinnedPreferenceIds=new Set;onFlushed;onSessionInvalidated;constructor(e,t={}){this.storage=e;const s={roles:t.cache?.roles??D.roles,preferences:t.cache?.preferences??D.preferences,contextEntries:t.cache?.contextEntries??D.contextEntries,transcriptWindows:t.cache?.transcriptWindows??D.transcriptWindows};this.cache=new E(s),this.config={cache:s,flush:{maxBufferSize:t.flush?.maxBufferSize??P,flushIntervalMs:t.flush?.flushIntervalMs??R},transcriptWindowSize:t.transcriptWindowSize??20}}getActiveSessionId(){return this.activeSession?.sessionId??null}async getRole(e){const t=this.cache.getRole(e);if(t)return l(t);const s=await this.storage.loadRole(e);return s?(this.cache.setRole(s),l(s)):u({code:"NOT_FOUND",resource:"role",id:e})}async getPreference(e){const t=this.cache.getPreference(e);if(t)return l(t);const s=await this.storage.loadPreference(e);return s?(this.cache.setPreference(s),l(s)):u({code:"NOT_FOUND",resource:"preference",id:e})}async getContext(e){const t=this.cache.getContext(e);if(t)return l(t);const s=await this.storage.loadContext(e);return s?(this.cache.setContext(s),l(s)):u({code:"NOT_FOUND",resource:"context",id:e})}async getContextByTopics(e,t){const s=new Set;for(const n of t){const t=e.workspace.indexes.topics[n];t&&t.contextKeys.forEach((e=>s.add(e)))}return(await Promise.all(Array.from(s).map((e=>this.getContext(e))))).filter((e=>e.ok)).map((e=>e.value)).sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async getTranscriptWindow(e,t){const s=t??this.config.transcriptWindowSize,n=this.activeSession?.sessionId===e,r=n?[...this.activeSession?.getDirtyBuffer()??[]]:[],o=await this.storage.getActiveChain(e),a=[...o,...r].slice(-s),i=o.length+r.length,c={sessionId:e,turns:a,flushedCount:i,hasMore:i>s};return this.cache.setTranscriptWindow(c,n),c}async saveRole(e){await this.storage.saveRole(e),this.cache.setRole(e)}async savePreference(e){await this.storage.savePreference(e),this.cache.setPreference(e)}async saveContext(e){await this.storage.saveContext(e),this.cache.setContext(e)}async copyTranscript(e,t){await this.storage.copyTranscript(e,t)}async deleteRole(e){await this.storage.deleteRole(e),this.cache.deleteRole(e)}async deletePreference(e){await this.storage.deletePreference(e),this.cache.deletePreference(e),this.pinnedPreferenceIds.delete(e)}async deleteContext(e){await this.storage.deleteContext(e),this.cache.invalidateContext(e)}async recordTurn(e,t){return this.activeSession?.sessionId===e?(await this.activeSession.record(t),this.cache.invalidateTranscriptWindow(e)):(await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version}),this.cache.invalidateTranscriptWindow(e)),this.onSessionInvalidated?.(e),l(void 0)}async editTurn(e,t,s,n,r){let o=null;if(this.activeSession?.sessionId===e&&(o=this.activeSession.getDirtyBuffer().find((e=>e.id===t&&e.version===n-1))??null),o||(o=await this.storage.loadTurn(e,t,n-1)),!o)return u({code:"NOT_FOUND",resource:"turn",id:t});const a={id:t,version:n,role:o.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:r??o.roleSnapshot,parent:o.parent};return this.activeSession?.sessionId===e?await this.activeSession.record(a):(await this.storage.saveTurn(e,a),await this.storage.setSessionHead(e,{id:a.id,version:a.version})),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async branchTurn(e,t){return await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version}),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async deleteTurnSubtree(e,t,s,n){return await this.storage.deleteTurnSubtree(e,t,s),await this.storage.setSessionHead(e,n),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async activateSession(e){if(this.activeSession?.sessionId===e.id)return l(void 0);this.activeSession&&await this.deactivateSession(),this.activeSession=new _(e.id,this.config.flush,(async(e,t)=>{for(const s of t)await this.storage.saveTurn(e,s);if(t.length>0){const s=t[t.length-1];await this.storage.setSessionHead(e,{id:s.id,version:s.version})}this.onFlushed?.(e,t.length)}));const t=await this.getRole(e.role);t.ok&&this.cache.setRole(t.value,!0);const s=$(e,t.ok?t.value:{preferences:[]}),n=[];await Promise.all(s.map((async e=>{const t=await this.getPreference(e);t.ok&&n.push(t.value)})));const r=F(n,e.topics);this.pinnedPreferenceIds=new Set;for(const e of r)this.cache.setPreference(e,!0),this.pinnedPreferenceIds.add(e.id);const o=await this.getTranscriptWindow(e.id,e.flushedTurnCount);return this.cache.setTranscriptWindow(o,!0),this.onSessionInvalidated?.(e.id),l(void 0)}async deactivateSession(e){if(!this.activeSession)return;const t=this.activeSession.sessionId;await this.activeSession.deactivate(),this.activeSession=null,e&&this.cache.unpinRole(e.role);for(const e of this.pinnedPreferenceIds)this.cache.unpinPreference(e);this.pinnedPreferenceIds=new Set,this.cache.unpinTranscriptWindow(t)}async resolveSession(e,t){const s=e.sessions[t];if(!s)return u({code:"NOT_FOUND",resource:"session",id:t});const n=await this.getRole(s.role);if(!n.ok)return n;const r=n.value,o=$(s,r),a={session:s,role:r,preferences:F((await Promise.all(o.map((e=>this.getPreference(e))))).filter((e=>e.ok)).map((e=>e.value)),s.topics),context:await this.getContextByTopics(e,s.topics),transcript:(await this.getTranscriptWindow(t,s.flushedTurnCount)).turns,systemPrompt:e.workspace.settings.prompt};return l(structuredClone(a))}async flush(){await(this.activeSession?.flush())}async dispose(){await this.deactivateSession()}},exports.IndexedDBBlobStorage=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace-blobs"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,1);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBBlobStorage] Database "${this.dbName}" blocked.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){e.objectStoreNames.contains(O)||e.createObjectStore(O,{keyPath:"sha256"}),e.objectStoreNames.contains(C)||e.createObjectStore(C,{keyPath:"sha256"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBBlobStorage] Database not open. Call open() first.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async storeBytes(e,t){const s=this.readTx(O);if(await j(s.objectStore(O).get(e)))return;const n=this.writeTx(O);n.objectStore(O).put({sha256:e,data:t}),await I(n)}async loadBytes(e){const t=this.readTx(O),s=await j(t.objectStore(O).get(e));return s?.data??null}async hasBytes(e){const t=this.readTx(O);return await j(t.objectStore(O).count(e))>0}async deleteBytes(e){const t=this.writeTx(O);t.objectStore(O).delete(e),await I(t)}async saveRecord(e){const t=this.writeTx(C);t.objectStore(C).put(e),await I(t)}async loadRecord(e){const t=this.readTx(C);return await j(t.objectStore(C).get(e))??null}async deleteRecord(e){const t=this.writeTx(C);t.objectStore(C).delete(e),await I(t)}async listRecords(){return j(this.readTx(C).objectStore(C).getAll())}async exportAllBytes(){const e=this.readTx(O);return(await j(e.objectStore(O).getAll())).map((({sha256:e,data:t})=>[e,t]))}async registerBlob(e,t){await new Promise(((s,n)=>{const r=this.getDB().transaction([O,C],"readwrite"),o=r.objectStore(O),a=r.objectStore(C),i=o.count(e.sha256);i.onsuccess=()=>{0===i.result&&o.put({sha256:e.sha256,data:t}),a.put(e)},i.onerror=()=>n(i.error),r.oncomplete=()=>s(),r.onerror=()=>n(r.error),r.onabort=()=>n(new Error("registerBlob transaction aborted"))}))}},exports.IndexedDBStorage=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,2);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBBackend] Database "${this.dbName}" blocked. Close other tabs.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){if(e.objectStoreNames.contains(y)||e.createObjectStore(y,{keyPath:"name"}),e.objectStoreNames.contains(w)||e.createObjectStore(w,{keyPath:"id"}),!e.objectStoreNames.contains(b)){e.createObjectStore(b,{keyPath:"key"}).createIndex("by_topic","topics",{multiEntry:!0})}if(e.objectStoreNames.contains(x)||e.createObjectStore(x,{keyPath:"id"}),!e.objectStoreNames.contains(g)){e.createObjectStore(g,{keyPath:["sessionId","id","version"]}).createIndex("by_sessionId","sessionId")}e.objectStoreNames.contains(S)||e.createObjectStore(S,{keyPath:"sessionId"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBBackend] Database not open. Call open() before using the backend.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async saveRole(e){const t=this.writeTx(y);t.objectStore(y).put(e),await k(t)}async loadRole(e){const t=this.readTx(y);return await T(t.objectStore(y).get(e))??null}async deleteRole(e){const t=this.writeTx(y);t.objectStore(y).delete(e),await k(t)}async savePreference(e){const t=this.writeTx(w);t.objectStore(w).put(e),await k(t)}async loadPreference(e){const t=this.readTx(w);return await T(t.objectStore(w).get(e))??null}async deletePreference(e){const t=this.writeTx(w);t.objectStore(w).delete(e),await k(t)}async saveContext(e){const t=this.writeTx(b);t.objectStore(b).put(e),await k(t)}async loadContext(e){const t=this.readTx(b);return await T(t.objectStore(b).get(e))??null}async deleteContext(e){const t=this.writeTx(b);t.objectStore(b).delete(e),await k(t)}async saveTurn(e,t){const s=this.getDB().transaction([g,S],"readwrite"),n=s.objectStore(g),r=s.objectStore(S),o=r.get(e),a=await T(o),i=a?.head??null;let c={...t};null===c.parent&&null!==i&&(c.parent={id:i.id,version:i.version}),c={...c,version:c.version??0},n.put({sessionId:e,...c}),r.put({sessionId:e,head:{id:c.id,version:c.version}}),await k(s)}async loadAllTurns(e,t){const s=this.readTx(g).objectStore(g).index("by_sessionId"),n=await T(s.getAll(e));return n.sort(((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime())),void 0!==t&&t>0?n.slice(-t):n}async countChainedTurns(e){const t=this.readTx(g).objectStore(g).index("by_sessionId");return(await T(t.getAllKeys(e))).length}async loadTurn(e,t,s){const n=this.readTx(g);return await T(n.objectStore(g).get([e,t,s]))??null}async setSessionHead(e,t){const s=this.writeTx(S);t?s.objectStore(S).put({sessionId:e,head:t}):s.objectStore(S).delete(e),await k(s)}async getSessionHead(e){const t=this.readTx(S),s=await T(t.objectStore(S).get(e));return s?.head??null}async getActiveChain(e){let t=await this.getSessionHead(e);const s=[];for(;null!==t;){const n=await this.loadTurn(e,t.id,t.version);if(!n)break;s.push(n),t=n.parent}return s.reverse()}async deleteTurnSubtree(e,t,s){const n=await this.loadAllTurns(e),r=new Set;r.add(`${t}:${s}`);let o=!0;for(;o;){o=!1;for(const e of n)if(e.parent){const t=`${e.parent.id}:${e.parent.version}`,s=`${e.id}:${e.version}`;r.has(t)&&!r.has(s)&&(r.add(s),o=!0)}}const a=this.getDB().transaction([g,S],"readwrite"),i=a.objectStore(g),c=a.objectStore(S);for(const t of r){const[s,n]=t.split(":");i.delete([e,s,Number(n)])}const d=await T(c.get(e));if(d?.head){const t=`${d.head.id}:${d.head.version}`;if(r.has(t)){let t=d.head;for(;t;){const e=n.find((e=>e.id===t?.id&&e.version===t?.version));if(!e||!e.parent){t=null;break}const s=`${e.parent.id}:${e.parent.version}`;if(!r.has(s)){t=e.parent;break}t=e.parent}t?c.put({sessionId:e,head:t}):c.delete(e)}}await k(a)}async copyTranscript(e,t){const s=await this.loadAllTurns(e);await new Promise(((n,r)=>{const o=this.getDB().transaction([g,S],"readwrite"),a=o.objectStore(g),i=o.objectStore(S);for(const e of s){const s={...e,sessionId:t};a.put(s)}const c=i.get(e);c.onsuccess=()=>{const e=c.result;e?.head&&i.put({sessionId:t,head:{...e.head}})},c.onerror=()=>r(c.error||new Error("Failed to read head")),o.oncomplete=()=>n(),o.onerror=()=>r(o.error),o.onabort=()=>r(new Error("copyTranscript transaction aborted"))}))}async saveIndexState(e){const t=this.writeTx(x);t.objectStore(x).put({id:v,state:e}),await k(t)}async loadIndexState(){const e=this.readTx(x),t=await T(e.objectStore(x).get(v));return t?.state??null}async exportBundle(){const e=this.getDB(),[t,s,n,r]=await Promise.all([this.getAllFromStore(e,y),this.getAllFromStore(e,w),this.getAllFromStore(e,b),this.getAllFromStore(e,x)]),o=await this.getAllFromStore(e,g),a=new Set(o.map((e=>e.sessionId))),i={};for(const e of a)i[e]=await this.getActiveChain(e);return{roles:Object.fromEntries(t.map((e=>[e.name,e]))),preferences:Object.fromEntries(s.map((e=>[e.id,e]))),context:Object.fromEntries(n.map((e=>[e.key,e]))),transcripts:i,indexState:r[0]?.state??null}}async importBundle(e){await new Promise(((t,s)=>{const n=this.getDB().transaction([y,w,b,g,S,x],"readwrite"),r=n.objectStore(y),o=n.objectStore(w),a=n.objectStore(b),i=n.objectStore(g),c=n.objectStore(S),d=n.objectStore(x);for(const t of Object.values(e.roles||{}))r.put(t);for(const t of Object.values(e.preferences||{}))o.put(t);for(const t of Object.values(e.context||{}))a.put(t);for(const[t,s]of Object.entries(e.transcripts||{})){for(const e of s)i.put({sessionId:t,...e,version:e.version??0,parent:e.parent??null});if(s.length>0){const e=s[s.length-1];c.put({sessionId:t,head:{id:e.id,version:e.version??0}})}}e.indexState&&d.put({id:v,state:e.indexState}),n.oncomplete=()=>t(),n.onerror=()=>s(n.error),n.onabort=()=>s(new Error("importBundle transaction aborted"))}))}getAllFromStore(e,t){return new Promise(((s,n)=>{const r=e.transaction(t,"readonly").objectStore(t).getAll();r.onsuccess=()=>s(r.result),r.onerror=()=>n(r.error)}))}},exports.MemoryBlobStorage=class{bytes=new Map;records=new Map;async storeBytes(e,t){this.bytes.has(e)||this.bytes.set(e,t)}async loadBytes(e){return this.bytes.get(e)??null}async hasBytes(e){return this.bytes.has(e)}async deleteBytes(e){this.bytes.delete(e)}async saveRecord(e){this.records.set(e.sha256,{...e})}async loadRecord(e){return this.records.get(e)??null}async deleteRecord(e){this.records.delete(e)}async listRecords(){return Array.from(this.records.values()).map((e=>({...e})))}async exportAllBytes(){return Array.from(this.bytes.entries()).map((([e,t])=>[e,new Uint8Array(t)]))}},exports.MemoryStorage=class e{roles=new Map;preferences=new Map;contexts=new Map;turnVersions=new Map;sessionHeads=new Map;async saveRole(e){this.roles.set(e.name,e)}async loadRole(e){return this.roles.get(e)??null}async deleteRole(e){this.roles.delete(e)}async savePreference(e){this.preferences.set(e.id,e)}async loadPreference(e){return this.preferences.get(e)??null}async deletePreference(e){this.preferences.delete(e)}async saveContext(e){this.contexts.set(e.key,e)}async loadContext(e){return this.contexts.get(e)??null}async deleteContext(e){this.contexts.delete(e)}async saveTurn(e,t){const s=this.sessionHeads.get(e)??null;let n={...t};null===n.parent&&null!==s&&(n.parent={id:s.id,version:s.version}),n={...n,version:n.version??0};const r=`${e}:${n.id}:${n.version}`;this.turnVersions.set(r,n),this.sessionHeads.set(e,{id:n.id,version:n.version})}async loadTurn(e,t,s){const n=`${e}:${t}:${s}`;return this.turnVersions.get(n)??null}async loadAllTurns(e,t){const s=`${e}:`,n=[];for(const[e,t]of this.turnVersions.entries())e.startsWith(s)&&n.push(t);return n.sort(((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime())),void 0!==t&&t>0?n.slice(-t):n}async setSessionHead(e,t){this.sessionHeads.set(e,t)}async getSessionHead(e){return this.sessionHeads.get(e)??null}async getActiveChain(e){let t=this.sessionHeads.get(e)??null;const s=[];for(;null!==t;){const n=await this.loadTurn(e,t.id,t.version);if(!n)break;s.push(n),t=n.parent}return s.reverse()}async deleteTurnSubtree(e,t,s){const n=await this.loadAllTurns(e),r=new Set;r.add(`${t}:${s}`);let o=!0;for(;o;){o=!1;for(const e of n)if(e.parent){const t=`${e.parent.id}:${e.parent.version}`,s=`${e.id}:${e.version}`;r.has(t)&&!r.has(s)&&(r.add(s),o=!0)}}for(const t of r)this.turnVersions.delete(`${e}:${t}`)}async countChainedTurns(e){return(await this.getActiveChain(e)).length}async copyTranscript(e,t){const s=await this.loadAllTurns(e);for(const e of s)await this.saveTurn(t,{...e});const n=await this.getSessionHead(e);await this.setSessionHead(t,n?{...n}:null)}static fromBundle(t){const s=new e;for(const e of Object.values(t.roles))s.roles.set(e.name,e);for(const e of Object.values(t.preferences))s.preferences.set(e.id,e);for(const e of Object.values(t.context))s.contexts.set(e.key,e);const n={};for(const e of Object.values(t.sessions)){const t=e.turns??[];let r=null;for(const n of t){const t={...n,version:n.version??0,parent:r};s.turnVersions.set(`${e.id}:${t.id}:${t.version}`,t),r={id:t.id,version:t.version}}s.sessionHeads.set(e.id,r),n[e.id]={id:e.id,label:e.label,role:e.role,topics:e.topics,preferences:e.preferences??[],metadata:e.metadata??{created:(new Date).toISOString(),updated:(new Date).toISOString()},flushedTurnCount:t.length,head:r}}const r={};for(const e of Object.values(t.roles))r[e.name]={name:e.name,label:e.label,description:e.description,preferences:e.preferences.length};const o={};for(const e of Object.values(t.preferences))o[e.id]={id:e.id,topics:e.topics,timestamp:e.timestamp,snippet:e.content.substring(0,100)};const a={};for(const e of Object.values(t.context))a[e.key]={key:e.key,topics:e.topics,timestamp:e.timestamp,source:e.key.split(":")[0],preview:"string"==typeof e.content?e.content.substring(0,200):JSON.stringify(e.content).substring(0,200),metadata:e.metadata};return{backend:s,indexState:{format:"aiworkspace/4.0",workspace:t.workspace,roles:r,preferences:o,context:a,sessions:n,blobs:t.blobs}}}},exports.PromptBuilder=class{summarizer;constructor(e){this.summarizer=e}async build(e,t={}){const{resolvedBlobs:s=new Map,tokenBudget:n,relevanceConfig:r={}}=t,o=[],a=function(e,t){const s=new Set,n=[];function r(e){s.has(e.sha256)||(s.add(e.sha256),n.push(e))}for(const t of e)for(const e of t.blocks)if(("image"===e.type||"document"===e.type)&&"blob"in e){const t=e;r({sha256:t.blob.sha256,mediaType:t.blob.mediaType,sizeBytes:t.blob.data?.byteLength??0,filename:t.blob.filename})}for(const e of t)for(const t of e.attachments??[])r(t);return n}(e.transcript,e.context),i=a.filter((e=>!s.has(e.sha256)));i.length>0&&o.push(`${i.length} blob(s) were not resolved and will be omitted: `+i.map((e=>e.sha256.slice(0,8))).join(", "));const{resolved:c,conflicts:d}=function(e){const t=[],s=new Map;for(const n of e)if(0!==n.topics.length)for(const e of n.topics){const r=s.get(e);if(!r){s.set(e,n);continue}const o=new Date(r.timestamp).getTime(),a=new Date(n.timestamp).getTime();a>o?(t.push({topic:e,kept:n.id,dropped:r.id,reason:"superseded_by_newer"}),s.set(e,n)):o>a&&t.push({topic:e,kept:r.id,dropped:n.id,reason:"superseded_by_newer"})}const n=new Set(t.map((e=>e.dropped))),r=new Set,o=[];for(const e of t)r.has(e.dropped)||(r.add(e.dropped),o.push(e));return{resolved:e.filter((e=>!n.has(e.id))),conflicts:o}}(e.preferences);d.length>0&&o.push(`${d.length} preference conflict(s) resolved. Dropped: ${d.map((e=>e.dropped)).join(", ")}`);const l=r.recentMessageWindow??3,u=e.transcript.filter((e=>"user"===e.role)).slice(-l).flatMap((e=>e.blocks.filter((e=>"text"===e.type)).map((e=>e.text)))),p=function(e,t,s){const n=s.recentMessageWindow??3,r=s.minScore??0,o=s.freshnessHalfLifeDays??30;if(0===t.length)return[...e].sort(((e,t)=>L(t.timestamp,o)-L(e.timestamp,o)));const a=K(t.slice(-n).join(" "));return e.map((e=>{const t="string"==typeof e.content?e.content:JSON.stringify(e.content);return{entry:e,score:.7*function(e,t){if(0===e.size&&0===t.size)return 0;let s=0;for(const n of e)t.has(n)&&s++;const n=e.size+t.size-s;return 0===n?0:s/n}(a,K(t))+.3*L(e.timestamp,o)}})).filter((e=>e.score>r)).sort(((e,t)=>t.score-e.score)).map((e=>e.entry))}(e.context,u,r);let h=e.transcript,f=null;if(this.summarizer&&h.length>0){const e=n?Math.floor(.25*n.total):2e3,t=await this.summarizer.summarize(h,e);f=t.summary,h=t.remaining}let m={preferences:0,interactions:0,contextEntries:0},y=c,w=h,b=p,g=null;if(n){const t=function(e,t,s,n,r,o,a){const i=a.estimator??U,c=a.blobTokensPerKB??.25;let d=a.total;d-=W(e??"",i),d-=W(t,i);const l=[];let u=0;for(const e of s){const t=W(e.content,i);d-t>=0?(d-=t,l.push(e)):u++}const p=[];let h=0;for(let e=n.length-1;e>=0;e--){const t=H(n[e],o,i,c);d-t>=0?(d-=t,p.unshift(n[e])):h++}const f=[];let m=0;for(const e of r){const t=W("string"==typeof e.content?e.content:JSON.stringify(e.content),i)+(e.attachments??[]).reduce(((e,t)=>e+z(t.sizeBytes,c)),0);d-t>=0?(d-=t,f.push(e)):m++}return{preferences:l,turns:p,context:f,truncated:{preferences:u,interactions:h,contextEntries:m}}}(e.systemPrompt,e.role.persona,c,h,p,s,n);if(y=t.preferences,w=t.turns,b=t.context,m=t.truncated,m.interactions>0&&e.transcript.length>0){const t=e.transcript.slice(0,m.interactions);for(let e=t.length-1;e>=0;e--)if("user"===t[e].role){g=t[e].roleSnapshot??null;break}}m.preferences>0&&o.push(`${m.preferences} preference(s) dropped due to token budget.`),m.interactions>0&&o.push(`${m.interactions} turn(s) trimmed from transcript start.`),m.contextEntries>0&&o.push(`${m.contextEntries} context entry/entries dropped due to token budget.`)}const S=[e.role.persona];if(y.length>0&&S.push(`<preferences>\n${y.map((e=>e.content)).join("\n\n")}\n</preferences>`),b.length>0){const e=b.map((e=>`[${e.key}]\n${J(e.content)}`)).join("\n\n");S.push(`<context>\n${e}\n</context>`)}e.systemPrompt&&S.unshift(e.systemPrompt);const x=S.join("\n\n")||null,v=function(e,t){if(0===e.length)return[];const s=[],n=e.map((e=>`[${e.key}]\n${J(e.content)}`)).join("\n\n");s.push({type:"text",text:`<context>\n${n}\n</context>`});for(const n of e)for(const e of n.attachments??[]){const n=t.get(e.sha256);n&&(e.mediaType.startsWith("image/")?s.push({type:"image",blob:n}):s.push({type:"document",blob:n,title:e.filename}))}return s}(b,s).filter((e=>"image"===e.type||"document"===e.type)),T=[];v.length>0&&T.push({role:"user",blocks:v});const k=function(e,t,s,n,r=null){const o=[];if(s>0||n){const e=[];n&&e.push({type:"text",text:`<summary>\n${n}\n</summary>`}),s>0&&e.push({type:"text",text:`[${s} earlier turn(s) omitted due to token budget]`}),o.push({role:"user",blocks:e}),o.push({role:"assistant",blocks:[{type:"text",text:"Understood."}]})}let a=r,i=null!==r;for(const s of e){const e=V(s,t);"user"===s.role&&s.roleSnapshot&&i&&s.roleSnapshot!==a&&e.unshift({type:"text",text:`[Role switched to: ${s.roleSnapshot}]`}),"user"===s.role&&(a=s.roleSnapshot??null,i=!0),o.push({role:s.role,blocks:e})}return o}(w,s,m.interactions,f,g);return T.push(...k),{system:x,turns:T,blobs:a,truncated:m,conflicts:d,warnings:o}}},exports.WorkspaceManager=class{contentStore;constructor(e){this.contentStore=e}reduce(e,t){return M(e,t)}async dispatch(e,t){const s=M(e,t);if(!s.ok)return s;try{await this.handleContentSideEffects(e,t)}catch(e){return u({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return s}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async activateSession(e,t){const s=e.sessions[t];return s?this.contentStore.activateSession(s):u({code:"NOT_FOUND",resource:"session",id:t})}async deactivateSession(e){const t=this.contentStore.getActiveSessionId();if(!t)return;const s=e?.sessions[t];await this.contentStore.deactivateSession(s)}async flush(){await this.contentStore.flush()}async dispose(){await this.contentStore.dispose()}async handleContentSideEffects(e,t){switch(t.type){case"role:add":await this.contentStore.saveRole(t.payload);break;case"role:update":{const{name:e,...s}=t.payload,n=await this.contentStore.getRole(e);if(!n.ok)throw new Error(`role:update — role "${e}" not found in backend`);const r={...n.value,...s,name:e};await this.contentStore.saveRole(r);break}case"role:delete":await this.contentStore.deleteRole(t.payload.name);break;case"preference:add":await this.contentStore.savePreference(t.payload);break;case"preference:update":{const{id:e,...s}=t.payload,n=await this.contentStore.getPreference(e);if(!n.ok)throw new Error(`preference:update — preference "${e}" not found in backend`);const r={...n.value,...s,id:e};await this.contentStore.savePreference(r);break}case"preference:delete":await this.contentStore.deletePreference(t.payload.id);break;case"context:add":case"context:update":await this.contentStore.saveContext(t.payload);break;case"context:delete":await this.contentStore.deleteContext(t.payload.key);break;case"turn:add":{const{sessionId:e,turn:s}=t.payload;await this.contentStore.recordTurn(e,s);break}case"turn:edit":{const{sessionId:e,turnId:s,newBlocks:n,newVersion:r,roleSnapshot:o}=t.payload;await this.contentStore.editTurn(e,s,n,r,o);break}case"turn:branch":{const{sessionId:e,newTurn:s}=t.payload;await this.contentStore.branchTurn(e,s);break}case"turn:delete":{const{sessionId:e,turnId:s,version:n,newHead:r}=t.payload;await this.contentStore.deleteTurnSubtree(e,s,n,r);break}case"session:fork":{const{sourceSessionId:e,newSessionId:s}=t.payload;this.contentStore.getActiveSessionId()===e&&await this.contentStore.flush(),await this.contentStore.copyTranscript(e,s);break}}}},exports.computeSHA256=N,exports.del=f,exports.err=u,exports.merge=m,exports.ok=l,exports.workspaceReducer=M;
1
+ "use strict";var e,t,s=Object.create,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,c=(e,t,c)=>(c=null!=e?s(i(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(i=n(t,c))||i.enumerable});return e})(e&&e.__esModule?c:r(c,"default",{value:e,enumerable:!0}),e)),d=(e={"node_modules/@asaidimu/events/index.js"(e,t){var s,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var s in t)r(e,s,{get:t[s],enumerable:!0})})(a,{createEventBus:()=>c}),t.exports=(s=a,((e,t,s,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))i.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(a=n(t,c))||a.enumerable});return e})(r({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],r=0,n=0;const o=new Map,i=new Map;let a=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?a=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{r++,n+=t,o.set(e,(o.get(e)||0)+1)},d=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const r=performance.now();try{(i.get(t)||[]).forEach((e=>e(s)))}catch(r){e.errorHandler({...r,eventName:t,payload:s})}c(t,performance.now()-r)}))},l=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(d,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?i.set(e,Array.from(s)):i.delete(e)};return a&&(a.onmessage=e=>{const{name:t,payload:s}=e.data;(i.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(s),h(e),()=>{r.delete(s),0===r.size?(t.delete(e),i.delete(e)):h(e)}},emit:({name:t,payload:r})=>{if(e.async)return s.push({name:t,payload:r}),s.length>=e.batchSize?d():l(),void(a&&a.postMessage({name:t,payload:r}));const n=performance.now();try{(i.get(t)||[]).forEach((e=>e(r))),a&&a.postMessage({name:t,payload:r})}catch(s){e.errorHandler({...s,eventName:t,payload:r})}c(t,performance.now()-n)},getMetrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:r>0?n/r:0}),clear:()=>{t.clear(),i.clear(),s=[],r=0,n=0,o.clear(),a&&(a.close(),a=null)}}}}},function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports});c(d());var l=Symbol.for("delete"),h=e=>Array.isArray(e)?[...e]:{...e};function u(){return l}c(d()),c(d()),c(d()),c(d()),c(d()),c(d());var p=function(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const r={};for(const[n,o]of Object.entries(e))if(o!==t)if("object"==typeof o&&null!==o){const e=s(o);void 0!==e&&(r[n]=e)}else r[n]=o;return r}return e===t?void 0:e}return function(e,r){if("object"!=typeof e||null===e)return"object"==typeof r&&null!==r?s(r):r===t?{}:r;if("object"!=typeof r||null===r)return e;const n=h(e),o=[{target:n,source:r}];for(;o.length>0;){const{target:e,source:s}=o.pop();for(const r of Object.keys(s)){const n=s[r];if(n!==t)if(Array.isArray(n))e[r]=n;else if("object"==typeof n&&null!==n){const t=r in e&&"object"==typeof e[r]&&null!==e[r]?e[r]:{};e[r]=h(t),o.push({target:e[r],source:n})}else e[r]=n;else delete e[r]}}return n}}({deleteMarker:l});function f(e){return{ok:!0,value:e}}function m(e){return{ok:!1,error:e}}var y="roles",g="preferences",b="context",w="turns",v="session_heads",x="index_state",S="blob_bytes",T="singleton";function k(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function O(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}function C(e,t){const s=new Map;for(const t of e)s.set(`${t.id}:${t.version}`,t);const r=[];let n=t;for(;n;){const e=s.get(`${n.id}:${n.version}`);if(!e)break;r.push(e),n=e.parent}return r.reverse()}var N=class{storage;constructor(e){this.storage=e}async append(e,t){const s=await this.storage.getSessionHead(e),r={...t,version:t.version??0,parent:null!==t.parent?t.parent:null!==s?{id:s.id,version:s.version}:null};return await this.storage.saveTurn(e,r),await this.storage.setSessionHead(e,{id:r.id,version:r.version}),r}async appendBatch(e,t){if(0!==t.length)for(const s of t)await this.append(e,s)}async replaceVersion(e,t){await this.storage.saveTurn(e,t)}async branch(e,t){await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version})}async getActiveChain(e,t=[]){const s=await this.storage.getSessionHead(e);if(!s&&0===t.length)return[];const r=await this.storage.loadAllTurns(e);return[...s?I(r,s):[],...t]}async countChained(e,t=[]){return(await this.getActiveChain(e,t)).length}async buildNodeGraph(e,t=[]){const s=await this.storage.loadAllTurns(e),r=await this.storage.getSessionHead(e),n=new Set;if(r){const e=I(s,r);for(const t of e)n.add(`${t.id}:${t.version}`)}const o={};for(const e of s){o[e.id]||(o[e.id]={id:e.id,versions:{},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{}});const t=o[e.id];t.versions[e.version]=e,n.has(`${e.id}:${e.version}`)&&(e.version>=t.activeVersion||!n.has(`${e.id}:${t.activeVersion}`))&&(t.activeVersion=e.version,t.blocks=e.blocks,t.timestamp=e.timestamp,t.roleSnapshot=e.roleSnapshot,t.parent=e.parent)}for(const e of Object.values(o))if(e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}for(const e of t)if(o[e.id]){const t=o[e.id];if(t.versions[e.version]=e,e.version>t.activeVersion&&(t.activeVersion=e.version,t.blocks=e.blocks,t.timestamp=e.timestamp,t.roleSnapshot=e.roleSnapshot),e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}}else if(o[e.id]={id:e.id,versions:{[e.version]:e},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{}},e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}return o}async deleteSubtree(e,t,s,r){const n=function(e,t,s){const r=new Map;for(const t of e)if(t.parent){const e=`${t.parent.id}:${t.parent.version}`;let s=r.get(e);s||(s=new Set,r.set(e,s)),s.add(`${t.id}:${t.version}`)}const n=new Set,o=[`${t}:${s}`];for(;o.length>0;){const e=o.pop();n.add(e);const t=r.get(e);if(t)for(const e of t)n.has(e)||o.push(e)}return n}(await this.storage.loadAllTurns(e),t,s);await Promise.all(Array.from(n).map((t=>{const[s,r]=t.split(":");return this.storage.deleteTurn(e,s,Number(r))}))),await this.storage.setSessionHead(e,r)}async copyTranscript(e,t){const s=await this.storage.getSessionHead(e),r=await this.storage.loadAllTurns(e),n=s?I(r,s):[];for(const e of n)await this.storage.saveTurn(t,{...e});await this.storage.setSessionHead(t,s?{...s}:null)}async getHead(e){return this.storage.getSessionHead(e)}async setHead(e,t){await this.storage.setSessionHead(e,t)}};function I(e,t){const s=new Map;for(const t of e)s.set(`${t.id}:${t.version}`,t);const r=[];let n=t;for(;null!==n;){const e=s.get(`${n.id}:${n.version}`);if(!e)break;r.push(e),n=e.parent}return r.reverse()}async function j(e){const t=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(t)).map((e=>e.toString(16).padStart(2,"0"))).join("")}var B=10,D=50,R=20,P=3,_=class{map=new Map;max;constructor(e){this.max=e}get(e){if(!this.map.has(e))return;const t=this.map.get(e);return this.map.delete(e),this.map.set(e,t),t}set(e,t){if(this.map.has(e)&&this.map.delete(e),this.map.set(e,t),this.map.size>this.max){const e=this.map.keys().next().value;void 0!==e&&this.map.delete(e)}}has(e){return this.map.has(e)}delete(e){this.map.delete(e)}},U=class{roles;preferences;contexts;pinnedRoles=new Map;pinnedPreferences=new Map;pinnedContexts=new Map;constructor(e){this.roles=new _(e.roles),this.preferences=new _(e.preferences),this.contexts=new _(e.context)}getRole(e){return this.pinnedRoles.get(e)??this.roles.get(e)}setRole(e,t=!1){t?(this.pinnedRoles.set(e.name,e),this.roles.delete(e.name)):this.pinnedRoles.has(e.name)?this.pinnedRoles.set(e.name,e):this.roles.set(e.name,e)}deleteRole(e){this.pinnedRoles.delete(e),this.roles.delete(e)}getPreference(e){return this.pinnedPreferences.get(e)??this.preferences.get(e)}setPreference(e,t=!1){t?(this.pinnedPreferences.set(e.id,e),this.preferences.delete(e.id)):this.pinnedPreferences.has(e.id)?this.pinnedPreferences.set(e.id,e):this.preferences.set(e.id,e)}unpinPreference(e){const t=this.pinnedPreferences.get(e);t&&(this.pinnedPreferences.delete(e),this.preferences.set(e,t))}deletePreference(e){this.pinnedPreferences.delete(e),this.preferences.delete(e)}getContext(e){return this.pinnedContexts.get(e)??this.contexts.get(e)}setContext(e,t=!1){t?(this.pinnedContexts.set(e.key,e),this.contexts.delete(e.key)):this.contexts.set(e.key,e)}invalidateContext(e){this.contexts.delete(e),this.pinnedContexts.delete(e)}};function A({index:e},t){switch(t.type){case"workspace:create":return f({...t.payload,index:{format:"aiworkspace/4.0",roles:{},preferences:{},context:{},sessions:{},topics:{}}});case"role:add":{const s=t.payload;if(e.roles[s.name])return m({code:"DUPLICATE_KEY",resource:"role",key:s.name});const r={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return f({index:{roles:{[s.name]:r}}})}case"preference:add":{const s=t.payload,r={id:s.id,topics:s.topics,timestamp:s.timestamp,snippet:s.content.substring(0,100)},n={};return s.topics.forEach((r=>{const o=e.topics[r];n[r]={topic:r,contextKeys:o?.contextKeys||[],preferences:[...o?.preferences||[],s.id],metadata:{created:o?.metadata?.created||t.timestamp,updated:t.timestamp,entries:o?.metadata?.entries||0}}})),f({index:{preferences:{[s.id]:r},topics:n}})}case"context:add":{const s=t.payload;if(e.context[s.key])return m({code:"DUPLICATE_KEY",resource:"context",key:s.key});const r={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"text"==s.content.kind?s.content.value.substring(0,200):"json"===s.content.kind?JSON.stringify(s.content.value).substring(0,200):void 0,metadata:s.metadata},n={};return s.topics.forEach((r=>{const o=e.topics[r],i=o?.contextKeys||[],a=i.includes(s.key)?i:[...i,s.key];n[r]={topic:r,contextKeys:a,metadata:{updated:t.timestamp,entries:a.length}}})),f({index:{context:{[s.key]:r},topics:n}})}case"session:create":{const{id:s,label:r,role:n,topics:o,preferences:i=[]}=t.payload;if(e.sessions[s])return m({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[n])return m({code:"NOT_FOUND",resource:"role",id:n});const a={id:s,label:r,role:n,topics:o,preferences:i,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null};return f({index:{sessions:{[s]:a}}})}case"turn:add":{const{sessionId:s,turn:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp},flushedTurnCount:(e.sessions[s]?.flushedTurnCount??0)+1}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:r,newVersion:n}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r,version:n},metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:role:switch":{const{sessionId:s,role:r}=t.payload;return e.sessions[s]?e.roles[r]?f({index:{sessions:{[s]:{role:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"role",id:r}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:r}=t.payload,n=e.sessions[s];if(!n)return m({code:"NOT_FOUND",resource:"session",id:s});const o=Array.from(new Set([...n.topics,...r]));return f({index:{sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{preferences:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload,a=e.sessions[s];if(!a)return m({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[r])return m({code:"DUPLICATE_KEY",resource:"session",key:r});const c=o??a.role;if(!e.roles[c])return m({code:"NOT_FOUND",resource:"role",id:c});const d={id:r,label:n,role:c,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head};return f({index:{sessions:{[r]:d}}})}case"role:update":{const{name:s,...r}=t.payload;if(!e.roles[s])return m({code:"NOT_FOUND",resource:"role",id:s});const n=e.roles[s],o={...n,...r,preferences:r.preferences?.length??n.preferences};return f({index:{roles:{[s]:o}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return m({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?m({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):f({index:{roles:{[s]:u()}}})}case"preference:update":{const{id:s,...r}=t.payload;if(!e.preferences[s])return m({code:"NOT_FOUND",resource:"preference",id:s});const n=e.preferences[s],o={...n,...r,snippet:r.content?r.content.substring(0,100):n.snippet},i={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(i[t]={preferences:r.preferences.filter((e=>e!==s))})})),r.topics.forEach((r=>{const n=e.topics[r]||{topic:r,contextKeys:[],preferences:[],metadata:{created:t.timestamp,updated:t.timestamp,entries:0}};i[r]={...n,preferences:[...new Set([...n.preferences,s])],metadata:{updated:t.timestamp}}}))),f({index:{preferences:{[s]:o},topics:i}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return m({code:"NOT_FOUND",resource:"preference",id:s});const r=e.preferences[s],n={};return r.topics.forEach((t=>{const r=e.topics[t];r&&(n[t]={preferences:r.preferences.filter((e=>e!==s))})})),f({index:{preferences:{[s]:u()},topics:n}})}case"context:update":{const{key:s,...r}=t.payload;if(!e.context[s])return m({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],o={...n,...r,preview:r.content?"text"===r.content.kind?r.content.value.substring(0,200):"json"===r.content.kind?JSON.stringify(r.content.value).substring(0,200):void 0:n.preview},i={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(i[t]={contextKeys:r.contextKeys.filter((e=>e!==s))})})),r.topics.forEach((r=>{const n=e.topics[r]||{contextKeys:[]},o=n.contextKeys.includes(s)?n.contextKeys:[...n.contextKeys,s];i[r]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),f({index:{context:{[s]:o},topics:i}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return m({code:"NOT_FOUND",resource:"context",id:s});const r=e.context[s],n={};return r.topics.forEach((r=>{const o=e.topics[r];o&&(n[r]={contextKeys:o.contextKeys.filter((e=>e!==s)),metadata:{updated:t.timestamp,entries:o.contextKeys.length-1}})})),f({index:{context:{[s]:u()},topics:n}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:u()}}}):m({code:"NOT_FOUND",resource:"session",id:s})}default:return f({})}}function F(e){return Math.ceil(e.length/4)}function E(e,t){return Math.ceil(e/1024*t)}function M(e){if("text"===e.kind)return e.value;if("json"===e.kind){const t=[],s=e=>{"string"==typeof e?t.push(e):e&&"object"==typeof e&&Object.values(e).forEach(s)};return s(e.value),t.join(" ")}return""}function $(e,t){return{id:crypto.randomUUID(),version:0,role:e,blocks:t,timestamp:(new Date).toISOString(),parent:null}}var V=class{rank(e){const{entries:t,recentMessages:s,config:r}=e,n=r.recentMessageWindow??3,o=r.minScore??0,i=r.freshnessHalfLifeDays??30;if(0===s.length)return[...t].sort(((e,t)=>this.freshnessWeight(t.timestamp,i)-this.freshnessWeight(e.timestamp,i)));const a=this.tokenize(s.slice(-n).join(" "));return t.map((e=>{const t=M(e.content);return{entry:e,score:.7*this.jaccardSimilarity(a,this.tokenize(t))+.3*this.freshnessWeight(e.timestamp,i)}})).filter((e=>e.score>o)).sort(((e,t)=>t.score-e.score)).map((e=>e.entry))}tokenize(e){return new Set(e.toLowerCase().replace(/[^\w\s]/g," ").split(/\s+/).filter((e=>e.length>2)))}jaccardSimilarity(e,t){if(0===e.size&&0===t.size)return 0;let s=0;for(const r of e)t.has(r)&&s++;const r=e.size+t.size-s;return 0===r?0:s/r}freshnessWeight(e,t){const s=(Date.now()-new Date(e).getTime())/864e5;return Math.pow(.5,s/t)}},z=class{plan(e){const{systemInstructions:t,persona:s,preferences:r,context:n,transcript:o,budget:i}=e;if(!i)return{preferences:r,context:n,transcript:o,truncated:{preferences:0,interactions:0,context:0},breakdown:{system:0,persona:0,preferences:0,transcript:0,context:0},totalUsed:0,lastRoleBeforeTruncation:null};const a=i.estimator??F,c=i.blobTokensPerKB??.25;let d=i.total;const l={system:0,persona:0,preferences:0,transcript:0,context:0},h=a(t??""),u=a(s);d-=h+u,l.system+=h,l.persona+=u;const p=[];let f=0;for(const e of r){const t=a(e.content);d>=t?(d-=t,l.preferences+=t,p.push(e)):f++}const m=[];let y=0,g=null;for(let e=o.length-1;e>=0;e--){const t=o[e],s=this.estimateTurnTokens(t,a,c);d>=s?(d-=s,l.transcript+=s,m.unshift(t)):(y++,"user"!==t.role||g||(g=t.roleSnapshot??null))}const b=[];let w=0;for(const e of n){let t=a(M(e.content));"blob"===e.content.kind&&(t+=E(e.content.sizeBytes,c)),d>=t?(d-=t,l.context+=t,b.push(e)):w++}return{preferences:p,context:b,transcript:m,truncated:{preferences:f,interactions:y,context:w},breakdown:l,totalUsed:i.total-Math.max(0,d),lastRoleBeforeTruncation:g}}estimateTurnTokens(e,t,s){return e.blocks.reduce(((e,r)=>{switch(r.type){case"text":return e+t(r.text);case"tool_use":return e+t(JSON.stringify(r.input));case"tool_result":return e+t("string"==typeof r.content?r.content:JSON.stringify(r.content));case"thinking":return e+t(r.thinking);case"image":case"document":{const t=r.ref;return t?e+E(t.sizeBytes,s):e}default:return e}}),0)}},H=class{assemble(e){const{session:t,plan:s,resolvedBlobs:r,summaryBlockText:n,warnings:o,conflicts:i,budgetTotal:a}=e,c=[],d=[];for(const e of s.context)if("text"===e.content.kind||"json"===e.content.kind)c.push(e);else if("blob"===e.content.kind){const t=r.get(e.content.sha256);t&&d.push(this.buildReferentialBlock(e.content,t))}const l=[];if(d.length>0&&l.push($("user",d)),n||s.truncated.interactions>0){const e=[];n&&e.push({type:"summary",text:n}),s.truncated.interactions>0&&e.push({type:"text",text:`[${s.truncated.interactions} earlier turn(s) omitted due to token budget]`}),l.push($("user",e)),l.push($("assistant",[{type:"text",text:"Understood."}]))}let h=s.lastRoleBeforeTruncation,u=null!==s.lastRoleBeforeTruncation;for(const e of s.transcript){const t=this.resolveTurnBlocks(e,r);"user"===e.role&&e.roleSnapshot&&u&&e.roleSnapshot!==h&&t.unshift({type:"role_transition",previousRole:h,newRole:e.roleSnapshot}),"user"===e.role&&(h=e.roleSnapshot??null,u=!0),l.push({...e,blocks:t})}return{system:{instructions:t.instructions,persona:t.role.persona,preferences:s.preferences,context:c},context:s.context,transcript:{turns:l},budget:{total:a,used:s.totalUsed,breakdown:s.breakdown},truncated:s.truncated,warnings:o,conflicts:i}}buildReferentialBlock(e,t){return e.mediaType.startsWith("image/")?{type:"image",blob:t}:{type:"document",blob:t,title:e.filename}}resolveTurnBlocks(e,t){return e.blocks.map((e=>{if("image"===e.type||"document"===e.type){const s=e.ref;if(s){const r=t.get(s.sha256);if(r)return{...e,blob:r}}}return e}))}},K={maxBufferSize:10,flushIntervalMs:3e4},L=class{sessionId;nodes;head;dirtyBuffer=[];flushTimer=null;flushChain=Promise.resolve();flushConfig;tree;contentStore;constructor(e,t,s,r,n,o=K){this.sessionId=e,this.nodes=t,this.head=s,this.tree=r,this.contentStore=n,this.flushConfig=o}activeChain(){if(!this.head)return[];const e=[];let t=this.head.id;for(;null!==t;){const s=this.nodes[t];if(!s)break;e.push(s),t=s.parent?.id??null}return e.reverse()}siblings(e){const t=this.nodes[e];if(!t)return[];if(!t.parent)return Object.values(this.nodes).filter((e=>null===e.parent));const s=this.nodes[t.parent.id];if(!s)return[t];const r=t.parent.version,n=s.children[r];return n?n.map((e=>this.nodes[e])).filter((e=>void 0!==e)):[t]}branchInfo(e){const t=this.nodes[e];if(!t)return{versions:[],currentIndex:-1,total:0,hasPrev:!1,hasNext:!1};const s=Object.keys(t.versions).map(Number).sort(((e,t)=>e-t)),r=s.indexOf(t.activeVersion);return{versions:s,currentIndex:r,total:s.length,hasPrev:r>0,hasNext:r<s.length-1}}async addTurn(e,t){const s=e.index.sessions[this.sessionId];if(!s)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const r={...t,version:t.version??0,parent:null!==t.parent?t.parent:null!==this.head?{id:this.head.id,version:this.head.version}:null};return this.upsertNode(r),this.head={id:r.id,version:r.version},this.dirtyBuffer.push(r),this.scheduleFlush(),this.dirtyBuffer.length>=this.flushConfig.maxBufferSize&&await this.flush(),f({index:{sessions:{[this.sessionId]:{head:{id:r.id,version:r.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:r.timestamp}}}}})}async editTurn(e,t,s,r){if(!e.index.sessions[this.sessionId])return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const n=this.nodes[t];if(!n)return m({code:"NOT_FOUND",resource:"turn",id:t});const o=n.activeVersion+1,i={id:t,version:o,role:n.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:r??n.roleSnapshot,parent:n.parent};n.versions[o]=i,n.activeVersion=o,n.blocks=s,n.timestamp=i.timestamp,void 0!==r&&(n.roleSnapshot=r),n.children[o]||(n.children[o]=[]);const a={id:t,version:o};return this.head=a,await this.tree.replaceVersion(this.sessionId,i),await this.tree.setHead(this.sessionId,a),f({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:i.timestamp}}}}})}async branchFrom(e,t){const s=e.index.sessions[this.sessionId];if(!s)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});if(!t.parent)return m({code:"INVALID_COMMAND",reason:"branchFrom requires newTurn.parent to be set"});return this.nodes[t.parent.id]?(this.upsertNode(t),this.head={id:t.id,version:t.version},await this.tree.branch(this.sessionId,t),f({index:{sessions:{[this.sessionId]:{head:{id:t.id,version:t.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:t.timestamp}}}}})):m({code:"NOT_FOUND",resource:"turn",id:t.parent.id})}async deleteTurn(e,t,s,r){const n=e.index.sessions[this.sessionId];if(!n)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const o=this.nodes[t];if(!o)return m({code:"NOT_FOUND",resource:"turn",id:t});const i=this.collectSubtreeIds(t);if(o.parent){const e=this.nodes[o.parent.id];if(e){const s=o.parent.version,r=e.children[s];r&&(e.children[s]=r.filter((e=>e!==t)))}}for(const e of i)delete this.nodes[e];this.head=r,await this.tree.deleteSubtree(this.sessionId,t,s,r);const a=(new Date).toISOString();return f({index:{sessions:{[this.sessionId]:{head:r,flushedTurnCount:Math.max(0,n.flushedTurnCount-i.size),metadata:{updated:a}}}}})}switchVersionLeft(e,t){return this.switchVersion(t,-1)}switchVersionRight(e,t){return this.switchVersion(t,1)}switchVersion(e,t){const s=this.nodes[e];if(!s)return m({code:"NOT_FOUND",resource:"turn",id:e});const r=Object.keys(s.versions).map(Number).sort(((e,t)=>e-t)),n=r.indexOf(s.activeVersion);if(-1===n)return m({code:"INVALID_COMMAND",reason:"Current version not found"});const o=n+t;if(o<0||o>=r.length)return m({code:"INVALID_COMMAND",reason:`No ${t<0?"previous":"next"} version available for turn ${e}`});const i=r[o];s.activeVersion=i,s.blocks=s.versions[i].blocks,s.timestamp=s.versions[i].timestamp,s.versions[i].roleSnapshot&&(s.roleSnapshot=s.versions[i].roleSnapshot);const a=this.findSubtreeTipForVersion(e,i);this.head=a;const c=(new Date).toISOString();return f({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:c}}}}})}async resolve(e){return e.index.sessions[this.sessionId]?this.contentStore.resolveSession(e,this.sessionId,this.activeChain().map((e=>e.versions[e.activeVersion]))):m({code:"NOT_FOUND",resource:"session",id:this.sessionId})}async flush(){return this.flushChain=this.flushChain.then((()=>this.doFlush())),this.flushChain}async dispose(){this.cancelFlushTimer(),await this.flush()}findSubtreeTipForVersion(e,t){let s=e,r=t;for(;;){const e=this.nodes[s];if(!e)break;const t=e.children[r];if(!t||0===t.length)break;s=t[0],r=this.nodes[s]?.activeVersion??0}return{id:s,version:r}}collectSubtreeIds(e){const t=new Set,s=[e];for(;s.length>0;){const e=s.pop();t.add(e);const r=this.nodes[e];if(r&&r.children)for(const e of Object.keys(r.children)){const n=r.children[Number(e)];if(n)for(const e of n)t.has(e)||s.push(e)}}return t}upsertNode(e){const t=e.id,s=e.version;if(this.nodes[t]){const r=this.nodes[t];r.versions[s]=e,s>=r.activeVersion&&(r.activeVersion=s,r.blocks=e.blocks,r.timestamp=e.timestamp,void 0!==e.roleSnapshot&&(r.roleSnapshot=e.roleSnapshot)),r.children[s]||(r.children[s]=[])}else this.nodes[t]={id:t,versions:{[s]:e},activeVersion:s,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{[s]:[]}};if(e.parent){const s=this.nodes[e.parent.id];if(s){const r=e.parent.version;s.children[r]||(s.children[r]=[]),s.children[r].includes(t)||s.children[r].push(t)}}}scheduleFlush(){null===this.flushTimer&&(this.flushTimer=setTimeout((()=>{this.flushTimer=null,this.flushChain=this.flushChain.then((()=>this.doFlush()))}),this.flushConfig.flushIntervalMs))}cancelFlushTimer(){null!==this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null)}async doFlush(){if(0===this.dirtyBuffer.length)return;const e=this.dirtyBuffer.splice(0,this.dirtyBuffer.length);try{await this.tree.appendBatch(this.sessionId,e),0===this.dirtyBuffer.length&&this.cancelFlushTimer()}catch(t){throw this.dirtyBuffer.unshift(...e),this.flushChain=Promise.resolve(),t}}};var W=10,J=3e4;exports.BlobStore=class{storage;config;recordCache=new Map;onRegistryChanged;constructor(e,t={}){this.storage=e,this.config={eagerEviction:t.eagerEviction??!1}}async init(){const e=await this.storage.listRecords();for(const t of e)this.recordCache.set(t.sha256,t)}async register(e,t,s){try{const r=await j(e),n=(new Date).toISOString(),o=this.recordCache.get(r);if(o){const e={...o,refCount:o.refCount+1,lastUsedAt:n};await this.storage.saveRecord(e),this.recordCache.set(r,e),this.onRegistryChanged?.(r,e)}else{const o={sha256:r,mediaType:t,sizeBytes:e.byteLength,filename:s,refCount:1,remoteIds:{},createdAt:n,lastUsedAt:n};"function"==typeof this.storage.registerBlob?await this.storage.registerBlob(o,e):(await this.storage.storeBytes(r,e),await this.storage.saveRecord(o)),this.recordCache.set(r,o),this.onRegistryChanged?.(r,o)}const i=this.recordCache.get(r);return f({sha256:r,mediaType:t,sizeBytes:i.sizeBytes,filename:i.filename,previewUrl:i.previewUrl})}catch(e){return m({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return m({code:"NOT_FOUND",resource:"blob",id:e});const s={...t,refCount:t.refCount+1,lastUsedAt:(new Date).toISOString()};return await this.storage.saveRecord(s),this.recordCache.set(e,s),this.onRegistryChanged?.(e,s),f(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return m({code:"NOT_FOUND",resource:"blob",id:e});const s=Math.max(0,t.refCount-1),r={...t,refCount:s,lastUsedAt:(new Date).toISOString()};return 0===s&&this.config.eagerEviction?(await this.storage.deleteBytes(e),await this.storage.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null)):(await this.storage.saveRecord(r),this.recordCache.set(e,r),this.onRegistryChanged?.(e,r)),f(void 0)}async recordRemoteId(e,t,s){const r=this.recordCache.get(e);if(!r)return m({code:"NOT_FOUND",resource:"blob",id:e});if(r.remoteIds[t]===s)return f(void 0);const n={...r,remoteIds:{...r.remoteIds,[t]:s}};return await this.storage.saveRecord(n),this.recordCache.set(e,n),f(void 0)}getRemoteId(e,t){return this.recordCache.get(e)?.remoteIds[t]??null}async resolveRef(e,t){try{if(t){const s=this.getRemoteId(e.sha256,t);if(s)return f({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.storage.loadBytes(e.sha256);return s?f({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):m({code:"BLOB_ERROR",reason:`Blob bytes not found locally for sha256=${e.sha256}. The blob may have been evicted. Re-register it before resolving.`})}catch(e){return m({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async resolveRefs(e,t){const s=function(e){const t=new Set,s=[];for(const r of e)t.has(r.sha256)||(t.add(r.sha256),s.push(r));return s}(e),r=await Promise.all(s.map((async e=>({ref:e,result:await this.resolveRef(e,t)})))),n=new Map,o=[];for(const{ref:e,result:t}of r)t.ok?n.set(e.sha256,t.value):o.push({ref:e,error:t.error});return{resolved:n,errors:o}}async gc(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((e=>this.storage.deleteBytes(e.sha256)))),e.length}async gcFull(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((async e=>{await this.storage.deleteBytes(e.sha256),await this.storage.deleteRecord(e.sha256),this.recordCache.delete(e.sha256),this.onRegistryChanged?.(e.sha256,null)}))),e.length}async purge(e){return this.recordCache.has(e)?(await this.storage.deleteBytes(e),await this.storage.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null),f(void 0)):m({code:"NOT_FOUND",resource:"blob",id:e})}getRecord(e){return this.recordCache.get(e)??null}getAllRecords(){const e={};for(const[t,s]of this.recordCache)e[t]=s;return e}},exports.ContentStore=class{storage;tree;cache;constructor(e,t={}){this.storage=e,this.tree=new N(e);const s={roles:t.cache?.roles??B,preferences:t.cache?.preferences??D,context:t.cache?.context??R,transcriptWindows:t.cache?.transcriptWindows??P};this.cache=new U(s)}getTurnTree(){return this.tree}async getRole(e){const t=this.cache.getRole(e);if(t)return f(t);const s=await this.storage.loadRole(e);return s?(this.cache.setRole(s),f(s)):m({code:"NOT_FOUND",resource:"role",id:e})}async getPreference(e){const t=this.cache.getPreference(e);if(t)return f(t);const s=await this.storage.loadPreference(e);return s?(this.cache.setPreference(s),f(s)):m({code:"NOT_FOUND",resource:"preference",id:e})}async getContext(e){const t=this.cache.getContext(e);if(t)return f(t);const s=await this.storage.loadContext(e);return s?(this.cache.setContext(s),f(s)):m({code:"NOT_FOUND",resource:"context",id:e})}async getContextByTopics(e,t){const s=new Set;for(const r of t){const t=e.topics[r];t&&t.contextKeys.forEach((e=>s.add(e)))}if(0===s.size)return[];const r=[],n=[];for(const e of s){const t=this.cache.getContext(e);t?n.push(t):r.push(e)}let o=[];if(r.length>0){const e=await this.storage.loadContextBatch(r);for(const[t,s]of e)this.cache.setContext(s),o.push(s)}return[...n,...o].sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async saveRole(e){await this.storage.saveRole(e),this.cache.setRole(e)}async savePreference(e){await this.storage.savePreference(e),this.cache.setPreference(e)}async saveContext(e){await this.storage.saveContext(e),this.cache.setContext(e)}async deleteRole(e){await this.storage.deleteRole(e),this.cache.deleteRole(e)}async deletePreference(e){await this.storage.deletePreference(e),this.cache.deletePreference(e)}async deleteContext(e){await this.storage.deleteContext(e),this.cache.invalidateContext(e)}async recordTurn(e,t){return await this.tree.append(e,t),f(void 0)}async editTurn(e,t,s,r,n){const o=await this.storage.loadTurn(e,t,r-1);if(!o)return m({code:"NOT_FOUND",resource:"turn",id:t});const i={id:t,version:r,role:o.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:n??o.roleSnapshot,parent:o.parent};await this.tree.replaceVersion(e,i);const a=await this.tree.getHead(e);return a?.id===t&&await this.tree.setHead(e,{id:i.id,version:i.version}),f(void 0)}async branchTurn(e,t){return await this.tree.branch(e,t),f(void 0)}async deleteTurnSubtree(e,t,s,r){return await this.tree.deleteSubtree(e,t,s,r),f(void 0)}async copyTranscript(e,t){await this.tree.copyTranscript(e,t)}async storeBytes(e,t){await this.storage.storeBytes(e,t)}async loadBytes(e){return this.storage.loadBytes(e)}async deleteBytes(e){await this.storage.deleteBytes(e)}async resolveSession(e,t,s){const r=e.index.sessions[t];if(!r)return m({code:"NOT_FOUND",resource:"session",id:t});const n=await this.getRole(r.role);if(!n.ok)return n;const o=n.value,i=function(e,t){return e.preferences.length>0?e.preferences:t.preferences}(r,o),a={session:r,role:o,preferences:function(e,t){return e.filter((e=>0===e.topics.length||e.topics.some((e=>t.includes(e)))))}((await Promise.all(i.map((e=>this.getPreference(e))))).filter((e=>e.ok)).map((e=>e.value)),r.topics),context:await this.getContextByTopics(e.index,r.topics),transcript:s??await this.tree.getActiveChain(t),instructions:e.settings?.prompt};return f({...a,preferences:Object.freeze([...a.preferences]),context:Object.freeze([...a.context]),transcript:Object.freeze([...a.transcript])})}},exports.IndexedDBStorage=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,3);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBStorage] Database "${this.dbName}" blocked. Close other tabs.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){if(e.objectStoreNames.contains(y)||e.createObjectStore(y,{keyPath:"name"}),e.objectStoreNames.contains(g)||e.createObjectStore(g,{keyPath:"id"}),!e.objectStoreNames.contains(b)){e.createObjectStore(b,{keyPath:"key"}).createIndex("by_topic","topics",{multiEntry:!0})}if(e.objectStoreNames.contains(x)||e.createObjectStore(x,{keyPath:"id"}),!e.objectStoreNames.contains(w)){e.createObjectStore(w,{keyPath:["sessionId","id","version"]}).createIndex("by_sessionId","sessionId")}e.objectStoreNames.contains(v)||e.createObjectStore(v,{keyPath:"sessionId"}),e.objectStoreNames.contains(S)||e.createObjectStore(S,{keyPath:"sha256"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBStorage] Database not open. Call open() before using the storage.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async saveRole(e){const t=this.writeTx(y);t.objectStore(y).put(e),await O(t)}async loadRole(e){const t=this.readTx(y);return await k(t.objectStore(y).get(e))??null}async deleteRole(e){const t=this.writeTx(y);t.objectStore(y).delete(e),await O(t)}async savePreference(e){const t=this.writeTx(g);t.objectStore(g).put(e),await O(t)}async loadPreference(e){const t=this.readTx(g);return await k(t.objectStore(g).get(e))??null}async deletePreference(e){const t=this.writeTx(g);t.objectStore(g).delete(e),await O(t)}async saveContext(e){const t=this.writeTx(b);t.objectStore(b).put(e),await O(t)}async loadContext(e){const t=this.readTx(b);return await k(t.objectStore(b).get(e))??null}async loadContextBatch(e){if(0===e.length)return new Map;const t=this.readTx(b).objectStore(b),s=await Promise.all(e.map((e=>k(t.get(e))))),r=new Map;for(let t=0;t<e.length;t++){const n=s[t];n&&r.set(e[t],n)}return r}async deleteContext(e){const t=this.writeTx(b);t.objectStore(b).delete(e),await O(t)}async saveTurn(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction([w,v],"readwrite"),o=n.objectStore(w),i=n.objectStore(v);o.put({sessionId:e,...t}),i.put({sessionId:e,head:{id:t.id,version:t.version}}),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("saveTurn transaction aborted"))}))}async loadTurn(e,t,s){const r=this.readTx(w),n=await k(r.objectStore(w).get([e,t,s]));if(!n)return null;const{sessionId:o,...i}=n;return i}async loadAllTurns(e){const t=this.readTx(w).objectStore(w).index("by_sessionId");return(await k(t.getAll(e))).map((({sessionId:e,...t})=>t))}async deleteTurn(e,t,s){const r=this.writeTx(w);r.objectStore(w).delete([e,t,s]),await O(r)}async setSessionHead(e,t){const s=this.writeTx(v);t?s.objectStore(v).put({sessionId:e,head:t}):s.objectStore(v).delete(e),await O(s)}async getSessionHead(e){const t=this.readTx(v),s=await k(t.objectStore(v).get(e));return s?.head??null}async storeBytes(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction(S,"readwrite"),o=n.objectStore(S),i=o.count(e);i.onsuccess=()=>{0===i.result&&o.put({sha256:e,data:t})},i.onerror=()=>r(i.error),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("storeBytes transaction aborted"))}))}async loadBytes(e){const t=this.readTx(S),s=await k(t.objectStore(S).get(e));return s?.data??null}async deleteBytes(e){const t=this.writeTx(S);t.objectStore(S).delete(e),await O(t)}async exportAllBytes(){const e=this.readTx(S);return(await k(e.objectStore(S).getAll())).map((({sha256:e,data:t})=>[e,t]))}async saveWorkspace(e){const t=this.writeTx(x);t.objectStore(x).put({id:T,state:e}),await O(t)}async loadWorkspace(){const e=this.readTx(x),t=await k(e.objectStore(x).get(T));return t?.state??null}async exportBundle(){const e=this.getDB(),[t,s,r,n]=await Promise.all([this.getAllFromStore(e,y),this.getAllFromStore(e,g),this.getAllFromStore(e,b),this.getAllFromStore(e,x)]),o=await this.getAllFromStore(e,w),i=new Set(o.map((e=>e.sessionId))),a={};for(const e of i){const t=await this.getSessionHead(e),s=o.filter((t=>t.sessionId===e)).map((({sessionId:e,...t})=>t));a[e]=t?C(s,t):[]}return{roles:Object.fromEntries(t.map((e=>[e.name,e]))),preferences:Object.fromEntries(s.map((e=>[e.id,e]))),context:Object.fromEntries(r.map((e=>[e.key,e]))),transcripts:a,workspace:n[0]?.state??null}}async importBundle(e){await new Promise(((t,s)=>{const r=this.getDB().transaction([y,g,b,w,v,x],"readwrite"),n=r.objectStore(y),o=r.objectStore(g),i=r.objectStore(b),a=r.objectStore(w),c=r.objectStore(v),d=r.objectStore(x);for(const t of Object.values(e.roles||{}))n.put(t);for(const t of Object.values(e.preferences||{}))o.put(t);for(const t of Object.values(e.context||{}))i.put(t);for(const[t,s]of Object.entries(e.transcripts||{})){for(const e of s)a.put({sessionId:t,...e,version:e.version??0,parent:e.parent??null});if(s.length>0){const e=s[s.length-1];c.put({sessionId:t,head:{id:e.id,version:e.version??0}})}}e.workspace&&d.put({id:T,state:e.workspace}),r.oncomplete=()=>t(),r.onerror=()=>s(r.error),r.onabort=()=>s(new Error("importBundle transaction aborted"))}))}getAllFromStore(e,t){return new Promise(((s,r)=>{const n=e.transaction(t,"readonly").objectStore(t).getAll();n.onsuccess=()=>s(n.result),n.onerror=()=>r(n.error)}))}},exports.PromptBuilder=class{retriever;planner;assembler;summarizer;blobResolver;constructor(e){this.blobResolver=e.blobResolver,this.retriever=e.retriever??new V,this.planner=e.planner??new z,this.assembler=e.assembler??new H,this.summarizer=e.summarizer}async build(e,t={}){const s=[],{resolved:r,conflicts:n}=this.resolvePreferenceConflicts(e.preferences);n.length>0&&s.push(`${n.length} preference conflict(s) resolved.`);const o=this.extractRecentUserQueries(e.transcript,t.relevanceConfig),i=this.retriever.rank({entries:e.context,recentMessages:o,config:t.relevanceConfig??{}});let a=e.transcript,c=null;if(this.summarizer&&a.length>0){const e=t.tokenBudget?Math.floor(.25*t.tokenBudget.total):2e3,s=await this.summarizer.summarize(a,e);c=s.summary,a=s.remaining}const d=this.planner.plan({systemInstructions:e.instructions,persona:e.role.persona,preferences:r,context:i,transcript:a,budget:t.tokenBudget}),l=this.collectUsedBlobRefs(d.context,d.transcript),h=this.deduplicateBlobRefs(l),{resolved:u,errors:p}=await this.blobResolver(h,t.providerId??null);for(const e of p)s.push(`Failed to resolve blob ${e.ref.sha256.slice(0,8)}: ${e.error.code}`);const f=h.filter((e=>!u.has(e.sha256)));return f.length>0&&s.push(`${f.length} blob(s) unresolved and omitted: `+f.map((e=>e.sha256.slice(0,8))).join(", ")),d.truncated.preferences>0&&s.push(`${d.truncated.preferences} preference(s) dropped.`),d.truncated.interactions>0&&s.push(`${d.truncated.interactions} turn(s) trimmed.`),d.truncated.context>0&&s.push(`${d.truncated.context} context entry/entries dropped.`),this.assembler.assemble({session:e,plan:d,resolvedBlobs:u,summaryBlockText:c,warnings:s,conflicts:n,budgetTotal:t.tokenBudget?.total??0})}collectUsedBlobRefs(e,t){const s=[];for(const t of e)"blob"===t.content.kind&&s.push(t.content);for(const e of t)for(const t of e.blocks)if("image"===t.type||"document"===t.type){const e=t.ref;e&&s.push(e)}return s}deduplicateBlobRefs(e){const t=new Set,s=[];for(const r of e)t.has(r.sha256)||(t.add(r.sha256),s.push(r));return s}extractRecentUserQueries(e,t){const s=t?.recentMessageWindow??3;return e.filter((e=>"user"===e.role)).slice(-s).flatMap((e=>e.blocks.filter((e=>"text"===e.type)).map((e=>e.text))))}resolvePreferenceConflicts(e){const t=[],s=new Map;for(const r of e)if(0!==r.topics.length)for(const e of r.topics){const n=s.get(e);if(!n){s.set(e,r);continue}const o=new Date(n.timestamp).getTime(),i=new Date(r.timestamp).getTime();i>o?(t.push({topic:e,kept:r.id,dropped:n.id,reason:"superseded_by_newer"}),s.set(e,r)):o>i&&t.push({topic:e,kept:n.id,dropped:r.id,reason:"superseded_by_newer"})}const r=new Set(t.map((e=>e.dropped)));return{resolved:e.filter((e=>!r.has(e.id))),conflicts:Array.from(new Set(t))}}},exports.Session=L,exports.SessionManager=class{workspaceManager;contentStore;flushConfig;constructor(e,t,s={}){this.workspaceManager=e,this.contentStore=t,this.flushConfig={maxBufferSize:s.flush?.maxBufferSize??W,flushIntervalMs:s.flush?.flushIntervalMs??J}}async open(e,t){const s=e.index.sessions[t];if(!s)return m({code:"NOT_FOUND",resource:"session",id:t});const r=this.contentStore.getTurnTree();try{const e=await r.buildNodeGraph(t);return f({session:new L(t,e,s.head,r,this.contentStore,this.flushConfig),patch:{}})}catch(e){return m({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}}async close(e){await e.dispose()}get workspace(){return this.workspaceManager}},exports.TurnTree=N,exports.WorkspaceManager=class{contentStore;constructor(e){this.contentStore=e}reduce(e,t){return A(e,t)}async dispatch(e,t){const s=A(e,t);if(!s.ok)return s;try{await this.handleContentSideEffects(t)}catch(e){return m({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return s}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async handleContentSideEffects(e){switch(e.type){case"role:add":await this.contentStore.saveRole(e.payload);break;case"role:update":{const{name:t,...s}=e.payload,r=await this.contentStore.getRole(t);if(!r.ok)throw new Error(`role:update — role "${t}" not found in backend`);const n={...r.value,...s,name:t};await this.contentStore.saveRole(n);break}case"role:delete":await this.contentStore.deleteRole(e.payload.name);break;case"preference:add":await this.contentStore.savePreference(e.payload);break;case"preference:update":{const{id:t,...s}=e.payload,r=await this.contentStore.getPreference(t);if(!r.ok)throw new Error(`preference:update — preference "${t}" not found in backend`);const n={...r.value,...s,id:t};await this.contentStore.savePreference(n);break}case"preference:delete":await this.contentStore.deletePreference(e.payload.id);break;case"context:add":case"context:update":await this.contentStore.saveContext(e.payload);break;case"context:delete":await this.contentStore.deleteContext(e.payload.key);break;case"turn:add":{const{sessionId:t,turn:s}=e.payload;await this.contentStore.recordTurn(t,s);break}case"turn:edit":{const{sessionId:t,turnId:s,newBlocks:r,newVersion:n,roleSnapshot:o}=e.payload;await this.contentStore.editTurn(t,s,r,n,o);break}case"turn:branch":{const{sessionId:t,newTurn:s}=e.payload;await this.contentStore.branchTurn(t,s);break}case"turn:delete":{const{sessionId:t,turnId:s,version:r,newHead:n}=e.payload;await this.contentStore.deleteTurnSubtree(t,s,r,n);break}case"session:fork":{const{sourceSessionId:t,newSessionId:s}=e.payload;await this.contentStore.copyTranscript(t,s);break}}}},exports.buildTurnNode=function(e,t=[]){return{id:e.id,versions:{[e.version]:e},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{[e.version]:[...t]}}},exports.computeSHA256=j,exports.del=u,exports.err=m,exports.merge=p,exports.ok=f,exports.workspaceReducer=A;
package/index.mjs CHANGED
@@ -1 +1 @@
1
- var e,t,s=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,a=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,c=(e,t,c)=>(c=null!=e?s(a(e)):{},((e,t,s,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))i.call(e,c)||c===s||n(e,c,{get:()=>t[c],enumerable:!(a=r(t,c))||a.enumerable});return e})(e&&e.__esModule?c:n(c,"default",{value:e,enumerable:!0}),e)),d=(e={"node_modules/@asaidimu/events/index.js"(e,t){var s,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var s in t)n(e,s,{get:t[s],enumerable:!0})})(i,{createEventBus:()=>c}),t.exports=(s=i,((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===s||n(e,c,{get:()=>t[c],enumerable:!(i=r(t,c))||i.enumerable});return e})(n({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],n=0,r=0;const o=new Map,a=new Map;let i=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?i=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,r+=t,o.set(e,(o.get(e)||0)+1)},d=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(s)))}catch(n){e.errorHandler({...n,eventName:t,payload:s})}c(t,performance.now()-n)}))},l=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(d,e.batchDelay)}})(),u=e=>{const s=t.get(e);s?a.set(e,Array.from(s)):a.delete(e)};return i&&(i.onmessage=e=>{const{name:t,payload:s}=e.data;(a.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(s),u(e),()=>{n.delete(s),0===n.size?(t.delete(e),a.delete(e)):u(e)}},emit:({name:t,payload:n})=>{if(e.async)return s.push({name:t,payload:n}),s.length>=e.batchSize?d():l(),void(i&&i.postMessage({name:t,payload:n}));const r=performance.now();try{(a.get(t)||[]).forEach((e=>e(n))),i&&i.postMessage({name:t,payload:n})}catch(s){e.errorHandler({...s,eventName:t,payload:n})}c(t,performance.now()-r)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:n>0?r/n:0}),clear:()=>{t.clear(),a.clear(),s=[],n=0,r=0,o.clear(),i&&(i.close(),i=null)}}}}},function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports});function l(e){return{ok:!0,value:e}}function u(e){return{ok:!1,error:e}}var h=class e{roles=new Map;preferences=new Map;contexts=new Map;turnVersions=new Map;sessionHeads=new Map;async saveRole(e){this.roles.set(e.name,e)}async loadRole(e){return this.roles.get(e)??null}async deleteRole(e){this.roles.delete(e)}async savePreference(e){this.preferences.set(e.id,e)}async loadPreference(e){return this.preferences.get(e)??null}async deletePreference(e){this.preferences.delete(e)}async saveContext(e){this.contexts.set(e.key,e)}async loadContext(e){return this.contexts.get(e)??null}async deleteContext(e){this.contexts.delete(e)}async saveTurn(e,t){const s=this.sessionHeads.get(e)??null;let n={...t};null===n.parent&&null!==s&&(n.parent={id:s.id,version:s.version}),n={...n,version:n.version??0};const r=`${e}:${n.id}:${n.version}`;this.turnVersions.set(r,n),this.sessionHeads.set(e,{id:n.id,version:n.version})}async loadTurn(e,t,s){const n=`${e}:${t}:${s}`;return this.turnVersions.get(n)??null}async loadAllTurns(e,t){const s=`${e}:`,n=[];for(const[e,t]of this.turnVersions.entries())e.startsWith(s)&&n.push(t);return n.sort(((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime())),void 0!==t&&t>0?n.slice(-t):n}async setSessionHead(e,t){this.sessionHeads.set(e,t)}async getSessionHead(e){return this.sessionHeads.get(e)??null}async getActiveChain(e){let t=this.sessionHeads.get(e)??null;const s=[];for(;null!==t;){const n=await this.loadTurn(e,t.id,t.version);if(!n)break;s.push(n),t=n.parent}return s.reverse()}async deleteTurnSubtree(e,t,s){const n=await this.loadAllTurns(e),r=new Set;r.add(`${t}:${s}`);let o=!0;for(;o;){o=!1;for(const e of n)if(e.parent){const t=`${e.parent.id}:${e.parent.version}`,s=`${e.id}:${e.version}`;r.has(t)&&!r.has(s)&&(r.add(s),o=!0)}}for(const t of r)this.turnVersions.delete(`${e}:${t}`)}async countChainedTurns(e){return(await this.getActiveChain(e)).length}async copyTranscript(e,t){const s=await this.loadAllTurns(e);for(const e of s)await this.saveTurn(t,{...e});const n=await this.getSessionHead(e);await this.setSessionHead(t,n?{...n}:null)}static fromBundle(t){const s=new e;for(const e of Object.values(t.roles))s.roles.set(e.name,e);for(const e of Object.values(t.preferences))s.preferences.set(e.id,e);for(const e of Object.values(t.context))s.contexts.set(e.key,e);const n={};for(const e of Object.values(t.sessions)){const t=e.turns??[];let r=null;for(const n of t){const t={...n,version:n.version??0,parent:r};s.turnVersions.set(`${e.id}:${t.id}:${t.version}`,t),r={id:t.id,version:t.version}}s.sessionHeads.set(e.id,r),n[e.id]={id:e.id,label:e.label,role:e.role,topics:e.topics,preferences:e.preferences??[],metadata:e.metadata??{created:(new Date).toISOString(),updated:(new Date).toISOString()},flushedTurnCount:t.length,head:r}}const r={};for(const e of Object.values(t.roles))r[e.name]={name:e.name,label:e.label,description:e.description,preferences:e.preferences.length};const o={};for(const e of Object.values(t.preferences))o[e.id]={id:e.id,topics:e.topics,timestamp:e.timestamp,snippet:e.content.substring(0,100)};const a={};for(const e of Object.values(t.context))a[e.key]={key:e.key,topics:e.topics,timestamp:e.timestamp,source:e.key.split(":")[0],preview:"string"==typeof e.content?e.content.substring(0,200):JSON.stringify(e.content).substring(0,200),metadata:e.metadata};return{backend:s,indexState:{format:"aiworkspace/4.0",workspace:t.workspace,roles:r,preferences:o,context:a,sessions:n,blobs:t.blobs}}}};c(d());var p=Symbol.for("delete"),f=e=>Array.isArray(e)?[...e]:{...e};function m(){return p}c(d()),c(d()),c(d()),c(d()),c(d()),c(d());var y=function(e){const t=e?.deleteMarker||p;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const n={};for(const[r,o]of Object.entries(e))if(o!==t)if("object"==typeof o&&null!==o){const e=s(o);void 0!==e&&(n[r]=e)}else n[r]=o;return n}return e===t?void 0:e}return function(e,n){if("object"!=typeof e||null===e)return"object"==typeof n&&null!==n?s(n):n===t?{}:n;if("object"!=typeof n||null===n)return e;const r=f(e),o=[{target:r,source:n}];for(;o.length>0;){const{target:e,source:s}=o.pop();for(const n of Object.keys(s)){const r=s[n];if(r!==t)if(Array.isArray(r))e[n]=r;else if("object"==typeof r&&null!==r){const t=n in e&&"object"==typeof e[n]&&null!==e[n]?e[n]:{};e[n]=f(t),o.push({target:e[n],source:r})}else e[n]=r;else delete e[n]}}return r}}({deleteMarker:p}),w="roles",b="preferences",g="context",v="turns",S="session_heads",x="index_state",T="singleton";function k(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function O(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}var C=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,2);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBBackend] Database "${this.dbName}" blocked. Close other tabs.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){if(e.objectStoreNames.contains(w)||e.createObjectStore(w,{keyPath:"name"}),e.objectStoreNames.contains(b)||e.createObjectStore(b,{keyPath:"id"}),!e.objectStoreNames.contains(g)){e.createObjectStore(g,{keyPath:"key"}).createIndex("by_topic","topics",{multiEntry:!0})}if(e.objectStoreNames.contains(x)||e.createObjectStore(x,{keyPath:"id"}),!e.objectStoreNames.contains(v)){e.createObjectStore(v,{keyPath:["sessionId","id","version"]}).createIndex("by_sessionId","sessionId")}e.objectStoreNames.contains(S)||e.createObjectStore(S,{keyPath:"sessionId"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBBackend] Database not open. Call open() before using the backend.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async saveRole(e){const t=this.writeTx(w);t.objectStore(w).put(e),await O(t)}async loadRole(e){const t=this.readTx(w);return await k(t.objectStore(w).get(e))??null}async deleteRole(e){const t=this.writeTx(w);t.objectStore(w).delete(e),await O(t)}async savePreference(e){const t=this.writeTx(b);t.objectStore(b).put(e),await O(t)}async loadPreference(e){const t=this.readTx(b);return await k(t.objectStore(b).get(e))??null}async deletePreference(e){const t=this.writeTx(b);t.objectStore(b).delete(e),await O(t)}async saveContext(e){const t=this.writeTx(g);t.objectStore(g).put(e),await O(t)}async loadContext(e){const t=this.readTx(g);return await k(t.objectStore(g).get(e))??null}async deleteContext(e){const t=this.writeTx(g);t.objectStore(g).delete(e),await O(t)}async saveTurn(e,t){const s=this.getDB().transaction([v,S],"readwrite"),n=s.objectStore(v),r=s.objectStore(S),o=r.get(e),a=await k(o),i=a?.head??null;let c={...t};null===c.parent&&null!==i&&(c.parent={id:i.id,version:i.version}),c={...c,version:c.version??0},n.put({sessionId:e,...c}),r.put({sessionId:e,head:{id:c.id,version:c.version}}),await O(s)}async loadAllTurns(e,t){const s=this.readTx(v).objectStore(v).index("by_sessionId"),n=await k(s.getAll(e));return n.sort(((e,t)=>new Date(e.timestamp).getTime()-new Date(t.timestamp).getTime())),void 0!==t&&t>0?n.slice(-t):n}async countChainedTurns(e){const t=this.readTx(v).objectStore(v).index("by_sessionId");return(await k(t.getAllKeys(e))).length}async loadTurn(e,t,s){const n=this.readTx(v);return await k(n.objectStore(v).get([e,t,s]))??null}async setSessionHead(e,t){const s=this.writeTx(S);t?s.objectStore(S).put({sessionId:e,head:t}):s.objectStore(S).delete(e),await O(s)}async getSessionHead(e){const t=this.readTx(S),s=await k(t.objectStore(S).get(e));return s?.head??null}async getActiveChain(e){let t=await this.getSessionHead(e);const s=[];for(;null!==t;){const n=await this.loadTurn(e,t.id,t.version);if(!n)break;s.push(n),t=n.parent}return s.reverse()}async deleteTurnSubtree(e,t,s){const n=await this.loadAllTurns(e),r=new Set;r.add(`${t}:${s}`);let o=!0;for(;o;){o=!1;for(const e of n)if(e.parent){const t=`${e.parent.id}:${e.parent.version}`,s=`${e.id}:${e.version}`;r.has(t)&&!r.has(s)&&(r.add(s),o=!0)}}const a=this.getDB().transaction([v,S],"readwrite"),i=a.objectStore(v),c=a.objectStore(S);for(const t of r){const[s,n]=t.split(":");i.delete([e,s,Number(n)])}const d=await k(c.get(e));if(d?.head){const t=`${d.head.id}:${d.head.version}`;if(r.has(t)){let t=d.head;for(;t;){const e=n.find((e=>e.id===t?.id&&e.version===t?.version));if(!e||!e.parent){t=null;break}const s=`${e.parent.id}:${e.parent.version}`;if(!r.has(s)){t=e.parent;break}t=e.parent}t?c.put({sessionId:e,head:t}):c.delete(e)}}await O(a)}async copyTranscript(e,t){const s=await this.loadAllTurns(e);await new Promise(((n,r)=>{const o=this.getDB().transaction([v,S],"readwrite"),a=o.objectStore(v),i=o.objectStore(S);for(const e of s){const s={...e,sessionId:t};a.put(s)}const c=i.get(e);c.onsuccess=()=>{const e=c.result;e?.head&&i.put({sessionId:t,head:{...e.head}})},c.onerror=()=>r(c.error||new Error("Failed to read head")),o.oncomplete=()=>n(),o.onerror=()=>r(o.error),o.onabort=()=>r(new Error("copyTranscript transaction aborted"))}))}async saveIndexState(e){const t=this.writeTx(x);t.objectStore(x).put({id:T,state:e}),await O(t)}async loadIndexState(){const e=this.readTx(x),t=await k(e.objectStore(x).get(T));return t?.state??null}async exportBundle(){const e=this.getDB(),[t,s,n,r]=await Promise.all([this.getAllFromStore(e,w),this.getAllFromStore(e,b),this.getAllFromStore(e,g),this.getAllFromStore(e,x)]),o=await this.getAllFromStore(e,v),a=new Set(o.map((e=>e.sessionId))),i={};for(const e of a)i[e]=await this.getActiveChain(e);return{roles:Object.fromEntries(t.map((e=>[e.name,e]))),preferences:Object.fromEntries(s.map((e=>[e.id,e]))),context:Object.fromEntries(n.map((e=>[e.key,e]))),transcripts:i,indexState:r[0]?.state??null}}async importBundle(e){await new Promise(((t,s)=>{const n=this.getDB().transaction([w,b,g,v,S,x],"readwrite"),r=n.objectStore(w),o=n.objectStore(b),a=n.objectStore(g),i=n.objectStore(v),c=n.objectStore(S),d=n.objectStore(x);for(const t of Object.values(e.roles||{}))r.put(t);for(const t of Object.values(e.preferences||{}))o.put(t);for(const t of Object.values(e.context||{}))a.put(t);for(const[t,s]of Object.entries(e.transcripts||{})){for(const e of s)i.put({sessionId:t,...e,version:e.version??0,parent:e.parent??null});if(s.length>0){const e=s[s.length-1];c.put({sessionId:t,head:{id:e.id,version:e.version??0}})}}e.indexState&&d.put({id:T,state:e.indexState}),n.oncomplete=()=>t(),n.onerror=()=>s(n.error),n.onabort=()=>s(new Error("importBundle transaction aborted"))}))}getAllFromStore(e,t){return new Promise(((s,n)=>{const r=e.transaction(t,"readonly").objectStore(t).getAll();r.onsuccess=()=>s(r.result),r.onerror=()=>n(r.error)}))}},j=class{bytes=new Map;records=new Map;async storeBytes(e,t){this.bytes.has(e)||this.bytes.set(e,t)}async loadBytes(e){return this.bytes.get(e)??null}async hasBytes(e){return this.bytes.has(e)}async deleteBytes(e){this.bytes.delete(e)}async saveRecord(e){this.records.set(e.sha256,{...e})}async loadRecord(e){return this.records.get(e)??null}async deleteRecord(e){this.records.delete(e)}async listRecords(){return Array.from(this.records.values()).map((e=>({...e})))}async exportAllBytes(){return Array.from(this.bytes.entries()).map((([e,t])=>[e,new Uint8Array(t)]))}},I="blob_bytes",N="blob_records";function D(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function B(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}var P=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace-blobs"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,1);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBBlobStorage] Database "${this.dbName}" blocked.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){e.objectStoreNames.contains(I)||e.createObjectStore(I,{keyPath:"sha256"}),e.objectStoreNames.contains(N)||e.createObjectStore(N,{keyPath:"sha256"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBBlobStorage] Database not open. Call open() first.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async storeBytes(e,t){const s=this.readTx(I);if(await D(s.objectStore(I).get(e)))return;const n=this.writeTx(I);n.objectStore(I).put({sha256:e,data:t}),await B(n)}async loadBytes(e){const t=this.readTx(I),s=await D(t.objectStore(I).get(e));return s?.data??null}async hasBytes(e){const t=this.readTx(I);return await D(t.objectStore(I).count(e))>0}async deleteBytes(e){const t=this.writeTx(I);t.objectStore(I).delete(e),await B(t)}async saveRecord(e){const t=this.writeTx(N);t.objectStore(N).put(e),await B(t)}async loadRecord(e){const t=this.readTx(N);return await D(t.objectStore(N).get(e))??null}async deleteRecord(e){const t=this.writeTx(N);t.objectStore(N).delete(e),await B(t)}async listRecords(){return D(this.readTx(N).objectStore(N).getAll())}async exportAllBytes(){const e=this.readTx(I);return(await D(e.objectStore(I).getAll())).map((({sha256:e,data:t})=>[e,t]))}async registerBlob(e,t){await new Promise(((s,n)=>{const r=this.getDB().transaction([I,N],"readwrite"),o=r.objectStore(I),a=r.objectStore(N),i=o.count(e.sha256);i.onsuccess=()=>{0===i.result&&o.put({sha256:e.sha256,data:t}),a.put(e)},i.onerror=()=>n(i.error),r.oncomplete=()=>s(),r.onerror=()=>n(r.error),r.onabort=()=>n(new Error("registerBlob transaction aborted"))}))}};async function R(e){const t=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(t)).map((e=>e.toString(16).padStart(2,"0"))).join("")}var E=class{backend;config;recordCache=new Map;onRegistryChanged;constructor(e,t={}){this.backend=e,this.config={eagerEviction:t.eagerEviction??!1}}async init(){const e=await this.backend.listRecords();for(const t of e)this.recordCache.set(t.sha256,t)}async register(e,t,s){try{const n=await R(e),r=(new Date).toISOString(),o=this.recordCache.get(n);if(o){const e={...o,refCount:o.refCount+1,lastUsedAt:r};await this.backend.saveRecord(e),this.recordCache.set(n,e),this.onRegistryChanged?.(n,A(e))}else{const o={sha256:n,mediaType:t,sizeBytes:e.byteLength,filename:s,refCount:1,remoteIds:{},createdAt:r,lastUsedAt:r};"registerBlob"in this.backend&&"function"==typeof this.backend.registerBlob?await this.backend.registerBlob(o,e):(await this.backend.storeBytes(n,e),await this.backend.saveRecord(o)),this.recordCache.set(n,o),this.onRegistryChanged?.(n,A(o))}const a=this.recordCache.get(n);return l({sha256:n,mediaType:t,sizeBytes:a.sizeBytes,filename:a.filename})}catch(e){return u({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return u({code:"NOT_FOUND",resource:"blob",id:e});const s={...t,refCount:t.refCount+1,lastUsedAt:(new Date).toISOString()};return await this.backend.saveRecord(s),this.recordCache.set(e,s),this.onRegistryChanged?.(e,A(s)),l(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return u({code:"NOT_FOUND",resource:"blob",id:e});const s=Math.max(0,t.refCount-1),n={...t,refCount:s,lastUsedAt:(new Date).toISOString()};return 0===s&&this.config.eagerEviction?(await this.backend.deleteBytes(e),await this.backend.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null)):(await this.backend.saveRecord(n),this.recordCache.set(e,n),this.onRegistryChanged?.(e,A(n))),l(void 0)}async recordRemoteId(e,t,s){const n=this.recordCache.get(e);if(!n)return u({code:"NOT_FOUND",resource:"blob",id:e});if(n.remoteIds[t]===s)return l(void 0);const r={...n,remoteIds:{...n.remoteIds,[t]:s}};return await this.backend.saveRecord(r),this.recordCache.set(e,r),l(void 0)}getRemoteId(e,t){return this.recordCache.get(e)?.remoteIds[t]??null}async resolveRef(e,t){try{if(t){const s=this.getRemoteId(e.sha256,t);if(s)return l({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.backend.loadBytes(e.sha256);return s?l({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):u({code:"BLOB_ERROR",reason:`Blob bytes not found locally for sha256=${e.sha256}. The blob may have been evicted. Re-register it before resolving.`})}catch(e){return u({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async resolveRefs(e,t){const s=function(e){const t=new Set,s=[];for(const n of e)t.has(n.sha256)||(t.add(n.sha256),s.push(n));return s}(e),n=await Promise.all(s.map((async e=>({ref:e,result:await this.resolveRef(e,t)})))),r=new Map,o=[];for(const{ref:e,result:t}of n)t.ok?r.set(e.sha256,t.value):o.push({ref:e,error:t.error});return{resolved:r,errors:o}}async gc(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((async e=>{await this.backend.deleteBytes(e.sha256)}))),e.length}async purge(e){return this.recordCache.has(e)?(await this.backend.deleteBytes(e),await this.backend.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null),l(void 0)):u({code:"NOT_FOUND",resource:"blob",id:e})}getRecord(e){return this.recordCache.get(e)??null}getSummary(e){const t=this.recordCache.get(e);return t?A(t):null}getAllSummaries(){const e={};for(const[t,s]of this.recordCache)e[t]=A(s);return e}};function A(e){return{sha256:e.sha256,mediaType:e.mediaType,sizeBytes:e.sizeBytes,filename:e.filename,refCount:e.refCount,createdAt:e.createdAt,lastUsedAt:e.lastUsedAt}}var _={roles:1/0,preferences:50,contextEntries:20,transcriptWindows:3},$=10,F=3e4,U=class{map=new Map;max;constructor(e){this.max=e}get(e){if(!this.map.has(e))return;const t=this.map.get(e);return this.map.delete(e),this.map.set(e,t),t}set(e,t){if(this.map.has(e)&&this.map.delete(e),this.map.set(e,t),this.map.size>this.max){const e=this.map.keys().next().value;void 0!==e&&this.map.delete(e)}}has(e){return this.map.has(e)}delete(e){this.map.delete(e)}},M=class{roles;preferences;contexts;transcriptWindows;pinnedRoles=new Map;pinnedPreferences=new Map;pinnedContexts=new Map;pinnedTranscriptWindows=new Map;constructor(e){this.roles=new U(e.roles),this.preferences=new U(e.preferences),this.contexts=new U(e.contextEntries),this.transcriptWindows=new U(e.transcriptWindows)}getRole(e){return this.pinnedRoles.get(e)??this.roles.get(e)}setRole(e,t=!1){t?(this.pinnedRoles.set(e.name,e),this.roles.delete(e.name)):this.pinnedRoles.has(e.name)?this.pinnedRoles.set(e.name,e):this.roles.set(e.name,e)}deleteRole(e){this.pinnedRoles.delete(e),this.roles.delete(e)}unpinRole(e){const t=this.pinnedRoles.get(e);t&&(this.pinnedRoles.delete(e),this.roles.set(e,t))}getPreference(e){return this.pinnedPreferences.get(e)??this.preferences.get(e)}setPreference(e,t=!1){t?(this.pinnedPreferences.set(e.id,e),this.preferences.delete(e.id)):this.pinnedPreferences.has(e.id)?this.pinnedPreferences.set(e.id,e):this.preferences.set(e.id,e)}unpinPreference(e){const t=this.pinnedPreferences.get(e);t&&(this.pinnedPreferences.delete(e),this.preferences.set(e,t))}deletePreference(e){this.pinnedPreferences.delete(e),this.preferences.delete(e)}getContext(e){return this.pinnedContexts.get(e)??this.contexts.get(e)}setContext(e,t=!1){t?(this.pinnedContexts.set(e.key,e),this.contexts.delete(e.key)):this.contexts.set(e.key,e)}unpinContext(e){const t=this.pinnedContexts.get(e);t&&(this.pinnedContexts.delete(e),this.contexts.set(e,t))}invalidateContext(e){this.contexts.delete(e),this.pinnedContexts.delete(e)}getTranscriptWindow(e){return this.pinnedTranscriptWindows.get(e)??this.transcriptWindows.get(e)}setTranscriptWindow(e,t=!1){t?(this.pinnedTranscriptWindows.set(e.sessionId,e),this.transcriptWindows.delete(e.sessionId)):this.transcriptWindows.set(e.sessionId,e)}unpinTranscriptWindow(e){const t=this.pinnedTranscriptWindows.get(e);t&&(this.pinnedTranscriptWindows.delete(e),this.transcriptWindows.set(e,t))}invalidateTranscriptWindow(e){this.transcriptWindows.delete(e),this.pinnedTranscriptWindows.delete(e)}},W=class{sessionId;dirtyBuffer=[];flushTimer=null;flushConfig;onFlush;flushChain=Promise.resolve();constructor(e,t,s){this.sessionId=e,this.flushConfig=t,this.onFlush=s,this.startTimer()}startTimer(){this.flushTimer=setInterval((()=>{this.flushChain=this.flushChain.then((()=>this.doFlush()))}),this.flushConfig.flushIntervalMs)}async record(e){this.dirtyBuffer.push(e),this.dirtyBuffer.length>=this.flushConfig.maxBufferSize&&await this.flush()}getDirtyBuffer(){return this.dirtyBuffer}async flush(){return this.flushChain=this.flushChain.then((()=>this.doFlush())),this.flushChain}async doFlush(){if(0===this.dirtyBuffer.length)return;const e=this.dirtyBuffer.splice(0,this.dirtyBuffer.length);await this.onFlush(this.sessionId,e)}async deactivate(){null!==this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),await this.flush()}};function z(e,t){return e.preferences.length>0?e.preferences:t.preferences}function H(e,t){return e.filter((e=>0===e.topics.length||e.topics.some((e=>t.includes(e)))))}var K=class{storage;cache;config;activeSession=null;pinnedPreferenceIds=new Set;onFlushed;onSessionInvalidated;constructor(e,t={}){this.storage=e;const s={roles:t.cache?.roles??_.roles,preferences:t.cache?.preferences??_.preferences,contextEntries:t.cache?.contextEntries??_.contextEntries,transcriptWindows:t.cache?.transcriptWindows??_.transcriptWindows};this.cache=new M(s),this.config={cache:s,flush:{maxBufferSize:t.flush?.maxBufferSize??$,flushIntervalMs:t.flush?.flushIntervalMs??F},transcriptWindowSize:t.transcriptWindowSize??20}}getActiveSessionId(){return this.activeSession?.sessionId??null}async getRole(e){const t=this.cache.getRole(e);if(t)return l(t);const s=await this.storage.loadRole(e);return s?(this.cache.setRole(s),l(s)):u({code:"NOT_FOUND",resource:"role",id:e})}async getPreference(e){const t=this.cache.getPreference(e);if(t)return l(t);const s=await this.storage.loadPreference(e);return s?(this.cache.setPreference(s),l(s)):u({code:"NOT_FOUND",resource:"preference",id:e})}async getContext(e){const t=this.cache.getContext(e);if(t)return l(t);const s=await this.storage.loadContext(e);return s?(this.cache.setContext(s),l(s)):u({code:"NOT_FOUND",resource:"context",id:e})}async getContextByTopics(e,t){const s=new Set;for(const n of t){const t=e.workspace.indexes.topics[n];t&&t.contextKeys.forEach((e=>s.add(e)))}return(await Promise.all(Array.from(s).map((e=>this.getContext(e))))).filter((e=>e.ok)).map((e=>e.value)).sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async getTranscriptWindow(e,t){const s=t??this.config.transcriptWindowSize,n=this.activeSession?.sessionId===e,r=n?[...this.activeSession?.getDirtyBuffer()??[]]:[],o=await this.storage.getActiveChain(e),a=[...o,...r].slice(-s),i=o.length+r.length,c={sessionId:e,turns:a,flushedCount:i,hasMore:i>s};return this.cache.setTranscriptWindow(c,n),c}async saveRole(e){await this.storage.saveRole(e),this.cache.setRole(e)}async savePreference(e){await this.storage.savePreference(e),this.cache.setPreference(e)}async saveContext(e){await this.storage.saveContext(e),this.cache.setContext(e)}async copyTranscript(e,t){await this.storage.copyTranscript(e,t)}async deleteRole(e){await this.storage.deleteRole(e),this.cache.deleteRole(e)}async deletePreference(e){await this.storage.deletePreference(e),this.cache.deletePreference(e),this.pinnedPreferenceIds.delete(e)}async deleteContext(e){await this.storage.deleteContext(e),this.cache.invalidateContext(e)}async recordTurn(e,t){return this.activeSession?.sessionId===e?(await this.activeSession.record(t),this.cache.invalidateTranscriptWindow(e)):(await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version}),this.cache.invalidateTranscriptWindow(e)),this.onSessionInvalidated?.(e),l(void 0)}async editTurn(e,t,s,n,r){let o=null;if(this.activeSession?.sessionId===e&&(o=this.activeSession.getDirtyBuffer().find((e=>e.id===t&&e.version===n-1))??null),o||(o=await this.storage.loadTurn(e,t,n-1)),!o)return u({code:"NOT_FOUND",resource:"turn",id:t});const a={id:t,version:n,role:o.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:r??o.roleSnapshot,parent:o.parent};return this.activeSession?.sessionId===e?await this.activeSession.record(a):(await this.storage.saveTurn(e,a),await this.storage.setSessionHead(e,{id:a.id,version:a.version})),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async branchTurn(e,t){return await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version}),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async deleteTurnSubtree(e,t,s,n){return await this.storage.deleteTurnSubtree(e,t,s),await this.storage.setSessionHead(e,n),this.cache.invalidateTranscriptWindow(e),this.onSessionInvalidated?.(e),l(void 0)}async activateSession(e){if(this.activeSession?.sessionId===e.id)return l(void 0);this.activeSession&&await this.deactivateSession(),this.activeSession=new W(e.id,this.config.flush,(async(e,t)=>{for(const s of t)await this.storage.saveTurn(e,s);if(t.length>0){const s=t[t.length-1];await this.storage.setSessionHead(e,{id:s.id,version:s.version})}this.onFlushed?.(e,t.length)}));const t=await this.getRole(e.role);t.ok&&this.cache.setRole(t.value,!0);const s=z(e,t.ok?t.value:{preferences:[]}),n=[];await Promise.all(s.map((async e=>{const t=await this.getPreference(e);t.ok&&n.push(t.value)})));const r=H(n,e.topics);this.pinnedPreferenceIds=new Set;for(const e of r)this.cache.setPreference(e,!0),this.pinnedPreferenceIds.add(e.id);const o=await this.getTranscriptWindow(e.id,e.flushedTurnCount);return this.cache.setTranscriptWindow(o,!0),this.onSessionInvalidated?.(e.id),l(void 0)}async deactivateSession(e){if(!this.activeSession)return;const t=this.activeSession.sessionId;await this.activeSession.deactivate(),this.activeSession=null,e&&this.cache.unpinRole(e.role);for(const e of this.pinnedPreferenceIds)this.cache.unpinPreference(e);this.pinnedPreferenceIds=new Set,this.cache.unpinTranscriptWindow(t)}async resolveSession(e,t){const s=e.sessions[t];if(!s)return u({code:"NOT_FOUND",resource:"session",id:t});const n=await this.getRole(s.role);if(!n.ok)return n;const r=n.value,o=z(s,r),a={session:s,role:r,preferences:H((await Promise.all(o.map((e=>this.getPreference(e))))).filter((e=>e.ok)).map((e=>e.value)),s.topics),context:await this.getContextByTopics(e,s.topics),transcript:(await this.getTranscriptWindow(t,s.flushedTurnCount)).turns,systemPrompt:e.workspace.settings.prompt};return l(structuredClone(a))}async flush(){await(this.activeSession?.flush())}async dispose(){await this.deactivateSession()}};function L(e,t){switch(t.type){case"workspace:create":{const{id:e,settings:s,project:n}=t.payload;return l({workspace:{id:e,settings:s,project:n,indexes:{sessions:{},roles:{},preferences:{},context:{},topics:{}}}})}case"role:add":{const s=t.payload;if(e.roles[s.name])return u({code:"DUPLICATE_KEY",resource:"role",key:s.name});const n={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return l({roles:{[s.name]:n},workspace:{indexes:{roles:{[s.name]:n}}}})}case"preference:add":{const s=t.payload,n={id:s.id,topics:s.topics,timestamp:s.timestamp,snippet:s.content.substring(0,100)},r={};return s.topics.forEach((n=>{const o=e.workspace.indexes.topics[n];r[n]={topic:n,contextKeys:o?.contextKeys||[],preferences:[...o?.preferences||[],s.id],metadata:{created:o?.metadata?.created||t.timestamp,updated:t.timestamp,entries:o?.metadata?.entries||0}}})),l({preferences:{[s.id]:n},workspace:{indexes:{preferences:{[s.id]:n},topics:r}}})}case"context:add":{const s=t.payload;if(e.context[s.key])return u({code:"DUPLICATE_KEY",resource:"context",key:s.key});const n={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"string"==typeof s.content?s.content.substring(0,200):JSON.stringify(s.content).substring(0,200),metadata:s.metadata},r={};return s.topics.forEach((n=>{const o=e.workspace.indexes.topics[n],a=o?.contextKeys||[],i=a.includes(s.key)?a:[...a,s.key];r[n]={topic:n,contextKeys:i,metadata:{updated:t.timestamp,entries:i.length}}})),l({context:{[s.key]:n},workspace:{indexes:{context:{[s.key]:n},topics:r}}})}case"session:create":{const{id:s,label:n,role:r,topics:o,preferences:a=[]}=t.payload;if(e.sessions[s])return u({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[r])return u({code:"NOT_FOUND",resource:"role",id:r});const i={id:s,label:n,role:r,topics:o,preferences:a,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null};return l({sessions:{[s]:i},workspace:{indexes:{sessions:{[s]:{id:s,label:n,role:r,topics:o,created:t.timestamp,updated:t.timestamp,turns:0}}}}})}case"turn:add":{const{sessionId:s,turn:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n.id,version:n.version},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{turns:(e.workspace.indexes.sessions[s]?.turns??0)+1,updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:n,newVersion:r}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n,version:r},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:{id:n.id,version:n.version},metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{head:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:role:switch":{const{sessionId:s,role:n}=t.payload;return e.sessions[s]?e.roles[n]?l({sessions:{[s]:{role:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{role:n,updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"role",id:n}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:n}=t.payload,r=e.sessions[s];if(!r)return u({code:"NOT_FOUND",resource:"session",id:s});const o=Array.from(new Set([...r.topics,...n]));return l({sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{topics:o,updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:n}=t.payload;return e.sessions[s]?l({sessions:{[s]:{preferences:n,metadata:{updated:t.timestamp}}},workspace:{indexes:{sessions:{[s]:{updated:t.timestamp}}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:n,label:r,role:o,topics:a}=t.payload,i=e.sessions[s];if(!i)return u({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[n])return u({code:"DUPLICATE_KEY",resource:"session",key:n});const c=o??i.role;if(!e.roles[c])return u({code:"NOT_FOUND",resource:"role",id:c});const d=a??[...i.topics],h={id:n,label:r,role:c,topics:d,preferences:[...i.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:i.flushedTurnCount,head:i.head};return l({sessions:{[n]:h},workspace:{indexes:{sessions:{[n]:{id:n,label:r,role:c,topics:d,created:t.timestamp,updated:t.timestamp,turns:i.flushedTurnCount}}}}})}case"role:update":{const{name:s,...n}=t.payload;if(!e.roles[s])return u({code:"NOT_FOUND",resource:"role",id:s});const r=e.roles[s],o={...r,...n,preferences:n.preferences?.length??r.preferences};return l({roles:{[s]:o},workspace:{indexes:{roles:{[s]:o}}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return u({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?u({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):l({roles:{[s]:m()},workspace:{indexes:{roles:{[s]:m()}}}})}case"preference:update":{const{id:s,...n}=t.payload;if(!e.preferences[s])return u({code:"NOT_FOUND",resource:"preference",id:s});const r=e.preferences[s],o={...r,...n,snippet:n.content?n.content.substring(0,100):r.snippet},a={};return n.topics&&(r.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(a[t]={preferences:n.preferences.filter((e=>e!==s))})})),n.topics.forEach((n=>{const r=e.workspace.indexes.topics[n]||{topic:n,contextKeys:[],preferences:[],metadata:{created:t.timestamp,updated:t.timestamp,entries:0}};a[n]={...r,preferences:[...new Set([...r.preferences,s])],metadata:{updated:t.timestamp}}}))),l({preferences:{[s]:o},workspace:{indexes:{preferences:{[s]:o},topics:a}}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return u({code:"NOT_FOUND",resource:"preference",id:s});const n=e.preferences[s],r={};return n.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(r[t]={preferences:n.preferences.filter((e=>e!==s))})})),l({preferences:{[s]:m()},workspace:{indexes:{preferences:{[s]:m()},topics:r}}})}case"context:update":{const{key:s,...n}=t.payload;if(!e.context[s])return u({code:"NOT_FOUND",resource:"context",id:s});const r=e.context[s],o={...r,...n,preview:n.content?"string"==typeof n.content?n.content.substring(0,200):JSON.stringify(n.content).substring(0,200):r.preview},a={};return n.topics&&(r.topics.forEach((t=>{const n=e.workspace.indexes.topics[t];n&&(a[t]={contextKeys:n.contextKeys.filter((e=>e!==s))})})),n.topics.forEach((n=>{const r=e.workspace.indexes.topics[n]||{contextKeys:[]},o=r.contextKeys.includes(s)?r.contextKeys:[...r.contextKeys,s];a[n]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),l({context:{[s]:o},workspace:{indexes:{context:{[s]:o},topics:a}}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return u({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],r={};return n.topics.forEach((n=>{const o=e.workspace.indexes.topics[n];o&&(r[n]={contextKeys:o.contextKeys.filter((e=>e!==s)),metadata:{updated:t.timestamp,entries:o.contextKeys.length-1}})})),l({context:{[s]:m()},workspace:{indexes:{context:{[s]:m()},topics:r}}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?l({sessions:{[s]:m()},workspace:{indexes:{sessions:{[s]:m()}}}}):u({code:"NOT_FOUND",resource:"session",id:s})}default:return l({})}}var V=class{contentStore;constructor(e){this.contentStore=e}reduce(e,t){return L(e,t)}async dispatch(e,t){const s=L(e,t);if(!s.ok)return s;try{await this.handleContentSideEffects(e,t)}catch(e){return u({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return s}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async activateSession(e,t){const s=e.sessions[t];return s?this.contentStore.activateSession(s):u({code:"NOT_FOUND",resource:"session",id:t})}async deactivateSession(e){const t=this.contentStore.getActiveSessionId();if(!t)return;const s=e?.sessions[t];await this.contentStore.deactivateSession(s)}async flush(){await this.contentStore.flush()}async dispose(){await this.contentStore.dispose()}async handleContentSideEffects(e,t){switch(t.type){case"role:add":await this.contentStore.saveRole(t.payload);break;case"role:update":{const{name:e,...s}=t.payload,n=await this.contentStore.getRole(e);if(!n.ok)throw new Error(`role:update — role "${e}" not found in backend`);const r={...n.value,...s,name:e};await this.contentStore.saveRole(r);break}case"role:delete":await this.contentStore.deleteRole(t.payload.name);break;case"preference:add":await this.contentStore.savePreference(t.payload);break;case"preference:update":{const{id:e,...s}=t.payload,n=await this.contentStore.getPreference(e);if(!n.ok)throw new Error(`preference:update — preference "${e}" not found in backend`);const r={...n.value,...s,id:e};await this.contentStore.savePreference(r);break}case"preference:delete":await this.contentStore.deletePreference(t.payload.id);break;case"context:add":case"context:update":await this.contentStore.saveContext(t.payload);break;case"context:delete":await this.contentStore.deleteContext(t.payload.key);break;case"turn:add":{const{sessionId:e,turn:s}=t.payload;await this.contentStore.recordTurn(e,s);break}case"turn:edit":{const{sessionId:e,turnId:s,newBlocks:n,newVersion:r,roleSnapshot:o}=t.payload;await this.contentStore.editTurn(e,s,n,r,o);break}case"turn:branch":{const{sessionId:e,newTurn:s}=t.payload;await this.contentStore.branchTurn(e,s);break}case"turn:delete":{const{sessionId:e,turnId:s,version:n,newHead:r}=t.payload;await this.contentStore.deleteTurnSubtree(e,s,n,r);break}case"session:fork":{const{sourceSessionId:e,newSessionId:s}=t.payload;this.contentStore.getActiveSessionId()===e&&await this.contentStore.flush(),await this.contentStore.copyTranscript(e,s);break}}}};function J(e){return Math.ceil(e.length/4)}function Y(e,t){return(t??J)(e)}function q(e,t){return Math.ceil(e/1024*t)}function G(e,t,s,n){return Z(e,t).reduce(((e,t)=>e+function(e,t,s){switch(e.type){case"text":return Y(e.text,t);case"image":case"document":return q(e.blob.data?.byteLength??0,s);case"tool_use":return Y(JSON.stringify(e.input),t);case"tool_result":return Y("string"==typeof e.content?e.content:JSON.stringify(e.content),t);case"thinking":return Y(e.thinking,t);default:return 0}}(t,s,n)),0)}function Q(e){return new Set(e.toLowerCase().replace(/[^\w\s]/g," ").split(/\s+/).filter((e=>e.length>2)))}function X(e,t){const s=(Date.now()-new Date(e).getTime())/864e5;return Math.pow(.5,s/t)}function Z(e,t){return e.blocks.map((e=>{if("image"===e.type){const s=t.get(e.blob.sha256);if(s)return{...e,blob:s}}if("document"===e.type){const s=t.get(e.blob.sha256);if(s)return{...e,blob:s}}return e}))}function ee(e){return"object"==typeof e&&null!==e?JSON.stringify(e):String(e)}var te=class{summarizer;constructor(e){this.summarizer=e}async build(e,t={}){const{resolvedBlobs:s=new Map,tokenBudget:n,relevanceConfig:r={}}=t,o=[],a=function(e,t){const s=new Set,n=[];function r(e){s.has(e.sha256)||(s.add(e.sha256),n.push(e))}for(const t of e)for(const e of t.blocks)if(("image"===e.type||"document"===e.type)&&"blob"in e){const t=e;r({sha256:t.blob.sha256,mediaType:t.blob.mediaType,sizeBytes:t.blob.data?.byteLength??0,filename:t.blob.filename})}for(const e of t)for(const t of e.attachments??[])r(t);return n}(e.transcript,e.context),i=a.filter((e=>!s.has(e.sha256)));i.length>0&&o.push(`${i.length} blob(s) were not resolved and will be omitted: `+i.map((e=>e.sha256.slice(0,8))).join(", "));const{resolved:c,conflicts:d}=function(e){const t=[],s=new Map;for(const n of e)if(0!==n.topics.length)for(const e of n.topics){const r=s.get(e);if(!r){s.set(e,n);continue}const o=new Date(r.timestamp).getTime(),a=new Date(n.timestamp).getTime();a>o?(t.push({topic:e,kept:n.id,dropped:r.id,reason:"superseded_by_newer"}),s.set(e,n)):o>a&&t.push({topic:e,kept:r.id,dropped:n.id,reason:"superseded_by_newer"})}const n=new Set(t.map((e=>e.dropped))),r=new Set,o=[];for(const e of t)r.has(e.dropped)||(r.add(e.dropped),o.push(e));return{resolved:e.filter((e=>!n.has(e.id))),conflicts:o}}(e.preferences);d.length>0&&o.push(`${d.length} preference conflict(s) resolved. Dropped: ${d.map((e=>e.dropped)).join(", ")}`);const l=r.recentMessageWindow??3,u=e.transcript.filter((e=>"user"===e.role)).slice(-l).flatMap((e=>e.blocks.filter((e=>"text"===e.type)).map((e=>e.text)))),h=function(e,t,s){const n=s.recentMessageWindow??3,r=s.minScore??0,o=s.freshnessHalfLifeDays??30;if(0===t.length)return[...e].sort(((e,t)=>X(t.timestamp,o)-X(e.timestamp,o)));const a=Q(t.slice(-n).join(" "));return e.map((e=>{const t="string"==typeof e.content?e.content:JSON.stringify(e.content);return{entry:e,score:.7*function(e,t){if(0===e.size&&0===t.size)return 0;let s=0;for(const n of e)t.has(n)&&s++;const n=e.size+t.size-s;return 0===n?0:s/n}(a,Q(t))+.3*X(e.timestamp,o)}})).filter((e=>e.score>r)).sort(((e,t)=>t.score-e.score)).map((e=>e.entry))}(e.context,u,r);let p=e.transcript,f=null;if(this.summarizer&&p.length>0){const e=n?Math.floor(.25*n.total):2e3,t=await this.summarizer.summarize(p,e);f=t.summary,p=t.remaining}let m={preferences:0,interactions:0,contextEntries:0},y=c,w=p,b=h,g=null;if(n){const t=function(e,t,s,n,r,o,a){const i=a.estimator??J,c=a.blobTokensPerKB??.25;let d=a.total;d-=Y(e??"",i),d-=Y(t,i);const l=[];let u=0;for(const e of s){const t=Y(e.content,i);d-t>=0?(d-=t,l.push(e)):u++}const h=[];let p=0;for(let e=n.length-1;e>=0;e--){const t=G(n[e],o,i,c);d-t>=0?(d-=t,h.unshift(n[e])):p++}const f=[];let m=0;for(const e of r){const t=Y("string"==typeof e.content?e.content:JSON.stringify(e.content),i)+(e.attachments??[]).reduce(((e,t)=>e+q(t.sizeBytes,c)),0);d-t>=0?(d-=t,f.push(e)):m++}return{preferences:l,turns:h,context:f,truncated:{preferences:u,interactions:p,contextEntries:m}}}(e.systemPrompt,e.role.persona,c,p,h,s,n);if(y=t.preferences,w=t.turns,b=t.context,m=t.truncated,m.interactions>0&&e.transcript.length>0){const t=e.transcript.slice(0,m.interactions);for(let e=t.length-1;e>=0;e--)if("user"===t[e].role){g=t[e].roleSnapshot??null;break}}m.preferences>0&&o.push(`${m.preferences} preference(s) dropped due to token budget.`),m.interactions>0&&o.push(`${m.interactions} turn(s) trimmed from transcript start.`),m.contextEntries>0&&o.push(`${m.contextEntries} context entry/entries dropped due to token budget.`)}const v=[e.role.persona];if(y.length>0&&v.push(`<preferences>\n${y.map((e=>e.content)).join("\n\n")}\n</preferences>`),b.length>0){const e=b.map((e=>`[${e.key}]\n${ee(e.content)}`)).join("\n\n");v.push(`<context>\n${e}\n</context>`)}e.systemPrompt&&v.unshift(e.systemPrompt);const S=v.join("\n\n")||null,x=function(e,t){if(0===e.length)return[];const s=[],n=e.map((e=>`[${e.key}]\n${ee(e.content)}`)).join("\n\n");s.push({type:"text",text:`<context>\n${n}\n</context>`});for(const n of e)for(const e of n.attachments??[]){const n=t.get(e.sha256);n&&(e.mediaType.startsWith("image/")?s.push({type:"image",blob:n}):s.push({type:"document",blob:n,title:e.filename}))}return s}(b,s).filter((e=>"image"===e.type||"document"===e.type)),T=[];x.length>0&&T.push({role:"user",blocks:x});const k=function(e,t,s,n,r=null){const o=[];if(s>0||n){const e=[];n&&e.push({type:"text",text:`<summary>\n${n}\n</summary>`}),s>0&&e.push({type:"text",text:`[${s} earlier turn(s) omitted due to token budget]`}),o.push({role:"user",blocks:e}),o.push({role:"assistant",blocks:[{type:"text",text:"Understood."}]})}let a=r,i=null!==r;for(const s of e){const e=Z(s,t);"user"===s.role&&s.roleSnapshot&&i&&s.roleSnapshot!==a&&e.unshift({type:"text",text:`[Role switched to: ${s.roleSnapshot}]`}),"user"===s.role&&(a=s.roleSnapshot??null,i=!0),o.push({role:s.role,blocks:e})}return o}(w,s,m.interactions,f,g);return T.push(...k),{system:S,turns:T,blobs:a,truncated:m,conflicts:d,warnings:o}}};export{E as BlobStore,K as ContentStore,P as IndexedDBBlobStorage,C as IndexedDBStorage,j as MemoryBlobStorage,h as MemoryStorage,te as PromptBuilder,V as WorkspaceManager,R as computeSHA256,m as del,u as err,y as merge,l as ok,L as workspaceReducer};
1
+ var e,t,s=Object.create,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,c=(e,t,c)=>(c=null!=e?s(i(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(i=n(t,c))||i.enumerable});return e})(e&&e.__esModule?c:r(c,"default",{value:e,enumerable:!0}),e)),d=(e={"node_modules/@asaidimu/events/index.js"(e,t){var s,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,i=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var s in t)r(e,s,{get:t[s],enumerable:!0})})(a,{createEventBus:()=>c}),t.exports=(s=a,((e,t,s,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))i.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(a=n(t,c))||a.enumerable});return e})(r({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],r=0,n=0;const o=new Map,i=new Map;let a=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?a=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{r++,n+=t,o.set(e,(o.get(e)||0)+1)},d=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const r=performance.now();try{(i.get(t)||[]).forEach((e=>e(s)))}catch(r){e.errorHandler({...r,eventName:t,payload:s})}c(t,performance.now()-r)}))},l=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(d,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?i.set(e,Array.from(s)):i.delete(e)};return a&&(a.onmessage=e=>{const{name:t,payload:s}=e.data;(i.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(s),h(e),()=>{r.delete(s),0===r.size?(t.delete(e),i.delete(e)):h(e)}},emit:({name:t,payload:r})=>{if(e.async)return s.push({name:t,payload:r}),s.length>=e.batchSize?d():l(),void(a&&a.postMessage({name:t,payload:r}));const n=performance.now();try{(i.get(t)||[]).forEach((e=>e(r))),a&&a.postMessage({name:t,payload:r})}catch(s){e.errorHandler({...s,eventName:t,payload:r})}c(t,performance.now()-n)},getMetrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:r>0?n/r:0}),clear:()=>{t.clear(),i.clear(),s=[],r=0,n=0,o.clear(),a&&(a.close(),a=null)}}}}},function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports});c(d());var l=Symbol.for("delete"),h=e=>Array.isArray(e)?[...e]:{...e};function u(){return l}c(d()),c(d()),c(d()),c(d()),c(d()),c(d());var p=function(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const r={};for(const[n,o]of Object.entries(e))if(o!==t)if("object"==typeof o&&null!==o){const e=s(o);void 0!==e&&(r[n]=e)}else r[n]=o;return r}return e===t?void 0:e}return function(e,r){if("object"!=typeof e||null===e)return"object"==typeof r&&null!==r?s(r):r===t?{}:r;if("object"!=typeof r||null===r)return e;const n=h(e),o=[{target:n,source:r}];for(;o.length>0;){const{target:e,source:s}=o.pop();for(const r of Object.keys(s)){const n=s[r];if(n!==t)if(Array.isArray(n))e[r]=n;else if("object"==typeof n&&null!==n){const t=r in e&&"object"==typeof e[r]&&null!==e[r]?e[r]:{};e[r]=h(t),o.push({target:e[r],source:n})}else e[r]=n;else delete e[r]}}return n}}({deleteMarker:l});function f(e){return{ok:!0,value:e}}function m(e){return{ok:!1,error:e}}var y="roles",g="preferences",b="context",w="turns",v="session_heads",x="index_state",S="blob_bytes",T="singleton";function k(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function O(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}var C=class{dbName;db=null;constructor(e={}){this.dbName=e.dbName??"aiworkspace"}async open(){this.db||(this.db=await new Promise(((e,t)=>{const s=indexedDB.open(this.dbName,3);s.onupgradeneeded=e=>{const t=e.target.result;this.createSchema(t)},s.onsuccess=()=>e(s.result),s.onerror=()=>t(s.error),s.onblocked=()=>t(new Error(`[IndexedDBStorage] Database "${this.dbName}" blocked. Close other tabs.`))})),this.db.onversionchange=()=>{this.db?.close(),this.db=null})}createSchema(e){if(e.objectStoreNames.contains(y)||e.createObjectStore(y,{keyPath:"name"}),e.objectStoreNames.contains(g)||e.createObjectStore(g,{keyPath:"id"}),!e.objectStoreNames.contains(b)){e.createObjectStore(b,{keyPath:"key"}).createIndex("by_topic","topics",{multiEntry:!0})}if(e.objectStoreNames.contains(x)||e.createObjectStore(x,{keyPath:"id"}),!e.objectStoreNames.contains(w)){e.createObjectStore(w,{keyPath:["sessionId","id","version"]}).createIndex("by_sessionId","sessionId")}e.objectStoreNames.contains(v)||e.createObjectStore(v,{keyPath:"sessionId"}),e.objectStoreNames.contains(S)||e.createObjectStore(S,{keyPath:"sha256"})}close(){this.db?.close(),this.db=null}async deleteDatabase(){this.close(),await new Promise(((e,t)=>{const s=indexedDB.deleteDatabase(this.dbName);s.onsuccess=()=>e(),s.onerror=()=>t(s.error)}))}getDB(){if(!this.db)throw new Error("[IndexedDBStorage] Database not open. Call open() before using the storage.");return this.db}readTx(...e){return this.getDB().transaction(e,"readonly")}writeTx(...e){return this.getDB().transaction(e,"readwrite")}async saveRole(e){const t=this.writeTx(y);t.objectStore(y).put(e),await O(t)}async loadRole(e){const t=this.readTx(y);return await k(t.objectStore(y).get(e))??null}async deleteRole(e){const t=this.writeTx(y);t.objectStore(y).delete(e),await O(t)}async savePreference(e){const t=this.writeTx(g);t.objectStore(g).put(e),await O(t)}async loadPreference(e){const t=this.readTx(g);return await k(t.objectStore(g).get(e))??null}async deletePreference(e){const t=this.writeTx(g);t.objectStore(g).delete(e),await O(t)}async saveContext(e){const t=this.writeTx(b);t.objectStore(b).put(e),await O(t)}async loadContext(e){const t=this.readTx(b);return await k(t.objectStore(b).get(e))??null}async loadContextBatch(e){if(0===e.length)return new Map;const t=this.readTx(b).objectStore(b),s=await Promise.all(e.map((e=>k(t.get(e))))),r=new Map;for(let t=0;t<e.length;t++){const n=s[t];n&&r.set(e[t],n)}return r}async deleteContext(e){const t=this.writeTx(b);t.objectStore(b).delete(e),await O(t)}async saveTurn(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction([w,v],"readwrite"),o=n.objectStore(w),i=n.objectStore(v);o.put({sessionId:e,...t}),i.put({sessionId:e,head:{id:t.id,version:t.version}}),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("saveTurn transaction aborted"))}))}async loadTurn(e,t,s){const r=this.readTx(w),n=await k(r.objectStore(w).get([e,t,s]));if(!n)return null;const{sessionId:o,...i}=n;return i}async loadAllTurns(e){const t=this.readTx(w).objectStore(w).index("by_sessionId");return(await k(t.getAll(e))).map((({sessionId:e,...t})=>t))}async deleteTurn(e,t,s){const r=this.writeTx(w);r.objectStore(w).delete([e,t,s]),await O(r)}async setSessionHead(e,t){const s=this.writeTx(v);t?s.objectStore(v).put({sessionId:e,head:t}):s.objectStore(v).delete(e),await O(s)}async getSessionHead(e){const t=this.readTx(v),s=await k(t.objectStore(v).get(e));return s?.head??null}async storeBytes(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction(S,"readwrite"),o=n.objectStore(S),i=o.count(e);i.onsuccess=()=>{0===i.result&&o.put({sha256:e,data:t})},i.onerror=()=>r(i.error),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("storeBytes transaction aborted"))}))}async loadBytes(e){const t=this.readTx(S),s=await k(t.objectStore(S).get(e));return s?.data??null}async deleteBytes(e){const t=this.writeTx(S);t.objectStore(S).delete(e),await O(t)}async exportAllBytes(){const e=this.readTx(S);return(await k(e.objectStore(S).getAll())).map((({sha256:e,data:t})=>[e,t]))}async saveWorkspace(e){const t=this.writeTx(x);t.objectStore(x).put({id:T,state:e}),await O(t)}async loadWorkspace(){const e=this.readTx(x),t=await k(e.objectStore(x).get(T));return t?.state??null}async exportBundle(){const e=this.getDB(),[t,s,r,n]=await Promise.all([this.getAllFromStore(e,y),this.getAllFromStore(e,g),this.getAllFromStore(e,b),this.getAllFromStore(e,x)]),o=await this.getAllFromStore(e,w),i=new Set(o.map((e=>e.sessionId))),a={};for(const e of i){const t=await this.getSessionHead(e),s=o.filter((t=>t.sessionId===e)).map((({sessionId:e,...t})=>t));a[e]=t?N(s,t):[]}return{roles:Object.fromEntries(t.map((e=>[e.name,e]))),preferences:Object.fromEntries(s.map((e=>[e.id,e]))),context:Object.fromEntries(r.map((e=>[e.key,e]))),transcripts:a,workspace:n[0]?.state??null}}async importBundle(e){await new Promise(((t,s)=>{const r=this.getDB().transaction([y,g,b,w,v,x],"readwrite"),n=r.objectStore(y),o=r.objectStore(g),i=r.objectStore(b),a=r.objectStore(w),c=r.objectStore(v),d=r.objectStore(x);for(const t of Object.values(e.roles||{}))n.put(t);for(const t of Object.values(e.preferences||{}))o.put(t);for(const t of Object.values(e.context||{}))i.put(t);for(const[t,s]of Object.entries(e.transcripts||{})){for(const e of s)a.put({sessionId:t,...e,version:e.version??0,parent:e.parent??null});if(s.length>0){const e=s[s.length-1];c.put({sessionId:t,head:{id:e.id,version:e.version??0}})}}e.workspace&&d.put({id:T,state:e.workspace}),r.oncomplete=()=>t(),r.onerror=()=>s(r.error),r.onabort=()=>s(new Error("importBundle transaction aborted"))}))}getAllFromStore(e,t){return new Promise(((s,r)=>{const n=e.transaction(t,"readonly").objectStore(t).getAll();n.onsuccess=()=>s(n.result),n.onerror=()=>r(n.error)}))}};function N(e,t){const s=new Map;for(const t of e)s.set(`${t.id}:${t.version}`,t);const r=[];let n=t;for(;n;){const e=s.get(`${n.id}:${n.version}`);if(!e)break;r.push(e),n=e.parent}return r.reverse()}var I=class{storage;constructor(e){this.storage=e}async append(e,t){const s=await this.storage.getSessionHead(e),r={...t,version:t.version??0,parent:null!==t.parent?t.parent:null!==s?{id:s.id,version:s.version}:null};return await this.storage.saveTurn(e,r),await this.storage.setSessionHead(e,{id:r.id,version:r.version}),r}async appendBatch(e,t){if(0!==t.length)for(const s of t)await this.append(e,s)}async replaceVersion(e,t){await this.storage.saveTurn(e,t)}async branch(e,t){await this.storage.saveTurn(e,t),await this.storage.setSessionHead(e,{id:t.id,version:t.version})}async getActiveChain(e,t=[]){const s=await this.storage.getSessionHead(e);if(!s&&0===t.length)return[];const r=await this.storage.loadAllTurns(e);return[...s?j(r,s):[],...t]}async countChained(e,t=[]){return(await this.getActiveChain(e,t)).length}async buildNodeGraph(e,t=[]){const s=await this.storage.loadAllTurns(e),r=await this.storage.getSessionHead(e),n=new Set;if(r){const e=j(s,r);for(const t of e)n.add(`${t.id}:${t.version}`)}const o={};for(const e of s){o[e.id]||(o[e.id]={id:e.id,versions:{},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{}});const t=o[e.id];t.versions[e.version]=e,n.has(`${e.id}:${e.version}`)&&(e.version>=t.activeVersion||!n.has(`${e.id}:${t.activeVersion}`))&&(t.activeVersion=e.version,t.blocks=e.blocks,t.timestamp=e.timestamp,t.roleSnapshot=e.roleSnapshot,t.parent=e.parent)}for(const e of Object.values(o))if(e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}for(const e of t)if(o[e.id]){const t=o[e.id];if(t.versions[e.version]=e,e.version>t.activeVersion&&(t.activeVersion=e.version,t.blocks=e.blocks,t.timestamp=e.timestamp,t.roleSnapshot=e.roleSnapshot),e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}}else if(o[e.id]={id:e.id,versions:{[e.version]:e},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{}},e.parent){const t=o[e.parent.id];if(t){const s=e.parent.version;t.children[s]||(t.children[s]=[]),t.children[s].includes(e.id)||t.children[s].push(e.id)}}return o}async deleteSubtree(e,t,s,r){const n=function(e,t,s){const r=new Map;for(const t of e)if(t.parent){const e=`${t.parent.id}:${t.parent.version}`;let s=r.get(e);s||(s=new Set,r.set(e,s)),s.add(`${t.id}:${t.version}`)}const n=new Set,o=[`${t}:${s}`];for(;o.length>0;){const e=o.pop();n.add(e);const t=r.get(e);if(t)for(const e of t)n.has(e)||o.push(e)}return n}(await this.storage.loadAllTurns(e),t,s);await Promise.all(Array.from(n).map((t=>{const[s,r]=t.split(":");return this.storage.deleteTurn(e,s,Number(r))}))),await this.storage.setSessionHead(e,r)}async copyTranscript(e,t){const s=await this.storage.getSessionHead(e),r=await this.storage.loadAllTurns(e),n=s?j(r,s):[];for(const e of n)await this.storage.saveTurn(t,{...e});await this.storage.setSessionHead(t,s?{...s}:null)}async getHead(e){return this.storage.getSessionHead(e)}async setHead(e,t){await this.storage.setSessionHead(e,t)}};function j(e,t){const s=new Map;for(const t of e)s.set(`${t.id}:${t.version}`,t);const r=[];let n=t;for(;null!==n;){const e=s.get(`${n.id}:${n.version}`);if(!e)break;r.push(e),n=e.parent}return r.reverse()}async function B(e){const t=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(t)).map((e=>e.toString(16).padStart(2,"0"))).join("")}var D=class{storage;config;recordCache=new Map;onRegistryChanged;constructor(e,t={}){this.storage=e,this.config={eagerEviction:t.eagerEviction??!1}}async init(){const e=await this.storage.listRecords();for(const t of e)this.recordCache.set(t.sha256,t)}async register(e,t,s){try{const r=await B(e),n=(new Date).toISOString(),o=this.recordCache.get(r);if(o){const e={...o,refCount:o.refCount+1,lastUsedAt:n};await this.storage.saveRecord(e),this.recordCache.set(r,e),this.onRegistryChanged?.(r,e)}else{const o={sha256:r,mediaType:t,sizeBytes:e.byteLength,filename:s,refCount:1,remoteIds:{},createdAt:n,lastUsedAt:n};"function"==typeof this.storage.registerBlob?await this.storage.registerBlob(o,e):(await this.storage.storeBytes(r,e),await this.storage.saveRecord(o)),this.recordCache.set(r,o),this.onRegistryChanged?.(r,o)}const i=this.recordCache.get(r);return f({sha256:r,mediaType:t,sizeBytes:i.sizeBytes,filename:i.filename,previewUrl:i.previewUrl})}catch(e){return m({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return m({code:"NOT_FOUND",resource:"blob",id:e});const s={...t,refCount:t.refCount+1,lastUsedAt:(new Date).toISOString()};return await this.storage.saveRecord(s),this.recordCache.set(e,s),this.onRegistryChanged?.(e,s),f(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return m({code:"NOT_FOUND",resource:"blob",id:e});const s=Math.max(0,t.refCount-1),r={...t,refCount:s,lastUsedAt:(new Date).toISOString()};return 0===s&&this.config.eagerEviction?(await this.storage.deleteBytes(e),await this.storage.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null)):(await this.storage.saveRecord(r),this.recordCache.set(e,r),this.onRegistryChanged?.(e,r)),f(void 0)}async recordRemoteId(e,t,s){const r=this.recordCache.get(e);if(!r)return m({code:"NOT_FOUND",resource:"blob",id:e});if(r.remoteIds[t]===s)return f(void 0);const n={...r,remoteIds:{...r.remoteIds,[t]:s}};return await this.storage.saveRecord(n),this.recordCache.set(e,n),f(void 0)}getRemoteId(e,t){return this.recordCache.get(e)?.remoteIds[t]??null}async resolveRef(e,t){try{if(t){const s=this.getRemoteId(e.sha256,t);if(s)return f({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.storage.loadBytes(e.sha256);return s?f({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):m({code:"BLOB_ERROR",reason:`Blob bytes not found locally for sha256=${e.sha256}. The blob may have been evicted. Re-register it before resolving.`})}catch(e){return m({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async resolveRefs(e,t){const s=function(e){const t=new Set,s=[];for(const r of e)t.has(r.sha256)||(t.add(r.sha256),s.push(r));return s}(e),r=await Promise.all(s.map((async e=>({ref:e,result:await this.resolveRef(e,t)})))),n=new Map,o=[];for(const{ref:e,result:t}of r)t.ok?n.set(e.sha256,t.value):o.push({ref:e,error:t.error});return{resolved:n,errors:o}}async gc(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((e=>this.storage.deleteBytes(e.sha256)))),e.length}async gcFull(){const e=Array.from(this.recordCache.values()).filter((e=>0===e.refCount));return await Promise.all(e.map((async e=>{await this.storage.deleteBytes(e.sha256),await this.storage.deleteRecord(e.sha256),this.recordCache.delete(e.sha256),this.onRegistryChanged?.(e.sha256,null)}))),e.length}async purge(e){return this.recordCache.has(e)?(await this.storage.deleteBytes(e),await this.storage.deleteRecord(e),this.recordCache.delete(e),this.onRegistryChanged?.(e,null),f(void 0)):m({code:"NOT_FOUND",resource:"blob",id:e})}getRecord(e){return this.recordCache.get(e)??null}getAllRecords(){const e={};for(const[t,s]of this.recordCache)e[t]=s;return e}};var R=10,P=50,_=20,U=3,F=class{map=new Map;max;constructor(e){this.max=e}get(e){if(!this.map.has(e))return;const t=this.map.get(e);return this.map.delete(e),this.map.set(e,t),t}set(e,t){if(this.map.has(e)&&this.map.delete(e),this.map.set(e,t),this.map.size>this.max){const e=this.map.keys().next().value;void 0!==e&&this.map.delete(e)}}has(e){return this.map.has(e)}delete(e){this.map.delete(e)}},A=class{roles;preferences;contexts;pinnedRoles=new Map;pinnedPreferences=new Map;pinnedContexts=new Map;constructor(e){this.roles=new F(e.roles),this.preferences=new F(e.preferences),this.contexts=new F(e.context)}getRole(e){return this.pinnedRoles.get(e)??this.roles.get(e)}setRole(e,t=!1){t?(this.pinnedRoles.set(e.name,e),this.roles.delete(e.name)):this.pinnedRoles.has(e.name)?this.pinnedRoles.set(e.name,e):this.roles.set(e.name,e)}deleteRole(e){this.pinnedRoles.delete(e),this.roles.delete(e)}getPreference(e){return this.pinnedPreferences.get(e)??this.preferences.get(e)}setPreference(e,t=!1){t?(this.pinnedPreferences.set(e.id,e),this.preferences.delete(e.id)):this.pinnedPreferences.has(e.id)?this.pinnedPreferences.set(e.id,e):this.preferences.set(e.id,e)}unpinPreference(e){const t=this.pinnedPreferences.get(e);t&&(this.pinnedPreferences.delete(e),this.preferences.set(e,t))}deletePreference(e){this.pinnedPreferences.delete(e),this.preferences.delete(e)}getContext(e){return this.pinnedContexts.get(e)??this.contexts.get(e)}setContext(e,t=!1){t?(this.pinnedContexts.set(e.key,e),this.contexts.delete(e.key)):this.contexts.set(e.key,e)}invalidateContext(e){this.contexts.delete(e),this.pinnedContexts.delete(e)}};var E=class{storage;tree;cache;constructor(e,t={}){this.storage=e,this.tree=new I(e);const s={roles:t.cache?.roles??R,preferences:t.cache?.preferences??P,context:t.cache?.context??_,transcriptWindows:t.cache?.transcriptWindows??U};this.cache=new A(s)}getTurnTree(){return this.tree}async getRole(e){const t=this.cache.getRole(e);if(t)return f(t);const s=await this.storage.loadRole(e);return s?(this.cache.setRole(s),f(s)):m({code:"NOT_FOUND",resource:"role",id:e})}async getPreference(e){const t=this.cache.getPreference(e);if(t)return f(t);const s=await this.storage.loadPreference(e);return s?(this.cache.setPreference(s),f(s)):m({code:"NOT_FOUND",resource:"preference",id:e})}async getContext(e){const t=this.cache.getContext(e);if(t)return f(t);const s=await this.storage.loadContext(e);return s?(this.cache.setContext(s),f(s)):m({code:"NOT_FOUND",resource:"context",id:e})}async getContextByTopics(e,t){const s=new Set;for(const r of t){const t=e.topics[r];t&&t.contextKeys.forEach((e=>s.add(e)))}if(0===s.size)return[];const r=[],n=[];for(const e of s){const t=this.cache.getContext(e);t?n.push(t):r.push(e)}let o=[];if(r.length>0){const e=await this.storage.loadContextBatch(r);for(const[t,s]of e)this.cache.setContext(s),o.push(s)}return[...n,...o].sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async saveRole(e){await this.storage.saveRole(e),this.cache.setRole(e)}async savePreference(e){await this.storage.savePreference(e),this.cache.setPreference(e)}async saveContext(e){await this.storage.saveContext(e),this.cache.setContext(e)}async deleteRole(e){await this.storage.deleteRole(e),this.cache.deleteRole(e)}async deletePreference(e){await this.storage.deletePreference(e),this.cache.deletePreference(e)}async deleteContext(e){await this.storage.deleteContext(e),this.cache.invalidateContext(e)}async recordTurn(e,t){return await this.tree.append(e,t),f(void 0)}async editTurn(e,t,s,r,n){const o=await this.storage.loadTurn(e,t,r-1);if(!o)return m({code:"NOT_FOUND",resource:"turn",id:t});const i={id:t,version:r,role:o.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:n??o.roleSnapshot,parent:o.parent};await this.tree.replaceVersion(e,i);const a=await this.tree.getHead(e);return a?.id===t&&await this.tree.setHead(e,{id:i.id,version:i.version}),f(void 0)}async branchTurn(e,t){return await this.tree.branch(e,t),f(void 0)}async deleteTurnSubtree(e,t,s,r){return await this.tree.deleteSubtree(e,t,s,r),f(void 0)}async copyTranscript(e,t){await this.tree.copyTranscript(e,t)}async storeBytes(e,t){await this.storage.storeBytes(e,t)}async loadBytes(e){return this.storage.loadBytes(e)}async deleteBytes(e){await this.storage.deleteBytes(e)}async resolveSession(e,t,s){const r=e.index.sessions[t];if(!r)return m({code:"NOT_FOUND",resource:"session",id:t});const n=await this.getRole(r.role);if(!n.ok)return n;const o=n.value,i=function(e,t){return e.preferences.length>0?e.preferences:t.preferences}(r,o),a={session:r,role:o,preferences:function(e,t){return e.filter((e=>0===e.topics.length||e.topics.some((e=>t.includes(e)))))}((await Promise.all(i.map((e=>this.getPreference(e))))).filter((e=>e.ok)).map((e=>e.value)),r.topics),context:await this.getContextByTopics(e.index,r.topics),transcript:s??await this.tree.getActiveChain(t),instructions:e.settings?.prompt};return f({...a,preferences:Object.freeze([...a.preferences]),context:Object.freeze([...a.context]),transcript:Object.freeze([...a.transcript])})}};function M({index:e},t){switch(t.type){case"workspace:create":return f({...t.payload,index:{format:"aiworkspace/4.0",roles:{},preferences:{},context:{},sessions:{},topics:{}}});case"role:add":{const s=t.payload;if(e.roles[s.name])return m({code:"DUPLICATE_KEY",resource:"role",key:s.name});const r={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return f({index:{roles:{[s.name]:r}}})}case"preference:add":{const s=t.payload,r={id:s.id,topics:s.topics,timestamp:s.timestamp,snippet:s.content.substring(0,100)},n={};return s.topics.forEach((r=>{const o=e.topics[r];n[r]={topic:r,contextKeys:o?.contextKeys||[],preferences:[...o?.preferences||[],s.id],metadata:{created:o?.metadata?.created||t.timestamp,updated:t.timestamp,entries:o?.metadata?.entries||0}}})),f({index:{preferences:{[s.id]:r},topics:n}})}case"context:add":{const s=t.payload;if(e.context[s.key])return m({code:"DUPLICATE_KEY",resource:"context",key:s.key});const r={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"text"==s.content.kind?s.content.value.substring(0,200):"json"===s.content.kind?JSON.stringify(s.content.value).substring(0,200):void 0,metadata:s.metadata},n={};return s.topics.forEach((r=>{const o=e.topics[r],i=o?.contextKeys||[],a=i.includes(s.key)?i:[...i,s.key];n[r]={topic:r,contextKeys:a,metadata:{updated:t.timestamp,entries:a.length}}})),f({index:{context:{[s.key]:r},topics:n}})}case"session:create":{const{id:s,label:r,role:n,topics:o,preferences:i=[]}=t.payload;if(e.sessions[s])return m({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[n])return m({code:"NOT_FOUND",resource:"role",id:n});const a={id:s,label:r,role:n,topics:o,preferences:i,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null};return f({index:{sessions:{[s]:a}}})}case"turn:add":{const{sessionId:s,turn:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp},flushedTurnCount:(e.sessions[s]?.flushedTurnCount??0)+1}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:r,newVersion:n}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r,version:n},metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{head:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:role:switch":{const{sessionId:s,role:r}=t.payload;return e.sessions[s]?e.roles[r]?f({index:{sessions:{[s]:{role:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"role",id:r}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:r}=t.payload,n=e.sessions[s];if(!n)return m({code:"NOT_FOUND",resource:"session",id:s});const o=Array.from(new Set([...n.topics,...r]));return f({index:{sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:r}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:{preferences:r,metadata:{updated:t.timestamp}}}}}):m({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload,a=e.sessions[s];if(!a)return m({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[r])return m({code:"DUPLICATE_KEY",resource:"session",key:r});const c=o??a.role;if(!e.roles[c])return m({code:"NOT_FOUND",resource:"role",id:c});const d={id:r,label:n,role:c,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head};return f({index:{sessions:{[r]:d}}})}case"role:update":{const{name:s,...r}=t.payload;if(!e.roles[s])return m({code:"NOT_FOUND",resource:"role",id:s});const n=e.roles[s],o={...n,...r,preferences:r.preferences?.length??n.preferences};return f({index:{roles:{[s]:o}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return m({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?m({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):f({index:{roles:{[s]:u()}}})}case"preference:update":{const{id:s,...r}=t.payload;if(!e.preferences[s])return m({code:"NOT_FOUND",resource:"preference",id:s});const n=e.preferences[s],o={...n,...r,snippet:r.content?r.content.substring(0,100):n.snippet},i={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(i[t]={preferences:r.preferences.filter((e=>e!==s))})})),r.topics.forEach((r=>{const n=e.topics[r]||{topic:r,contextKeys:[],preferences:[],metadata:{created:t.timestamp,updated:t.timestamp,entries:0}};i[r]={...n,preferences:[...new Set([...n.preferences,s])],metadata:{updated:t.timestamp}}}))),f({index:{preferences:{[s]:o},topics:i}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return m({code:"NOT_FOUND",resource:"preference",id:s});const r=e.preferences[s],n={};return r.topics.forEach((t=>{const r=e.topics[t];r&&(n[t]={preferences:r.preferences.filter((e=>e!==s))})})),f({index:{preferences:{[s]:u()},topics:n}})}case"context:update":{const{key:s,...r}=t.payload;if(!e.context[s])return m({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],o={...n,...r,preview:r.content?"text"===r.content.kind?r.content.value.substring(0,200):"json"===r.content.kind?JSON.stringify(r.content.value).substring(0,200):void 0:n.preview},i={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(i[t]={contextKeys:r.contextKeys.filter((e=>e!==s))})})),r.topics.forEach((r=>{const n=e.topics[r]||{contextKeys:[]},o=n.contextKeys.includes(s)?n.contextKeys:[...n.contextKeys,s];i[r]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),f({index:{context:{[s]:o},topics:i}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return m({code:"NOT_FOUND",resource:"context",id:s});const r=e.context[s],n={};return r.topics.forEach((r=>{const o=e.topics[r];o&&(n[r]={contextKeys:o.contextKeys.filter((e=>e!==s)),metadata:{updated:t.timestamp,entries:o.contextKeys.length-1}})})),f({index:{context:{[s]:u()},topics:n}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?f({index:{sessions:{[s]:u()}}}):m({code:"NOT_FOUND",resource:"session",id:s})}default:return f({})}}var $=class{contentStore;constructor(e){this.contentStore=e}reduce(e,t){return M(e,t)}async dispatch(e,t){const s=M(e,t);if(!s.ok)return s;try{await this.handleContentSideEffects(t)}catch(e){return m({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return s}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async handleContentSideEffects(e){switch(e.type){case"role:add":await this.contentStore.saveRole(e.payload);break;case"role:update":{const{name:t,...s}=e.payload,r=await this.contentStore.getRole(t);if(!r.ok)throw new Error(`role:update — role "${t}" not found in backend`);const n={...r.value,...s,name:t};await this.contentStore.saveRole(n);break}case"role:delete":await this.contentStore.deleteRole(e.payload.name);break;case"preference:add":await this.contentStore.savePreference(e.payload);break;case"preference:update":{const{id:t,...s}=e.payload,r=await this.contentStore.getPreference(t);if(!r.ok)throw new Error(`preference:update — preference "${t}" not found in backend`);const n={...r.value,...s,id:t};await this.contentStore.savePreference(n);break}case"preference:delete":await this.contentStore.deletePreference(e.payload.id);break;case"context:add":case"context:update":await this.contentStore.saveContext(e.payload);break;case"context:delete":await this.contentStore.deleteContext(e.payload.key);break;case"turn:add":{const{sessionId:t,turn:s}=e.payload;await this.contentStore.recordTurn(t,s);break}case"turn:edit":{const{sessionId:t,turnId:s,newBlocks:r,newVersion:n,roleSnapshot:o}=e.payload;await this.contentStore.editTurn(t,s,r,n,o);break}case"turn:branch":{const{sessionId:t,newTurn:s}=e.payload;await this.contentStore.branchTurn(t,s);break}case"turn:delete":{const{sessionId:t,turnId:s,version:r,newHead:n}=e.payload;await this.contentStore.deleteTurnSubtree(t,s,r,n);break}case"session:fork":{const{sourceSessionId:t,newSessionId:s}=e.payload;await this.contentStore.copyTranscript(t,s);break}}}};function V(e){return Math.ceil(e.length/4)}function z(e,t){return Math.ceil(e/1024*t)}function H(e){if("text"===e.kind)return e.value;if("json"===e.kind){const t=[],s=e=>{"string"==typeof e?t.push(e):e&&"object"==typeof e&&Object.values(e).forEach(s)};return s(e.value),t.join(" ")}return""}function K(e,t){return{id:crypto.randomUUID(),version:0,role:e,blocks:t,timestamp:(new Date).toISOString(),parent:null}}var L=class{rank(e){const{entries:t,recentMessages:s,config:r}=e,n=r.recentMessageWindow??3,o=r.minScore??0,i=r.freshnessHalfLifeDays??30;if(0===s.length)return[...t].sort(((e,t)=>this.freshnessWeight(t.timestamp,i)-this.freshnessWeight(e.timestamp,i)));const a=this.tokenize(s.slice(-n).join(" "));return t.map((e=>{const t=H(e.content);return{entry:e,score:.7*this.jaccardSimilarity(a,this.tokenize(t))+.3*this.freshnessWeight(e.timestamp,i)}})).filter((e=>e.score>o)).sort(((e,t)=>t.score-e.score)).map((e=>e.entry))}tokenize(e){return new Set(e.toLowerCase().replace(/[^\w\s]/g," ").split(/\s+/).filter((e=>e.length>2)))}jaccardSimilarity(e,t){if(0===e.size&&0===t.size)return 0;let s=0;for(const r of e)t.has(r)&&s++;const r=e.size+t.size-s;return 0===r?0:s/r}freshnessWeight(e,t){const s=(Date.now()-new Date(e).getTime())/864e5;return Math.pow(.5,s/t)}},W=class{plan(e){const{systemInstructions:t,persona:s,preferences:r,context:n,transcript:o,budget:i}=e;if(!i)return{preferences:r,context:n,transcript:o,truncated:{preferences:0,interactions:0,context:0},breakdown:{system:0,persona:0,preferences:0,transcript:0,context:0},totalUsed:0,lastRoleBeforeTruncation:null};const a=i.estimator??V,c=i.blobTokensPerKB??.25;let d=i.total;const l={system:0,persona:0,preferences:0,transcript:0,context:0},h=a(t??""),u=a(s);d-=h+u,l.system+=h,l.persona+=u;const p=[];let f=0;for(const e of r){const t=a(e.content);d>=t?(d-=t,l.preferences+=t,p.push(e)):f++}const m=[];let y=0,g=null;for(let e=o.length-1;e>=0;e--){const t=o[e],s=this.estimateTurnTokens(t,a,c);d>=s?(d-=s,l.transcript+=s,m.unshift(t)):(y++,"user"!==t.role||g||(g=t.roleSnapshot??null))}const b=[];let w=0;for(const e of n){let t=a(H(e.content));"blob"===e.content.kind&&(t+=z(e.content.sizeBytes,c)),d>=t?(d-=t,l.context+=t,b.push(e)):w++}return{preferences:p,context:b,transcript:m,truncated:{preferences:f,interactions:y,context:w},breakdown:l,totalUsed:i.total-Math.max(0,d),lastRoleBeforeTruncation:g}}estimateTurnTokens(e,t,s){return e.blocks.reduce(((e,r)=>{switch(r.type){case"text":return e+t(r.text);case"tool_use":return e+t(JSON.stringify(r.input));case"tool_result":return e+t("string"==typeof r.content?r.content:JSON.stringify(r.content));case"thinking":return e+t(r.thinking);case"image":case"document":{const t=r.ref;return t?e+z(t.sizeBytes,s):e}default:return e}}),0)}},J=class{assemble(e){const{session:t,plan:s,resolvedBlobs:r,summaryBlockText:n,warnings:o,conflicts:i,budgetTotal:a}=e,c=[],d=[];for(const e of s.context)if("text"===e.content.kind||"json"===e.content.kind)c.push(e);else if("blob"===e.content.kind){const t=r.get(e.content.sha256);t&&d.push(this.buildReferentialBlock(e.content,t))}const l=[];if(d.length>0&&l.push(K("user",d)),n||s.truncated.interactions>0){const e=[];n&&e.push({type:"summary",text:n}),s.truncated.interactions>0&&e.push({type:"text",text:`[${s.truncated.interactions} earlier turn(s) omitted due to token budget]`}),l.push(K("user",e)),l.push(K("assistant",[{type:"text",text:"Understood."}]))}let h=s.lastRoleBeforeTruncation,u=null!==s.lastRoleBeforeTruncation;for(const e of s.transcript){const t=this.resolveTurnBlocks(e,r);"user"===e.role&&e.roleSnapshot&&u&&e.roleSnapshot!==h&&t.unshift({type:"role_transition",previousRole:h,newRole:e.roleSnapshot}),"user"===e.role&&(h=e.roleSnapshot??null,u=!0),l.push({...e,blocks:t})}return{system:{instructions:t.instructions,persona:t.role.persona,preferences:s.preferences,context:c},context:s.context,transcript:{turns:l},budget:{total:a,used:s.totalUsed,breakdown:s.breakdown},truncated:s.truncated,warnings:o,conflicts:i}}buildReferentialBlock(e,t){return e.mediaType.startsWith("image/")?{type:"image",blob:t}:{type:"document",blob:t,title:e.filename}}resolveTurnBlocks(e,t){return e.blocks.map((e=>{if("image"===e.type||"document"===e.type){const s=e.ref;if(s){const r=t.get(s.sha256);if(r)return{...e,blob:r}}}return e}))}},Y=class{retriever;planner;assembler;summarizer;blobResolver;constructor(e){this.blobResolver=e.blobResolver,this.retriever=e.retriever??new L,this.planner=e.planner??new W,this.assembler=e.assembler??new J,this.summarizer=e.summarizer}async build(e,t={}){const s=[],{resolved:r,conflicts:n}=this.resolvePreferenceConflicts(e.preferences);n.length>0&&s.push(`${n.length} preference conflict(s) resolved.`);const o=this.extractRecentUserQueries(e.transcript,t.relevanceConfig),i=this.retriever.rank({entries:e.context,recentMessages:o,config:t.relevanceConfig??{}});let a=e.transcript,c=null;if(this.summarizer&&a.length>0){const e=t.tokenBudget?Math.floor(.25*t.tokenBudget.total):2e3,s=await this.summarizer.summarize(a,e);c=s.summary,a=s.remaining}const d=this.planner.plan({systemInstructions:e.instructions,persona:e.role.persona,preferences:r,context:i,transcript:a,budget:t.tokenBudget}),l=this.collectUsedBlobRefs(d.context,d.transcript),h=this.deduplicateBlobRefs(l),{resolved:u,errors:p}=await this.blobResolver(h,t.providerId??null);for(const e of p)s.push(`Failed to resolve blob ${e.ref.sha256.slice(0,8)}: ${e.error.code}`);const f=h.filter((e=>!u.has(e.sha256)));return f.length>0&&s.push(`${f.length} blob(s) unresolved and omitted: `+f.map((e=>e.sha256.slice(0,8))).join(", ")),d.truncated.preferences>0&&s.push(`${d.truncated.preferences} preference(s) dropped.`),d.truncated.interactions>0&&s.push(`${d.truncated.interactions} turn(s) trimmed.`),d.truncated.context>0&&s.push(`${d.truncated.context} context entry/entries dropped.`),this.assembler.assemble({session:e,plan:d,resolvedBlobs:u,summaryBlockText:c,warnings:s,conflicts:n,budgetTotal:t.tokenBudget?.total??0})}collectUsedBlobRefs(e,t){const s=[];for(const t of e)"blob"===t.content.kind&&s.push(t.content);for(const e of t)for(const t of e.blocks)if("image"===t.type||"document"===t.type){const e=t.ref;e&&s.push(e)}return s}deduplicateBlobRefs(e){const t=new Set,s=[];for(const r of e)t.has(r.sha256)||(t.add(r.sha256),s.push(r));return s}extractRecentUserQueries(e,t){const s=t?.recentMessageWindow??3;return e.filter((e=>"user"===e.role)).slice(-s).flatMap((e=>e.blocks.filter((e=>"text"===e.type)).map((e=>e.text))))}resolvePreferenceConflicts(e){const t=[],s=new Map;for(const r of e)if(0!==r.topics.length)for(const e of r.topics){const n=s.get(e);if(!n){s.set(e,r);continue}const o=new Date(n.timestamp).getTime(),i=new Date(r.timestamp).getTime();i>o?(t.push({topic:e,kept:r.id,dropped:n.id,reason:"superseded_by_newer"}),s.set(e,r)):o>i&&t.push({topic:e,kept:n.id,dropped:r.id,reason:"superseded_by_newer"})}const r=new Set(t.map((e=>e.dropped)));return{resolved:e.filter((e=>!r.has(e.id))),conflicts:Array.from(new Set(t))}}},G={maxBufferSize:10,flushIntervalMs:3e4},Q=class{sessionId;nodes;head;dirtyBuffer=[];flushTimer=null;flushChain=Promise.resolve();flushConfig;tree;contentStore;constructor(e,t,s,r,n,o=G){this.sessionId=e,this.nodes=t,this.head=s,this.tree=r,this.contentStore=n,this.flushConfig=o}activeChain(){if(!this.head)return[];const e=[];let t=this.head.id;for(;null!==t;){const s=this.nodes[t];if(!s)break;e.push(s),t=s.parent?.id??null}return e.reverse()}siblings(e){const t=this.nodes[e];if(!t)return[];if(!t.parent)return Object.values(this.nodes).filter((e=>null===e.parent));const s=this.nodes[t.parent.id];if(!s)return[t];const r=t.parent.version,n=s.children[r];return n?n.map((e=>this.nodes[e])).filter((e=>void 0!==e)):[t]}branchInfo(e){const t=this.nodes[e];if(!t)return{versions:[],currentIndex:-1,total:0,hasPrev:!1,hasNext:!1};const s=Object.keys(t.versions).map(Number).sort(((e,t)=>e-t)),r=s.indexOf(t.activeVersion);return{versions:s,currentIndex:r,total:s.length,hasPrev:r>0,hasNext:r<s.length-1}}async addTurn(e,t){const s=e.index.sessions[this.sessionId];if(!s)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const r={...t,version:t.version??0,parent:null!==t.parent?t.parent:null!==this.head?{id:this.head.id,version:this.head.version}:null};return this.upsertNode(r),this.head={id:r.id,version:r.version},this.dirtyBuffer.push(r),this.scheduleFlush(),this.dirtyBuffer.length>=this.flushConfig.maxBufferSize&&await this.flush(),f({index:{sessions:{[this.sessionId]:{head:{id:r.id,version:r.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:r.timestamp}}}}})}async editTurn(e,t,s,r){if(!e.index.sessions[this.sessionId])return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const n=this.nodes[t];if(!n)return m({code:"NOT_FOUND",resource:"turn",id:t});const o=n.activeVersion+1,i={id:t,version:o,role:n.role,blocks:s,timestamp:(new Date).toISOString(),roleSnapshot:r??n.roleSnapshot,parent:n.parent};n.versions[o]=i,n.activeVersion=o,n.blocks=s,n.timestamp=i.timestamp,void 0!==r&&(n.roleSnapshot=r),n.children[o]||(n.children[o]=[]);const a={id:t,version:o};return this.head=a,await this.tree.replaceVersion(this.sessionId,i),await this.tree.setHead(this.sessionId,a),f({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:i.timestamp}}}}})}async branchFrom(e,t){const s=e.index.sessions[this.sessionId];if(!s)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});if(!t.parent)return m({code:"INVALID_COMMAND",reason:"branchFrom requires newTurn.parent to be set"});return this.nodes[t.parent.id]?(this.upsertNode(t),this.head={id:t.id,version:t.version},await this.tree.branch(this.sessionId,t),f({index:{sessions:{[this.sessionId]:{head:{id:t.id,version:t.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:t.timestamp}}}}})):m({code:"NOT_FOUND",resource:"turn",id:t.parent.id})}async deleteTurn(e,t,s,r){const n=e.index.sessions[this.sessionId];if(!n)return m({code:"NOT_FOUND",resource:"session",id:this.sessionId});const o=this.nodes[t];if(!o)return m({code:"NOT_FOUND",resource:"turn",id:t});const i=this.collectSubtreeIds(t);if(o.parent){const e=this.nodes[o.parent.id];if(e){const s=o.parent.version,r=e.children[s];r&&(e.children[s]=r.filter((e=>e!==t)))}}for(const e of i)delete this.nodes[e];this.head=r,await this.tree.deleteSubtree(this.sessionId,t,s,r);const a=(new Date).toISOString();return f({index:{sessions:{[this.sessionId]:{head:r,flushedTurnCount:Math.max(0,n.flushedTurnCount-i.size),metadata:{updated:a}}}}})}switchVersionLeft(e,t){return this.switchVersion(t,-1)}switchVersionRight(e,t){return this.switchVersion(t,1)}switchVersion(e,t){const s=this.nodes[e];if(!s)return m({code:"NOT_FOUND",resource:"turn",id:e});const r=Object.keys(s.versions).map(Number).sort(((e,t)=>e-t)),n=r.indexOf(s.activeVersion);if(-1===n)return m({code:"INVALID_COMMAND",reason:"Current version not found"});const o=n+t;if(o<0||o>=r.length)return m({code:"INVALID_COMMAND",reason:`No ${t<0?"previous":"next"} version available for turn ${e}`});const i=r[o];s.activeVersion=i,s.blocks=s.versions[i].blocks,s.timestamp=s.versions[i].timestamp,s.versions[i].roleSnapshot&&(s.roleSnapshot=s.versions[i].roleSnapshot);const a=this.findSubtreeTipForVersion(e,i);this.head=a;const c=(new Date).toISOString();return f({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:c}}}}})}async resolve(e){return e.index.sessions[this.sessionId]?this.contentStore.resolveSession(e,this.sessionId,this.activeChain().map((e=>e.versions[e.activeVersion]))):m({code:"NOT_FOUND",resource:"session",id:this.sessionId})}async flush(){return this.flushChain=this.flushChain.then((()=>this.doFlush())),this.flushChain}async dispose(){this.cancelFlushTimer(),await this.flush()}findSubtreeTipForVersion(e,t){let s=e,r=t;for(;;){const e=this.nodes[s];if(!e)break;const t=e.children[r];if(!t||0===t.length)break;s=t[0],r=this.nodes[s]?.activeVersion??0}return{id:s,version:r}}collectSubtreeIds(e){const t=new Set,s=[e];for(;s.length>0;){const e=s.pop();t.add(e);const r=this.nodes[e];if(r&&r.children)for(const e of Object.keys(r.children)){const n=r.children[Number(e)];if(n)for(const e of n)t.has(e)||s.push(e)}}return t}upsertNode(e){const t=e.id,s=e.version;if(this.nodes[t]){const r=this.nodes[t];r.versions[s]=e,s>=r.activeVersion&&(r.activeVersion=s,r.blocks=e.blocks,r.timestamp=e.timestamp,void 0!==e.roleSnapshot&&(r.roleSnapshot=e.roleSnapshot)),r.children[s]||(r.children[s]=[])}else this.nodes[t]={id:t,versions:{[s]:e},activeVersion:s,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{[s]:[]}};if(e.parent){const s=this.nodes[e.parent.id];if(s){const r=e.parent.version;s.children[r]||(s.children[r]=[]),s.children[r].includes(t)||s.children[r].push(t)}}}scheduleFlush(){null===this.flushTimer&&(this.flushTimer=setTimeout((()=>{this.flushTimer=null,this.flushChain=this.flushChain.then((()=>this.doFlush()))}),this.flushConfig.flushIntervalMs))}cancelFlushTimer(){null!==this.flushTimer&&(clearTimeout(this.flushTimer),this.flushTimer=null)}async doFlush(){if(0===this.dirtyBuffer.length)return;const e=this.dirtyBuffer.splice(0,this.dirtyBuffer.length);try{await this.tree.appendBatch(this.sessionId,e),0===this.dirtyBuffer.length&&this.cancelFlushTimer()}catch(t){throw this.dirtyBuffer.unshift(...e),this.flushChain=Promise.resolve(),t}}};function q(e,t=[]){return{id:e.id,versions:{[e.version]:e},activeVersion:e.version,role:e.role,blocks:e.blocks,timestamp:e.timestamp,roleSnapshot:e.roleSnapshot,parent:e.parent,children:{[e.version]:[...t]}}}var X=10,Z=3e4,ee=class{workspaceManager;contentStore;flushConfig;constructor(e,t,s={}){this.workspaceManager=e,this.contentStore=t,this.flushConfig={maxBufferSize:s.flush?.maxBufferSize??X,flushIntervalMs:s.flush?.flushIntervalMs??Z}}async open(e,t){const s=e.index.sessions[t];if(!s)return m({code:"NOT_FOUND",resource:"session",id:t});const r=this.contentStore.getTurnTree();try{const e=await r.buildNodeGraph(t);return f({session:new Q(t,e,s.head,r,this.contentStore,this.flushConfig),patch:{}})}catch(e){return m({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}}async close(e){await e.dispose()}get workspace(){return this.workspaceManager}};export{D as BlobStore,E as ContentStore,C as IndexedDBStorage,Y as PromptBuilder,Q as Session,ee as SessionManager,I as TurnTree,$ as WorkspaceManager,q as buildTurnNode,B as computeSHA256,u as del,m as err,p as merge,f as ok,M as workspaceReducer};
package/package.json CHANGED
@@ -1,10 +1,24 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-workspace",
3
- "version": "1.0.0",
4
- "description": "A collection of workspace utilities.",
3
+ "version": "2.0.0",
4
+ "description": "Content-addressed workspace and conversation management for AI applications.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
7
7
  "types": "index.d.ts",
8
+ "keywords": [
9
+ "typescript",
10
+ "utility"
11
+ ],
12
+ "author": "Saidimu <47994458+asaidimu@users.noreply.github.com>",
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/asaidimu/erp-utils.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/asaidimu/erp-utils/issues"
20
+ },
21
+ "homepage": "https://github.com/asaidimu/erp-utils/tree/main/src/workspace#readme",
8
22
  "files": [
9
23
  "./*"
10
24
  ],