@asaidimu/utils-workspace 1.0.1 → 2.1.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/README.md +274 -322
- package/index.d.mts +938 -426
- package/index.d.ts +938 -426
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +5 -1
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=require("uuid"),r=Object.create,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,d=(e,t,s)=>(s=null!=e?r(a(e)):{},((e,t,s,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let a of i(t))c.call(e,a)||a===s||n(e,a,{get:()=>t[a],enumerable:!(r=o(t,a))||r.enumerable});return e})(e&&e.__esModule?s:n(s,"default",{value:e,enumerable:!0}),e)),l=(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)}})(),u=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),u(e),()=>{r.delete(s),0===r.size?(t.delete(e),i.delete(e)):u(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[i(e)[0]])((t={exports:{}}).exports,t),t.exports}),u=[{name:"role",version:"1.0.0",description:"AI persona with a system prompt and associated preference defaults.",fields:{name:{name:"name",type:"string",required:!0},label:{name:"label",type:"string",required:!0},description:{name:"description",type:"string",required:!1},persona:{name:"persona",type:"string",required:!0},preferences:{name:"preferences",type:"array",required:!1,itemsType:"string"}},indexes:[{name:"by_name",fields:["name"],type:"unique"},{name:"by_label",fields:["label"],type:"normal"}],constraints:[],migrations:[]},{name:"preference",version:"1.0.0",description:"A user behavioural instruction, scoped to zero or more topics.",fields:{id:{name:"id",type:"string",required:!0},content:{name:"content",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},timestamp:{name:"timestamp",type:"string",required:!0}},indexes:[{name:"by_id",fields:["id"],type:"unique"},{name:"by_topics",fields:["topics"],type:"normal"},{name:"by_timestamp",fields:["timestamp"],type:"btree"}],constraints:[],migrations:[]},{name:"context",version:"1.0.0",description:"Injected background knowledge, scoped to topics. Content is a discriminated union.",fields:{key:{name:"key",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},content:{name:"content",type:"record",required:!0},timestamp:{name:"timestamp",type:"string",required:!0},metadata:{name:"metadata",type:"record",required:!1}},indexes:[{name:"by_key",fields:["key"],type:"unique"},{name:"by_topics",fields:["topics"],type:"normal"},{name:"by_timestamp",fields:["timestamp"],type:"btree"}],constraints:[],migrations:[]},{name:"session",version:"1.0.0",description:"Session metadata. The head field tracks the current tip of the turn DAG.",fields:{id:{name:"id",type:"string",required:!0},label:{name:"label",type:"string",required:!0},role:{name:"role",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},preferences:{name:"preferences",type:"array",required:!1,itemsType:"string"},metadata:{name:"metadata",type:"record",required:!1},flushedTurnCount:{name:"flushedTurnCount",type:"number",required:!0},head:{name:"head",type:"record",required:!1}},indexes:[{name:"by_id",fields:["id"],type:"unique"},{name:"by_role",fields:["role"],type:"normal"}],constraints:[],migrations:[]},{name:"turn",version:"1.0.0",description:["A single message in a session transcript, stored as a flat document.","The DAG is reconstructed in memory by TurnTree.buildNodeGraph() at session open time.","$id is a composite key: `${sessionId}:${id}:${version}`."].join(" "),fields:{id:{name:"id",type:"string",required:!0},sessionId:{name:"sessionId",type:"string",required:!0},version:{name:"version",type:"number",required:!0},role:{name:"role",type:"enum",required:!0,values:["user","assistant","tool"]},blocks:{name:"blocks",type:"array",required:!0},timestamp:{name:"timestamp",type:"string",required:!0},roleSnapshot:{name:"roleSnapshot",type:"string",required:!1},parent:{name:"parent",type:"record",required:!1}},indexes:[{name:"by_session",fields:["sessionId"],type:"normal"},{name:"by_session_parent",fields:["sessionId","parent"],type:"composite"},{name:"by_session_id_ver",fields:["sessionId","id","version"],type:"composite",unique:!0}],constraints:[],migrations:[]}];var h={ROLE:"role",PREFERENCE:"preference",CONTEXT:"context",SESSION:"session",TURN:"turn"};d(l());var p=Symbol.for("delete"),f=e=>Array.isArray(e)?[...e]:{...e};function m(){return p}d(l()),d(l()),d(l()),d(l()),d(l()),d(l());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 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=f(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]=f(t),o.push({target:e[r],source:n})}else e[r]=n;else delete e[r]}}return n}}({deleteMarker:p});function b(e){return{ok:!0,value:e}}function g(e){return{ok:!1,error:e}}function w(e){return Object.fromEntries(Object.entries(e).filter((([e,t])=>null!=t)))}var v=class{db;constructor(e){this.db=e}async turns(){return this.db.collection(h.TURN)}async sessions(){return this.db.collection(h.SESSION)}turnFilter(e,t,s){return{operator:"and",conditions:[{field:"sessionId",operator:"eq",value:e},{field:"id",operator:"eq",value:t},{field:"version",operator:"eq",value:s}]}}async getHead(e){const t=await this.sessions(),s=await t.find({field:"id",operator:"eq",value:e});return s?.head??null}async setHead(e,t){const s=await this.sessions(),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return;const n={...r.state(),head:t??void 0};await r.update(n)}async append(e,t){const s=await this.getHead(e),r={...t,sessionId:e,version:t.version??0,parent:t.parent?t.parent:s?{id:s.id,version:s.version}:null},n=await this.turns();return await n.create(w(r)),r}async appendBatch(e,t,s){if(0!==t.length){for(const s of t)await this.append(e,s);await this.setHead(e,s)}}async replaceVersion(e,t){const s=await this.turns(),r=await s.find(this.turnFilter(e,t.id,t.version)),n=w(t);r?await r.update({...n,sessionId:e}):await s.create({...n,sessionId:e})}async branch(e,t){const s=await this.turns();await s.create(w({...t,sessionId:e})),await this.setHead(e,{id:t.id,version:t.version})}async loadAllTurns(e){const t=await this.turns();return(await t.filter({field:"sessionId",operator:"eq",value:e})).map((e=>e.state()))}async getActiveChain(e,t=[]){const s=await this.getHead(e);if(!s&&0===t.length)return[];const r=await this.loadAllTurns(e);return[...s?x(r,s):[],...t]}async buildNodeGraph(e,t=[]){const s=await this.loadAllTurns(e),r=await this.getHead(e),n=new Set;if(r)for(const e of x(s,r))n.add(`${e.id}:${e.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.loadAllTurns(e),t,s),o=await this.turns();await Promise.all(Array.from(n).map((async t=>{const[s,r]=t.split(":"),n=await o.find(this.turnFilter(e,s,Number(r)));n&&await n.delete()}))),await this.setHead(e,r)}async copyTranscript(e,t){const s=await this.getHead(e),r=await this.loadAllTurns(e),n=s?x(r,s):[],o=await this.turns();for(const e of n)await o.create(w({...e,sessionId:t}));await this.setHead(t,s?{...s}:null)}};function x(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()}async function S(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 T=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 S(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 b({sha256:r,mediaType:t,sizeBytes:i.sizeBytes,filename:i.filename,previewUrl:i.previewUrl})}catch(e){return g({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return g({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),b(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return g({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)),b(void 0)}async recordRemoteId(e,t,s){const r=this.recordCache.get(e);if(!r)return g({code:"NOT_FOUND",resource:"blob",id:e});if(r.remoteIds[t]===s)return b(void 0);const n={...r,remoteIds:{...r.remoteIds,[t]:s}};return await this.storage.saveRecord(n),this.recordCache.set(e,n),b(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 b({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.storage.loadBytes(e.sha256);return s?b({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):g({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 g({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),b(void 0)):g({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 O=10,k=50,C=20,N=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)}};function B({index:e},t){switch(t.type){case"role:add":{const s=t.payload;if(e.roles[s.name])return g({code:"DUPLICATE_KEY",resource:"role",key:s.name});const r={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return b({index:{roles:{[s.name]:r}}})}case"role:update":{const{name:s,...r}=t.payload;if(!e.roles[s])return g({code:"NOT_FOUND",resource:"role",id:s});const n=e.roles[s],o={...n,...r,preferences:r.preferences?.length??n.preferences};return b({index:{roles:{[s]:o}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return g({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?g({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):b({index:{roles:{[s]:m()}}})}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}}})),b({index:{preferences:{[s.id]:r},topics:n}})}case"preference:update":{const{id:s,...r}=t.payload;if(!e.preferences[s])return g({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}}}))),b({index:{preferences:{[s]:o},topics:i}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return g({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))})})),b({index:{preferences:{[s]:m()},topics:n}})}case"context:add":{const s=t.payload;if(e.context[s.key])return g({code:"DUPLICATE_KEY",resource:"context",key:s.key});const r=s.content,n={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"text"===r.kind?r.value.substring(0,200):"json"===r.kind?JSON.stringify(r.value).substring(0,200):void 0,metadata:s.metadata},o={};return s.topics.forEach((r=>{const n=e.topics[r],i=n?.contextKeys??[],a=i.includes(s.key)?i:[...i,s.key];o[r]={topic:r,contextKeys:a,preferences:n?.preferences??[],metadata:{updated:t.timestamp,entries:a.length}}})),b({index:{context:{[s.key]:n},topics:o}})}case"context:update":{const{key:s,...r}=t.payload;if(!e.context[s])return g({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],o=r.content,i={...n,...r,preview:o?"text"===o.kind?o.value.substring(0,200):"json"===o.kind?JSON.stringify(o.value).substring(0,200):void 0:n.preview},a={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(a[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];a[r]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),b({index:{context:{[s]:i},topics:a}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return g({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}})})),b({index:{context:{[s]:m()},topics:n}})}case"session:create":{const{id:s,label:r,role:n,topics:o,preferences:i=[]}=t.payload;if(e.sessions[s])return g({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[n])return g({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 b({index:{sessions:{[s]:a}}})}case"session:role:switch":{const{sessionId:s,role:r}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{role:r,metadata:{updated:t.timestamp}}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:r}=t.payload;if(!e.sessions[s])return g({code:"NOT_FOUND",resource:"session",id:s});const n=e.sessions[s],o=[...new Set([...n.topics,...r])];return b({index:{sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:r}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{preferences:r,metadata:{updated:t.timestamp}}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload;if(!e.sessions[s])return g({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[r])return g({code:"DUPLICATE_KEY",resource:"session",key:r});const a=e.sessions[s],c={id:r,label:n,role:o??a.role,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head};return b({index:{sessions:{[r]:c}}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:m()}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"turn:add":{const{sessionId:s,turn:r}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp},flushedTurnCount:(e.sessions[s]?.flushedTurnCount??0)+1}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:r,newVersion:n}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{head:{id:r,version:n},metadata:{updated:t.timestamp}}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:r}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp}}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:r}=t.payload;return e.sessions[s]?b({index:{sessions:{[s]:{head:r,metadata:{updated:t.timestamp}}}}}):g({code:"NOT_FOUND",resource:"session",id:s})}case"blob:register":default:return b({});case"blob:retain":{const{sha256:s}=t.payload;return e.blobs[s]?b({}):g({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:release":{const{sha256:s}=t.payload;return e.blobs[s]?b({}):g({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:purge":{const{sha256:s}=t.payload;return e.blobs[s]?b({}):g({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:record_remote_id":{const{sha256:s}=t.payload;return e.blobs[s]?b({}):g({code:"NOT_FOUND",resource:"blob",id:s})}}}function I(e){return Math.ceil(e.length/4)}function R(e,t){return Math.ceil(e/1024*t)}function E(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 D(e,t){return{id:crypto.randomUUID(),version:0,role:e,blocks:t,timestamp:(new Date).toISOString(),parent:null}}var _=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=E(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)}},j=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??I,c=i.blobTokensPerKB??.25;let d=i.total;const l={system:0,persona:0,preferences:0,transcript:0,context:0},u=a(t??""),h=a(s);d-=u+h,l.system+=u,l.persona+=h;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,b=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||b||(b=t.roleSnapshot??null))}const g=[];let w=0;for(const e of n){let t=a(E(e.content));"blob"===e.content.kind&&(t+=R(e.content.sizeBytes,c)),d>=t?(d-=t,l.context+=t,g.push(e)):w++}return{preferences:p,context:g,transcript:m,truncated:{preferences:f,interactions:y,context:w},breakdown:l,totalUsed:i.total-Math.max(0,d),lastRoleBeforeTruncation:b}}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+R(t.sizeBytes,s):e}default:return e}}),0)}},U=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(D("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(D("user",e)),l.push(D("assistant",[{type:"text",text:"Understood."}]))}let u=s.lastRoleBeforeTruncation,h=null!==s.lastRoleBeforeTruncation;for(const e of s.transcript){const t=this.resolveTurnBlocks(e,r);"user"===e.role&&e.roleSnapshot&&h&&e.roleSnapshot!==u&&t.unshift({type:"role_transition",previousRole:u,newRole:e.roleSnapshot}),"user"===e.role&&(u=e.roleSnapshot??null,h=!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}))}},A={maxBufferSize:10,flushIntervalMs:3e4},F=class{sessionId;nodes;head;dirtyBuffer=[];flushTimer=null;flushChain=Promise.resolve();flushConfig;tree;contentStore;constructor(e,t,s,r,n,o=A){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 g({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(),b({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 g({code:"NOT_FOUND",resource:"session",id:this.sessionId});const n=this.nodes[t];if(!n)return g({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),b({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:i.timestamp}}}}})}async branchFrom(e,t){const s=e.index.sessions[this.sessionId];if(!s)return g({code:"NOT_FOUND",resource:"session",id:this.sessionId});if(!t.parent)return g({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),b({index:{sessions:{[this.sessionId]:{head:{id:t.id,version:t.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:t.timestamp}}}}})):g({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 g({code:"NOT_FOUND",resource:"session",id:this.sessionId});const o=this.nodes[t];if(!o)return g({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 b({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 g({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 g({code:"INVALID_COMMAND",reason:"Current version not found"});const o=n+t;if(o<0||o>=r.length)return g({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 b({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]))):g({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),t=this.head;try{await this.tree.appendBatch(this.sessionId,e,t),0===this.dirtyBuffer.length&&this.cancelFlushTimer()}catch(t){throw this.dirtyBuffer.unshift(...e),this.flushChain=Promise.resolve(),t}}};var q=10,M=3e4,P="blob_bytes",$="blob_records";function z(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function V(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}exports.BlobStore=T,exports.COLLECTIONS=h,exports.ContentStore=class e{db;tree;blobs;roleCache;preferenceCache;contextCache;onBlobRegistryChanged;constructor(e,t,s={}){this.db=e,this.tree=new v(e),this.blobs=new T(t),this.blobs.onRegistryChanged=(e,t)=>{this.onBlobRegistryChanged?.(e,t)};const r={roles:s.cache?.roles??O,preferences:s.cache?.preferences??k,context:s.cache?.context??C};this.roleCache=new N(r.roles),this.preferenceCache=new N(r.preferences),this.contextCache=new N(r.context)}static async create(t,s,r){const n=new e(t,s,r);return await n.init(),n}async init(e){await this.db.open(e),await this.blobs.init()}getTurnTree(){return this.tree}async getRole(e){const t=this.roleCache.get(e);if(t)return b(t);const s=await this.db.collection(h.ROLE),r=await s.find({field:"name",operator:"eq",value:e});if(!r)return g({code:"NOT_FOUND",resource:"role",id:e});const n=r.state();return this.roleCache.set(e,n),b(n)}async saveRole(e){const t=await this.db.collection(h.ROLE),s=await t.find({field:"name",operator:"eq",value:e.name});s?await s.update(e):await t.create(e),this.roleCache.set(e.name,e)}async deleteRole(e){const t=await this.db.collection(h.ROLE),s=await t.find({field:"name",operator:"eq",value:e});s&&await s.delete(),this.roleCache.delete(e)}async getPreference(e){const t=this.preferenceCache.get(e);if(t)return b(t);const s=await this.db.collection(h.PREFERENCE),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return g({code:"NOT_FOUND",resource:"preference",id:e});const n=r.state();return this.preferenceCache.set(e,n),b(n)}async savePreference(e){const t=await this.db.collection(h.PREFERENCE),s=await t.find({field:"id",operator:"eq",value:e.id});s?await s.update(e):await t.create(e),this.preferenceCache.set(e.id,e)}async deletePreference(e){const t=await this.db.collection(h.PREFERENCE),s=await t.find({field:"id",operator:"eq",value:e});s&&await s.delete(),this.preferenceCache.delete(e)}async getContext(e){const t=this.contextCache.get(e);if(t)return b(t);const s=await this.db.collection(h.CONTEXT),r=await s.find({field:"key",operator:"eq",value:e});if(!r)return g({code:"NOT_FOUND",resource:"context",id:e});const n=r.state();return this.contextCache.set(e,n),b(n)}async saveContext(e){const t=await this.db.collection(h.CONTEXT),s=await t.find({field:"key",operator:"eq",value:e.key});s?await s.update(e):await t.create(e),this.contextCache.set(e.key,e)}async deleteContext(e){const t=await this.db.collection(h.CONTEXT),s=await t.find({field:"key",operator:"eq",value:e});s&&await s.delete(),this.contextCache.delete(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.contextCache.get(e);t?n.push(t):r.push(e)}let o=[];if(r.length>0){const e=await this.db.collection(h.CONTEXT),t=await e.filter({operator:"or",conditions:r.map((e=>({field:"key",operator:"eq",value:e})))});for(const e of t){const t=e.state();this.contextCache.set(t.key,t),o.push(t)}}return[...n,...o].sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async saveSession(e){const t=await this.db.collection(h.SESSION),s=await t.find({field:"id",operator:"eq",value:e.id}),r=w(e);s?await s.update(r):await t.create(r)}async updateSessionMeta(e,t){const s=await this.db.collection(h.SESSION),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return;const n=r.state(),o=y(n,t);await r.update(w(o))}async deleteSession(e){const t=await this.db.collection(h.SESSION),s=await t.find({field:"id",operator:"eq",value:e});s&&await s.delete()}async registerBlob(e,t,s){return this.blobs.register(e,t,s)}async retainBlob(e){return this.blobs.retain(e)}async releaseBlob(e){return this.blobs.release(e)}async purgeBlob(e){return this.blobs.purge(e)}async recordBlobRemoteId(e,t,s){return this.blobs.recordRemoteId(e,t,s)}getBlobRecord(e){return this.blobs.getRecord(e)}getAllBlobRecords(){return this.blobs.getAllRecords()}getBlobResolver(){return this.blobs.resolveRefs.bind(this.blobs)}async recordTurn(e,t){return await this.tree.append(e,t),b(void 0)}async editTurn(e,t,s,r,n){const o=(await this.tree.loadAllTurns(e)).find((e=>e.id===t&&e.version===r-1));if(!o)return g({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}),b(void 0)}async branchTurn(e,t){return await this.tree.branch(e,t),b(void 0)}async deleteTurnSubtree(e,t,s,r){return await this.tree.deleteSubtree(e,t,s,r),b(void 0)}async copyTranscript(e,t){await this.tree.copyTranscript(e,t)}async resolveSession(e,t,s){const r=e.index.sessions[t];if(!r)return g({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 b({...a,preferences:Object.freeze([...a.preferences]),context:Object.freeze([...a.context]),transcript:Object.freeze([...a.transcript])})}},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(P)||e.createObjectStore(P,{keyPath:"sha256"}),e.objectStoreNames.contains($)||e.createObjectStore($,{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(P);if(await z(s.objectStore(P).get(e)))return;const r=this.writeTx(P);r.objectStore(P).put({sha256:e,data:t}),await V(r)}async loadBytes(e){const t=this.readTx(P),s=await z(t.objectStore(P).get(e));return s?.data??null}async hasBytes(e){const t=this.readTx(P);return await z(t.objectStore(P).count(e))>0}async deleteBytes(e){const t=this.writeTx(P);t.objectStore(P).delete(e),await V(t)}async saveRecord(e){const t=this.writeTx($);t.objectStore($).put(e),await V(t)}async loadRecord(e){const t=this.readTx($);return await z(t.objectStore($).get(e))??null}async deleteRecord(e){const t=this.writeTx($);t.objectStore($).delete(e),await V(t)}async listRecords(){return z(this.readTx($).objectStore($).getAll())}async exportAllBytes(){const e=this.readTx(P);return(await z(e.objectStore(P).getAll())).map((({sha256:e,data:t})=>[e,t]))}async registerBlob(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction([P,$],"readwrite"),o=n.objectStore(P),i=n.objectStore($),a=o.count(e.sha256);a.onsuccess=()=>{0===a.result&&o.put({sha256:e.sha256,data:t}),i.put(e)},a.onerror=()=>r(a.error),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("registerBlob transaction aborted"))}))}},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)]))}async registerBlob(e,t){this.bytes.has(e.sha256)||this.bytes.set(e.sha256,t),this.records.set(e.sha256,{...e})}},exports.PromptBuilder=class{retriever;planner;assembler;summarizer;blobResolver;constructor(e){this.blobResolver=e.blobResolver,this.retriever=e.retriever??new _,this.planner=e.planner??new j,this.assembler=e.assembler??new U,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),u=this.deduplicateBlobRefs(l),{resolved:h,errors:p}=await this.blobResolver(u,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=u.filter((e=>!h.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:h,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=F,exports.SessionManager=class{workspaceManager;contentStore;flushConfig;constructor(e,t,s={}){this.workspaceManager=e,this.contentStore=t,this.flushConfig={maxBufferSize:s.flush?.maxBufferSize??q,flushIntervalMs:s.flush?.flushIntervalMs??M}}async open(e,t){const s=e.index.sessions[t];if(!s)return g({code:"NOT_FOUND",resource:"session",id:t});const r=this.contentStore.getTurnTree();try{const e=await r.buildNodeGraph(t);return b({session:new F(t,e,s.head,r,this.contentStore,this.flushConfig),patch:{}})}catch(e){return g({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}}async close(e){await e.dispose()}get workspace(){return this.workspaceManager}},exports.TurnTree=v,exports.WorkspaceManager=class{contentStore;onWorkspacePatch;constructor(e){this.contentStore=e,this.contentStore.onBlobRegistryChanged=(e,t)=>{const s={index:{blobs:{[e]:t??void 0}}};this.onWorkspacePatch?.(s)}}reduce(e,t){return B(e,t)}async dispatch(e,t){const s=B(e,t);if(!s.ok)return s;let r={};try{r=await this.handleContentSideEffects(e,t)}catch(e){return g({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return b(y(s.value,r))}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async handleContentSideEffects(e,t){switch(t.type){case"blob:register":{const{data:e,mediaType:s,filename:r}=t.payload,n=await this.contentStore.registerBlob(e,s,r);if(!n.ok)throw Object.assign(new Error(n.error.code),{wsError:n.error});const o=n.value,i=this.contentStore.getBlobRecord(o.sha256);if(!i)throw new Error("Record missing after register");return{index:{blobs:{[o.sha256]:i}}}}case"blob:retain":{const{sha256:e}=t.payload,s=await this.contentStore.retainBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});const r=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:r??void 0}}}}case"blob:release":{const{sha256:e}=t.payload,s=await this.contentStore.releaseBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});const r=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:r??void 0}}}}case"blob:purge":{const{sha256:e}=t.payload,s=await this.contentStore.purgeBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});return{index:{blobs:{[e]:void 0}}}}case"blob:record_remote_id":{const{sha256:e,providerId:s,fileId:r}=t.payload,n=await this.contentStore.recordBlobRemoteId(e,s,r);if(!n.ok)throw Object.assign(new Error(n.error.code),{wsError:n.error});const o=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:o??void 0}}}}case"role:add":return await this.contentStore.saveRole(t.payload),{};case"role:update":{const{name:e,...s}=t.payload,r=await this.contentStore.getRole(e);if(!r.ok)throw new Error(`role:update — "${e}" not found`);return await this.contentStore.saveRole({...r.value,...s,name:e}),{}}case"role:delete":return await this.contentStore.deleteRole(t.payload.name),{};case"preference:add":return await this.contentStore.savePreference(t.payload),{};case"preference:update":{const{id:e,...s}=t.payload,r=await this.contentStore.getPreference(e);if(!r.ok)throw new Error(`preference:update — "${e}" not found`);return await this.contentStore.savePreference({...r.value,...s,id:e}),{}}case"preference:delete":return await this.contentStore.deletePreference(t.payload.id),{};case"context:add":case"context:update":return await this.contentStore.saveContext(t.payload),{};case"context:delete":return await this.contentStore.deleteContext(t.payload.key),{};case"session:create":{const{id:e,label:s,role:r,topics:n,preferences:o=[]}=t.payload;return await this.contentStore.saveSession({id:e,label:s,role:r,topics:n,preferences:o,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null}),{}}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload;if(!e.index.sessions[s])throw new Error(`session:fork — source session "${s}" not found`);await this.contentStore.copyTranscript(s,r);const a=e.index.sessions[s],c={id:r,label:n,role:o??a.role,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head?{...a.head}:null};return await this.contentStore.saveSession(c),{}}case"session:delete":return await this.contentStore.deleteSession(t.payload.sessionId),{};case"session:role:switch":case"session:topics:add":case"session:preferences:override":{const e=t.payload.sessionId,s=await this.contentStore.db.collection("session"),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return{};if("session:role:switch"===t.type)await this.contentStore.updateSessionMeta(e,{role:t.payload.role});else if("session:topics:add"===t.type){const s=r.state();await this.contentStore.updateSessionMeta(e,{topics:[...new Set([...s.topics,...t.payload.topics])]})}else await this.contentStore.updateSessionMeta(e,{preferences:t.payload.preferences});return{}}case"turn:add":return await this.contentStore.recordTurn(t.payload.sessionId,t.payload.turn),{};case"turn:edit":{const{sessionId:e,turnId:s,newBlocks:r,newVersion:n,roleSnapshot:o}=t.payload;return await this.contentStore.editTurn(e,s,r,n,o),{}}case"turn:branch":return await this.contentStore.branchTurn(t.payload.sessionId,t.payload.newTurn),{};case"turn:delete":{const{sessionId:e,turnId:s,version:r,newHead:n}=t.payload;return await this.contentStore.deleteTurnSubtree(e,s,r,n),{}}default:return{}}}},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=S,exports.createSimpleWorkspace=function({name:e,owner:t,language:r}){return{id:s.v7(),settings:{language:r},project:{name:e,owner:t},index:{roles:{},topics:{},preferences:{},context:{},sessions:{},blobs:{}}}},exports.createWorkspaceDatabase=function(e){let t=!1;return{async open(s=[]){if(t)return;t=!0;const r=[...u,...s];await e.setupCollections(r)},collection:async t=>e.collection(t),close(){e.close()}}},exports.del=m,exports.err=g,exports.extractBlobRecord=function(e){const t=e?.index?.blobs;if(!t)return null;const s=t[Object.keys(t)[0]];return s||null},exports.extractBlobRef=function(e){return{sha256:e.sha256,mediaType:e.mediaType,sizeBytes:e.sizeBytes,filename:e.filename,previewUrl:e.previewUrl}},exports.merge=y,exports.ok=b,exports.omitNullUndefined=w,exports.workspaceReducer=B;
|
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
|
+
import{v7 as e}from"uuid";var t,s,r=Object.create,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,d=(e,t,s)=>(s=null!=e?r(a(e)):{},((e,t,s,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let a of i(t))c.call(e,a)||a===s||n(e,a,{get:()=>t[a],enumerable:!(r=o(t,a))||r.enumerable});return e})(e&&e.__esModule?s:n(s,"default",{value:e,enumerable:!0}),e)),l=(t={"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)}})(),u=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),u(e),()=>{r.delete(s),0===r.size?(t.delete(e),i.delete(e)):u(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 s||(0,t[i(t)[0]])((s={exports:{}}).exports,s),s.exports}),u=[{name:"role",version:"1.0.0",description:"AI persona with a system prompt and associated preference defaults.",fields:{name:{name:"name",type:"string",required:!0},label:{name:"label",type:"string",required:!0},description:{name:"description",type:"string",required:!1},persona:{name:"persona",type:"string",required:!0},preferences:{name:"preferences",type:"array",required:!1,itemsType:"string"}},indexes:[{name:"by_name",fields:["name"],type:"unique"},{name:"by_label",fields:["label"],type:"normal"}],constraints:[],migrations:[]},{name:"preference",version:"1.0.0",description:"A user behavioural instruction, scoped to zero or more topics.",fields:{id:{name:"id",type:"string",required:!0},content:{name:"content",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},timestamp:{name:"timestamp",type:"string",required:!0}},indexes:[{name:"by_id",fields:["id"],type:"unique"},{name:"by_topics",fields:["topics"],type:"normal"},{name:"by_timestamp",fields:["timestamp"],type:"btree"}],constraints:[],migrations:[]},{name:"context",version:"1.0.0",description:"Injected background knowledge, scoped to topics. Content is a discriminated union.",fields:{key:{name:"key",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},content:{name:"content",type:"record",required:!0},timestamp:{name:"timestamp",type:"string",required:!0},metadata:{name:"metadata",type:"record",required:!1}},indexes:[{name:"by_key",fields:["key"],type:"unique"},{name:"by_topics",fields:["topics"],type:"normal"},{name:"by_timestamp",fields:["timestamp"],type:"btree"}],constraints:[],migrations:[]},{name:"session",version:"1.0.0",description:"Session metadata. The head field tracks the current tip of the turn DAG.",fields:{id:{name:"id",type:"string",required:!0},label:{name:"label",type:"string",required:!0},role:{name:"role",type:"string",required:!0},topics:{name:"topics",type:"array",required:!1,itemsType:"string"},preferences:{name:"preferences",type:"array",required:!1,itemsType:"string"},metadata:{name:"metadata",type:"record",required:!1},flushedTurnCount:{name:"flushedTurnCount",type:"number",required:!0},head:{name:"head",type:"record",required:!1}},indexes:[{name:"by_id",fields:["id"],type:"unique"},{name:"by_role",fields:["role"],type:"normal"}],constraints:[],migrations:[]},{name:"turn",version:"1.0.0",description:["A single message in a session transcript, stored as a flat document.","The DAG is reconstructed in memory by TurnTree.buildNodeGraph() at session open time.","$id is a composite key: `${sessionId}:${id}:${version}`."].join(" "),fields:{id:{name:"id",type:"string",required:!0},sessionId:{name:"sessionId",type:"string",required:!0},version:{name:"version",type:"number",required:!0},role:{name:"role",type:"enum",required:!0,values:["user","assistant","tool"]},blocks:{name:"blocks",type:"array",required:!0},timestamp:{name:"timestamp",type:"string",required:!0},roleSnapshot:{name:"roleSnapshot",type:"string",required:!1},parent:{name:"parent",type:"record",required:!1}},indexes:[{name:"by_session",fields:["sessionId"],type:"normal"},{name:"by_session_parent",fields:["sessionId","parent"],type:"composite"},{name:"by_session_id_ver",fields:["sessionId","id","version"],type:"composite",unique:!0}],constraints:[],migrations:[]}];function h(e){let t=!1;return{async open(s=[]){if(t)return;t=!0;const r=[...u,...s];await e.setupCollections(r)},collection:async t=>e.collection(t),close(){e.close()}}}var p={ROLE:"role",PREFERENCE:"preference",CONTEXT:"context",SESSION:"session",TURN:"turn"};d(l());var f=Symbol.for("delete"),m=e=>Array.isArray(e)?[...e]:{...e};function y(){return f}d(l()),d(l()),d(l()),d(l()),d(l()),d(l());var b=function(e){const t=e?.deleteMarker||f;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=m(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]=m(t),o.push({target:e[r],source:n})}else e[r]=n;else delete e[r]}}return n}}({deleteMarker:f});function g(e){return{ok:!0,value:e}}function w(e){return{ok:!1,error:e}}function v(e){return Object.fromEntries(Object.entries(e).filter((([e,t])=>null!=t)))}function S({name:t,owner:s,language:r}){return{id:e(),settings:{language:r},project:{name:t,owner:s},index:{roles:{},topics:{},preferences:{},context:{},sessions:{},blobs:{}}}}function x(e){const t=e?.index?.blobs;if(!t)return null;const s=t[Object.keys(t)[0]];return s||null}function T(e){return{sha256:e.sha256,mediaType:e.mediaType,sizeBytes:e.sizeBytes,filename:e.filename,previewUrl:e.previewUrl}}var O=class{db;constructor(e){this.db=e}async turns(){return this.db.collection(p.TURN)}async sessions(){return this.db.collection(p.SESSION)}turnFilter(e,t,s){return{operator:"and",conditions:[{field:"sessionId",operator:"eq",value:e},{field:"id",operator:"eq",value:t},{field:"version",operator:"eq",value:s}]}}async getHead(e){const t=await this.sessions(),s=await t.find({field:"id",operator:"eq",value:e});return s?.head??null}async setHead(e,t){const s=await this.sessions(),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return;const n={...r.state(),head:t??void 0};await r.update(n)}async append(e,t){const s=await this.getHead(e),r={...t,sessionId:e,version:t.version??0,parent:t.parent?t.parent:s?{id:s.id,version:s.version}:null},n=await this.turns();return await n.create(v(r)),r}async appendBatch(e,t,s){if(0!==t.length){for(const s of t)await this.append(e,s);await this.setHead(e,s)}}async replaceVersion(e,t){const s=await this.turns(),r=await s.find(this.turnFilter(e,t.id,t.version)),n=v(t);r?await r.update({...n,sessionId:e}):await s.create({...n,sessionId:e})}async branch(e,t){const s=await this.turns();await s.create(v({...t,sessionId:e})),await this.setHead(e,{id:t.id,version:t.version})}async loadAllTurns(e){const t=await this.turns();return(await t.filter({field:"sessionId",operator:"eq",value:e})).map((e=>e.state()))}async getActiveChain(e,t=[]){const s=await this.getHead(e);if(!s&&0===t.length)return[];const r=await this.loadAllTurns(e);return[...s?C(r,s):[],...t]}async buildNodeGraph(e,t=[]){const s=await this.loadAllTurns(e),r=await this.getHead(e),n=new Set;if(r)for(const e of C(s,r))n.add(`${e.id}:${e.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.loadAllTurns(e),t,s),o=await this.turns();await Promise.all(Array.from(n).map((async t=>{const[s,r]=t.split(":"),n=await o.find(this.turnFilter(e,s,Number(r)));n&&await n.delete()}))),await this.setHead(e,r)}async copyTranscript(e,t){const s=await this.getHead(e),r=await this.loadAllTurns(e),n=s?C(r,s):[],o=await this.turns();for(const e of n)await o.create(v({...e,sessionId:t}));await this.setHead(t,s?{...s}:null)}};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()}async function k(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 N=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 k(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 g({sha256:r,mediaType:t,sizeBytes:i.sizeBytes,filename:i.filename,previewUrl:i.previewUrl})}catch(e){return w({code:"BLOB_ERROR",reason:e instanceof Error?e.message:String(e)})}}async retain(e){const t=this.recordCache.get(e);if(!t)return w({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),g(void 0)}async release(e){const t=this.recordCache.get(e);if(!t)return w({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)),g(void 0)}async recordRemoteId(e,t,s){const r=this.recordCache.get(e);if(!r)return w({code:"NOT_FOUND",resource:"blob",id:e});if(r.remoteIds[t]===s)return g(void 0);const n={...r,remoteIds:{...r.remoteIds,[t]:s}};return await this.storage.saveRecord(n),this.recordCache.set(e,n),g(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 g({kind:"remote",sha256:e.sha256,mediaType:e.mediaType,fileId:s,providerId:t})}const s=await this.storage.loadBytes(e.sha256);return s?g({kind:"inline",sha256:e.sha256,mediaType:e.mediaType,data:s}):w({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 w({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),g(void 0)):w({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 I=10,B=50,R=20,E=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)}};var D=class e{db;tree;blobs;roleCache;preferenceCache;contextCache;onBlobRegistryChanged;constructor(e,t,s={}){this.db=e,this.tree=new O(e),this.blobs=new N(t),this.blobs.onRegistryChanged=(e,t)=>{this.onBlobRegistryChanged?.(e,t)};const r={roles:s.cache?.roles??I,preferences:s.cache?.preferences??B,context:s.cache?.context??R};this.roleCache=new E(r.roles),this.preferenceCache=new E(r.preferences),this.contextCache=new E(r.context)}static async create(t,s,r){const n=new e(t,s,r);return await n.init(),n}async init(e){await this.db.open(e),await this.blobs.init()}getTurnTree(){return this.tree}async getRole(e){const t=this.roleCache.get(e);if(t)return g(t);const s=await this.db.collection(p.ROLE),r=await s.find({field:"name",operator:"eq",value:e});if(!r)return w({code:"NOT_FOUND",resource:"role",id:e});const n=r.state();return this.roleCache.set(e,n),g(n)}async saveRole(e){const t=await this.db.collection(p.ROLE),s=await t.find({field:"name",operator:"eq",value:e.name});s?await s.update(e):await t.create(e),this.roleCache.set(e.name,e)}async deleteRole(e){const t=await this.db.collection(p.ROLE),s=await t.find({field:"name",operator:"eq",value:e});s&&await s.delete(),this.roleCache.delete(e)}async getPreference(e){const t=this.preferenceCache.get(e);if(t)return g(t);const s=await this.db.collection(p.PREFERENCE),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return w({code:"NOT_FOUND",resource:"preference",id:e});const n=r.state();return this.preferenceCache.set(e,n),g(n)}async savePreference(e){const t=await this.db.collection(p.PREFERENCE),s=await t.find({field:"id",operator:"eq",value:e.id});s?await s.update(e):await t.create(e),this.preferenceCache.set(e.id,e)}async deletePreference(e){const t=await this.db.collection(p.PREFERENCE),s=await t.find({field:"id",operator:"eq",value:e});s&&await s.delete(),this.preferenceCache.delete(e)}async getContext(e){const t=this.contextCache.get(e);if(t)return g(t);const s=await this.db.collection(p.CONTEXT),r=await s.find({field:"key",operator:"eq",value:e});if(!r)return w({code:"NOT_FOUND",resource:"context",id:e});const n=r.state();return this.contextCache.set(e,n),g(n)}async saveContext(e){const t=await this.db.collection(p.CONTEXT),s=await t.find({field:"key",operator:"eq",value:e.key});s?await s.update(e):await t.create(e),this.contextCache.set(e.key,e)}async deleteContext(e){const t=await this.db.collection(p.CONTEXT),s=await t.find({field:"key",operator:"eq",value:e});s&&await s.delete(),this.contextCache.delete(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.contextCache.get(e);t?n.push(t):r.push(e)}let o=[];if(r.length>0){const e=await this.db.collection(p.CONTEXT),t=await e.filter({operator:"or",conditions:r.map((e=>({field:"key",operator:"eq",value:e})))});for(const e of t){const t=e.state();this.contextCache.set(t.key,t),o.push(t)}}return[...n,...o].sort(((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime()))}async saveSession(e){const t=await this.db.collection(p.SESSION),s=await t.find({field:"id",operator:"eq",value:e.id}),r=v(e);s?await s.update(r):await t.create(r)}async updateSessionMeta(e,t){const s=await this.db.collection(p.SESSION),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return;const n=r.state(),o=b(n,t);await r.update(v(o))}async deleteSession(e){const t=await this.db.collection(p.SESSION),s=await t.find({field:"id",operator:"eq",value:e});s&&await s.delete()}async registerBlob(e,t,s){return this.blobs.register(e,t,s)}async retainBlob(e){return this.blobs.retain(e)}async releaseBlob(e){return this.blobs.release(e)}async purgeBlob(e){return this.blobs.purge(e)}async recordBlobRemoteId(e,t,s){return this.blobs.recordRemoteId(e,t,s)}getBlobRecord(e){return this.blobs.getRecord(e)}getAllBlobRecords(){return this.blobs.getAllRecords()}getBlobResolver(){return this.blobs.resolveRefs.bind(this.blobs)}async recordTurn(e,t){return await this.tree.append(e,t),g(void 0)}async editTurn(e,t,s,r,n){const o=(await this.tree.loadAllTurns(e)).find((e=>e.id===t&&e.version===r-1));if(!o)return w({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}),g(void 0)}async branchTurn(e,t){return await this.tree.branch(e,t),g(void 0)}async deleteTurnSubtree(e,t,s,r){return await this.tree.deleteSubtree(e,t,s,r),g(void 0)}async copyTranscript(e,t){await this.tree.copyTranscript(e,t)}async resolveSession(e,t,s){const r=e.index.sessions[t];if(!r)return w({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 g({...a,preferences:Object.freeze([...a.preferences]),context:Object.freeze([...a.context]),transcript:Object.freeze([...a.transcript])})}};function _({index:e},t){switch(t.type){case"role:add":{const s=t.payload;if(e.roles[s.name])return w({code:"DUPLICATE_KEY",resource:"role",key:s.name});const r={name:s.name,label:s.label,description:s.description,preferences:s.preferences.length};return g({index:{roles:{[s.name]:r}}})}case"role:update":{const{name:s,...r}=t.payload;if(!e.roles[s])return w({code:"NOT_FOUND",resource:"role",id:s});const n=e.roles[s],o={...n,...r,preferences:r.preferences?.length??n.preferences};return g({index:{roles:{[s]:o}}})}case"role:delete":{const{name:s}=t.payload;if(!e.roles[s])return w({code:"NOT_FOUND",resource:"role",id:s});return Object.values(e.sessions).some((e=>e.role===s))?w({code:"INVALID_COMMAND",reason:`Cannot delete role "${s}" — it is still referenced by one or more sessions`}):g({index:{roles:{[s]:y()}}})}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}}})),g({index:{preferences:{[s.id]:r},topics:n}})}case"preference:update":{const{id:s,...r}=t.payload;if(!e.preferences[s])return w({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}}}))),g({index:{preferences:{[s]:o},topics:i}})}case"preference:delete":{const{id:s}=t.payload;if(!e.preferences[s])return w({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))})})),g({index:{preferences:{[s]:y()},topics:n}})}case"context:add":{const s=t.payload;if(e.context[s.key])return w({code:"DUPLICATE_KEY",resource:"context",key:s.key});const r=s.content,n={key:s.key,topics:s.topics,timestamp:s.timestamp,source:s.key.split(":")[0],preview:"text"===r.kind?r.value.substring(0,200):"json"===r.kind?JSON.stringify(r.value).substring(0,200):void 0,metadata:s.metadata},o={};return s.topics.forEach((r=>{const n=e.topics[r],i=n?.contextKeys??[],a=i.includes(s.key)?i:[...i,s.key];o[r]={topic:r,contextKeys:a,preferences:n?.preferences??[],metadata:{updated:t.timestamp,entries:a.length}}})),g({index:{context:{[s.key]:n},topics:o}})}case"context:update":{const{key:s,...r}=t.payload;if(!e.context[s])return w({code:"NOT_FOUND",resource:"context",id:s});const n=e.context[s],o=r.content,i={...n,...r,preview:o?"text"===o.kind?o.value.substring(0,200):"json"===o.kind?JSON.stringify(o.value).substring(0,200):void 0:n.preview},a={};return r.topics&&(n.topics.forEach((t=>{const r=e.topics[t];r&&(a[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];a[r]={contextKeys:o,metadata:{updated:t.timestamp,entries:o.length}}}))),g({index:{context:{[s]:i},topics:a}})}case"context:delete":{const{key:s}=t.payload;if(!e.context[s])return w({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}})})),g({index:{context:{[s]:y()},topics:n}})}case"session:create":{const{id:s,label:r,role:n,topics:o,preferences:i=[]}=t.payload;if(e.sessions[s])return w({code:"DUPLICATE_KEY",resource:"session",key:s});if(!e.roles[n])return w({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 g({index:{sessions:{[s]:a}}})}case"session:role:switch":{const{sessionId:s,role:r}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{role:r,metadata:{updated:t.timestamp}}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"session:topics:add":{const{sessionId:s,topics:r}=t.payload;if(!e.sessions[s])return w({code:"NOT_FOUND",resource:"session",id:s});const n=e.sessions[s],o=[...new Set([...n.topics,...r])];return g({index:{sessions:{[s]:{topics:o,metadata:{updated:t.timestamp}}}}})}case"session:preferences:override":{const{sessionId:s,preferences:r}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{preferences:r,metadata:{updated:t.timestamp}}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload;if(!e.sessions[s])return w({code:"NOT_FOUND",resource:"session",id:s});if(e.sessions[r])return w({code:"DUPLICATE_KEY",resource:"session",key:r});const a=e.sessions[s],c={id:r,label:n,role:o??a.role,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head};return g({index:{sessions:{[r]:c}}})}case"session:delete":{const{sessionId:s}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:y()}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"turn:add":{const{sessionId:s,turn:r}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp},flushedTurnCount:(e.sessions[s]?.flushedTurnCount??0)+1}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"turn:edit":{const{sessionId:s,turnId:r,newVersion:n}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{head:{id:r,version:n},metadata:{updated:t.timestamp}}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"turn:branch":{const{sessionId:s,newTurn:r}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{head:{id:r.id,version:r.version},metadata:{updated:t.timestamp}}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"turn:delete":{const{sessionId:s,newHead:r}=t.payload;return e.sessions[s]?g({index:{sessions:{[s]:{head:r,metadata:{updated:t.timestamp}}}}}):w({code:"NOT_FOUND",resource:"session",id:s})}case"blob:register":default:return g({});case"blob:retain":{const{sha256:s}=t.payload;return e.blobs[s]?g({}):w({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:release":{const{sha256:s}=t.payload;return e.blobs[s]?g({}):w({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:purge":{const{sha256:s}=t.payload;return e.blobs[s]?g({}):w({code:"NOT_FOUND",resource:"blob",id:s})}case"blob:record_remote_id":{const{sha256:s}=t.payload;return e.blobs[s]?g({}):w({code:"NOT_FOUND",resource:"blob",id:s})}}}var j=class{contentStore;onWorkspacePatch;constructor(e){this.contentStore=e,this.contentStore.onBlobRegistryChanged=(e,t)=>{const s={index:{blobs:{[e]:t??void 0}}};this.onWorkspacePatch?.(s)}}reduce(e,t){return _(e,t)}async dispatch(e,t){const s=_(e,t);if(!s.ok)return s;let r={};try{r=await this.handleContentSideEffects(e,t)}catch(e){return w({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}return g(b(s.value,r))}async resolveSession(e,t){return this.contentStore.resolveSession(e,t)}async handleContentSideEffects(e,t){switch(t.type){case"blob:register":{const{data:e,mediaType:s,filename:r}=t.payload,n=await this.contentStore.registerBlob(e,s,r);if(!n.ok)throw Object.assign(new Error(n.error.code),{wsError:n.error});const o=n.value,i=this.contentStore.getBlobRecord(o.sha256);if(!i)throw new Error("Record missing after register");return{index:{blobs:{[o.sha256]:i}}}}case"blob:retain":{const{sha256:e}=t.payload,s=await this.contentStore.retainBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});const r=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:r??void 0}}}}case"blob:release":{const{sha256:e}=t.payload,s=await this.contentStore.releaseBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});const r=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:r??void 0}}}}case"blob:purge":{const{sha256:e}=t.payload,s=await this.contentStore.purgeBlob(e);if(!s.ok)throw Object.assign(new Error(s.error.code),{wsError:s.error});return{index:{blobs:{[e]:void 0}}}}case"blob:record_remote_id":{const{sha256:e,providerId:s,fileId:r}=t.payload,n=await this.contentStore.recordBlobRemoteId(e,s,r);if(!n.ok)throw Object.assign(new Error(n.error.code),{wsError:n.error});const o=this.contentStore.getBlobRecord(e);return{index:{blobs:{[e]:o??void 0}}}}case"role:add":return await this.contentStore.saveRole(t.payload),{};case"role:update":{const{name:e,...s}=t.payload,r=await this.contentStore.getRole(e);if(!r.ok)throw new Error(`role:update — "${e}" not found`);return await this.contentStore.saveRole({...r.value,...s,name:e}),{}}case"role:delete":return await this.contentStore.deleteRole(t.payload.name),{};case"preference:add":return await this.contentStore.savePreference(t.payload),{};case"preference:update":{const{id:e,...s}=t.payload,r=await this.contentStore.getPreference(e);if(!r.ok)throw new Error(`preference:update — "${e}" not found`);return await this.contentStore.savePreference({...r.value,...s,id:e}),{}}case"preference:delete":return await this.contentStore.deletePreference(t.payload.id),{};case"context:add":case"context:update":return await this.contentStore.saveContext(t.payload),{};case"context:delete":return await this.contentStore.deleteContext(t.payload.key),{};case"session:create":{const{id:e,label:s,role:r,topics:n,preferences:o=[]}=t.payload;return await this.contentStore.saveSession({id:e,label:s,role:r,topics:n,preferences:o,metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:0,head:null}),{}}case"session:fork":{const{sourceSessionId:s,newSessionId:r,label:n,role:o,topics:i}=t.payload;if(!e.index.sessions[s])throw new Error(`session:fork — source session "${s}" not found`);await this.contentStore.copyTranscript(s,r);const a=e.index.sessions[s],c={id:r,label:n,role:o??a.role,topics:i??[...a.topics],preferences:[...a.preferences],metadata:{created:t.timestamp,updated:t.timestamp},flushedTurnCount:a.flushedTurnCount,head:a.head?{...a.head}:null};return await this.contentStore.saveSession(c),{}}case"session:delete":return await this.contentStore.deleteSession(t.payload.sessionId),{};case"session:role:switch":case"session:topics:add":case"session:preferences:override":{const e=t.payload.sessionId,s=await this.contentStore.db.collection("session"),r=await s.find({field:"id",operator:"eq",value:e});if(!r)return{};if("session:role:switch"===t.type)await this.contentStore.updateSessionMeta(e,{role:t.payload.role});else if("session:topics:add"===t.type){const s=r.state();await this.contentStore.updateSessionMeta(e,{topics:[...new Set([...s.topics,...t.payload.topics])]})}else await this.contentStore.updateSessionMeta(e,{preferences:t.payload.preferences});return{}}case"turn:add":return await this.contentStore.recordTurn(t.payload.sessionId,t.payload.turn),{};case"turn:edit":{const{sessionId:e,turnId:s,newBlocks:r,newVersion:n,roleSnapshot:o}=t.payload;return await this.contentStore.editTurn(e,s,r,n,o),{}}case"turn:branch":return await this.contentStore.branchTurn(t.payload.sessionId,t.payload.newTurn),{};case"turn:delete":{const{sessionId:e,turnId:s,version:r,newHead:n}=t.payload;return await this.contentStore.deleteTurnSubtree(e,s,r,n),{}}default:return{}}}};function U(e){return Math.ceil(e.length/4)}function F(e,t){return Math.ceil(e/1024*t)}function A(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 q(e,t){return{id:crypto.randomUUID(),version:0,role:e,blocks:t,timestamp:(new Date).toISOString(),parent:null}}var M=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=A(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)}},P=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??U,c=i.blobTokensPerKB??.25;let d=i.total;const l={system:0,persona:0,preferences:0,transcript:0,context:0},u=a(t??""),h=a(s);d-=u+h,l.system+=u,l.persona+=h;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,b=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||b||(b=t.roleSnapshot??null))}const g=[];let w=0;for(const e of n){let t=a(A(e.content));"blob"===e.content.kind&&(t+=F(e.content.sizeBytes,c)),d>=t?(d-=t,l.context+=t,g.push(e)):w++}return{preferences:p,context:g,transcript:m,truncated:{preferences:f,interactions:y,context:w},breakdown:l,totalUsed:i.total-Math.max(0,d),lastRoleBeforeTruncation:b}}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+F(t.sizeBytes,s):e}default:return e}}),0)}},$=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(q("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(q("user",e)),l.push(q("assistant",[{type:"text",text:"Understood."}]))}let u=s.lastRoleBeforeTruncation,h=null!==s.lastRoleBeforeTruncation;for(const e of s.transcript){const t=this.resolveTurnBlocks(e,r);"user"===e.role&&e.roleSnapshot&&h&&e.roleSnapshot!==u&&t.unshift({type:"role_transition",previousRole:u,newRole:e.roleSnapshot}),"user"===e.role&&(u=e.roleSnapshot??null,h=!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}))}},z=class{retriever;planner;assembler;summarizer;blobResolver;constructor(e){this.blobResolver=e.blobResolver,this.retriever=e.retriever??new M,this.planner=e.planner??new P,this.assembler=e.assembler??new $,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),u=this.deduplicateBlobRefs(l),{resolved:h,errors:p}=await this.blobResolver(u,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=u.filter((e=>!h.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:h,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))}}},V={maxBufferSize:10,flushIntervalMs:3e4},K=class{sessionId;nodes;head;dirtyBuffer=[];flushTimer=null;flushChain=Promise.resolve();flushConfig;tree;contentStore;constructor(e,t,s,r,n,o=V){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 w({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(),g({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 w({code:"NOT_FOUND",resource:"session",id:this.sessionId});const n=this.nodes[t];if(!n)return w({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),g({index:{sessions:{[this.sessionId]:{head:a,metadata:{updated:i.timestamp}}}}})}async branchFrom(e,t){const s=e.index.sessions[this.sessionId];if(!s)return w({code:"NOT_FOUND",resource:"session",id:this.sessionId});if(!t.parent)return w({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),g({index:{sessions:{[this.sessionId]:{head:{id:t.id,version:t.version},flushedTurnCount:s.flushedTurnCount+1,metadata:{updated:t.timestamp}}}}})):w({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 w({code:"NOT_FOUND",resource:"session",id:this.sessionId});const o=this.nodes[t];if(!o)return w({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 g({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 w({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 w({code:"INVALID_COMMAND",reason:"Current version not found"});const o=n+t;if(o<0||o>=r.length)return w({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 g({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]))):w({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),t=this.head;try{await this.tree.appendBatch(this.sessionId,e,t),0===this.dirtyBuffer.length&&this.cancelFlushTimer()}catch(t){throw this.dirtyBuffer.unshift(...e),this.flushChain=Promise.resolve(),t}}};function H(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 L=10,W=3e4,G=class{workspaceManager;contentStore;flushConfig;constructor(e,t,s={}){this.workspaceManager=e,this.contentStore=t,this.flushConfig={maxBufferSize:s.flush?.maxBufferSize??L,flushIntervalMs:s.flush?.flushIntervalMs??W}}async open(e,t){const s=e.index.sessions[t];if(!s)return w({code:"NOT_FOUND",resource:"session",id:t});const r=this.contentStore.getTurnTree();try{const e=await r.buildNodeGraph(t);return g({session:new K(t,e,s.head,r,this.contentStore,this.flushConfig),patch:{}})}catch(e){return w({code:"BACKEND_ERROR",reason:e instanceof Error?e.message:String(e)})}}async close(e){await e.dispose()}get workspace(){return this.workspaceManager}},X=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)]))}async registerBlob(e,t){this.bytes.has(e.sha256)||this.bytes.set(e.sha256,t),this.records.set(e.sha256,{...e})}},J="blob_bytes",Y="blob_records";function Q(e){return new Promise(((t,s)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>s(e.error)}))}function Z(e){return new Promise(((t,s)=>{e.oncomplete=()=>t(),e.onerror=()=>s(e.error),e.onabort=()=>s(new Error("Transaction aborted"))}))}var ee=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(J)||e.createObjectStore(J,{keyPath:"sha256"}),e.objectStoreNames.contains(Y)||e.createObjectStore(Y,{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(J);if(await Q(s.objectStore(J).get(e)))return;const r=this.writeTx(J);r.objectStore(J).put({sha256:e,data:t}),await Z(r)}async loadBytes(e){const t=this.readTx(J),s=await Q(t.objectStore(J).get(e));return s?.data??null}async hasBytes(e){const t=this.readTx(J);return await Q(t.objectStore(J).count(e))>0}async deleteBytes(e){const t=this.writeTx(J);t.objectStore(J).delete(e),await Z(t)}async saveRecord(e){const t=this.writeTx(Y);t.objectStore(Y).put(e),await Z(t)}async loadRecord(e){const t=this.readTx(Y);return await Q(t.objectStore(Y).get(e))??null}async deleteRecord(e){const t=this.writeTx(Y);t.objectStore(Y).delete(e),await Z(t)}async listRecords(){return Q(this.readTx(Y).objectStore(Y).getAll())}async exportAllBytes(){const e=this.readTx(J);return(await Q(e.objectStore(J).getAll())).map((({sha256:e,data:t})=>[e,t]))}async registerBlob(e,t){await new Promise(((s,r)=>{const n=this.getDB().transaction([J,Y],"readwrite"),o=n.objectStore(J),i=n.objectStore(Y),a=o.count(e.sha256);a.onsuccess=()=>{0===a.result&&o.put({sha256:e.sha256,data:t}),i.put(e)},a.onerror=()=>r(a.error),n.oncomplete=()=>s(),n.onerror=()=>r(n.error),n.onabort=()=>r(new Error("registerBlob transaction aborted"))}))}};export{N as BlobStore,p as COLLECTIONS,D as ContentStore,ee as IndexedDBBlobStorage,X as MemoryBlobStorage,z as PromptBuilder,K as Session,G as SessionManager,O as TurnTree,j as WorkspaceManager,H as buildTurnNode,k as computeSHA256,S as createSimpleWorkspace,h as createWorkspaceDatabase,y as del,w as err,x as extractBlobRecord,T as extractBlobRef,b as merge,g as ok,v as omitNullUndefined,_ as workspaceReducer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaidimu/utils-workspace",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Content-addressed workspace and conversation management for AI applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -58,5 +58,9 @@
|
|
|
58
58
|
}
|
|
59
59
|
]
|
|
60
60
|
]
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@asaidimu/anansi": "^4.0.2",
|
|
64
|
+
"uuid": "^13.0.0"
|
|
61
65
|
}
|
|
62
66
|
}
|