claude-mem 13.34.2 → 13.36.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.qoder-plugin/plugin.json +15 -0
- package/README.md +5 -16
- package/dist/bug-report/index.js +68 -68
- package/dist/npx-cli/index.js +371 -336
- package/dist/opencode-plugin/index.js +43 -41
- package/dsh/package.json +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/package.json +4 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.qoder-plugin/plugin.json +15 -0
- package/plugin/hooks/codex-hooks.json +1 -1
- package/plugin/hooks/hooks.json +1 -1
- package/plugin/hooks/qoder-hooks.json +97 -0
- package/plugin/hooks/qoder-repo-hooks.json +97 -0
- package/plugin/package.json +1 -1
- package/plugin/qoder.mcp.json +12 -0
- package/plugin/scripts/bun-runner.js +24 -5
- package/plugin/scripts/context-generator.cjs +59 -58
- package/plugin/scripts/context-generator.cjs.map +2 -2
- package/plugin/scripts/mcp-server.cjs +101 -57
- package/plugin/scripts/mcp-server.cjs.map +3 -3
- package/plugin/scripts/qoder-hook-launcher.cjs +114 -0
- package/plugin/scripts/server-service.cjs +197 -162
- package/plugin/scripts/server-service.cjs.map +3 -3
- package/plugin/scripts/transcript-watcher.cjs +27 -28
- package/plugin/scripts/transcript-watcher.cjs.map +3 -3
- package/plugin/scripts/worker-service.cjs +605 -534
- package/plugin/scripts/worker-service.cjs.map +3 -3
- package/plugin/skills/mem-search/SKILL.md +81 -128
- package/plugin/skills/screenpipe/SKILL.md +80 -0
- package/plugin/skills/screenpipe/screenpipe.mjs +157 -0
- package/plugin/sqlite/SessionStore.js +181 -176
- package/plugin/sqlite/SessionStore.js.map +3 -3
- package/plugin/sqlite/observations/files.js +7 -7
- package/plugin/sqlite/observations/files.js.map +2 -2
- package/plugin/ui/viewer-bundle.js +12 -12
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
var __CM_FILENAME__ = typeof __filename !== "undefined" ? __filename : require("node:path").resolve(process.argv[1] || "");
|
|
2
2
|
var __CM_DIRNAME__ = typeof __dirname !== "undefined" ? __dirname : require("node:path").dirname(__CM_FILENAME__);
|
|
3
3
|
var __IMPORT_META_URL__ = require("node:url").pathToFileURL(__CM_FILENAME__).href;
|
|
4
|
-
"use strict";var
|
|
5
|
-
`);let
|
|
6
|
-
`,"utf-8"),
|
|
7
|
-
`)}finally{if(
|
|
8
|
-
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?this.safeStringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;let s=t;if(typeof t=="string")try{s=JSON.parse(t)}catch{s=t}if(e==="Bash"&&s.command)return`${e}(${s.command})`;if(s.file_path)return`${e}(${s.file_path})`;if(s.notebook_path)return`${e}(${s.notebook_path})`;if(e==="Glob"&&s.pattern)return`${e}(${s.pattern})`;if(e==="Grep"&&s.pattern)return`${e}(${s.pattern})`;if(s.url)return`${e}(${s.url})`;if(s.query)return`${e}(${s.query})`;if(e==="Task"){if(s.subagent_type)return`${e}(${s.subagent_type})`;if(s.description)return`${e}(${s.description})`}return e==="Skill"&&s.skill?`${e}(${s.skill})`:e==="LSP"&&s.operation?`${e}(${s.operation})`:e}formatTimestamp(e){let t=e.getFullYear(),s=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),
|
|
4
|
+
"use strict";var Me=Object.defineProperty;var us=Object.getOwnPropertyDescriptor;var ls=Object.getOwnPropertyNames;var ps=Object.prototype.hasOwnProperty;var ms=(o,e)=>{for(var t in e)Me(o,t,{get:e[t],enumerable:!0})},Ts=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ls(e))!ps.call(o,n)&&n!==t&&Me(o,n,{get:()=>e[n],enumerable:!(s=us(e,n))||s.enumerable});return o};var Ss=o=>Ts(Me({},"__esModule",{value:!0}),o);var On={};ms(On,{SessionStore:()=>tt,TELEGRAM_WRAPUP_CLAIM_STALE_AFTER_MS:()=>ds,rollupObservationFileLists:()=>cs});module.exports=Ss(On);var As=new Set;function j(o,e,t="additive"){for(let s of As)s({scope:o,reason:e,kind:t})}var et=require("bun:sqlite"),he=require("crypto");var I=require("path"),ve=require("os"),le=require("fs"),at=require("url");var L=require("fs"),st=require("crypto"),F=require("path");var gs=null;function Os(o){return(gs??process.stderr.write.bind(process.stderr))(o)}function W(o){Os(o)}var Nn=Promise.resolve();var fs=process.platform==="win32";function Ue(o){return o.replace(/^\uFEFF/,"")}function ye(o){return JSON.parse(Ue(o))}function Z(o){return ye((0,L.readFileSync)(o,"utf-8"))}function Rs(o){(0,L.existsSync)(o)||(0,L.mkdirSync)(o,{recursive:!0})}function P(o,e,t={}){let s=o,n=new Set;try{for(;(0,L.lstatSync)(s).isSymbolicLink();){let u=(0,F.resolve)(s);if(n.has(u))throw Object.assign(new Error(`Symlink loop at ${s}`),{code:"ELOOP"});n.add(u);try{s=(0,L.realpathSync)(s);break}catch(l){if(l.code!=="ENOENT")throw l;let p=l instanceof Error?l:new Error(String(l));W(`claude-mem: realpathSync failed for ${s}, resolving symlink manually: ${p.message}
|
|
5
|
+
`);let S=(0,L.readlinkSync)(s);s=(0,F.resolve)((0,F.dirname)(s),S)}}}catch(u){if(u.code!=="ENOENT")throw u}Rs((0,F.dirname)(s));let i=(0,F.dirname)(s),r=(0,F.basename)(s),a=(0,F.join)(i,`.${r}.${process.pid}.${(0,st.randomBytes)(6).toString("hex")}.tmp`),_=Buffer.from(JSON.stringify(e,null,2)+`
|
|
6
|
+
`,"utf-8"),E=t.mode;if(E===void 0)try{E=(0,L.statSync)(s).mode&511}catch{}let d;try{d=E!==void 0?(0,L.openSync)(a,"w",E):(0,L.openSync)(a,"w");let u=0;for(;u<_.length;){let l=(0,L.writeSync)(d,_,u,_.length-u);if(l===0)throw new Error(`writeSync stalled at ${u}/${_.length} bytes`);u+=l}if((0,L.fsyncSync)(d),(0,L.closeSync)(d),d=void 0,(0,L.renameSync)(a,s),!fs){let l;try{l=(0,L.openSync)(i,"r"),(0,L.fsyncSync)(l)}catch(p){let S=p instanceof Error?p:new Error(String(p));W(`claude-mem: directory fsync failed for ${i}: ${S.message}
|
|
7
|
+
`)}finally{if(l!==void 0)try{(0,L.closeSync)(l)}catch{}}}}catch(u){if(d!==void 0)try{(0,L.closeSync)(d)}catch{}try{(0,L.unlinkSync)(a)}catch{}throw u}}var Ns=o=>o!==null&&typeof o=="object"&&!Array.isArray(o);function nt(o){let e=o.env;return Ns(e)&&Object.keys(e).some(t=>t.startsWith("CLAUDE_MEM_"))?"nested":"flat"}function K(o){return nt(o)==="nested"?o.env:o}function rt(o){return nt(o)!=="nested"?o:Object.fromEntries(Object.entries(o).filter(([e])=>!e.startsWith("CLAUDE_MEM_")))}var ot=require("os"),it=require("path");function ue(o,e=process.platform,t=(0,ot.homedir)()){return typeof o!="string"||o.length===0?o:o==="~"?t:o.startsWith("~/")||e==="win32"&&o.startsWith("~\\")?(0,it.join)(t,o.slice(2)):o}function bs(){return typeof __CM_DIRNAME__<"u"?__CM_DIRNAME__:(0,I.dirname)((0,at.fileURLToPath)(__IMPORT_META_URL__))}var wn=bs();function Cs(){if(process.env.CLAUDE_MEM_DATA_DIR)return ue(process.env.CLAUDE_MEM_DATA_DIR);let o=(0,I.join)((0,ve.homedir)(),".claude-mem"),e=(0,I.join)(o,"settings.json");try{if((0,le.existsSync)(e)){let t=Z(e);if(t===null||typeof t!="object"||Array.isArray(t))return o;let s=K(t);if(typeof s.CLAUDE_MEM_DATA_DIR=="string"&&s.CLAUDE_MEM_DATA_DIR)return ue(s.CLAUDE_MEM_DATA_DIR)}}catch{}return o}var M=Cs(),Ls=(0,I.join)((0,ve.homedir)(),".claude"),Is=process.env.CLAUDE_CONFIG_DIR||Ls,Pn=(0,I.join)(Is,"plugins","marketplaces","thedotmack"),hs=(0,I.join)(M,"logs"),pe=(0,I.join)(M,"settings.json"),_t="claude-mem.db";var me=(0,I.join)(M,_t),Ds=(0,I.join)(M,"observer-sessions"),ee=(0,I.basename)(Ds);function Te(o){(0,le.mkdirSync)(o,{recursive:!0})}var Fe={dataDir:()=>M,workerPid:()=>(0,I.join)(M,"worker.pid"),serverPid:()=>(0,I.join)(M,".server-beta.pid"),serverPort:()=>(0,I.join)(M,".server-beta.port"),serverRuntime:()=>(0,I.join)(M,".server-beta.runtime.json"),settings:()=>(0,I.join)(M,"settings.json"),database:()=>(0,I.join)(M,_t),chroma:()=>(0,I.join)(M,"chroma"),combinedCerts:()=>(0,I.join)(M,"combined_certs.pem"),transcriptsConfig:()=>(0,I.join)(M,"transcript-watch.json"),transcriptsState:()=>(0,I.join)(M,"transcript-watch-state.json"),corpora:()=>(0,I.join)(M,"corpora"),supervisorRegistry:()=>(0,I.join)(M,"supervisor.json"),envFile:()=>(0,I.join)(M,".env"),logsDir:()=>hs};var X=require("fs"),Et=require("path");var Pe=(i=>(i[i.DEBUG=0]="DEBUG",i[i.INFO=1]="INFO",i[i.WARN=2]="WARN",i[i.ERROR=3]="ERROR",i[i.SILENT=4]="SILENT",i))(Pe||{}),we=null,xe=class{level=null;useColor;logFilePath=null;logFileInitialized=!1;logFileDate=null;constructor(){this.useColor=process.stdout.isTTY??!1}ensureLogFileInitialized(){let e=new Date().toISOString().split("T")[0];if(this.logFileInitialized&&this.logFileDate===e)return;let t=this.logFileDate!==e;this.logFileInitialized=!1,this.logFileDate=e;try{let s=Fe.logsDir();(0,X.existsSync)(s)||(0,X.mkdirSync)(s,{recursive:!0}),this.logFilePath=(0,Et.join)(s,`claude-mem-${e}.log`),this.logFileInitialized=!0}catch(s){t&&console.error("[LOGGER] Failed to initialize log file:",s instanceof Error?s.message:String(s)),this.logFilePath=null}}getLevel(){if(this.level===null)try{let e=Fe.settings();if((0,X.existsSync)(e)){let s=(K(Z(e)).CLAUDE_MEM_LOG_LEVEL||"INFO").toString().toUpperCase();this.level=Pe[s]??1}else this.level=1}catch(e){console.error("[LOGGER] Failed to load log level from settings:",e instanceof Error?e.message:String(e)),this.level=1}return this.level}safeStringify(e,t,s=6){let n=new WeakSet,i=(r,a)=>{if(typeof r=="bigint")return`${r}n`;if(r===null||typeof r!="object")return r;let _=r.toJSON,E=typeof _=="function"?_.call(r):r;if(typeof E=="bigint")return`${E}n`;if(E===null||typeof E!="object")return E;if(n.has(E))return"[Circular]";if(a>=s)return Array.isArray(E)?"[Array]":"[Object]";n.add(E);try{if(Array.isArray(E))return E.map(u=>i(u,a+1));let d={};for(let u of Object.keys(E))try{d[u]=i(E[u],a+1)}catch{d[u]="[unreadable]"}return d}finally{n.delete(E)}};try{return JSON.stringify(i(e,0),null,t)??String(e)}catch{return Array.isArray(e)?`[${e.length} items]`:"[unserializable]"}}formatData(e){if(e==null)return"";if(typeof e=="string")return e;if(typeof e=="number"||typeof e=="boolean")return e.toString();if(typeof e=="object"){if(e instanceof Error)return this.getLevel()===0?`${e.message}
|
|
8
|
+
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?this.safeStringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;let s=t;if(typeof t=="string")try{s=JSON.parse(t)}catch{s=t}if(s===null)return e;if(e==="Bash"&&s.command)return`${e}(${s.command})`;if(s.file_path)return`${e}(${s.file_path})`;if(s.notebook_path)return`${e}(${s.notebook_path})`;if(e==="Glob"&&s.pattern)return`${e}(${s.pattern})`;if(e==="Grep"&&s.pattern)return`${e}(${s.pattern})`;if(s.url)return`${e}(${s.url})`;if(s.query)return`${e}(${s.query})`;if(e==="Task"){if(s.subagent_type)return`${e}(${s.subagent_type})`;if(s.description)return`${e}(${s.description})`}return e==="Skill"&&s.skill?`${e}(${s.skill})`:e==="LSP"&&s.operation?`${e}(${s.operation})`:e}formatTimestamp(e){let t=e.getFullYear(),s=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),r=String(e.getMinutes()).padStart(2,"0"),a=String(e.getSeconds()).padStart(2,"0"),_=String(e.getMilliseconds()).padStart(3,"0");return`${t}-${s}-${n} ${i}:${r}:${a}.${_}`}log(e,t,s,n,i){if(e<this.getLevel())return;this.ensureLogFileInitialized();let r=this.formatTimestamp(new Date),a=Pe[e].padEnd(5),_=t.padEnd(6),E="";n?.correlationId?E=`[${n.correlationId}] `:n?.sessionId&&(E=`[session-${n.sessionId}] `);let d="";i!=null&&(i instanceof Error?d=this.getLevel()===0?`
|
|
9
9
|
${i.message}
|
|
10
|
-
${i.stack}`:` ${i.message}`:this.getLevel()===0&&typeof i=="object"?
|
|
11
|
-
`+this.safeStringify(i,2):
|
|
12
|
-
`,"utf8")}catch(
|
|
13
|
-
${
|
|
10
|
+
${i.stack}`:` ${i.message}`:this.getLevel()===0&&typeof i=="object"?d=`
|
|
11
|
+
`+this.safeStringify(i,2):d=" "+this.formatData(i));let u="";if(n){let{sessionId:p,memorySessionId:S,correlationId:h,...f}=n;Object.keys(f).length>0&&(u=` {${Object.entries(f).map(([R,m])=>typeof m!="object"||m===null||m instanceof Error||m instanceof Date?`${R}=${m}`:`${R}=${Array.isArray(m)?this.safeStringify(m):this.formatData(m)}`).join(", ")}}`)}let l=`[${r}] [${a}] [${_}] ${E}${s}${u}${d}`;if(this.logFilePath)try{(0,X.appendFileSync)(this.logFilePath,l+`
|
|
12
|
+
`,"utf8")}catch(p){let S=p instanceof Error?p:new Error(String(p));W(`[LOGGER] Failed to write to log file: ${S.message}
|
|
13
|
+
${S.stack??""}
|
|
14
14
|
`)}else W(l+`
|
|
15
|
-
`)}debug(e,t,s,n){this.log(0,e,t,s,n)}info(e,t,s,n){this.log(1,e,t,s,n)}warn(e,t,s,n){this.log(2,e,t,s,n)}setErrorSink(e){
|
|
15
|
+
`)}debug(e,t,s,n){this.log(0,e,t,s,n)}info(e,t,s,n){this.log(1,e,t,s,n)}warn(e,t,s,n){this.log(2,e,t,s,n)}setErrorSink(e){we=e}error(e,t,s,n){this.log(3,e,t,s,n),this.routeErrorToSink(t,s,n)}routeErrorToSink(e,t,s){try{if(!we||!(s instanceof Error))return;we(s)}catch{}}dataIn(e,t,s,n){this.info(e,`\u2192 ${t}`,s,n)}dataOut(e,t,s,n){this.info(e,`\u2190 ${t}`,s,n)}success(e,t,s,n){this.info(e,`\u2713 ${t}`,s,n)}failure(e,t,s,n){this.error(e,`\u2717 ${t}`,s,n)}},c=new xe;function w(o){let e=o.projects?.length?o.projects:o.project?[o.project]:[];return[...new Set(e.map(t=>t.trim()).filter(Boolean))]}function x(o,e,t){let s=e.map(()=>"?").join(",");return t.includeMerged?{sql:`(${o}.project COLLATE NOCASE IN (${s}) OR ${o}.merged_into_project COLLATE NOCASE IN (${s}))`,params:[...e,...e]}:{sql:`${o}.project COLLATE NOCASE IN (${s})`,params:[...e]}}function dt(o,e){let t=w({projects:e});if(t.length===0)return[];let s=t.map(()=>"?").join(","),n=[`SELECT project AS key FROM sdk_sessions WHERE project COLLATE NOCASE IN (${s})`,`SELECT project FROM observations WHERE project COLLATE NOCASE IN (${s})`,`SELECT merged_into_project FROM observations WHERE merged_into_project COLLATE NOCASE IN (${s})`,`SELECT project FROM session_summaries WHERE project COLLATE NOCASE IN (${s})`,`SELECT merged_into_project FROM session_summaries WHERE merged_into_project COLLATE NOCASE IN (${s})`,`SELECT project FROM observations WHERE merged_into_project COLLATE NOCASE IN (${s})`,`SELECT project FROM session_summaries WHERE merged_into_project COLLATE NOCASE IN (${s})`],i=o.prepare(n.join(" UNION "));try{let r=i.all(...n.flatMap(()=>t));return[...new Set([...t,...r.map(a=>a.key)])]}finally{i.finalize()}}var ct=require("crypto");function ke(o){return typeof o=="string"&&o.trim()!==""}function ut(o,e,t){return(0,ct.createHash)("sha256").update([o||"",e||"",t||""].join("\0")).digest("hex").slice(0,16)}function lt(o){if(!o)return[];try{let e=JSON.parse(o);return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}catch{return[]}}function Be(o=new Date){return o.toISOString().slice(0,10)}function pt(o,e=new Date,t=10){let s=Be(e);if(o.includes(s))return o;let n=[...o,s];return n.length>t?n.slice(n.length-t):n}function mt(o){let e=Be(new Date(o));return{dates:JSON.stringify([e]),lastReinforced:e}}function Se(o,e,t=new Date){let s=o.prepare("SELECT reinforcement_dates FROM observations WHERE id = ?").get(e);if(!s)return!1;let n=lt(s.reinforcement_dates),i=pt(n,t);return i===n?!1:(o.prepare("UPDATE observations SET reinforcement_dates = ?, last_reinforced = ? WHERE id = ?").run(JSON.stringify(i),i[i.length-1],e),!0)}var At=require("crypto");var T="claude";function Ms(o){return o.trim().toLowerCase().replace(/\s+/g,"-")}function b(o){if(!o)return T;let e=Ms(o);return e?e==="transcript"||e.includes("codex")?"codex":e.includes("cursor")?"cursor":e.includes("claude")?"claude":e.includes("kimi")?"kimi":e==="pi-mono"?"pi":e==="agy"||e==="antigravity"||e.startsWith("antigravity-")?"antigravity-cli":e:T}function Tt(o){let e=["claude","codex","antigravity-cli","cursor","kimi"];return[...o].sort((t,s)=>{let n=e.indexOf(t),i=e.indexOf(s);return n!==-1||i!==-1?n===-1?1:i===-1?-1:n-i:t.localeCompare(s)})}var Us=new Set(["mem_search","search","timeline","get_observations","get_summaries","get_tool_uses","session_start_context","observation_search","observation_context","memory_search","memory_context"]);function ys(o){if(!o.startsWith("mcp__"))return null;let e=o.split("__");if(e.length<3)return null;let t=e[1].toLowerCase();return!t.includes("claude-mem")&&!t.includes("claude_mem")&&!t.includes("mcp-search")&&!t.includes("mcp_search")&&!t.includes("cmem")?null:e.slice(2).join("__")}function Xe(o){if(!o)return!1;if(o.startsWith("memory_")||o==="mem_search"||o==="get_summaries")return!0;let e=ys(o);return e!==null&&Us.has(e)}var vs=64*1024;function St(o,e=vs){let t=Buffer.byteLength(o,"utf8");if(t<=e)return o;let s=Buffer.from(o,"utf8"),n=e;for(;n>0&&(s[n]&192)===128;)n--;return`${s.subarray(0,n).toString("utf8")}\u2026[truncated: ${t} bytes]`}function Fs(o,e,t){return(0,At.createHash)("sha256").update([o||"",e||"",t||""].join("\0")).digest("hex").slice(0,16)}function gt(o){o.run(`
|
|
16
16
|
CREATE TABLE IF NOT EXISTS tool_uses (
|
|
17
17
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
18
|
tool_use_id TEXT NOT NULL,
|
|
@@ -20,7 +20,7 @@ ${L.stack??""}
|
|
|
20
20
|
memory_session_id TEXT,
|
|
21
21
|
session_db_id INTEGER,
|
|
22
22
|
project TEXT NOT NULL,
|
|
23
|
-
platform_source TEXT NOT NULL DEFAULT '${
|
|
23
|
+
platform_source TEXT NOT NULL DEFAULT '${T}',
|
|
24
24
|
tool_name TEXT NOT NULL,
|
|
25
25
|
tool_input TEXT,
|
|
26
26
|
tool_response TEXT,
|
|
@@ -36,7 +36,7 @@ ${L.stack??""}
|
|
|
36
36
|
created_at_epoch INTEGER NOT NULL,
|
|
37
37
|
UNIQUE(content_session_id, tool_use_id)
|
|
38
38
|
)
|
|
39
|
-
`),
|
|
39
|
+
`),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_project ON tool_uses(project)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_project_nocase_created ON tool_uses(project COLLATE NOCASE, created_at_epoch DESC, id DESC)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_memory_session ON tool_uses(memory_session_id)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_content_session ON tool_uses(content_session_id)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_session_db_id ON tool_uses(session_db_id)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_tool_name ON tool_uses(tool_name)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_created_at_epoch ON tool_uses(created_at_epoch)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_observation_id ON tool_uses(observation_id)"),o.run("CREATE INDEX IF NOT EXISTS idx_tool_uses_or_generation_id ON tool_uses(or_generation_id)")}function Ot(o,e){if(!e.toolUseId||!e.contentSessionId||!e.toolName||Xe(e.toolName))return null;let t=e.createdAtEpoch??Date.now(),s=new Date(t).toISOString(),n=Fs(e.toolName,e.toolInput,e.toolResponse),i=e.toolInput!=null?St(e.toolInput):null,r=e.toolResponse!=null?St(e.toolResponse):null,a=o.prepare(`
|
|
40
40
|
INSERT INTO tool_uses (
|
|
41
41
|
tool_use_id, content_session_id, memory_session_id, session_db_id, project,
|
|
42
42
|
platform_source, tool_name, tool_input, tool_response, cwd, prompt_number,
|
|
@@ -61,7 +61,7 @@ ${L.stack??""}
|
|
|
61
61
|
or_session_id = COALESCE(excluded.or_session_id, tool_uses.or_session_id),
|
|
62
62
|
content_hash = excluded.content_hash
|
|
63
63
|
RETURNING id
|
|
64
|
-
`).get(e.toolUseId,e.contentSessionId,e.memorySessionId??null,e.sessionDbId??null,e.project??"",b(e.platformSource),e.toolName,i,
|
|
64
|
+
`).get(e.toolUseId,e.contentSessionId,e.memorySessionId??null,e.sessionDbId??null,e.project??"",b(e.platformSource),e.toolName,i,r,e.cwd??null,e.promptNumber??null,e.agentType??null,e.agentId??null,e.orGenerationId??null,e.orSessionId??null,n,s,t);return a?a.id:null}function ft(o,e){let t=e.toolUseIds.filter(i=>typeof i=="string"&&i.length>0);if(t.length===0)return 0;let s=t.map(()=>"?").join(","),n=o.prepare(`
|
|
65
65
|
UPDATE tool_uses
|
|
66
66
|
SET observation_id = COALESCE(observation_id, ?),
|
|
67
67
|
memory_session_id = CASE WHEN observation_id IS NULL
|
|
@@ -71,23 +71,23 @@ ${L.stack??""}
|
|
|
71
71
|
WHERE content_session_id = ?
|
|
72
72
|
AND tool_use_id IN (${s})
|
|
73
73
|
AND (observation_id IS NULL OR observation_id = ?)
|
|
74
|
-
`).run(e.observationId,e.memorySessionId??null,e.memorySessionId??null,e.contentSessionId,...t,e.observationId);return Number(n.changes??0)}function
|
|
74
|
+
`).run(e.observationId,e.memorySessionId??null,e.memorySessionId??null,e.contentSessionId,...t,e.observationId);return Number(n.changes??0)}function Rt(o){return o?{clause:`COALESCE(NULLIF(platform_source, ''), '${T}') = ?`,param:b(o)}:null}function Nt(o,e,t={}){let s=[],n=[];for(let d of e){if(typeof d=="number"&&Number.isInteger(d)){s.push(d);continue}if(typeof d=="string"&&d.trim().length>0){let u=Number(d);Number.isInteger(u)&&String(u)===d.trim()&&s.push(u),n.push(d.trim())}}if(s.length===0&&n.length===0)return[];let i=[],r=[];s.length>0&&(i.push(`id IN (${s.map(()=>"?").join(",")})`),r.push(...s)),n.length>0&&(i.push(`tool_use_id IN (${n.map(()=>"?").join(",")})`),r.push(...n));let a=[`(${i.join(" OR ")})`];t.project&&(a.push("project COLLATE NOCASE = ?"),r.push(t.project)),t.contentSessionId&&(a.push("content_session_id = ?"),r.push(t.contentSessionId));let _=Rt(t.platformSource);_&&(a.push(_.clause),r.push(_.param));let E=t.limit&&t.limit>0?`LIMIT ${Math.floor(t.limit)}`:"";return o.prepare(`
|
|
75
75
|
SELECT * FROM tool_uses
|
|
76
76
|
WHERE ${a.join(" AND ")}
|
|
77
77
|
ORDER BY created_at_epoch DESC
|
|
78
78
|
${E}
|
|
79
|
-
`).all(...
|
|
79
|
+
`).all(...r)}function bt(o,e={}){let t=[],s=[];if(e.project&&(t.push("project COLLATE NOCASE = ?"),s.push(e.project)),e.contentSessionId&&(t.push("content_session_id = ?"),s.push(e.contentSessionId)),e.memorySessionId&&(t.push("memory_session_id = ?"),s.push(e.memorySessionId)),typeof e.sessionDbId=="number"&&(t.push("session_db_id = ?"),s.push(e.sessionDbId)),e.toolName){let E=Array.isArray(e.toolName)?e.toolName:[e.toolName];E.length>0&&(t.push(`tool_name IN (${E.map(()=>"?").join(",")})`),s.push(...E))}e.agentId&&(t.push("agent_id = ?"),s.push(e.agentId));let n=Rt(e.platformSource);n&&(t.push(n.clause),s.push(n.param)),typeof e.dateStart=="number"&&(t.push("created_at_epoch >= ?"),s.push(e.dateStart)),typeof e.dateEnd=="number"&&(t.push("created_at_epoch <= ?"),s.push(e.dateEnd));let i=t.length>0?`WHERE ${t.join(" AND ")}`:"",r=e.orderBy==="date_asc"?"ASC":"DESC",a=Math.min(Math.max(Math.floor(e.limit??50),1),500),_=Math.max(Math.floor(e.offset??0),0);return o.prepare(`
|
|
80
80
|
SELECT * FROM tool_uses
|
|
81
81
|
${i}
|
|
82
|
-
ORDER BY created_at_epoch ${
|
|
82
|
+
ORDER BY created_at_epoch ${r}, id ${r}
|
|
83
83
|
LIMIT ${a} OFFSET ${_}
|
|
84
|
-
`).all(...s)}function
|
|
84
|
+
`).all(...s)}function Ct(o,e={}){let t=[],s=[];e.project&&(t.push("project COLLATE NOCASE = ?"),s.push(e.project)),e.contentSessionId&&(t.push("content_session_id = ?"),s.push(e.contentSessionId)),e.agentId&&(t.push("agent_id = ?"),s.push(e.agentId)),typeof e.dateStart=="number"&&(t.push("created_at_epoch >= ?"),s.push(e.dateStart)),typeof e.dateEnd=="number"&&(t.push("created_at_epoch <= ?"),s.push(e.dateEnd));let n=t.length>0?`WHERE ${t.join(" AND ")}`:"";return o.prepare(`
|
|
85
85
|
SELECT tool_name, COUNT(DISTINCT tool_use_id) AS uses
|
|
86
86
|
FROM tool_uses
|
|
87
87
|
${n}
|
|
88
88
|
GROUP BY tool_name
|
|
89
89
|
ORDER BY uses DESC, tool_name ASC
|
|
90
|
-
`).all(...s)}function
|
|
90
|
+
`).all(...s)}function Lt(o){o.run(`
|
|
91
91
|
CREATE TABLE IF NOT EXISTS work_state_entries (
|
|
92
92
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
93
93
|
project TEXT NOT NULL,
|
|
@@ -96,34 +96,34 @@ ${L.stack??""}
|
|
|
96
96
|
created_at TEXT NOT NULL,
|
|
97
97
|
created_at_epoch INTEGER NOT NULL
|
|
98
98
|
)
|
|
99
|
-
`),
|
|
99
|
+
`),o.run("CREATE INDEX IF NOT EXISTS idx_work_state_entries_project ON work_state_entries(project COLLATE NOCASE, list_name, id)")}function It(o,e){let t=e.createdAtEpoch??Date.now(),s=o.prepare(`
|
|
100
100
|
INSERT INTO work_state_entries (project, list_name, fields, created_at, created_at_epoch)
|
|
101
101
|
VALUES (?, ?, ?, ?, ?)
|
|
102
|
-
`).run(e.project,e.listName,JSON.stringify(e.fields),new Date(t).toISOString(),t),n=Number(s.lastInsertRowid);return
|
|
102
|
+
`).run(e.project,e.listName,JSON.stringify(e.fields),new Date(t).toISOString(),t),n=Number(s.lastInsertRowid);return c.debug("DB","Work state entry appended",{id:n,project:e.project,listName:e.listName}),n}function ht(o,e,t){if(e.length===0)return[];let s=e.map(()=>"?").join(", "),n=t===void 0?"":" AND list_name = ?";return o.prepare(`
|
|
103
103
|
SELECT id, project, list_name, fields, created_at_epoch
|
|
104
104
|
FROM work_state_entries
|
|
105
105
|
WHERE project COLLATE NOCASE IN (${s})${n}
|
|
106
106
|
ORDER BY id
|
|
107
|
-
`).all(...e,...t===void 0?[]:[t]).map(o=>({...o,fields:JSON.parse(o.fields)}))}var G=require("fs"),k=require("path"),Z=require("os");var ue={HEALTH_CHECK:3e3,API_REQUEST:3e4,SESSION_INIT_HOOK_CAP:15e3,SESSION_INIT_REQUEST:1e4,SESSION_INIT_REQUEST_MAX:14e3,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function Ls(r=process.platform){return r==="win32"?8e3:5e3}function Nt(r=process.platform){return ue.SESSION_INIT_HOOK_CAP-Ls(r)}function bt(r){return process.platform==="win32"?Math.round(r*ue.WINDOWS_MULTIPLIER):r}function Ct(r){try{return new URL(r).hostname.toLowerCase()==="openrouter.ai"}catch{return!1}}var Is="security_alert",hs="sync-hub.black-pond-afbb.workers.dev",Ds="ziczmqtpmaxbornfghye.supabase.co",Ms="https://sync.cmem.ai",Us=new Set(["xiaomi/mimo-v2-flash:free"]);function ys(r){let e=r.CLAUDE_MEM_OPENROUTER_MODEL;if(typeof e!="string"||!Us.has(e.trim()))return!1;let t=typeof r.CLAUDE_MEM_OPENROUTER_BASE_URL=="string"?r.CLAUDE_MEM_OPENROUTER_BASE_URL.trim():"";return t===""||Ct(t)}var Lt=18e4,It=[{key:"CLAUDE_MEM_LLM_TIMEOUT_MS",legacy:"30000",markerTag:"llm-timeout-migrated-v1"},{key:"CLAUDE_MEM_FIELD_OPTIMIZE_TIMEOUT_MS",legacy:"30000",markerTag:"field-optimize-timeout-migrated-v1"}];function Dt(r,e){return(0,k.join)((0,k.dirname)(r),`.${(0,k.basename)(r)}.${e.markerTag}`)}function we(r,e){try{(0,G.writeFileSync)(Dt(r,e),new Date().toISOString(),{encoding:"utf-8",mode:384})}catch{}}var ht=new Set;function vs(r){if(typeof r!="string")return null;let e=r.trim();if(e.length===0)return null;try{let t=new URL(e).hostname;if(t===hs||t===Ds)return Ms}catch{return null}return null}var Y=class{static DEFAULTS={CLAUDE_MEM_MODEL:"claude-haiku-4-5-20251001",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_SESSION_START_INCLUDE_ALL_SOURCES:"false",CLAUDE_MEM_WORKER_PORT:String(37700+(process.getuid?.()??77)%100),CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_ALLOWED_ORIGINS:"",CLAUDE_MEM_PUBLIC_URL:"",CLAUDE_MEM_API_TIMEOUT_MS:String(bt(ue.API_REQUEST)),CLAUDE_MEM_SESSION_INIT_TIMEOUT_MS:String(Nt()),CLAUDE_MEM_IDLE_EXIT_SEC:"0",CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_SKIP_BASH_PATTERNS:"",CLAUDE_MEM_SKIP_SUBAGENT_OBSERVATIONS:"false",CLAUDE_MEM_SKIP_AGENT_TYPES:"",CLAUDE_MEM_CAPTURE_ADVISOR_CALLS:"false",CLAUDE_MEM_PROVIDER:"claude",CLAUDE_MEM_CODEX_MODEL:"",CLAUDE_MEM_CODEX_PATH:"codex",CLAUDE_MEM_CODEX_REASONING_EFFORT:"low",CLAUDE_MEM_CODEX_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_CODEX_OBSERVATION_BATCH_SIZE:"8",CLAUDE_MEM_CODEX_OBSERVATION_BATCH_MAX_CHARS:"32000",CLAUDE_MEM_CLAUDE_AUTH_METHOD:"subscription",CLAUDE_MEM_GEMINI_API_KEY:"",CLAUDE_MEM_GEMINI_API_KEYS:"",CLAUDE_MEM_GEMINI_MODEL:"gemini-flash-latest",CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED:"true",CLAUDE_MEM_OPENROUTER_API_KEY:"",CLAUDE_MEM_OPENROUTER_API_KEYS:"",CLAUDE_MEM_OPENROUTER_MODEL:"cohere/north-mini-code:free",CLAUDE_MEM_OPENROUTER_BASE_URL:"",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_OPENROUTER_EXTRA_BODY:"",CLAUDE_MEM_OPENROUTER_REASONING_EFFORT:"",CLAUDE_MEM_OPENAI_COMPAT_PRESET:"",CLAUDE_MEM_OPENAI_COMPAT_API_KEY:"",CLAUDE_MEM_OPENAI_COMPAT_API_KEYS:"",CLAUDE_MEM_OPENAI_COMPAT_BASE_URL:"",CLAUDE_MEM_OPENAI_COMPAT_MODEL:"",CLAUDE_MEM_QUOTA_FALLBACK_PROVIDER:"",CLAUDE_MEM_QUOTA_FALLBACK_MODEL:"",CLAUDE_MEM_QUOTA_THRESHOLD_FIVE_HOUR:"0.95",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY:"0.93",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY_OPUS:"0.93",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY_SONNET:"0.92",CLAUDE_MEM_QUOTA_THRESHOLD_OVERAGE:"0.95",CLAUDE_MEM_DATA_DIR:(0,k.join)((0,Z.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",CLAUDE_MEM_CLAUDE_CONFIG_DIR:"",CLAUDE_MEM_MODE:"code",CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT:"true",CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES:"",CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS:"",CLAUDE_MEM_CONTEXT_FULL_COUNT:"0",CLAUDE_MEM_CONTEXT_FULL_FIELD:"narrative",CLAUDE_MEM_CONTEXT_SESSION_COUNT:"10",CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY:"true",CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE:"false",CLAUDE_MEM_CONTEXT_MAIN_AGENT_ONLY:"true",CLAUDE_MEM_REINFORCE_ALPHA:"0",CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT:"true",CLAUDE_MEM_WELCOME_HINT_ENABLED:"true",CLAUDE_MEM_FILE_READ_GATE_ENABLED:"true",CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED:"false",CLAUDE_MEM_FOLDER_USE_LOCAL_MD:"false",CLAUDE_MEM_TRANSCRIPTS_ENABLED:"true",CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH:(0,k.join)((0,Z.homedir)(),".claude-mem","transcript-watch.json"),CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION:"false",CLAUDE_MEM_CODEX_SUBAGENT_INGESTION:"false",CLAUDE_MEM_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_OBSERVER_MAX_CONVERSATION_CHARS:"400000",CLAUDE_MEM_OBSERVER_CONTEXT_WINDOW:"",CLAUDE_MEM_OBSERVER_MAX_OUTPUT_TOKENS:"4096",CLAUDE_MEM_OBSERVE_BARE_PROMPTS:"false",CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD:"3",CLAUDE_MEM_REDACT_ENABLED:"false",CLAUDE_MEM_REDACT_DISABLED_BUILTINS:"",CLAUDE_MEM_REDACT_CUSTOM_PATTERNS:"[]",CLAUDE_MEM_REDACT_LOG_MATCHES:"false",CLAUDE_MEM_EXCLUDED_PROJECTS:"",CLAUDE_MEM_PROJECT_ENVIRONMENTS:"[]",CLAUDE_MEM_FOLDER_MD_EXCLUDE:"[]",CLAUDE_MEM_FOLDER_MD_SKELETON_DENYLIST:"[]",CLAUDE_MEM_SEMANTIC_INJECT:"false",CLAUDE_MEM_SEMANTIC_INJECT_LIMIT:"5",CLAUDE_MEM_TIER_ROUTING_ENABLED:"true",CLAUDE_MEM_TIER_SIMPLE_MODEL:"haiku",CLAUDE_MEM_TIER_SUMMARY_MODEL:"",CLAUDE_MEM_TIER_FAST_MODEL:"haiku",CLAUDE_MEM_TIER_SMART_MODEL:"sonnet",CLAUDE_MEM_CHROMA_ENABLED:"true",CLAUDE_MEM_CHROMA_MODE:"local",CLAUDE_MEM_CHROMA_HOST:"127.0.0.1",CLAUDE_MEM_CHROMA_PORT:"8000",CLAUDE_MEM_CHROMA_SSL:"false",CLAUDE_MEM_CHROMA_API_KEY:"",CLAUDE_MEM_CHROMA_TENANT:"default_tenant",CLAUDE_MEM_CHROMA_DATABASE:"default_database",CLAUDE_MEM_CHROMA_PREWARM_TIMEOUT_MS:"120000",CLAUDE_MEM_CHROMA_MUTATION_TIMEOUT_MS:"600000",CLAUDE_MEM_CHROMA_MAX_PENDING_MUTATIONS:"5000",CLAUDE_MEM_CHROMA_EMBEDDING_FUNCTION:"default",CLAUDE_MEM_CLOUD_SYNC_TOKEN:"",CLAUDE_MEM_CLOUD_SYNC_USER_ID:"",CLAUDE_MEM_CLOUD_SYNC_HUB_URL:"",CLAUDE_MEM_CLOUD_SYNC_DEVICE_ID:"",CLAUDE_MEM_CLOUD_SYNC_DEVICE_NAME:(0,Z.hostname)(),CLAUDE_MEM_CLOUD_SYNC_WS:"true",CLAUDE_MEM_CLOUD_SYNC_CONTENT_BATCH_SIZE:"40",CLAUDE_MEM_CLOUD_SYNC_REQUEST_TIMEOUT_MS:"90000",CLAUDE_MEM_LLM_TIMEOUT_MS:String(Lt),CLAUDE_MEM_FIELD_OPTIMIZE_TIMEOUT_MS:String(Lt),CLAUDE_MEM_TV_TOKEN:"",CLAUDE_MEM_PRO_TRIAL_EMAIL:"",CLAUDE_MEM_PRO_TRIAL_AT:"",CLAUDE_MEM_PRO_TRIAL_STATE:"",CLAUDE_MEM_PRO_TRIAL_ENDS_AT:"",CLAUDE_MEM_PRO_PLAN:"",CLAUDE_MEM_PRO_FALLBACK_AT:"",CLAUDE_MEM_PRO_FALLBACK_MESSAGE:"",CLAUDE_MEM_PRO_FALLBACK_ACTION:"",CLAUDE_MEM_PRO_FALLBACK_URL:"",CLAUDE_MEM_PRO_MEMORY_KEY:"",CLAUDE_MEM_PRO_MEMORY_BASE_URL:"",CLAUDE_MEM_PRO_MEMORY_MODEL:"",CLAUDE_MEM_TELEGRAM_ENABLED:"true",CLAUDE_MEM_TELEGRAM_BOT_TOKEN:"",CLAUDE_MEM_TELEGRAM_CHAT_ID:"",CLAUDE_MEM_TELEGRAM_WRAPUPS_ENABLED:"true",CLAUDE_MEM_TELEGRAM_OBSERVATION_ALERTS_ENABLED:"false",CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES:"{}",CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:"security_alert,sensitive",CLAUDE_MEM_TELEGRAM_TRIGGER_CONCEPTS:"",CLAUDE_MEM_GROK_BOT_AWARENESS_ENABLED:"true",CLAUDE_MEM_GROK_BOT_AWARENESS_AGENT_IDS:"521e962d-2ec3-4488-bfbc-54d5209ce118,95601360-61f7-4fd9-bb3a-2c976b2b85c0",CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_TYPES:"decision,bugfix,security_alert,sensitive",CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_CONCEPTS:"",CLAUDE_MEM_GROK_BOT_WEBHOOK_URL:"",CLAUDE_MEM_GROK_BOT_WEBHOOK_SECRET:"",CLAUDE_MEM_GROK_BOT_INJECT_ENABLED:"true",CLAUDE_MEM_GROK_BOT_INJECT_AGENT_IDS:"*",CLAUDE_MEM_GROK_BOT_INJECT_TIER:"episode",CLAUDE_MEM_GROK_BOT_INJECT_WINDOW:"80",CLAUDE_MEM_GROK_BOT_INJECT_FALLBACK:"house",CLAUDE_MEM_GROK_BOT_INJECT_PLATFORM_SOURCE:"",CLAUDE_MEM_GROK_BOT_INJECT_PROJECTS_BY_AGENT:"",CLAUDE_MEM_GROK_BOT_INJECT_MAX_LINE_CHARS:"160",CLAUDE_MEM_GROK_BOT_INJECT_DEBOUNCE_MS:"1500",CLAUDE_MEM_GROK_BOT_INJECT_STANDING_LINE:"",CLAUDE_MEM_CCS_ALIGN_ENABLED:"true",CLAUDE_MEM_CCS_ALIGN_VIEWER_IDS:"ccs-align",CLAUDE_MEM_CCS_ALIGN_TRIGGER_TYPES:"decision,bugfix,security_alert,sensitive",CLAUDE_MEM_CCS_ALIGN_PATCH_SHADOWS:"false",CLAUDE_MEM_QUEUE_ENGINE:"sqlite",CLAUDE_MEM_REDIS_URL:"",CLAUDE_MEM_REDIS_HOST:"127.0.0.1",CLAUDE_MEM_REDIS_PORT:"6379",CLAUDE_MEM_REDIS_MODE:"external",CLAUDE_MEM_QUEUE_REDIS_PREFIX:`claude_mem_${process.env.CLAUDE_MEM_WORKER_PORT??String(37700+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_AUTH_MODE:"api-key",CLAUDE_MEM_RUNTIME:"worker",CLAUDE_MEM_SERVER_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_API_KEY:"",CLAUDE_MEM_SERVER_PROJECT_ID:"",CLAUDE_MEM_SERVER_BETA_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_BETA_API_KEY:"",CLAUDE_MEM_SERVER_BETA_PROJECT_ID:"",CLAUDE_MEM_DEDUP_ENABLED:"false",CLAUDE_MEM_DEDUP_COSINE_THRESHOLD:"0.80",CLAUDE_MEM_DEDUP_IDF_VETO_DF:"10",CLAUDE_MEM_DEDUP_MIN_SHARED_TOKENS:"2",CLAUDE_MEM_DEDUP_MIN_PROJECT_DOCS:"10",CLAUDE_MEM_DEDUP_MAX_SCAN:"2000",CLAUDE_MEM_DEDUP_MAX_BACKFILL_ROWS:"50000",CLAUDE_MEM_WORKER_AUTOSTART:"true",CLAUDE_MEM_PROJECT_NAME_SOURCE:"path"};static getAllDefaults(){return{...this.DEFAULTS}}static get(e){let t=process.env[e]??this.DEFAULTS[e];return e==="CLAUDE_MEM_WORKER_HOST"?this.normalizeWorkerHost(t):t}static normalizeWorkerHost(e){return e==="localhost"?"127.0.0.1":e}static finalizeSettings(e,t){let s=t?this.applyEnvOverrides(e):e;return s.CLAUDE_MEM_WORKER_HOST=this.normalizeWorkerHost(s.CLAUDE_MEM_WORKER_HOST),s}static getInt(e){let t=this.get(e);return parseInt(t,10)}static applyEnvOverrides(e){let t={...e};for(let s of Object.keys(this.DEFAULTS))process.env[s]!==void 0&&(t[s]=process.env[s]);return t}static loadFromFile(e,t=!0){try{if(!(0,G.existsSync)(e)){let d=this.getAllDefaults();try{P(e,d,{mode:384});for(let l of It)we(e,l);console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(l){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,l instanceof Error?l.message:String(l))}return this.finalizeSettings(d,t)}let s=(0,G.readFileSync)(e,"utf-8"),n=Ie(s),i=K(n),o=i!==n,a=Qe(n),_=o&&Object.keys(a).some(d=>d!=="env");if(o&&!_)try{P(e,i,{mode:384}),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(d){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,d instanceof Error?d.message:String(d))}if(i.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES===Is){i={...i,CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:this.DEFAULTS.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES};try{P(e,_?{...a,env:i}:i,{mode:384}),console.warn("[SETTINGS] Migrated Telegram trigger types off the legacy default:",e)}catch(d){console.warn("[SETTINGS] Failed to migrate Telegram trigger types:",e,d instanceof Error?d.message:String(d))}}if(ys(i)){let d=String(i.CLAUDE_MEM_OPENROUTER_MODEL).trim();i={...i,CLAUDE_MEM_OPENROUTER_MODEL:this.DEFAULTS.CLAUDE_MEM_OPENROUTER_MODEL};try{P(e,_?{...a,env:i}:i,{mode:384}),console.warn(`[SETTINGS] Migrated OpenRouter model off the retired default ${d} to ${this.DEFAULTS.CLAUDE_MEM_OPENROUTER_MODEL}:`,e)}catch(l){console.warn("[SETTINGS] Failed to migrate the retired OpenRouter model:",e,l instanceof Error?l.message:String(l))}}let E=vs(i.CLAUDE_MEM_CLOUD_SYNC_HUB_URL);if(E!==null){i={...i,CLAUDE_MEM_CLOUD_SYNC_HUB_URL:E};try{P(e,_?{...a,env:i}:i,{mode:384}),console.warn("[SETTINGS] Migrated cloud sync hub URL to",E,"from a retired hub host:",e)}catch(d){console.warn("[SETTINGS] Failed to migrate cloud sync hub URL:",e,d instanceof Error?d.message:String(d))}}for(let d of It)if(!(0,G.existsSync)(Dt(e,d))){if(i[d.key]!==d.legacy){we(e,d);continue}i={...i,[d.key]:this.DEFAULTS[d.key]};try{P(e,_?{...a,env:i}:i,{mode:384}),we(e,d),console.warn(`[SETTINGS] Migrated ${d.key} off the old ${d.legacy}ms default to ${this.DEFAULTS[d.key]}ms:`,e)}catch(l){let O=`${d.key}\0${e}`;ht.has(O)||(ht.add(O),console.warn(`[SETTINGS] Failed to migrate ${d.key}; using the new default in memory (reported once per process):`,e,l instanceof Error?l.message:String(l)))}}let c={...this.DEFAULTS};for(let d of Object.keys(this.DEFAULTS))i[d]!==void 0&&(c[d]=i[d]);return this.finalizeSettings(c,t)}catch(s){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,s instanceof Error?s.message:String(s));let n=this.getAllDefaults();return this.finalizeSettings(n,t)}}};var Ft=require("crypto");function ee(r){return(r??"").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu," ").replace(/\s+/g," ").trim()}function H(r){return(r??"").toLowerCase().trim().split(/\s+/).filter(Boolean)}function le(r,e){return Math.log(1+e/(r+.5))}function Mt(r,e){return t=>le(r(t),e)}function Ut(r,e){let t=new Map;for(let s of new Set(r))t.set(s,e(s));return t}function yt(r,e,t){let s=Ut(r,t),n=Ut(e,t),i=0,o=0,a=0;for(let[_,E]of s){o+=E*E;let c=n.get(_);c!==void 0&&(i+=E*c)}for(let[,_]of n)a+=_*_;return o===0||a===0?0:i/Math.sqrt(o*a)}function vt(r,e,t,s){let n=new Set(r),i=new Set(e);for(let o of n)if(!i.has(o)&&t(o)>s)return!0;for(let o of i)if(!n.has(o)&&t(o)>s)return!0;return!1}function Pe(r,e,t,s){let n=ee(r);if(n!==""&&n===ee(e))return{tier:"exact",method:"exact",score:1};let i=H(r),o=H(e),a=s.minSharedTokens??2,_=new Set(o),E=0;for(let d of new Set(i))_.has(d)&&E++;if(E<a)return{tier:"none",method:"none",score:0};let c=yt(i,o,t);return c>=s.cosineThreshold&&!vt(i,o,t,s.vetoThetaIdf)?{tier:"candidate",method:"idf_cosine",score:c}:{tier:"none",method:"none",score:c}}function pe(r,e){return!!r&&!!e}function xe(r,e,t,s=!1){let n=ee(t);if(n==="")return null;let i=b(e),o=s?"subagent":"main";return(0,Ft.createHash)("sha256").update(`${r}\0${i}\0${o}\0${n}`).digest("hex").slice(0,32)}function wt(r,e,t){return t===null?null:r.prepare("SELECT id, occurrence_count, created_at_epoch FROM observations WHERE project = ? AND title_norm_key = ? ORDER BY created_at_epoch ASC, id ASC LIMIT 1").get(e,t)??null}function Pt(r,e,t){let s=[...new Set(H(t))],n=r.prepare("INSERT INTO token_df (project, token, df) VALUES (?, ?, 1) ON CONFLICT(project, token) DO UPDATE SET df = df + 1");for(let i of s)n.run(e,i);r.prepare("INSERT INTO dedup_meta (project, doc_count) VALUES (?, 1) ON CONFLICT(project) DO UPDATE SET doc_count = doc_count + 1").run(e)}function xt(r,e){return r.prepare("SELECT doc_count FROM dedup_meta WHERE project = ?").get(e)?.doc_count??0}function kt(r,e){let t=xt(r,e),s=r.prepare("SELECT token, df FROM token_df WHERE project = ?").all(e),n=new Map(s.map(i=>[i.token,i.df]));return{idfFn:Mt(i=>n.get(i)??0,t),docCount:t}}function Bt(r){return r.prepare("INSERT OR IGNORE INTO observation_dedup_candidates (observation_id, duplicate_of_id, project, method, score, status, created_at, created_at_epoch) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")}function Xt(r,e,t){return xt(r,e)>=t}function Fs(r,e,t=Number.POSITIVE_INFINITY){let s=r.prepare("SELECT COUNT(*) c FROM observations WHERE project = ?").get(e).c;if(s>t)return u.warn("DEDUP",`Skipping dedup backfill for project ${e}: ${s} rows exceeds cap ${t} (CLAUDE_MEM_DEDUP_MAX_BACKFILL_ROWS)`),0;let n=r.prepare("SELECT o.id, o.title, o.agent_id, o.agent_type, s.platform_source FROM observations o LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id WHERE o.project = ?").all(e),i=r.prepare("UPDATE observations SET title_norm_key = ? WHERE id = ?"),o=r.prepare("INSERT INTO token_df (project, token, df) VALUES (?, ?, ?)");return r.transaction(()=>{let _=new Map;for(let E of n){i.run(xe(e,E.platform_source,E.title,pe(E.agent_id,E.agent_type)),E.id);for(let c of new Set(H(E.title)))_.set(c,(_.get(c)??0)+1)}r.prepare("DELETE FROM token_df WHERE project = ?").run(e);for(let[E,c]of _)o.run(e,E,c);r.prepare("INSERT INTO dedup_meta (project, doc_count, last_rebuild_doc_count, deleted_since_rebuild) VALUES (?, ?, ?, 0) ON CONFLICT(project) DO UPDATE SET doc_count = excluded.doc_count, last_rebuild_doc_count = excluded.last_rebuild_doc_count, deleted_since_rebuild = 0").run(e,n.length,n.length)})(),n.length}function ws(r,e,t){let s=r.prepare("SELECT id, title FROM observations WHERE project = ? AND title IS NOT NULL ORDER BY id ASC").all(e);if(s.length<2)return 0;if(s.length>t.maxBackfillRows)return u.warn("DEDUP",`Skipping dedup sweep for project ${e}: ${s.length} rows exceeds cap ${t.maxBackfillRows}`),0;let{idfFn:n,docCount:i}=kt(r,e),o={cosineThreshold:t.cosineThreshold,vetoThetaIdf:le(t.idfVetoDf,i),minSharedTokens:t.minSharedTokens},a=s.map(f=>new Set(H(f.title))),_=new Map;for(let f of a)for(let g of f)_.set(g,(_.get(g)??0)+1);let E=Math.max(2,Math.ceil(Math.sqrt(s.length))*4),c=new Map;a.forEach((f,g)=>{for(let m of f){let N=_.get(m);if(N<2||N>E)continue;let A=c.get(m);A||(A=[],c.set(m,A)),A.push(g)}});let d=new Map;for(let f of c.values())for(let g=0;g<f.length;g++)for(let m=g+1;m<f.length;m++){let N=`${f[g]}:${f[m]}`;d.set(N,(d.get(N)??0)+1)}let l=Bt(r),O=new Date().toISOString(),L=Date.now(),I=0;for(let[f,g]of d){if(g<t.minSharedTokens)continue;let[m,N]=f.split(":").map(Number),A=Pe(s[m].title,s[N].title,n,o);A.tier==="candidate"&&(I+=l.run(s[N].id,s[m].id,e,A.method,A.score,"pending",O,L).changes)}return I}function Gt(r,e){return r.prepare("SELECT DISTINCT project FROM observations").all().map(s=>s.project).map(s=>{let n=Fs(r,s,e.maxBackfillRows),i=ws(r,s,e);return{project:s,docs:n,candidates:i}})}function Ht(r,e,t,s,n){if(!s)return 0;let{idfFn:i,docCount:o}=kt(r,e),a={cosineThreshold:n.cosineThreshold,vetoThetaIdf:le(n.idfVetoDf,o),minSharedTokens:n.minSharedTokens},_=r.prepare("SELECT id, title FROM observations WHERE project = ? AND id != ? AND title IS NOT NULL ORDER BY created_at_epoch DESC, id DESC LIMIT ?").all(e,t,n.maxScan);_.length===n.maxScan&&u.debug("DEDUP",`Tier-1 scan hit MAX_SCAN=${n.maxScan} for project ${e}; older rows covered by dedup-scan`);let E=Bt(r),c=new Date().toISOString(),d=Date.now(),l=0;for(let O of _){let L=Pe(s,O.title,i,a);L.tier==="candidate"&&(l+=E.run(t,O.id,e,L.method,L.score,"pending",c,d).changes)}return l}function jt(r,e,t,s,n){let i=Date.now()-s,o=n!==void 0?"up.session_db_id = ?":"up.content_session_id = ?",a=n??e;return r.prepare(`
|
|
107
|
+
`).all(...e,...t===void 0?[]:[t]).map(r=>({...r,fields:JSON.parse(r.fields)}))}var G=require("fs"),k=require("path"),te=require("os");var Ae={HEALTH_CHECK:3e3,API_REQUEST:3e4,SESSION_INIT_HOOK_CAP:15e3,SESSION_INIT_REQUEST:1e4,SESSION_INIT_REQUEST_MAX:14e3,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function ws(o=process.platform){return o==="win32"?8e3:5e3}function Dt(o=process.platform){return Ae.SESSION_INIT_HOOK_CAP-ws(o)}function Mt(o){return process.platform==="win32"?Math.round(o*Ae.WINDOWS_MULTIPLIER):o}function Ut(o){try{return new URL(o).hostname.toLowerCase()==="openrouter.ai"}catch{return!1}}var Ps="security_alert",xs="sync-hub.black-pond-afbb.workers.dev",ks="ziczmqtpmaxbornfghye.supabase.co",Bs="https://sync.cmem.ai",Xs=new Set(["xiaomi/mimo-v2-flash:free"]);function Gs(o){return typeof o=="boolean"?String(o):o}function Hs(o){let e=o.CLAUDE_MEM_OPENROUTER_MODEL;if(typeof e!="string"||!Xs.has(e.trim()))return!1;let t=typeof o.CLAUDE_MEM_OPENROUTER_BASE_URL=="string"?o.CLAUDE_MEM_OPENROUTER_BASE_URL.trim():"";return t===""||Ut(t)}var yt=18e4,vt=[{key:"CLAUDE_MEM_LLM_TIMEOUT_MS",legacy:"30000",markerTag:"llm-timeout-migrated-v1"},{key:"CLAUDE_MEM_FIELD_OPTIMIZE_TIMEOUT_MS",legacy:"30000",markerTag:"field-optimize-timeout-migrated-v1"}];function wt(o,e){return(0,k.join)((0,k.dirname)(o),`.${(0,k.basename)(o)}.${e.markerTag}`)}function Ge(o,e){try{(0,G.writeFileSync)(wt(o,e),new Date().toISOString(),{encoding:"utf-8",mode:384})}catch{}}var Ft=new Set;function $s(o){if(typeof o!="string")return null;let e=o.trim();if(e.length===0)return null;try{let t=new URL(e).hostname;if(t===xs||t===ks)return Bs}catch{return null}return null}var Y=class{static DEFAULTS={CLAUDE_MEM_MEMORY_SEARCH_HOOK_ENABLED:"true",CLAUDE_MEM_MEMORY_INSTRUCTIONS_ENABLED:"true",CLAUDE_MEM_MEMORY_WATCH_ROOTS:"",CLAUDE_MEM_MODEL:"claude-haiku-4-5-20251001",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_SESSION_START_INCLUDE_ALL_SOURCES:"false",CLAUDE_MEM_WORKER_PORT:String(37700+(process.getuid?.()??77)%100),CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_ALLOWED_ORIGINS:"",CLAUDE_MEM_PUBLIC_URL:"",CLAUDE_MEM_API_TIMEOUT_MS:String(Mt(Ae.API_REQUEST)),CLAUDE_MEM_SESSION_INIT_TIMEOUT_MS:String(Dt()),CLAUDE_MEM_IDLE_EXIT_SEC:"0",CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_SKIP_BASH_PATTERNS:"",CLAUDE_MEM_SKIP_SUBAGENT_OBSERVATIONS:"false",CLAUDE_MEM_SKIP_AGENT_TYPES:"",CLAUDE_MEM_CAPTURE_ADVISOR_CALLS:"false",CLAUDE_MEM_PROVIDER:"claude",CLAUDE_MEM_CODEX_MODEL:"",CLAUDE_MEM_CODEX_PATH:"codex",CLAUDE_MEM_CODEX_REASONING_EFFORT:"low",CLAUDE_MEM_CODEX_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_CODEX_OBSERVATION_BATCH_SIZE:"8",CLAUDE_MEM_CODEX_OBSERVATION_BATCH_MAX_CHARS:"32000",CLAUDE_MEM_CLAUDE_AUTH_METHOD:"subscription",CLAUDE_MEM_GEMINI_API_KEY:"",CLAUDE_MEM_GEMINI_API_KEYS:"",CLAUDE_MEM_GEMINI_MODEL:"gemini-flash-latest",CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED:"true",CLAUDE_MEM_OPENROUTER_API_KEY:"",CLAUDE_MEM_OPENROUTER_API_KEYS:"",CLAUDE_MEM_OPENROUTER_MODEL:"cohere/north-mini-code:free",CLAUDE_MEM_OPENROUTER_BASE_URL:"",CLAUDE_MEM_OPENROUTER_TEMPERATURE:"",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_OPENROUTER_EXTRA_BODY:"",CLAUDE_MEM_OPENROUTER_REASONING_EFFORT:"",CLAUDE_MEM_OPENAI_COMPAT_PRESET:"",CLAUDE_MEM_OPENAI_COMPAT_API_KEY:"",CLAUDE_MEM_OPENAI_COMPAT_API_KEYS:"",CLAUDE_MEM_OPENAI_COMPAT_BASE_URL:"",CLAUDE_MEM_OPENAI_COMPAT_MODEL:"",CLAUDE_MEM_QUOTA_FALLBACK_PROVIDER:"",CLAUDE_MEM_QUOTA_FALLBACK_MODEL:"",CLAUDE_MEM_QUOTA_THRESHOLD_FIVE_HOUR:"0.95",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY:"0.93",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY_OPUS:"0.93",CLAUDE_MEM_QUOTA_THRESHOLD_SEVEN_DAY_SONNET:"0.92",CLAUDE_MEM_QUOTA_THRESHOLD_OVERAGE:"0.95",CLAUDE_MEM_DATA_DIR:(0,k.join)((0,te.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",CLAUDE_MEM_CLAUDE_CONFIG_DIR:"",CLAUDE_MEM_OBSERVER_CLAUDE_CONFIG_DIR:"",CLAUDE_MEM_MODE:"code",CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT:"false",CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT:"true",CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES:"",CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS:"",CLAUDE_MEM_CONTEXT_FULL_COUNT:"0",CLAUDE_MEM_CONTEXT_FULL_FIELD:"narrative",CLAUDE_MEM_CONTEXT_SESSION_COUNT:"10",CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY:"true",CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE:"false",CLAUDE_MEM_CONTEXT_MAIN_AGENT_ONLY:"true",CLAUDE_MEM_REINFORCE_ALPHA:"0",CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT:"true",CLAUDE_MEM_WELCOME_HINT_ENABLED:"true",CLAUDE_MEM_WORK_STATE_ENABLED:"true",CLAUDE_MEM_FILE_READ_GATE_ENABLED:"true",CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED:"false",CLAUDE_MEM_FOLDER_USE_LOCAL_MD:"false",CLAUDE_MEM_TRANSCRIPTS_ENABLED:"true",CLAUDE_MEM_TRANSCRIPTS_CONFIG_PATH:(0,k.join)((0,te.homedir)(),".claude-mem","transcript-watch.json"),CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION:"false",CLAUDE_MEM_CODEX_SUBAGENT_INGESTION:"false",CLAUDE_MEM_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_OBSERVER_MAX_CONVERSATION_CHARS:"400000",CLAUDE_MEM_OBSERVER_CONTEXT_WINDOW:"",CLAUDE_MEM_OBSERVER_MAX_OUTPUT_TOKENS:"4096",CLAUDE_MEM_OBSERVE_BARE_PROMPTS:"false",CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD:"3",CLAUDE_MEM_REDACT_ENABLED:"false",CLAUDE_MEM_REDACT_DISABLED_BUILTINS:"",CLAUDE_MEM_REDACT_CUSTOM_PATTERNS:"[]",CLAUDE_MEM_REDACT_LOG_MATCHES:"false",CLAUDE_MEM_EXCLUDED_PROJECTS:"",CLAUDE_MEM_PROJECT_ENVIRONMENTS:"[]",CLAUDE_MEM_FOLDER_MD_EXCLUDE:"[]",CLAUDE_MEM_FOLDER_MD_SKELETON_DENYLIST:"[]",CLAUDE_MEM_SEMANTIC_INJECT:"false",CLAUDE_MEM_SEMANTIC_INJECT_LIMIT:"5",CLAUDE_MEM_SEMANTIC_INJECT_FORMAT:"narrative",CLAUDE_MEM_TIER_ROUTING_ENABLED:"true",CLAUDE_MEM_TIER_SIMPLE_MODEL:"haiku",CLAUDE_MEM_TIER_SUMMARY_MODEL:"",CLAUDE_MEM_TIER_FAST_MODEL:"haiku",CLAUDE_MEM_TIER_SMART_MODEL:"sonnet",CLAUDE_MEM_CHROMA_ENABLED:"true",CLAUDE_MEM_CHROMA_MODE:"local",CLAUDE_MEM_CHROMA_HOST:"127.0.0.1",CLAUDE_MEM_CHROMA_PORT:"8000",CLAUDE_MEM_CHROMA_SSL:"false",CLAUDE_MEM_CHROMA_API_KEY:"",CLAUDE_MEM_CHROMA_TENANT:"default_tenant",CLAUDE_MEM_CHROMA_DATABASE:"default_database",CLAUDE_MEM_CHROMA_PREWARM_TIMEOUT_MS:"120000",CLAUDE_MEM_CHROMA_MUTATION_TIMEOUT_MS:"600000",CLAUDE_MEM_CHROMA_MAX_PENDING_MUTATIONS:"5000",CLAUDE_MEM_CHROMA_EMBEDDING_FUNCTION:"default",CLAUDE_MEM_CHROMA_UVX_PATH:"",CLAUDE_MEM_CLOUD_SYNC_TOKEN:"",CLAUDE_MEM_CLOUD_SYNC_USER_ID:"",CLAUDE_MEM_CLOUD_SYNC_HUB_URL:"",CLAUDE_MEM_CLOUD_SYNC_DEVICE_ID:"",CLAUDE_MEM_CLOUD_SYNC_DEVICE_NAME:(0,te.hostname)(),CLAUDE_MEM_CLOUD_SYNC_WS:"true",CLAUDE_MEM_CLOUD_SYNC_CONTENT_BATCH_SIZE:"40",CLAUDE_MEM_CLOUD_SYNC_REQUEST_TIMEOUT_MS:"90000",CLAUDE_MEM_LLM_TIMEOUT_MS:String(yt),CLAUDE_MEM_FIELD_OPTIMIZE_TIMEOUT_MS:String(yt),CLAUDE_MEM_TV_TOKEN:"",CLAUDE_MEM_PRO_TRIAL_EMAIL:"",CLAUDE_MEM_PRO_TRIAL_AT:"",CLAUDE_MEM_PRO_TRIAL_STATE:"",CLAUDE_MEM_PRO_TRIAL_ENDS_AT:"",CLAUDE_MEM_PRO_PLAN:"",CLAUDE_MEM_PRO_FALLBACK_AT:"",CLAUDE_MEM_PRO_FALLBACK_MESSAGE:"",CLAUDE_MEM_PRO_FALLBACK_ACTION:"",CLAUDE_MEM_PRO_FALLBACK_URL:"",CLAUDE_MEM_PRO_MEMORY_KEY:"",CLAUDE_MEM_PRO_MEMORY_BASE_URL:"",CLAUDE_MEM_PRO_MEMORY_MODEL:"",CLAUDE_MEM_TELEGRAM_ENABLED:"true",CLAUDE_MEM_TELEGRAM_BOT_TOKEN:"",CLAUDE_MEM_TELEGRAM_CHAT_ID:"",CLAUDE_MEM_TELEGRAM_WRAPUPS_ENABLED:"true",CLAUDE_MEM_TELEGRAM_OBSERVATION_ALERTS_ENABLED:"false",CLAUDE_MEM_TELEGRAM_WRAPUP_ROUTES:"{}",CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:"security_alert,sensitive",CLAUDE_MEM_TELEGRAM_TRIGGER_CONCEPTS:"",CLAUDE_MEM_GROK_BOT_AWARENESS_ENABLED:"true",CLAUDE_MEM_GROK_BOT_AWARENESS_AGENT_IDS:"521e962d-2ec3-4488-bfbc-54d5209ce118,95601360-61f7-4fd9-bb3a-2c976b2b85c0",CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_TYPES:"decision,bugfix,security_alert,sensitive",CLAUDE_MEM_GROK_BOT_AWARENESS_TRIGGER_CONCEPTS:"",CLAUDE_MEM_GROK_BOT_WEBHOOK_URL:"",CLAUDE_MEM_GROK_BOT_WEBHOOK_SECRET:"",CLAUDE_MEM_GROK_BOT_INJECT_ENABLED:"true",CLAUDE_MEM_GROK_BOT_INJECT_AGENT_IDS:"*",CLAUDE_MEM_GROK_BOT_INJECT_TIER:"episode",CLAUDE_MEM_GROK_BOT_INJECT_WINDOW:"80",CLAUDE_MEM_GROK_BOT_INJECT_FALLBACK:"house",CLAUDE_MEM_GROK_BOT_INJECT_PLATFORM_SOURCE:"",CLAUDE_MEM_GROK_BOT_INJECT_PROJECTS_BY_AGENT:"",CLAUDE_MEM_GROK_BOT_INJECT_MAX_LINE_CHARS:"160",CLAUDE_MEM_GROK_BOT_INJECT_DEBOUNCE_MS:"1500",CLAUDE_MEM_GROK_BOT_INJECT_STANDING_LINE:"",CLAUDE_MEM_CCS_ALIGN_ENABLED:"true",CLAUDE_MEM_CCS_ALIGN_VIEWER_IDS:"ccs-align",CLAUDE_MEM_CCS_ALIGN_TRIGGER_TYPES:"decision,bugfix,security_alert,sensitive",CLAUDE_MEM_CCS_ALIGN_PATCH_SHADOWS:"false",CLAUDE_MEM_QUEUE_ENGINE:"sqlite",CLAUDE_MEM_REDIS_URL:"",CLAUDE_MEM_REDIS_HOST:"127.0.0.1",CLAUDE_MEM_REDIS_PORT:"6379",CLAUDE_MEM_REDIS_MODE:"external",CLAUDE_MEM_QUEUE_REDIS_PREFIX:`claude_mem_${process.env.CLAUDE_MEM_WORKER_PORT??String(37700+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_AUTH_MODE:"api-key",CLAUDE_MEM_RUNTIME:"worker",CLAUDE_MEM_SERVER_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_API_KEY:"",CLAUDE_MEM_SERVER_PROJECT_ID:"",CLAUDE_MEM_SERVER_BETA_URL:`http://127.0.0.1:${process.env.CLAUDE_MEM_SERVER_PORT??String(37877+(process.getuid?.()??77)%100)}`,CLAUDE_MEM_SERVER_BETA_API_KEY:"",CLAUDE_MEM_SERVER_BETA_PROJECT_ID:"",CLAUDE_MEM_DEDUP_ENABLED:"false",CLAUDE_MEM_DEDUP_COSINE_THRESHOLD:"0.80",CLAUDE_MEM_DEDUP_IDF_VETO_DF:"10",CLAUDE_MEM_DEDUP_MIN_SHARED_TOKENS:"2",CLAUDE_MEM_DEDUP_MIN_PROJECT_DOCS:"10",CLAUDE_MEM_DEDUP_MAX_SCAN:"2000",CLAUDE_MEM_DEDUP_MAX_BACKFILL_ROWS:"50000",CLAUDE_MEM_TOOL_USES_RETENTION_DAYS:"0",CLAUDE_MEM_WORKER_AUTOSTART:"true",CLAUDE_MEM_PROJECT_NAME_SOURCE:"path"};static getAllDefaults(){return{...this.DEFAULTS}}static get(e){let t=process.env[e]??this.DEFAULTS[e];return e==="CLAUDE_MEM_WORKER_HOST"?this.normalizeWorkerHost(t):t}static normalizeWorkerHost(e){return e==="localhost"?"127.0.0.1":e}static finalizeSettings(e,t){let s=t?this.applyEnvOverrides(e):e;return s.CLAUDE_MEM_WORKER_HOST=this.normalizeWorkerHost(s.CLAUDE_MEM_WORKER_HOST),s}static getInt(e){let t=this.get(e);return parseInt(t,10)}static applyEnvOverrides(e){let t={...e};for(let s of Object.keys(this.DEFAULTS))process.env[s]!==void 0&&(t[s]=process.env[s]);return t}static loadFromFile(e,t=!0,s={}){try{if(!(0,G.existsSync)(e)){let l=this.getAllDefaults();if(!s.readOnly)try{P(e,l,{mode:384});for(let p of vt)Ge(e,p);console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(p){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,p instanceof Error?p.message:String(p))}return this.finalizeSettings(l,t)}let n=(0,G.readFileSync)(e,"utf-8"),i=ye(n),r=K(i),a=r!==i,_=rt(i),E=a&&Object.keys(_).some(l=>l!=="env");if(a&&!E&&!s.readOnly)try{P(e,r,{mode:384}),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(l){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,l instanceof Error?l.message:String(l))}if(r.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES===Ps&&(r={...r,CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:this.DEFAULTS.CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES},!s.readOnly))try{P(e,E?{..._,env:r}:r,{mode:384}),console.warn("[SETTINGS] Migrated Telegram trigger types off the legacy default:",e)}catch(l){console.warn("[SETTINGS] Failed to migrate Telegram trigger types:",e,l instanceof Error?l.message:String(l))}if(Hs(r)){let l=String(r.CLAUDE_MEM_OPENROUTER_MODEL).trim();if(r={...r,CLAUDE_MEM_OPENROUTER_MODEL:this.DEFAULTS.CLAUDE_MEM_OPENROUTER_MODEL},!s.readOnly)try{P(e,E?{..._,env:r}:r,{mode:384}),console.warn(`[SETTINGS] Migrated OpenRouter model off the retired default ${l} to ${this.DEFAULTS.CLAUDE_MEM_OPENROUTER_MODEL}:`,e)}catch(p){console.warn("[SETTINGS] Failed to migrate the retired OpenRouter model:",e,p instanceof Error?p.message:String(p))}}let d=$s(r.CLAUDE_MEM_CLOUD_SYNC_HUB_URL);if(d!==null&&(r={...r,CLAUDE_MEM_CLOUD_SYNC_HUB_URL:d},!s.readOnly))try{P(e,E?{..._,env:r}:r,{mode:384}),console.warn("[SETTINGS] Migrated cloud sync hub URL to",d,"from a retired hub host:",e)}catch(l){console.warn("[SETTINGS] Failed to migrate cloud sync hub URL:",e,l instanceof Error?l.message:String(l))}for(let l of vt)if(!(0,G.existsSync)(wt(e,l))){if(r[l.key]!==l.legacy){s.readOnly||Ge(e,l);continue}if(r={...r,[l.key]:this.DEFAULTS[l.key]},!s.readOnly)try{P(e,E?{..._,env:r}:r,{mode:384}),Ge(e,l),console.warn(`[SETTINGS] Migrated ${l.key} off the old ${l.legacy}ms default to ${this.DEFAULTS[l.key]}ms:`,e)}catch(p){let S=`${l.key}\0${e}`;Ft.has(S)||(Ft.add(S),console.warn(`[SETTINGS] Failed to migrate ${l.key}; using the new default in memory (reported once per process):`,e,p instanceof Error?p.message:String(p)))}}let u={...this.DEFAULTS};for(let l of Object.keys(this.DEFAULTS))r[l]!==void 0&&(u[l]=Gs(r[l]));return this.finalizeSettings(u,t)}catch(n){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,n instanceof Error?n.message:String(n));let i=this.getAllDefaults();return this.finalizeSettings(i,t)}}};var Xt=require("crypto");function se(o){let e=(o??"").normalize("NFC").toLowerCase().replace(/[^\p{L}\p{N}\p{M}\s]/gu," ").replace(/\s+/g," ").trim();return/[\p{L}\p{N}]/u.test(e)?e:""}function H(o){return(o??"").toLowerCase().trim().split(/\s+/).filter(Boolean)}function He(o,e){return Math.log(1+e/(o+.5))}function Pt(o,e){return t=>He(o(t),e)}function xt(o,e){let t=new Map;for(let s of new Set(o))t.set(s,e(s));return t}function kt(o,e,t){let s=xt(o,t),n=xt(e,t),i=0,r=0,a=0;for(let[_,E]of s){r+=E*E;let d=n.get(_);d!==void 0&&(i+=E*d)}for(let[,_]of n)a+=_*_;return r===0||a===0?0:i/Math.sqrt(r*a)}function Bt(o,e,t,s){let n=new Set(o),i=new Set(e);for(let r of n)if(!i.has(r)&&t(r)>s)return!0;for(let r of i)if(!n.has(r)&&t(r)>s)return!0;return!1}function $e(o,e,t,s){let n=se(o);if(n!==""&&n===se(e))return{tier:"exact",method:"exact",score:1};let i=H(o),r=H(e),a=s.minSharedTokens??2,_=new Set(r),E=0;for(let u of new Set(i))_.has(u)&&E++;if(E<a)return{tier:"none",method:"none",score:0};let d=kt(i,r,t);return d>=s.cosineThreshold&&!Bt(i,r,t,s.vetoThetaIdf)?{tier:"candidate",method:"idf_cosine",score:d}:{tier:"none",method:"none",score:d}}function ne(o,e){return!!o&&!!e}function ge(o,e,t,s=!1){let n=se(t);if(n==="")return null;let i=b(e),r=s?"subagent":"main";return(0,Xt.createHash)("sha256").update(`${o}\0${i}\0${r}\0${n}`).digest("hex").slice(0,32)}function Gt(o,e,t){return t===null?null:o.prepare("SELECT id, occurrence_count, created_at_epoch FROM observations WHERE project = ? AND title_norm_key = ? ORDER BY created_at_epoch ASC, id ASC LIMIT 1").get(e,t)??null}function Ht(o,e,t){let s=[...new Set(H(t))],n=o.prepare("INSERT INTO token_df (project, token, df) VALUES (?, ?, 1) ON CONFLICT(project, token) DO UPDATE SET df = df + 1");for(let i of s)n.run(e,i);o.prepare("INSERT INTO dedup_meta (project, doc_count) VALUES (?, 1) ON CONFLICT(project) DO UPDATE SET doc_count = doc_count + 1").run(e)}function $t(o,e){return He(o+1,e)}function jt(o,e){return o.prepare("SELECT doc_count FROM dedup_meta WHERE project = ?").get(e)?.doc_count??0}function Wt(o,e){let t=jt(o,e),s=o.prepare("SELECT token, df FROM token_df WHERE project = ?").all(e),n=new Map(s.map(i=>[i.token,i.df]));return{idfFn:Pt(i=>n.get(i)??0,t),docCount:t}}function Kt(o){return o.prepare("INSERT OR IGNORE INTO observation_dedup_candidates (observation_id, duplicate_of_id, project, method, score, status, created_at, created_at_epoch) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")}function Yt(o,e,t){return jt(o,e)>=t}function js(o,e,t=Number.POSITIVE_INFINITY){let s=o.prepare("SELECT COUNT(*) c FROM observations WHERE project = ?").get(e).c;if(s>t)return c.warn("DEDUP",`Skipping dedup backfill for project ${e}: ${s} rows exceeds cap ${t} (CLAUDE_MEM_DEDUP_MAX_BACKFILL_ROWS)`),0;let n=o.prepare("SELECT o.id, o.title, o.agent_id, o.agent_type, s.platform_source FROM observations o LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id WHERE o.project = ?").all(e),i=o.prepare("UPDATE observations SET title_norm_key = ? WHERE id = ?"),r=o.prepare("INSERT INTO token_df (project, token, df) VALUES (?, ?, ?)");return o.transaction(()=>{let _=new Map;for(let E of n){i.run(ge(e,E.platform_source,E.title,ne(E.agent_id,E.agent_type)),E.id);for(let d of new Set(H(E.title)))_.set(d,(_.get(d)??0)+1)}o.prepare("DELETE FROM token_df WHERE project = ?").run(e);for(let[E,d]of _)r.run(e,E,d);o.prepare("INSERT INTO dedup_meta (project, doc_count, last_rebuild_doc_count, deleted_since_rebuild) VALUES (?, ?, ?, 0) ON CONFLICT(project) DO UPDATE SET doc_count = excluded.doc_count, last_rebuild_doc_count = excluded.last_rebuild_doc_count, deleted_since_rebuild = 0").run(e,n.length,n.length)})(),n.length}function Ws(o,e,t){let s=o.prepare("SELECT id, title FROM observations WHERE project = ? AND title IS NOT NULL ORDER BY id ASC").all(e);if(s.length<2)return 0;if(s.length>t.maxBackfillRows)return c.warn("DEDUP",`Skipping dedup sweep for project ${e}: ${s.length} rows exceeds cap ${t.maxBackfillRows}`),0;let{idfFn:n,docCount:i}=Wt(o,e),r={cosineThreshold:t.cosineThreshold,vetoThetaIdf:$t(t.idfVetoDf,i),minSharedTokens:t.minSharedTokens},a=s.map(f=>new Set(H(f.title))),_=new Map;for(let f of a)for(let C of f)_.set(C,(_.get(C)??0)+1);let E=Math.max(2,Math.ceil(Math.sqrt(s.length))*4),d=new Map;a.forEach((f,C)=>{for(let R of f){let m=_.get(R);if(m<2||m>E)continue;let A=d.get(R);A||(A=[],d.set(R,A)),A.push(C)}});let u=new Map;for(let f of d.values())for(let C=0;C<f.length;C++)for(let R=C+1;R<f.length;R++){let m=`${f[C]}:${f[R]}`;u.set(m,(u.get(m)??0)+1)}let l=Kt(o),p=new Date().toISOString(),S=Date.now(),h=0;for(let[f,C]of u){if(C<t.minSharedTokens)continue;let[R,m]=f.split(":").map(Number),A=$e(s[R].title,s[m].title,n,r);A.tier==="candidate"&&(h+=l.run(s[m].id,s[R].id,e,A.method,A.score,"pending",p,S).changes)}return h}function Vt(o,e){return o.prepare("SELECT DISTINCT project FROM observations").all().map(s=>s.project).map(s=>{let n=js(o,s,e.maxBackfillRows),i=Ws(o,s,e);return{project:s,docs:n,candidates:i}})}function qt(o,e,t,s,n){if(!s)return 0;let{idfFn:i,docCount:r}=Wt(o,e),a={cosineThreshold:n.cosineThreshold,vetoThetaIdf:$t(n.idfVetoDf,r),minSharedTokens:n.minSharedTokens},_=o.prepare("SELECT id, title FROM observations WHERE project = ? AND id != ? AND title IS NOT NULL ORDER BY created_at_epoch DESC, id DESC LIMIT ?").all(e,t,n.maxScan);_.length===n.maxScan&&c.debug("DEDUP",`Tier-1 scan hit MAX_SCAN=${n.maxScan} for project ${e}; older rows covered by dedup-scan`);let E=Kt(o),d=new Date().toISOString(),u=Date.now(),l=0;for(let p of _){let S=$e(s,p.title,i,a);S.tier==="candidate"&&(l+=E.run(t,p.id,e,S.method,S.score,"pending",d,u).changes)}return l}function Jt(o,e,t,s,n){let i=Date.now()-s,r=n!==void 0?"up.session_db_id = ?":"up.content_session_id = ?",a=n??e;return o.prepare(`
|
|
108
108
|
SELECT
|
|
109
109
|
up.*,
|
|
110
110
|
s.memory_session_id,
|
|
111
111
|
s.project,
|
|
112
|
-
COALESCE(s.platform_source, '${
|
|
112
|
+
COALESCE(s.platform_source, '${T}') as platform_source
|
|
113
113
|
FROM user_prompts up
|
|
114
114
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
115
|
-
WHERE ${
|
|
115
|
+
WHERE ${r}
|
|
116
116
|
AND up.prompt_text = ?
|
|
117
117
|
AND up.created_at_epoch >= ?
|
|
118
118
|
ORDER BY up.created_at_epoch DESC
|
|
119
119
|
LIMIT 1
|
|
120
|
-
`).get(a,t,i)??void 0}var
|
|
120
|
+
`).get(a,t,i)??void 0}var Oe=require("fs");var Ks=[{name:"aws_access_key",regex:/AKIA[0-9A-Z]{16}/g},{name:"aws_secret_key",regex:/(?<=AWS_SECRET_ACCESS_KEY\s*[=:]\s*['"]?)[A-Za-z0-9/+=]{40}/g},{name:"github_pat",regex:/\bgh[oprs]_[A-Za-z0-9]{36}\b|\bgithub_pat_[A-Za-z0-9_]{82}\b/g},{name:"openai_key",regex:/\bsk-(?!ant-)[A-Za-z0-9_-]{20,}\b/g},{name:"anthropic_key",regex:/\bsk-ant-[A-Za-z0-9_-]{20,}\b/g},{name:"slack_token",regex:/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g},{name:"jwt",regex:/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{name:"private_key_pem",regex:/-----BEGIN (?:RSA |DSA |EC |OPENSSH |PGP )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |DSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/g},{name:"stripe_key",regex:/\b(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g},{name:"google_api_key",regex:/\bAIza[0-9A-Za-z_-]{35}\b/g},{name:"claude_mem_key",regex:/\bcmem_[A-Za-z0-9_-]{32,}|\bcm_pro_[A-Za-z0-9_-]{8,}/g}],Ys=1024*1024,Vs="<redacted type='oversize'/>";function Zt(o,e){if(!e.enabled||o.length===0)return{redacted:o,counts:{},oversize:!1};if(o.length>Ys)return c.warn("REDACT","field exceeds the 1M-char redaction cap; replaced by an oversize marker",void 0,{inputLength:o.length}),{redacted:Vs,counts:{oversize:1},oversize:!0};let t=new Set(e.disabledBuiltinPatterns??[]),s={},n=o,i=[];for(let a of e.customPatterns??[]){if(!a.name||a.name.length===0){c.warn("REDACT","custom pattern skipped: missing name",void 0,{pattern:a});continue}try{i.push({name:a.name,regex:new RegExp(a.regex,"g")})}catch(_){c.warn("REDACT","custom pattern skipped: invalid regex",{name:a.name},_ instanceof Error?_:new Error(String(_)))}}let r=[...i,...Ks];for(let a of r)t.has(a.name)||(a.regex.lastIndex=0,n=n.replace(a.regex,()=>(s[a.name]=(s[a.name]??0)+1,`<redacted type='${a.name}'/>`)));return e.logMatches&&Object.keys(s).length>0&&c.debug("REDACT","patterns matched",void 0,{counts:s}),{redacted:n,counts:s,oversize:!1}}function qs(o){if(!o||o.trim()==="")return[];try{let e=JSON.parse(o);return Array.isArray(e)?e.filter(t=>t&&typeof t.name=="string"&&typeof t.regex=="string"):(c.warn("REDACT","CLAUDE_MEM_REDACT_CUSTOM_PATTERNS is not a JSON array, ignoring"),[])}catch(e){return c.warn("REDACT","failed to parse CLAUDE_MEM_REDACT_CUSTOM_PATTERNS as JSON",void 0,e instanceof Error?e:new Error(String(e))),[]}}function Js(o){return{enabled:o.CLAUDE_MEM_REDACT_ENABLED==="true",disabledBuiltinPatterns:(o.CLAUDE_MEM_REDACT_DISABLED_BUILTINS??"").split(",").map(e=>e.trim()).filter(Boolean),customPatterns:qs(o.CLAUDE_MEM_REDACT_CUSTOM_PATTERNS??"[]"),logMatches:o.CLAUDE_MEM_REDACT_LOG_MATCHES==="true"}}var re=null,zt=0,zs=5e3,oe=null,Qt=!1,Qs={enabled:!0,disabledBuiltinPatterns:[],customPatterns:[],logMatches:!1},Zs=/"CLAUDE_MEM_REDACT_ENABLED"\s*:\s*"true"/;function en(o){if(!(0,Oe.existsSync)(o))return null;try{return(0,Oe.readFileSync)(o,"utf-8")}catch{return""}}function tn(o){if(o===null)return!1;try{let e=JSON.parse(Ue(o));return e===null||typeof e!="object"||Array.isArray(e)}catch{return!0}}function sn(o,e,t){return process.env.CLAUDE_MEM_REDACT_ENABLED==="false"||!(oe?.enabled===!0||Zs.test(e))?t:(Qt||(Qt=!0,c.warn("REDACT","settings.json could not be read; secret redaction stays on until it is repaired",{settingsPath:o,using:oe?.enabled?"the last configuration that loaded":"the built-in patterns"})),oe?.enabled?oe:Qs)}function es(o=pe){let e=Date.now();if(re&&e-zt<zs)return re;let t=Y.loadFromFile(o),s=Js(t),n=s.enabled?null:en(o);return tn(n)?re=sn(o,n,s):(re=s,oe=s),zt=e,re}var ns=["private","claude-mem-context","system_instruction","system-instruction","persisted-output","system-reminder"],ts=new RegExp(`<(${ns.join("|")})\\b[^>]*>[\\s\\S]*?</\\1>`,"g");var ss=100;function nn(o){let e=Object.fromEntries(ns.map(i=>[i,0]));ts.lastIndex=0;let t=0,s=o.replace(ts,(i,r)=>(e[r]=(e[r]??0)+1,t+=1,""));return t>ss&&c.warn("SYSTEM","tag count exceeds limit",void 0,{tagCount:t,maxAllowed:ss,contentLength:o.length}),{stripped:Zt(s.trim(),es()).redacted,counts:e}}function fe(o){return nn(o).stripped}var rn=["task-notification"],kr=new RegExp(`^\\s*<(${rn.join("|")})\\b[^>]*>(?:(?!<\\1\\b|</\\1\\b)[\\s\\S])*</\\1>\\s*$`),Br=256*1024;var je=4e3,We="[media prompt]";function ie(o){let e=o.trim(),s=fe(o).trim()||e;return s.length<=je?s:(c.debug("DB","Truncated stored prompt text to the configured cap",{originalLength:s.length,storedLength:je}),`${s.slice(0,je-1)}\u2026`)}var on=require("bun:sqlite");var an=5e3,_n=4194304,q=65;function En(o){return o.prepare("PRAGMA user_version").get().user_version}var Ke=class extends Error{reason="schema_newer_than_binary";constructor(e){super(e),this.name="SchemaNewerThanBinaryError"}};function Re(o,e){let t=En(o);if(!(t<=e))throw new Ke(`SQLite database has schema v${t}; this claude-mem knows up to schema v${e}. Upgrade claude-mem before opening this database.`)}function Ne(o,e){o.run(`PRAGMA user_version = ${e}`)}function dn(o){return o.prepare(`
|
|
121
121
|
SELECT name
|
|
122
122
|
FROM sqlite_master
|
|
123
123
|
WHERE type = 'table'
|
|
124
124
|
AND name NOT LIKE 'sqlite_%'
|
|
125
125
|
LIMIT 1
|
|
126
|
-
`).get()!=null}function V(
|
|
126
|
+
`).get()!=null}function V(o,e,t){try{o.run(e)}catch(s){let n=s instanceof Error?s:new Error(String(s));throw c.warn("DB",`Failed to apply SQLite pragma ${t}`,{sql:e},n),s}}function be(o,e={}){let{enableWal:t=!0,enableIncrementalAutoVacuum:s=!0}=e;V(o,`PRAGMA busy_timeout = ${an}`,"busy_timeout"),V(o,"PRAGMA foreign_keys = ON","foreign_keys"),V(o,"PRAGMA synchronous = NORMAL","synchronous"),V(o,`PRAGMA journal_size_limit = ${_n}`,"journal_size_limit"),s&&!dn(o)&&V(o,"PRAGMA auto_vacuum = INCREMENTAL","auto_vacuum"),t&&V(o,"PRAGMA journal_mode = WAL","journal_mode")}var rs=!1;function Ce(o,...e){return typeof o.iterate=="function"?o.iterate(...e):(rs||(rs=!0,c.warn("DB","bun:sqlite lacks Statement.iterate(); falling back to .all()",{bunVersion:typeof Bun<"u"?Bun.version:"unknown",requiredBunVersion:">=1.1.31",impact:"rows are materialized in memory; upgrade Bun to restore streaming"})),o.all(...e))}function Ye(o,e,t,s){try{let n=Number(s.limit);if(!Number.isInteger(n)||n<0)throw new Error("Page limit must be a non-negative integer");let i=Number(s.offset??0);if(!Number.isInteger(i))throw new Error("Page offset must be an integer");let r=[];if(n===0)return r;let a=Math.max(0,i);for(let _ of Ce(o,...e))if(t(_)){if(a>0){a--;continue}if(r.push(_),r.length===n)break}return r}finally{o.finalize()}}var Je=require("bun:sqlite");function J(o){return o.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/\/+$/,"")}function Ve(o,e){let t=J(o),s=J(e);if(t.startsWith(s+"/"))return!t.slice(s.length+1).includes("/");let n=s.split("/"),i=t.split("/");if(i.length<2)return s===""||s===".";let r=i.slice(0,-1).join("/"),a=i[i.length-1],_=/^([A-Za-z]:)?\//;if(!_.test(s)&&_.test(t)&&s!==""&&r.endsWith("/"+s))return a!=="";if(s.endsWith("/"+r)||s===r)return!a.includes("/");for(let E=0;E<n.length;E++)if(n.slice(E).join("/")===r)return!0;return!1}var cn=/^\d{4}-\d{2}-\d{2}$/;function $(o,e){if(typeof o=="number")return o;let t=o.trim(),s=new Date(t).getTime();return e==="end"&&cn.test(t)?s+864e5-1:s}var qe="\\u0E00-\\u0EFF\\u1000-\\u109F\\u1780-\\u17FF\\u3040-\\u30FF\\u3100-\\u318F\\u3400-\\u4DBF\\u4E00-\\u9FFF\\uAC00-\\uD7AF\\uF900-\\uFAFF",os=["observations_ai","observations_ad","observations_au"],is=["session_summaries_ai","session_summaries_ad","session_summaries_au"],ae=`
|
|
127
127
|
CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN
|
|
128
128
|
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
|
129
129
|
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
|
@@ -141,7 +141,7 @@ ${L.stack??""}
|
|
|
141
141
|
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
|
142
142
|
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
|
143
143
|
END;
|
|
144
|
-
`,
|
|
144
|
+
`,_e=`
|
|
145
145
|
CREATE TRIGGER IF NOT EXISTS session_summaries_ai AFTER INSERT ON session_summaries BEGIN
|
|
146
146
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
147
147
|
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
@@ -159,7 +159,7 @@ ${L.stack??""}
|
|
|
159
159
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
160
160
|
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
161
161
|
END;
|
|
162
|
-
`,
|
|
162
|
+
`,as=class o{db;constructor(e=me){e instanceof Je.Database?this.db=e:(Te(M),this.db=new Je.Database(e)),Re(this.db,q),be(this.db),this._fts5Available=this.isFts5Available(),this.ensureFTSTables()}_fts5Available;ensureFTSTables(){let e=this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%_fts'").all(),t=e.some(r=>r.name==="observations_fts"),s=e.some(r=>r.name==="session_summaries_fts");if(t&&s&&this.hasAllFtsTriggers(os)&&this.hasAllFtsTriggers(is))return;if(!this.isFts5Available()){c.warn("DB","FTS5 not available on this platform \u2014 skipping FTS table creation (search uses ChromaDB)");return}let n=t&&s;c.info("DB",n?"Converging FTS5 indexes and recreating missing sync triggers":"Creating FTS5 tables");let i=!1;try{this.db.transaction(()=>{let r=this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%_fts'").all(),a=!r.some(u=>u.name==="observations_fts"),_=!r.some(u=>u.name==="session_summaries_fts"),E=!a&&!this.hasAllFtsTriggers(os),d=!_&&!this.hasAllFtsTriggers(is);this.createFTSTablesAndTriggers(a,_),E&&(this.rebuildFtsIndex("observations_fts"),this.db.run(ae)),d&&(this.rebuildFtsIndex("session_summaries_fts"),this.db.run(_e))}).immediate(),i=!0,c.info("DB",n?"FTS5 indexes converged and sync triggers recreated":"FTS5 tables created successfully")}catch(r){this._fts5Available=!1,c.warn("DB","FTS5 table creation failed \u2014 search will use ChromaDB and LIKE queries",{},r instanceof Error?r:void 0)}i&&Ne(this.db,q)}hasAllFtsTriggers(e){let t=e.map(()=>"?").join(", ");return this.db.prepare(`SELECT name FROM sqlite_master WHERE type='trigger' AND name IN (${t})`).all(...e).length===e.length}rebuildFtsIndex(e){this.db.run(`INSERT INTO ${e}(${e}) VALUES('rebuild')`)}isFts5Available(){try{return this.db.run("CREATE VIRTUAL TABLE temp._fts5_probe USING fts5(test_column)"),this.db.run("DROP TABLE temp._fts5_probe"),!0}catch(e){return c.debug("DB","FTS5 probe failed \u2014 FTS5 unavailable on this platform",void 0,e instanceof Error?e:new Error(String(e))),!1}}canReadFtsIndex(e){try{return this.db.prepare(`SELECT rowid FROM ${e} WHERE ${e} MATCH ? LIMIT 0`).all('"fts_read_probe"'),!0}catch{return!1}}createFTSTablesAndTriggers(e,t){e&&(this.db.run(`
|
|
163
163
|
CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5(
|
|
164
164
|
title,
|
|
165
165
|
subtitle,
|
|
@@ -174,7 +174,7 @@ ${L.stack??""}
|
|
|
174
174
|
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
|
175
175
|
SELECT id, title, subtitle, narrative, text, facts, concepts
|
|
176
176
|
FROM observations;
|
|
177
|
-
`),this.db.run(
|
|
177
|
+
`),this.db.run(ae)),t&&(this.db.run(`
|
|
178
178
|
CREATE VIRTUAL TABLE IF NOT EXISTS session_summaries_fts USING fts5(
|
|
179
179
|
request,
|
|
180
180
|
investigated,
|
|
@@ -189,30 +189,33 @@ ${L.stack??""}
|
|
|
189
189
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
190
190
|
SELECT id, request, investigated, learned, completed, next_steps, notes
|
|
191
191
|
FROM session_summaries;
|
|
192
|
-
`),this.db.run(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
`),this.db.run(_e))}buildFilterClause(e,t,s="o"){let n=[],i=w(e);if(i.length>0){let r=x(s,i,{includeMerged:!0});n.push(r.sql),t.push(...r.params)}if(e.platformSource&&(n.push(`COALESCE(NULLIF((SELECT s2.platform_source FROM sdk_sessions s2 WHERE s2.memory_session_id = ${s}.memory_session_id), ''), '${T}') = ?`),t.push(b(e.platformSource))),e.type)if(Array.isArray(e.type)){let r=e.type.map(()=>"?").join(",");n.push(`${s}.type IN (${r})`),t.push(...e.type)}else n.push(`${s}.type = ?`),t.push(e.type);if(e.dateRange){let{start:r,end:a}=e.dateRange;r&&(n.push(`${s}.created_at_epoch >= ?`),t.push($(r,"start"))),a&&(n.push(`${s}.created_at_epoch <= ?`),t.push($(a,"end")))}if(e.concepts){let r=Array.isArray(e.concepts)?e.concepts:[e.concepts],a=`${s}.concepts`,_=`CASE WHEN json_valid(${a}) THEN CASE
|
|
193
|
+
WHEN json_type(${a}) = 'array' THEN ${a}
|
|
194
|
+
WHEN json_type(${a}) = 'text' THEN json_array(json_extract(${a}, '$'))
|
|
195
|
+
ELSE json_array(${a}) END ELSE json_array(${a}) END`,E=r.map(()=>`EXISTS (SELECT 1 FROM json_each(${_}) WHERE type = 'text' AND value = ?)`);E.length>0&&(n.push(`(${E.join(" OR ")})`),t.push(...r))}if(e.files){let r=Array.isArray(e.files)?e.files:[e.files],a=s==="s"?"files_edited":"files_modified",_=r.map(()=>`(
|
|
196
|
+
EXISTS (SELECT 1 FROM json_each(${o.fileArrayJson(`${s}.files_read`)}) WHERE type = 'text' AND value LIKE ? ESCAPE '\\')
|
|
197
|
+
OR EXISTS (SELECT 1 FROM json_each(${o.fileArrayJson(`${s}.${a}`)}) WHERE type = 'text' AND value LIKE ? ESCAPE '\\')
|
|
198
|
+
)`);_.length>0&&(n.push(`(${_.join(" OR ")})`),r.forEach(E=>{let d=E.replace(/[\\%_]/g,"\\$&");t.push(`%${d}%`,`%${d}%`)}))}return n.length>0?n.join(" AND "):""}static UNSEGMENTED_SCRIPT=new RegExp(`[${qe}]`);static UNSEGMENTED_RUN=new RegExp(`[${qe}]+|[^\\s${qe}]+`,"g");static MAX_SUBSTRING_TERMS=500;static buildSubstringClause(e,t){let s=[...new Set(e.match(o.UNSEGMENTED_RUN)??[])].slice(0,o.MAX_SUBSTRING_TERMS);s.length===0&&s.push(e);let n=[];return{clause:`(${s.map(r=>{let a=`%${r.replace(/[\\%_]/g,"\\$&")}%`;for(let _=0;_<t.length;_+=1)n.push(a);return`(${t.map(_=>`${_} LIKE ? ESCAPE '\\'`).join(" OR ")})`}).join(" AND ")})`,params:n}}static MIN_ANY_TERM_TOKENS=3;static buildFTSMatchQuery(e){let t=(e.match(/\S+/g)??[]).filter(s=>/[\p{L}\p{N}]/u.test(s));return t.length===0?`"${e.replace(/"/g,'""')}"`:t.map(s=>`"${s.replace(/"/g,'""')}"`).join(" AND ")}static buildFTSAnyTermQuery(e){let t=(e.match(/\S+/g)??[]).filter(s=>/[\p{L}\p{N}]/u.test(s));return t.length<o.MIN_ANY_TERM_TOKENS?null:t.map(s=>`"${s.replace(/"/g,'""')}"`).join(" OR ")}buildOrderClause(e="relevance",t=!0,s="observations_fts"){switch(e){case"relevance":return t?`ORDER BY ${s}.rank ASC`:"ORDER BY o.created_at_epoch DESC";case"date_desc":return"ORDER BY o.created_at_epoch DESC, o.id DESC";case"date_asc":return"ORDER BY o.created_at_epoch ASC, o.id ASC";default:return"ORDER BY o.created_at_epoch DESC"}}searchObservationsBySubstring(e,t,s,n,i){let r=o.buildSubstringClause(e,["o.title","o.subtitle","o.narrative","o.text","o.facts","o.concepts"]),a=[],_=this.buildFilterClause(t,a,"o"),E=`
|
|
196
199
|
SELECT o.*, o.discovery_tokens
|
|
197
200
|
FROM observations o
|
|
198
|
-
WHERE ${
|
|
201
|
+
WHERE ${r.clause}
|
|
199
202
|
${_?"AND "+_:""}
|
|
200
203
|
${this.buildOrderClause(s,!1)}
|
|
201
204
|
LIMIT ? OFFSET ?
|
|
202
|
-
`;return this.db.prepare(E).all(...
|
|
205
|
+
`;return this.db.prepare(E).all(...r.params,...a,n,i)}searchSessionsBySubstring(e,t,s,n,i){let r=o.buildSubstringClause(e,["s.request","s.investigated","s.learned","s.completed","s.next_steps","s.notes"]),a={...t};delete a.type;let _=[],E=this.buildFilterClause(a,_,"s"),d=s==="date_asc"?"ORDER BY s.created_at_epoch ASC, s.id ASC":"ORDER BY s.created_at_epoch DESC, s.id DESC",u=`
|
|
203
206
|
SELECT s.*, s.discovery_tokens
|
|
204
207
|
FROM session_summaries s
|
|
205
|
-
WHERE ${
|
|
208
|
+
WHERE ${r.clause}
|
|
206
209
|
${E?"AND "+E:""}
|
|
207
|
-
${
|
|
210
|
+
${d}
|
|
208
211
|
LIMIT ? OFFSET ?
|
|
209
|
-
`;return this.db.prepare(
|
|
212
|
+
`;return this.db.prepare(u).all(...r.params,..._,n,i)}searchObservations(e,t={}){let s=[],{limit:n=50,offset:i=0,orderBy:r="relevance",...a}=t;if(!e){let _=this.buildFilterClause(a,s,"o");if(!_)return[];let E=this.buildOrderClause(r,!1),d=`
|
|
210
213
|
SELECT o.*, o.discovery_tokens
|
|
211
214
|
FROM observations o
|
|
212
215
|
WHERE ${_}
|
|
213
216
|
${E}
|
|
214
217
|
LIMIT ? OFFSET ?
|
|
215
|
-
`;return s.push(n,i),this.db.prepare(
|
|
218
|
+
`;return s.push(n,i),this.db.prepare(d).all(...s)}if(o.UNSEGMENTED_SCRIPT.test(e))return this.searchObservationsBySubstring(e,a,r,n,i);if(this._fts5Available||this.canReadFtsIndex("observations_fts")){let _=this.buildFilterClause(a,s,"o"),E=this.buildOrderClause(r,!0,"observations_fts"),d=`
|
|
216
219
|
SELECT o.*, o.discovery_tokens
|
|
217
220
|
FROM observations o
|
|
218
221
|
JOIN observations_fts ON observations_fts.rowid = o.id
|
|
@@ -220,79 +223,81 @@ ${L.stack??""}
|
|
|
220
223
|
${_?"AND "+_:""}
|
|
221
224
|
${E}
|
|
222
225
|
LIMIT ? OFFSET ?
|
|
223
|
-
`;s.unshift(
|
|
226
|
+
`;s.unshift(o.buildFTSMatchQuery(e));let u;try{u=this.db.prepare(d).all(...s,n,i)}catch(p){throw c.warn("DB","FTS5 observation search failed",{},p instanceof Error?p:void 0),p}if(u.length>0||i>0&&this.db.prepare(d).all(...s,1,0).length>0)return u;let l=this.searchObservationsBySubstring(e,a,r,n,i);return l.length>0||i>0&&this.searchObservationsBySubstring(e,a,r,1,0).length>0?l:this.searchFtsAnyTerm(d,e,s,n,i)??l}return this.searchObservationsBySubstring(e,a,r,n,i)}searchSessions(e,t={}){let s=[],{limit:n=50,offset:i=0,orderBy:r="relevance",...a}=t;if(!e){let _={...a};delete _.type;let E=this.buildFilterClause(_,s,"s");if(!E)return[];let u=`
|
|
224
227
|
SELECT s.*, s.discovery_tokens
|
|
225
228
|
FROM session_summaries s
|
|
226
229
|
WHERE ${E}
|
|
227
|
-
${
|
|
230
|
+
${r==="date_asc"?"ORDER BY s.created_at_epoch ASC, s.id ASC":"ORDER BY s.created_at_epoch DESC, s.id DESC"}
|
|
228
231
|
LIMIT ? OFFSET ?
|
|
229
|
-
`;return s.push(n,i),this.db.prepare(
|
|
232
|
+
`;return s.push(n,i),this.db.prepare(u).all(...s)}if(o.UNSEGMENTED_SCRIPT.test(e))return this.searchSessionsBySubstring(e,a,r,n,i);if(this._fts5Available||this.canReadFtsIndex("session_summaries_fts")){let _={...a};delete _.type;let E=this.buildFilterClause(_,s,"s"),d=r==="date_asc"?"ORDER BY s.created_at_epoch ASC, s.id ASC":r==="date_desc"?"ORDER BY s.created_at_epoch DESC, s.id DESC":"ORDER BY session_summaries_fts.rank ASC",u=`
|
|
230
233
|
SELECT s.*, s.discovery_tokens
|
|
231
234
|
FROM session_summaries s
|
|
232
235
|
JOIN session_summaries_fts ON session_summaries_fts.rowid = s.id
|
|
233
236
|
WHERE session_summaries_fts MATCH ?
|
|
234
237
|
${E?"AND "+E:""}
|
|
235
|
-
${
|
|
238
|
+
${d}
|
|
236
239
|
LIMIT ? OFFSET ?
|
|
237
|
-
`;s.unshift(
|
|
240
|
+
`;s.unshift(o.buildFTSMatchQuery(e));let l;try{l=this.db.prepare(u).all(...s,n,i)}catch(S){throw c.warn("DB","FTS5 session search failed",{},S instanceof Error?S:void 0),S}if(l.length>0||i>0&&this.db.prepare(u).all(...s,1,0).length>0)return l;let p=this.searchSessionsBySubstring(e,a,r,n,i);return p.length>0||i>0&&this.searchSessionsBySubstring(e,a,r,1,0).length>0?p:this.searchFtsAnyTerm(u,e,s,n,i)??p}return this.searchSessionsBySubstring(e,a,r,n,i)}searchFtsAnyTerm(e,t,s,n,i){let r=o.buildFTSAnyTermQuery(t);if(!r)return null;let a=[r,...s.slice(1)],_=this.db.prepare(e).all(...a,n,i);return _.length>0||i>0&&this.db.prepare(e).all(...a,1,0).length>0?_:null}findByConcept(e,t={}){let s=[],{limit:n=50,offset:i=0,orderBy:r="date_desc",...a}=t,_={...a,concepts:e},E=this.buildFilterClause(_,s,"o"),d=this.buildOrderClause(r,!1),u=`
|
|
238
241
|
SELECT o.*, o.discovery_tokens
|
|
239
242
|
FROM observations o
|
|
240
243
|
WHERE ${E}
|
|
241
|
-
${
|
|
244
|
+
${d}
|
|
242
245
|
LIMIT ? OFFSET ?
|
|
243
|
-
`;return s.push(n,i),this.db.prepare(
|
|
246
|
+
`;return s.push(n,i),this.db.prepare(u).all(...s)}hasDirectChildFile(e,t){let s=n=>{if(!n)return!1;try{let i=JSON.parse(n);if(Array.isArray(i))return i.some(r=>typeof r=="string"&&Ve(r,t))}catch(i){c.debug("DB",`Failed to parse files JSON for observation ${e.id}`,void 0,i instanceof Error?i:void 0)}return!1};return s(e.files_modified)||s(e.files_read)}hasDirectChildFileSession(e,t){let s=n=>{if(!n)return!1;try{let i=JSON.parse(n);if(Array.isArray(i))return i.some(r=>typeof r=="string"&&Ve(r,t))}catch(i){c.debug("DB",`Failed to parse files JSON for session summary ${e.id}`,void 0,i instanceof Error?i:void 0)}return!1};return s(e.files_read)||s(e.files_edited)}static filePathPatterns(e,t){let s=_=>_.replace(/[\\%_]/g,"\\$&"),n=t?[e,J(e),J(e).replaceAll("/","\\")]:[e],i=[...new Set(n)].map(_=>`%${s(_)}%`);if(!t||!/^([A-Za-z]:)?[\\/]/.test(e))return i;let r=J(e).split("/").filter(_=>_.length>0),a=/^[A-Za-z]:$/.test(r[0]??"")?1:0;for(let _=a;_<r.length;_+=1){let E=r.slice(_);i.push(`${s(E.join("/")+"/")}%`),e.includes("\\")&&i.push(`${s(E.join("\\")+"\\")}%`)}return i}static fileArrayJson(e){return`CASE WHEN json_valid(${e}) THEN CASE WHEN json_type(${e}) = 'array' THEN ${e} ELSE '[]' END ELSE '[]' END`}static jsonArrayLikeClause(e,t){let s=Array.from({length:t},()=>"type = 'text' AND value LIKE ? ESCAPE '\\'").join(" OR ");return`(${e.map(n=>`EXISTS (SELECT 1 FROM json_each(${o.fileArrayJson(n)}) WHERE ${s})`).join(" OR ")})`}findByFile(e,t={}){let s=[],{limit:n=50,offset:i=0,orderBy:r="date_desc",isFolder:a=!1,..._}=t;delete _.files;let E=a?"":"LIMIT ? OFFSET ?",d=o.filePathPatterns(e,a),u=this.buildFilterClause(_,s,"o");s.push(...d,...d);let l=[u,o.jsonArrayLikeClause(["o.files_read","o.files_modified"],d.length)].filter(Boolean).join(" AND "),p=`${this.buildOrderClause(r,!1)}, o.id ${r==="date_asc"?"ASC":"DESC"}`,S=`
|
|
244
247
|
SELECT o.*, o.discovery_tokens
|
|
245
248
|
FROM observations o
|
|
246
249
|
WHERE ${l}
|
|
247
|
-
${
|
|
250
|
+
${p}
|
|
248
251
|
${E}
|
|
249
|
-
`;a||s.push(n,i);let
|
|
252
|
+
`;a||s.push(n,i);let h=this.db.prepare(S),f=a?Ye(h,s,O=>this.hasDirectChildFile(O,e),{limit:n,offset:i}):h.all(...s),C=[],R={..._};delete R.type;let m=[],A=w(R);if(A.length>0){let O=x("s",A,{includeMerged:!0});m.push(O.sql),C.push(...O.params)}if(R.platformSource&&(m.push(`COALESCE(NULLIF((SELECT s2.platform_source FROM sdk_sessions s2 WHERE s2.memory_session_id = s.memory_session_id), ''), '${T}') = ?`),C.push(b(R.platformSource))),R.dateRange){let{start:O,end:v}=R.dateRange;O&&(m.push("s.created_at_epoch >= ?"),C.push($(O,"start"))),v&&(m.push("s.created_at_epoch <= ?"),C.push($(v,"end")))}m.push(o.jsonArrayLikeClause(["s.files_read","s.files_edited"],d.length)),C.push(...d,...d);let y=`
|
|
250
253
|
SELECT s.*, s.discovery_tokens
|
|
251
254
|
FROM session_summaries s
|
|
252
|
-
WHERE ${
|
|
253
|
-
ORDER BY s.created_at_epoch ${
|
|
255
|
+
WHERE ${m.join(" AND ")}
|
|
256
|
+
ORDER BY s.created_at_epoch ${r==="date_asc"?"ASC":"DESC"}
|
|
254
257
|
${E}
|
|
255
|
-
`;a||
|
|
258
|
+
`;a||C.push(n,i);let g=this.db.prepare(y),D=a?Ye(g,C,O=>this.hasDirectChildFileSession(O,e),{limit:n,offset:i}):g.all(...C);return{observations:f,sessions:D}}findByType(e,t={}){let s=[],{limit:n=50,offset:i=0,orderBy:r="date_desc",...a}=t,_={...a,type:e},E=this.buildFilterClause(_,s,"o"),d=this.buildOrderClause(r,!1),u=`
|
|
256
259
|
SELECT o.*, o.discovery_tokens
|
|
257
260
|
FROM observations o
|
|
258
261
|
WHERE ${E}
|
|
259
|
-
${
|
|
262
|
+
${d}
|
|
260
263
|
LIMIT ? OFFSET ?
|
|
261
|
-
`;return s.push(n,i),this.db.prepare(
|
|
264
|
+
`;return s.push(n,i),this.db.prepare(u).all(...s)}searchUserPrompts(e,t={}){let s=[],{limit:n=20,offset:i=0,orderBy:r="relevance",...a}=t,_=[],E=w(a);if(E.length>0){let S=x("s",E,{includeMerged:!1});_.push(S.sql),s.push(...S.params)}if(a.platformSource&&(_.push(`COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?`),s.push(b(a.platformSource))),a.dateRange){let{start:S,end:h}=a.dateRange;S&&(_.push("up.created_at_epoch >= ?"),s.push($(S,"start"))),h&&(_.push("up.created_at_epoch <= ?"),s.push($(h,"end")))}if(!e){if(_.length===0)return[];let S=`WHERE ${_.join(" AND ")}`,f=`
|
|
262
265
|
SELECT
|
|
263
266
|
up.*,
|
|
264
267
|
s.project,
|
|
265
268
|
s.memory_session_id,
|
|
266
|
-
COALESCE(NULLIF(s.platform_source, ''), '${
|
|
269
|
+
COALESCE(NULLIF(s.platform_source, ''), '${T}') as platform_source
|
|
267
270
|
FROM user_prompts up
|
|
268
271
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
269
|
-
${
|
|
270
|
-
${
|
|
272
|
+
${S}
|
|
273
|
+
${r==="date_asc"?"ORDER BY up.created_at_epoch ASC, up.id ASC":"ORDER BY up.created_at_epoch DESC, up.id DESC"}
|
|
271
274
|
LIMIT ? OFFSET ?
|
|
272
|
-
`;return s.push(n,i),this.db.prepare(f).all(...s)}let
|
|
275
|
+
`;return s.push(n,i),this.db.prepare(f).all(...s)}let d=e.replace(/[\\%_]/g,"\\$&");_.push("up.prompt_text LIKE ? ESCAPE '\\'"),s.push(`%${d}%`);let u=`WHERE ${_.join(" AND ")}`,p=`
|
|
273
276
|
SELECT
|
|
274
277
|
up.*,
|
|
275
278
|
s.project,
|
|
276
279
|
s.memory_session_id,
|
|
277
|
-
COALESCE(NULLIF(s.platform_source, ''), '${
|
|
280
|
+
COALESCE(NULLIF(s.platform_source, ''), '${T}') as platform_source
|
|
278
281
|
FROM user_prompts up
|
|
279
282
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
280
|
-
${
|
|
281
|
-
${
|
|
283
|
+
${u}
|
|
284
|
+
${r==="date_asc"?"ORDER BY up.created_at_epoch ASC, up.id ASC":"ORDER BY up.created_at_epoch DESC, up.id DESC"}
|
|
282
285
|
LIMIT ? OFFSET ?
|
|
283
|
-
`;return s.push(n,i),this.db.prepare(
|
|
284
|
-
ON user_prompts(session_db_id, native_prompt_id) WHERE native_prompt_id IS NOT NULL`)}).immediate()}
|
|
286
|
+
`;return s.push(n,i),this.db.prepare(p).all(...s)}close(){this.db.close()}};var _s=4096;var un=new Set(["set_title","set_prompt_session","remap_project"]),ln=/^(?:0|[1-9][0-9]*)$/,Es=18446744073709551615n;function U(o){throw c.debug("CLOUD_SYNC","Rejected invalid canonical content",{reason:o}),new Error(`canonical content: ${o}`)}function Ie(o,e={}){return typeof o!="string"||!ln.test(o)?U("decimal values must be unsigned base-10 strings without leading zeroes"):(BigInt(o)>Es&&U("decimal value exceeds uint64"),e.positive&&o==="0"&&U("decimal value must be positive"),o)}function ze(o){let e=Ie(o);return BigInt(e)===Es&&U("uint64 sequence overflow"),(BigInt(e)+1n).toString(10)}function pn(o){(o===null||typeof o!="object"||Array.isArray(o))&&U("mutation must be an object");let e=o;if((typeof e.op!="string"||!un.has(e.op))&&U("unsupported mutation op"),e.op==="set_title"){let i=Ee(e,["fields","op","target"],"set_title"),r=Le(i.target,["content_session_id","memory_session_id","platform_source"],"set_title.target");r.memory_session_id===void 0&&r.content_session_id===void 0&&U("set_title target requires a session identifier");for(let _ of["memory_session_id","content_session_id","platform_source"])r[_]!==void 0&&B(r[_],_);let a=Ee(i.fields,["custom_title"],"set_title.fields");B(a.custom_title,"custom_title");return}if(e.op==="set_prompt_session"){let i=Ee(e,["fields","op","target"],"set_prompt_session"),r=Ee(i.target,["origin_device_id","origin_local_id"],"set_prompt_session.target");mn(r.origin_device_id),Ie(r.origin_local_id);let a=Le(i.fields,["content_session_id","memory_session_id","platform_source","project"],"set_prompt_session.fields");B(a.memory_session_id,"memory_session_id");for(let _ of["content_session_id","platform_source","project"])a[_]!==void 0&&B(a[_],_);return}let t=Ee(e,["fields","op","where"],"remap_project"),s=Le(t.where,["memory_session_id","merged_into_project_is_null","project"],"remap_project.where");s.project!==void 0&&B(s.project,"project"),s.memory_session_id!==void 0&&B(s.memory_session_id,"memory_session_id"),s.merged_into_project_is_null!==void 0&&s.merged_into_project_is_null!==!0&&U("merged_into_project_is_null may only be true"),Object.keys(s).length===0&&U("remap_project where is empty");let n=Le(t.fields,["merged_into_project","project"],"remap_project.fields");n.project!==void 0&&B(n.project,"project"),n.merged_into_project!==void 0&&B(n.merged_into_project,"merged_into_project"),Object.keys(n).length===0&&U("remap_project fields are empty")}function Qe(o){pn(o)}function mn(o){return typeof o!="string"||o.length===0||Buffer.byteLength(o,"utf8")>128?U("origin_device_id must be a non-empty string of at most 128 UTF-8 bytes"):o}function B(o,e){return typeof o!="string"||o.length===0||o.trim().length===0||Buffer.byteLength(o,"utf8")>_s?U(`${e} must be a non-blank string of at most ${_s} UTF-8 bytes`):o}function Ee(o,e,t){if(o===null||typeof o!="object"||Array.isArray(o))return U(`${t} must be an object`);let s=o,n=Object.keys(s).sort(),i=[...e].sort();return(n.length!==i.length||n.some((r,a)=>r!==i[a]))&&U(`${t} must contain exactly: ${i.join(", ")}`),s}function Le(o,e,t){if(o===null||typeof o!="object"||Array.isArray(o))return U(`${t} must be an object`);let s=o,n=new Set(e),i=Object.keys(s).find(r=>!n.has(r));return i&&U(`${t} contains unknown field ${i}`),s}var ds=5*6e4,N=o=>typeof o=="object"&&o!==null?JSON.stringify(o):o??null;function cs(o){let e=[],t=[],s=new Set,n=new Set;for(let i of o){for(let r of i.files_read??[])!r||s.has(r)||(s.add(r),e.push(r));for(let r of i.files_modified??[])!r||n.has(r)||(n.add(r),t.push(r))}return{files_read:e,files_edited:t}}var Tn=200,Sn=1e3,An=56,gn=57;function Ze(o){let e=Number(o);return Number.isSafeInteger(e)&&e>0?e:void 0}var tt=class{db;syncOpsEnabled;statementCache=new Map;constructor(e=me,t={}){this.syncOpsEnabled=t.syncOpsEnabled??!0,e instanceof et.Database?this.db=e:(e!==":memory:"&&Te(M),this.db=new et.Database(e)),Re(this.db,q),be(this.db),Ne(this.db,q),this.initializeSchema(),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields(),this.makeObservationsTextNullable(),this.createUserPromptsTable(),this.ensureDiscoveryTokensColumn(),this.createPendingMessagesTable(),this.renameSessionIdColumns(),this.addFailedAtEpochColumn(),this.addOnUpdateCascadeToForeignKeys(),this.addObservationContentHashColumn(),this.addSessionCustomTitleColumn(),this.addSessionPlatformSourceColumn(),this.addObservationModelColumns(),this.ensureMergedIntoProjectColumns(),this.addObservationSubagentColumns(),this.addObservationsUniqueContentHashIndex(),this.addObservationsMetadataColumn(),this.dropDeadPendingMessagesColumns(),this.ensurePendingMessagesToolUseIdColumn(),this.dropWorkerPidColumn(),this.ensureSDKSessionsPlatformContentIdentity(),this.ensureUserPromptsSessionDbId(),this.ensurePendingMessagesSessionToolUniqueIndex(),this.ensureSyncedAtColumns(),this.ensureSyncOriginColumns(),this.ensureSyncOutbox(),this.ensureSyncEntityLedger(),this.ensureSyncRevisionTextAffinity(),this.initializeSyncHubLaunchBaseline(),this.normalizeConceptTags(),this.ensureSDKSessionsObservedColumns(),this.ensureToolUsesTable(),this.ensureTelegramWrapupsTable(),this.addDedupTables(),this.refreshUnicodeTitleNormKeys(),this.ensureReinforcementColumns(),this.ensureSessionCwdColumn(),this.dropWriteOnlyUserPromptsFtsAndScopeFtsUpdateTriggers(),this.ensureProjectNocaseIndexes(),this.ensureAdvisorCallsTable(),this.ensureSessionProjectKeySourceColumn(),this.requeuePromptsDeadLetteredForSize(),this.ensureWorkStateTable(),this.ensureHookSpoolConsumedTable(),this.ensureProjectRecencyIndexes(),this.ensureMergedIntoProjectCoveringIndexes(),this.ensureNativePromptIdentity()}ensureNativePromptIdentity(){this.db.transaction(()=>{let e=this.db.query("PRAGMA table_info(user_prompts)").all();for(let t of["native_prompt_id","native_prompt_hash"])e.some(s=>s.name===t)||this.db.run(`ALTER TABLE user_prompts ADD COLUMN ${t} TEXT`);this.db.run(`CREATE UNIQUE INDEX IF NOT EXISTS idx_user_prompts_native_identity
|
|
287
|
+
ON user_prompts(session_db_id, native_prompt_id) WHERE native_prompt_id IS NOT NULL`)}).immediate()}refreshUnicodeTitleNormKeys(){this.db.transaction(()=>{if(this.db.query("SELECT version FROM schema_versions WHERE version = 65").get())return;let e=this.db.prepare(`SELECT o.id, o.project, o.title, o.agent_id, o.agent_type,
|
|
288
|
+
s.platform_source FROM observations o LEFT JOIN sdk_sessions s
|
|
289
|
+
ON s.memory_session_id = o.memory_session_id ORDER BY o.id`),t=this.db.prepare("UPDATE observations SET title_norm_key = ? WHERE id = ?");try{for(let s of Ce(e)){let n=s;t.run(ge(n.project,n.platform_source,n.title,ne(n.agent_id,n.agent_type)),n.id)}this.db.prepare("INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)").run(65,new Date().toISOString())}finally{e.finalize(),t.finalize()}}).immediate()}getIndexColumns(e){return this.db.query(`PRAGMA index_info(${JSON.stringify(e)})`).all().map(t=>t.name)}hasUniqueIndexOnColumns(e,t){return this.db.query(`PRAGMA index_list(${e})`).all().some(n=>{if(n.unique!==1)return!1;let i=this.getIndexColumns(n.name);return i.length===t.length&&i.every((r,a)=>r===t[a])})}resolvePromptSessionDbId(e,t,s){if(t!==void 0)return t;let n=s?b(s):void 0;return n?this.db.prepare(`
|
|
285
290
|
SELECT id
|
|
286
291
|
FROM sdk_sessions
|
|
287
292
|
WHERE COALESCE(NULLIF(platform_source, ''), ?) = ?
|
|
288
293
|
AND content_session_id = ?
|
|
289
294
|
LIMIT 1
|
|
290
|
-
`).get(
|
|
295
|
+
`).get(T,n,e)?.id??null:this.db.prepare(`
|
|
291
296
|
SELECT id
|
|
292
297
|
FROM sdk_sessions
|
|
293
298
|
WHERE content_session_id = ?
|
|
294
|
-
ORDER BY CASE COALESCE(NULLIF(platform_source, ''), '${
|
|
295
|
-
WHEN '${
|
|
299
|
+
ORDER BY CASE COALESCE(NULLIF(platform_source, ''), '${T}')
|
|
300
|
+
WHEN '${T}' THEN 0
|
|
296
301
|
ELSE 1
|
|
297
302
|
END, id
|
|
298
303
|
LIMIT 1
|
|
@@ -327,17 +332,17 @@ ${L.stack??""}
|
|
|
327
332
|
FOREIGN KEY (duplicate_of_id) REFERENCES observations(id) ON DELETE CASCADE,
|
|
328
333
|
UNIQUE(observation_id, duplicate_of_id)
|
|
329
334
|
)
|
|
330
|
-
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_token_df_project ON token_df(project)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_dedup_candidates_project ON observation_dedup_candidates(project, status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_dedup_candidates_obs ON observation_dedup_candidates(observation_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(
|
|
335
|
+
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_token_df_project ON token_df(project)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_dedup_candidates_project ON observation_dedup_candidates(project, status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_dedup_candidates_obs ON observation_dedup_candidates(observation_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(An,new Date().toISOString())}dropWorkerPidColumn(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(32),s=this.db.query("PRAGMA table_info(pending_messages)").all().some(n=>n.name==="worker_pid");if(!(e&&!s)){if(s)try{this.db.run("DROP INDEX IF EXISTS idx_pending_messages_worker_pid"),this.db.run("ALTER TABLE pending_messages DROP COLUMN worker_pid"),c.debug("DB","Dropped worker_pid column and its index from pending_messages")}catch(n){c.warn("DB","Failed to drop worker_pid column from pending_messages",{},n instanceof Error?n:new Error(String(n)));return}e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(32,new Date().toISOString())}}ensureSDKSessionsPlatformContentIdentity(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(33),t=this.hasUniqueIndexOnColumns("sdk_sessions",["content_session_id"]),s=this.hasUniqueIndexOnColumns("sdk_sessions",["platform_source","content_session_id"]),i=this.db.query("PRAGMA table_info(sdk_sessions)").all().some(r=>r.name==="platform_source");if(!(e&&!t&&s&&i)){if(i||this.db.run(`ALTER TABLE sdk_sessions ADD COLUMN platform_source TEXT NOT NULL DEFAULT '${T}'`),this.db.run(`
|
|
331
336
|
UPDATE sdk_sessions
|
|
332
|
-
SET platform_source = '${
|
|
337
|
+
SET platform_source = '${T}'
|
|
333
338
|
WHERE platform_source IS NULL OR platform_source = ''
|
|
334
|
-
`),t){this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildSdkSessionsWithCompositeIdentity(e),this.db.run("COMMIT")}catch(
|
|
339
|
+
`),t){this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildSdkSessionsWithCompositeIdentity(e),this.db.run("COMMIT")}catch(r){this.db.run("ROLLBACK");let a=r instanceof Error?r:new Error(String(r));throw c.error("DB","Failed to rebuild sdk_sessions with composite identity, rolled back",{},a),r}finally{this.db.run("PRAGMA foreign_keys = ON")}return}this.db.run("CREATE UNIQUE INDEX IF NOT EXISTS ux_sdk_sessions_platform_content ON sdk_sessions(platform_source, content_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source)"),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(33,new Date().toISOString())}}rebuildSdkSessionsWithCompositeIdentity(e){this.db.run("DROP TABLE IF EXISTS sdk_sessions_new"),this.db.run(`
|
|
335
340
|
CREATE TABLE sdk_sessions_new (
|
|
336
341
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
337
342
|
content_session_id TEXT NOT NULL,
|
|
338
343
|
memory_session_id TEXT UNIQUE,
|
|
339
344
|
project TEXT NOT NULL,
|
|
340
|
-
platform_source TEXT NOT NULL DEFAULT '${
|
|
345
|
+
platform_source TEXT NOT NULL DEFAULT '${T}',
|
|
341
346
|
user_prompt TEXT,
|
|
342
347
|
started_at TEXT NOT NULL,
|
|
343
348
|
started_at_epoch INTEGER NOT NULL,
|
|
@@ -356,27 +361,27 @@ ${L.stack??""}
|
|
|
356
361
|
)
|
|
357
362
|
SELECT
|
|
358
363
|
id, content_session_id, memory_session_id, project,
|
|
359
|
-
COALESCE(NULLIF(platform_source, ''), '${
|
|
364
|
+
COALESCE(NULLIF(platform_source, ''), '${T}'),
|
|
360
365
|
user_prompt, started_at, started_at_epoch, completed_at, completed_at_epoch,
|
|
361
366
|
status, worker_port, prompt_counter, custom_title
|
|
362
367
|
FROM sdk_sessions
|
|
363
|
-
`),this.db.run("DROP TABLE sdk_sessions"),this.db.run("ALTER TABLE sdk_sessions_new RENAME TO sdk_sessions"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_claude_id ON sdk_sessions(content_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_sdk_id ON sdk_sessions(memory_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_project ON sdk_sessions(project)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_status ON sdk_sessions(status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_started ON sdk_sessions(started_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source)"),this.db.run("CREATE UNIQUE INDEX IF NOT EXISTS ux_sdk_sessions_platform_content ON sdk_sessions(platform_source, content_session_id)"),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(33,new Date().toISOString())}ensureUserPromptsSessionDbId(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(34);if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='user_prompts'").all().length===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(34,new Date().toISOString());return}let n=this.db.query("PRAGMA table_info(user_prompts)").all().some(_=>_.name==="session_db_id"),
|
|
368
|
+
`),this.db.run("DROP TABLE sdk_sessions"),this.db.run("ALTER TABLE sdk_sessions_new RENAME TO sdk_sessions"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_claude_id ON sdk_sessions(content_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_sdk_id ON sdk_sessions(memory_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_project ON sdk_sessions(project)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_status ON sdk_sessions(status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_started ON sdk_sessions(started_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source)"),this.db.run("CREATE UNIQUE INDEX IF NOT EXISTS ux_sdk_sessions_platform_content ON sdk_sessions(platform_source, content_session_id)"),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(33,new Date().toISOString())}ensureUserPromptsSessionDbId(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(34);if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='user_prompts'").all().length===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(34,new Date().toISOString());return}let n=this.db.query("PRAGMA table_info(user_prompts)").all().some(_=>_.name==="session_db_id"),r=this.db.query("PRAGMA foreign_key_list(user_prompts)").all().some(_=>_.table==="sdk_sessions"&&_.from==="content_session_id");if(e&&n&&!r)return;let a=n?`COALESCE(up.session_db_id, (
|
|
364
369
|
SELECT s.id FROM sdk_sessions s
|
|
365
370
|
WHERE s.content_session_id = up.content_session_id
|
|
366
|
-
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${
|
|
367
|
-
WHEN '${
|
|
371
|
+
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${T}')
|
|
372
|
+
WHEN '${T}' THEN 0
|
|
368
373
|
ELSE 1
|
|
369
374
|
END, s.id
|
|
370
375
|
LIMIT 1
|
|
371
376
|
))`:`(
|
|
372
377
|
SELECT s.id FROM sdk_sessions s
|
|
373
378
|
WHERE s.content_session_id = up.content_session_id
|
|
374
|
-
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${
|
|
375
|
-
WHEN '${
|
|
379
|
+
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${T}')
|
|
380
|
+
WHEN '${T}' THEN 0
|
|
376
381
|
ELSE 1
|
|
377
382
|
END, s.id
|
|
378
383
|
LIMIT 1
|
|
379
|
-
)`;this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildUserPromptsWithSessionDbId(e,a),this.db.run("COMMIT")}catch(_){this.db.run("ROLLBACK");let E=_ instanceof Error?_:new Error(String(_));throw
|
|
384
|
+
)`;this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildUserPromptsWithSessionDbId(e,a),this.db.run("COMMIT")}catch(_){this.db.run("ROLLBACK");let E=_ instanceof Error?_:new Error(String(_));throw c.error("DB","Failed to rebuild user_prompts with session_db_id, rolled back",{},E),_}finally{this.db.run("PRAGMA foreign_keys = ON")}}rebuildUserPromptsWithSessionDbId(e,t){this.db.run("DROP TRIGGER IF EXISTS user_prompts_ai"),this.db.run("DROP TRIGGER IF EXISTS user_prompts_ad"),this.db.run("DROP TRIGGER IF EXISTS user_prompts_au"),this.db.run("DROP TABLE IF EXISTS user_prompts_new"),this.db.run(`
|
|
380
385
|
CREATE TABLE user_prompts_new (
|
|
381
386
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
382
387
|
session_db_id INTEGER,
|
|
@@ -401,7 +406,7 @@ ${L.stack??""}
|
|
|
401
406
|
up.created_at,
|
|
402
407
|
up.created_at_epoch
|
|
403
408
|
FROM user_prompts up
|
|
404
|
-
`),this.db.run("DROP TABLE user_prompts"),this.db.run("ALTER TABLE user_prompts_new RENAME TO user_prompts"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_session ON user_prompts(session_db_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_claude_session ON user_prompts(content_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_created ON user_prompts(created_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_prompt_number ON user_prompts(prompt_number)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_lookup ON user_prompts(session_db_id, prompt_number)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_content_lookup ON user_prompts(content_session_id, prompt_number)"),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(34,new Date().toISOString())}ensurePendingMessagesSessionToolUniqueIndex(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(35);if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='pending_messages'").all().length===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(35,new Date().toISOString());return}let s=this.hasUniqueIndexOnColumns("pending_messages",["session_db_id","tool_use_id"]);if(!(e&&s)){this.db.run("BEGIN TRANSACTION");try{this.recreatePendingSessionToolUniqueIndex(e),this.db.run("COMMIT")}catch(n){this.db.run("ROLLBACK");let i=n instanceof Error?n:new Error(String(n));throw
|
|
409
|
+
`),this.db.run("DROP TABLE user_prompts"),this.db.run("ALTER TABLE user_prompts_new RENAME TO user_prompts"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_session ON user_prompts(session_db_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_claude_session ON user_prompts(content_session_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_created ON user_prompts(created_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_prompt_number ON user_prompts(prompt_number)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_lookup ON user_prompts(session_db_id, prompt_number)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_user_prompts_content_lookup ON user_prompts(content_session_id, prompt_number)"),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(34,new Date().toISOString())}ensurePendingMessagesSessionToolUniqueIndex(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(35);if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='pending_messages'").all().length===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(35,new Date().toISOString());return}let s=this.hasUniqueIndexOnColumns("pending_messages",["session_db_id","tool_use_id"]);if(!(e&&s)){this.db.run("BEGIN TRANSACTION");try{this.recreatePendingSessionToolUniqueIndex(e),this.db.run("COMMIT")}catch(n){this.db.run("ROLLBACK");let i=n instanceof Error?n:new Error(String(n));throw c.error("DB","Failed to recreate ux_pending_session_tool index, rolled back",{},i),n}}}recreatePendingSessionToolUniqueIndex(e){this.db.run("DROP INDEX IF EXISTS ux_pending_session_tool"),this.db.run(`
|
|
405
410
|
DELETE FROM pending_messages
|
|
406
411
|
WHERE id IN (
|
|
407
412
|
SELECT id
|
|
@@ -424,7 +429,7 @@ ${L.stack??""}
|
|
|
424
429
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
425
430
|
ON pending_messages(session_db_id, tool_use_id)
|
|
426
431
|
WHERE tool_use_id IS NOT NULL
|
|
427
|
-
`),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(35,new Date().toISOString())}ensureSyncedAtColumns(){for(let e of["observations","session_summaries","user_prompts"])this.db.query(`PRAGMA table_info(${e})`).all().some(n=>n.name==="synced_at")||(this.db.run(`ALTER TABLE ${e} ADD COLUMN synced_at INTEGER`),
|
|
432
|
+
`),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(35,new Date().toISOString())}ensureSyncedAtColumns(){for(let e of["observations","session_summaries","user_prompts"])this.db.query(`PRAGMA table_info(${e})`).all().some(n=>n.name==="synced_at")||(this.db.run(`ALTER TABLE ${e} ADD COLUMN synced_at INTEGER`),c.debug("DB",`Added synced_at column to ${e} table`)),this.db.run(`CREATE INDEX IF NOT EXISTS idx_${e}_unsynced ON ${e}(id) WHERE synced_at IS NULL`);this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(39,new Date().toISOString())}ensureSyncOriginColumns(){for(let e of["observations","session_summaries","user_prompts"]){let t=this.db.query(`PRAGMA table_info(${e})`).all(),s=new Set(t.map(n=>n.name));s.has("origin_device_id")||(this.db.run(`ALTER TABLE ${e} ADD COLUMN origin_device_id TEXT`),c.debug("DB",`Added origin_device_id column to ${e} table`)),s.has("origin_local_id")||(this.db.run(`ALTER TABLE ${e} ADD COLUMN origin_local_id TEXT`),c.debug("DB",`Added origin_local_id column to ${e} table`)),s.has("sync_rev")||(this.db.run(`ALTER TABLE ${e} ADD COLUMN sync_rev TEXT NOT NULL DEFAULT '1'`),c.debug("DB",`Added sync_rev column to ${e} table`)),this.db.run(`
|
|
428
433
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_${e}_origin
|
|
429
434
|
ON ${e}(origin_device_id, origin_local_id)
|
|
430
435
|
WHERE origin_device_id IS NOT NULL
|
|
@@ -443,17 +448,17 @@ ${L.stack??""}
|
|
|
443
448
|
operation_sha256 TEXT,
|
|
444
449
|
created_at_epoch INTEGER NOT NULL
|
|
445
450
|
)
|
|
446
|
-
`);let e=new Set(this.db.query("PRAGMA table_info(sync_outbox)").all().map(t=>t.name));e.has("canonical_body")||this.db.run("ALTER TABLE sync_outbox ADD COLUMN canonical_body TEXT"),e.has("operation_sha256")||this.db.run("ALTER TABLE sync_outbox ADD COLUMN operation_sha256 TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(42,new Date().toISOString())}ensureSyncRevisionTextAffinity(){let e=[{table:"observations",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"session_summaries",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"user_prompts",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"sync_outbox",column:"rev",temporary:"rev_text_v46"}],t=(
|
|
451
|
+
`);let e=new Set(this.db.query("PRAGMA table_info(sync_outbox)").all().map(t=>t.name));e.has("canonical_body")||this.db.run("ALTER TABLE sync_outbox ADD COLUMN canonical_body TEXT"),e.has("operation_sha256")||this.db.run("ALTER TABLE sync_outbox ADD COLUMN operation_sha256 TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(42,new Date().toISOString())}ensureSyncRevisionTextAffinity(){let e=[{table:"observations",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"session_summaries",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"user_prompts",column:"sync_rev",temporary:"sync_rev_text_v46"},{table:"sync_outbox",column:"rev",temporary:"rev_text_v46"}],t=(r,a)=>this.db.query(`PRAGMA table_info(${r})`).all().find(_=>_.name===a),s=r=>r?.type.trim().toUpperCase()==="TEXT";if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(46)&&e.every(r=>s(t(r.table,r.column))))return;this.db.transaction(()=>{for(let r of e){let a=this.db.query(`PRAGMA table_info(${r.table})`).all(),_=a.find(d=>d.name===r.column);if(!_)throw new Error(`schema v46: missing ${r.table}.${r.column}`);for(let d of Ce(this.db.query(`
|
|
447
452
|
SELECT CAST(id AS TEXT) AS row_id,
|
|
448
|
-
typeof(${
|
|
449
|
-
CAST(${
|
|
450
|
-
FROM ${
|
|
451
|
-
`))){let d
|
|
453
|
+
typeof(${r.column}) AS storage_type,
|
|
454
|
+
CAST(${r.column} AS TEXT) AS revision
|
|
455
|
+
FROM ${r.table}
|
|
456
|
+
`))){let u=d;if(u.storage_type==="real")throw new Error(`schema v46: ${r.table}.${r.column} row ${u.row_id} is REAL and unrecoverably rounded`);if(u.storage_type!=="integer"&&u.storage_type!=="text")throw new Error(`schema v46: ${r.table}.${r.column} row ${u.row_id} has unsupported ${u.storage_type} storage`);try{Ie(u.revision,{positive:!0})}catch{throw new Error(`schema v46: ${r.table}.${r.column} row ${u.row_id} is not a positive canonical uint64 revision`)}}if(s(_))continue;if(a.some(d=>d.name===r.temporary))throw new Error(`schema v46: unexpected temporary column ${r.table}.${r.temporary}`);this.db.run(`ALTER TABLE ${r.table} ADD COLUMN ${r.temporary} TEXT NOT NULL DEFAULT '1'`),this.db.run(`UPDATE ${r.table} SET ${r.temporary} = CAST(${r.column} AS TEXT)`);let E=this.db.prepare(`
|
|
452
457
|
SELECT CAST(id AS TEXT) AS row_id
|
|
453
|
-
FROM ${
|
|
454
|
-
WHERE ${
|
|
458
|
+
FROM ${r.table}
|
|
459
|
+
WHERE ${r.temporary} <> CAST(${r.column} AS TEXT)
|
|
455
460
|
LIMIT 1
|
|
456
|
-
`).get();if(E)throw new Error(`schema v46: failed to copy ${
|
|
461
|
+
`).get();if(E)throw new Error(`schema v46: failed to copy ${r.table}.${r.column} row ${E.row_id} exactly`);this.db.run(`ALTER TABLE ${r.table} DROP COLUMN ${r.column}`),this.db.run(`ALTER TABLE ${r.table} RENAME COLUMN ${r.temporary} TO ${r.column}`)}this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(46,new Date().toISOString())})()}ensureSyncEntityLedger(){this.db.run(`
|
|
457
462
|
CREATE TABLE IF NOT EXISTS sync_entity_heads (
|
|
458
463
|
entity_id TEXT PRIMARY KEY,
|
|
459
464
|
kind TEXT NOT NULL CHECK (kind IN ('observation', 'summary', 'prompt')),
|
|
@@ -520,13 +525,13 @@ ${L.stack??""}
|
|
|
520
525
|
through_rev TEXT NOT NULL,
|
|
521
526
|
PRIMARY KEY (kind, origin_local_id)
|
|
522
527
|
)
|
|
523
|
-
`);let s=this.db.prepare("SELECT version, applied_at FROM schema_versions WHERE version = ?").get(47);if(!s){let a=Date.now();this.db.transaction(()=>{this.db.run("DELETE FROM sync_launch_exclusions");for(let{table:
|
|
528
|
+
`);let s=this.db.prepare("SELECT version, applied_at FROM schema_versions WHERE version = ?").get(47);if(!s){let a=Date.now();this.db.transaction(()=>{this.db.run("DELETE FROM sync_launch_exclusions");for(let{table:d,kind:u}of e)this.db.prepare(`
|
|
524
529
|
INSERT INTO sync_launch_exclusions (kind, origin_local_id, through_rev)
|
|
525
530
|
SELECT ?, CAST(id AS TEXT), CAST(sync_rev AS TEXT)
|
|
526
|
-
FROM ${
|
|
531
|
+
FROM ${d}
|
|
527
532
|
WHERE origin_device_id IS NULL
|
|
528
|
-
`).run(
|
|
529
|
-
UPDATE ${
|
|
533
|
+
`).run(u),this.db.prepare(`
|
|
534
|
+
UPDATE ${d} SET synced_at = ?
|
|
530
535
|
WHERE synced_at IS NULL AND origin_device_id IS NULL
|
|
531
536
|
`).run(a);this.db.run("DELETE FROM sync_outbox"),this.db.run("DELETE FROM sync_content_outbox"),this.db.run("DELETE FROM sync_dead_letter"),this.db.run("DELETE FROM sync_state");let E=new Date(a).toISOString();this.db.prepare("INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)").run(47,E),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(48,E)})();return}if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(48)&&t)return;let i=Date.parse(s.applied_at);if(!Number.isSafeInteger(i)||i<0)throw new Error(`schema v48: invalid v47 applied_at ${s.applied_at}`);this.db.transaction(()=>{for(let{table:a,kind:_}of e)this.db.prepare(`
|
|
532
537
|
INSERT OR IGNORE INTO sync_launch_exclusions (kind, origin_local_id, through_rev)
|
|
@@ -548,10 +553,10 @@ ${L.stack??""}
|
|
|
548
553
|
ELSE value END)
|
|
549
554
|
FROM json_each(observations.concepts))
|
|
550
555
|
WHERE concepts LIKE '%:%' AND json_valid(concepts)
|
|
551
|
-
`);for(let i of n){if(i.origin_device_id!==null)continue;let
|
|
556
|
+
`);for(let i of n){if(i.origin_device_id!==null)continue;let r=ze(i.sync_rev);this.db.prepare(`
|
|
552
557
|
UPDATE observations SET sync_rev = ?, synced_at = NULL
|
|
553
558
|
WHERE id = ? AND origin_device_id IS NULL
|
|
554
|
-
`).run(
|
|
559
|
+
`).run(r,i.id)}this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(49,new Date().toISOString())})(),c.debug("DB",`Normalized prefixed concept tags in ${t} observations (v49)`)}dropDeadPendingMessagesColumns(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(31),t=this.db.query("PRAGMA table_info(pending_messages)").all(),s=new Set(t.map(r=>r.name)),i=["retry_count","failed_at_epoch","completed_at_epoch"].filter(r=>s.has(r));if(!(e&&i.length===0)){if(i.length>0){this.db.run("BEGIN TRANSACTION");try{this.db.run("DELETE FROM pending_messages WHERE status NOT IN ('pending', 'processing')");for(let r of i)this.db.run(`ALTER TABLE pending_messages DROP COLUMN ${r}`),c.debug("DB",`Dropped dead column ${r} from pending_messages`);e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(31,new Date().toISOString()),this.db.run("COMMIT")}catch(r){this.db.run("ROLLBACK"),c.warn("DB","Failed to drop dead columns from pending_messages",{},r instanceof Error?r:new Error(String(r)));return}return}e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(31,new Date().toISOString())}}initializeSchema(){this.db.run(`
|
|
555
560
|
CREATE TABLE IF NOT EXISTS schema_versions (
|
|
556
561
|
id INTEGER PRIMARY KEY,
|
|
557
562
|
version INTEGER UNIQUE NOT NULL,
|
|
@@ -614,7 +619,7 @@ ${L.stack??""}
|
|
|
614
619
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
615
620
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_project ON session_summaries(project);
|
|
616
621
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
617
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(4,new Date().toISOString())}ensureWorkerPortColumn(){this.db.query("PRAGMA table_info(sdk_sessions)").all().some(s=>s.name==="worker_port")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),
|
|
622
|
+
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(4,new Date().toISOString())}ensureWorkerPortColumn(){this.db.query("PRAGMA table_info(sdk_sessions)").all().some(s=>s.name==="worker_port")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),c.debug("DB","Added worker_port column to sdk_sessions table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(5,new Date().toISOString())}ensurePromptTrackingColumns(){this.db.query("PRAGMA table_info(sdk_sessions)").all().some(a=>a.name==="prompt_counter")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),c.debug("DB","Added prompt_counter column to sdk_sessions table")),this.db.query("PRAGMA table_info(observations)").all().some(a=>a.name==="prompt_number")||(this.db.run("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),c.debug("DB","Added prompt_number column to observations table")),this.db.query("PRAGMA table_info(session_summaries)").all().some(a=>a.name==="prompt_number")||(this.db.run("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),c.debug("DB","Added prompt_number column to session_summaries table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(6,new Date().toISOString())}repairOrphanedSessionParents(e){let t=this.db.prepare(`
|
|
618
623
|
SELECT COUNT(DISTINCT c.memory_session_id) AS n
|
|
619
624
|
FROM ${e} c
|
|
620
625
|
WHERE c.memory_session_id IS NOT NULL
|
|
@@ -634,7 +639,7 @@ ${L.stack??""}
|
|
|
634
639
|
AND NOT EXISTS (SELECT 1 FROM sdk_sessions s WHERE s.memory_session_id = c.memory_session_id)
|
|
635
640
|
GROUP BY c.memory_session_id
|
|
636
641
|
ON CONFLICT DO NOTHING
|
|
637
|
-
`),
|
|
642
|
+
`),c.warn("DB",`Created ${t} stub sdk_sessions parent(s) for orphaned ${e} rows before rebuild (#3378)`))}hasMemorySessionIdOnUpdateCascade(e){return this.db.query(`PRAGMA foreign_key_list(${e})`).all().some(s=>s.table==="sdk_sessions"&&s.from==="memory_session_id"&&s.on_update==="CASCADE")}carryLiveColumnsOntoNewTable(e,t,s){let n=this.db.query(`PRAGMA table_info(${e})`).all(),i=n.filter(r=>!s.includes(r.name));for(let r of i){let a=r.type?` ${r.type}`:"",_=r.dflt_value===null||r.dflt_value===void 0?"":` DEFAULT ${r.dflt_value}`;this.db.run(`ALTER TABLE ${t} ADD COLUMN "${r.name}"${a}${_}`),c.debug("DB",`Carried ${r.name} over the ${e} rebuild (#3849)`)}return n.map(r=>r.name)}removeSessionSummariesUniqueConstraint(){if(!this.db.query("PRAGMA index_list(session_summaries)").all().some(a=>a.unique===1&&a.origin==="u")){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString());return}c.debug("DB","Removing UNIQUE constraint from session_summaries.memory_session_id"),this.db.run("BEGIN TRANSACTION"),this.repairOrphanedSessionParents("session_summaries");let s=["id","memory_session_id","project","request","investigated","learned","completed","next_steps","files_read","files_edited","notes","prompt_number","created_at","created_at_epoch"],i=this.db.query("PRAGMA table_info(session_summaries)").all().filter(a=>!s.includes(a.name));this.db.run("DROP TABLE IF EXISTS session_summaries_new"),this.db.run(`
|
|
638
643
|
CREATE TABLE session_summaries_new (
|
|
639
644
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
640
645
|
memory_session_id TEXT NOT NULL,
|
|
@@ -652,15 +657,15 @@ ${L.stack??""}
|
|
|
652
657
|
created_at_epoch INTEGER NOT NULL,
|
|
653
658
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
654
659
|
)
|
|
655
|
-
`);for(let a of i){let _=a.type?` ${a.type}`:"",E=a.dflt_value===null||a.dflt_value===void 0?"":` DEFAULT ${a.dflt_value}`;this.db.run(`ALTER TABLE session_summaries_new ADD COLUMN "${a.name}"${_}${E}`),
|
|
656
|
-
INSERT INTO session_summaries_new (${
|
|
657
|
-
SELECT ${
|
|
660
|
+
`);for(let a of i){let _=a.type?` ${a.type}`:"",E=a.dflt_value===null||a.dflt_value===void 0?"":` DEFAULT ${a.dflt_value}`;this.db.run(`ALTER TABLE session_summaries_new ADD COLUMN "${a.name}"${_}${E}`),c.debug("DB",`Carried ${a.name} over the session_summaries UNIQUE-constraint rebuild (#3890)`)}let r=[...s,...i.map(a=>a.name)].map(a=>`"${a}"`).join(", ");this.db.run(`
|
|
661
|
+
INSERT INTO session_summaries_new (${r})
|
|
662
|
+
SELECT ${r}
|
|
658
663
|
FROM session_summaries
|
|
659
664
|
`),this.db.run("DROP TABLE session_summaries"),this.db.run("ALTER TABLE session_summaries_new RENAME TO session_summaries"),this.db.run(`
|
|
660
665
|
CREATE INDEX idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
661
666
|
CREATE INDEX idx_session_summaries_project ON session_summaries(project);
|
|
662
667
|
CREATE INDEX idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
663
|
-
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString()),
|
|
668
|
+
`),this.recreateFtsTriggersIfIndexed("session_summaries"),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString()),c.debug("DB","Successfully removed UNIQUE constraint from session_summaries.memory_session_id")}addObservationHierarchicalFields(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(8))return;if(this.db.query("PRAGMA table_info(observations)").all().some(n=>n.name==="title")){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString());return}c.debug("DB","Adding hierarchical fields to observations table"),this.db.run(`
|
|
664
669
|
ALTER TABLE observations ADD COLUMN title TEXT;
|
|
665
670
|
ALTER TABLE observations ADD COLUMN subtitle TEXT;
|
|
666
671
|
ALTER TABLE observations ADD COLUMN facts TEXT;
|
|
@@ -668,7 +673,7 @@ ${L.stack??""}
|
|
|
668
673
|
ALTER TABLE observations ADD COLUMN concepts TEXT;
|
|
669
674
|
ALTER TABLE observations ADD COLUMN files_read TEXT;
|
|
670
675
|
ALTER TABLE observations ADD COLUMN files_modified TEXT;
|
|
671
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString()),
|
|
676
|
+
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString()),c.debug("DB","Successfully added hierarchical fields to observations table")}makeObservationsTextNullable(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(9))return;let s=this.db.query("PRAGMA table_info(observations)").all().find(n=>n.name==="text");if(!s||s.notnull===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString());return}c.debug("DB","Making observations.text nullable"),this.db.run("BEGIN TRANSACTION"),this.repairOrphanedSessionParents("observations"),this.db.run("DROP TABLE IF EXISTS observations_new"),this.db.run(`
|
|
672
677
|
CREATE TABLE observations_new (
|
|
673
678
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
674
679
|
memory_session_id TEXT NOT NULL,
|
|
@@ -698,7 +703,7 @@ ${L.stack??""}
|
|
|
698
703
|
CREATE INDEX idx_observations_project ON observations(project);
|
|
699
704
|
CREATE INDEX idx_observations_type ON observations(type);
|
|
700
705
|
CREATE INDEX idx_observations_created ON observations(created_at_epoch DESC);
|
|
701
|
-
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString()),
|
|
706
|
+
`),this.recreateFtsTriggersIfIndexed("observations"),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString()),c.debug("DB","Successfully made observations.text nullable")}recreateFtsTriggersIfIndexed(e){let t=`${e}_fts`;this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").all(t).length>0&&(this.db.run(`INSERT INTO ${t}(${t}) VALUES('rebuild')`),this.db.run(e==="observations"?ae:_e))}createUserPromptsTable(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(10))return;if(this.db.query("PRAGMA table_info(user_prompts)").all().length>0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(10,new Date().toISOString());return}c.debug("DB","Creating user_prompts table"),this.db.run("BEGIN TRANSACTION"),this.db.run(`
|
|
702
707
|
CREATE TABLE user_prompts (
|
|
703
708
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
704
709
|
session_db_id INTEGER,
|
|
@@ -716,7 +721,7 @@ ${L.stack??""}
|
|
|
716
721
|
CREATE INDEX idx_user_prompts_prompt_number ON user_prompts(prompt_number);
|
|
717
722
|
CREATE INDEX idx_user_prompts_lookup ON user_prompts(session_db_id, prompt_number);
|
|
718
723
|
CREATE INDEX idx_user_prompts_content_lookup ON user_prompts(content_session_id, prompt_number);
|
|
719
|
-
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(10,new Date().toISOString()),
|
|
724
|
+
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(10,new Date().toISOString()),c.debug("DB","Successfully created user_prompts table")}ensureDiscoveryTokensColumn(){this.db.query("PRAGMA table_info(observations)").all().some(i=>i.name==="discovery_tokens")||(this.db.run("ALTER TABLE observations ADD COLUMN discovery_tokens INTEGER DEFAULT 0"),c.debug("DB","Added discovery_tokens column to observations table")),this.db.query("PRAGMA table_info(session_summaries)").all().some(i=>i.name==="discovery_tokens")||(this.db.run("ALTER TABLE session_summaries ADD COLUMN discovery_tokens INTEGER DEFAULT 0"),c.debug("DB","Added discovery_tokens column to session_summaries table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(11,new Date().toISOString())}createPendingMessagesTable(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(16))return;if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='pending_messages'").all().length>0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(16,new Date().toISOString());return}c.debug("DB","Creating pending_messages table"),this.db.run(`
|
|
720
725
|
CREATE TABLE pending_messages (
|
|
721
726
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
722
727
|
session_db_id INTEGER NOT NULL,
|
|
@@ -733,7 +738,7 @@ ${L.stack??""}
|
|
|
733
738
|
created_at_epoch INTEGER NOT NULL,
|
|
734
739
|
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
|
735
740
|
)
|
|
736
|
-
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_session ON pending_messages(session_db_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_status ON pending_messages(status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_claude_session ON pending_messages(content_session_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(16,new Date().toISOString()),
|
|
741
|
+
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_session ON pending_messages(session_db_id)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_status ON pending_messages(status)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_pending_messages_claude_session ON pending_messages(content_session_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(16,new Date().toISOString()),c.debug("DB","pending_messages table created successfully")}renameSessionIdColumns(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(17))return;c.debug("DB","Checking session ID columns for semantic clarity rename");let t=0,s=(n,i,r)=>{let a=this.db.query(`PRAGMA table_info(${n})`).all(),_=a.some(d=>d.name===i);return a.some(d=>d.name===r)?!1:_?(this.db.run(`ALTER TABLE ${n} RENAME COLUMN ${i} TO ${r}`),c.debug("DB",`Renamed ${n}.${i} to ${r}`),!0):(c.warn("DB",`Column ${i} not found in ${n}, skipping rename`),!1)};s("sdk_sessions","claude_session_id","content_session_id")&&t++,s("sdk_sessions","sdk_session_id","memory_session_id")&&t++,s("pending_messages","claude_session_id","content_session_id")&&t++,s("observations","sdk_session_id","memory_session_id")&&t++,s("session_summaries","sdk_session_id","memory_session_id")&&t++,s("user_prompts","claude_session_id","content_session_id")&&t++,this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(17,new Date().toISOString()),t>0?c.debug("DB",`Successfully renamed ${t} session ID columns`):c.debug("DB","No session ID column renames needed (already up to date)")}addFailedAtEpochColumn(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(20))return;this.db.query("PRAGMA table_info(pending_messages)").all().some(n=>n.name==="failed_at_epoch")||(this.db.run("ALTER TABLE pending_messages ADD COLUMN failed_at_epoch INTEGER"),c.debug("DB","Added failed_at_epoch column to pending_messages table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(20,new Date().toISOString())}addOnUpdateCascadeToForeignKeys(){let e=!this.hasMemorySessionIdOnUpdateCascade("observations"),t=!this.hasMemorySessionIdOnUpdateCascade("session_summaries");if(!e&&!t){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(21,new Date().toISOString());return}c.debug("DB","Adding ON UPDATE CASCADE to FK constraints on observations and session_summaries"),this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");let s=["id","memory_session_id","project","text","type","title","subtitle","facts","narrative","concepts","files_read","files_modified","prompt_number","discovery_tokens","created_at","created_at_epoch"],n=`
|
|
737
742
|
CREATE TABLE observations_new (
|
|
738
743
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
739
744
|
memory_session_id TEXT NOT NULL,
|
|
@@ -758,7 +763,7 @@ ${L.stack??""}
|
|
|
758
763
|
CREATE INDEX idx_observations_project ON observations(project);
|
|
759
764
|
CREATE INDEX idx_observations_type ON observations(type);
|
|
760
765
|
CREATE INDEX idx_observations_created ON observations(created_at_epoch DESC);
|
|
761
|
-
`,
|
|
766
|
+
`,r=["id","memory_session_id","project","request","investigated","learned","completed","next_steps","files_read","files_edited","notes","prompt_number","discovery_tokens","created_at","created_at_epoch"],a=`
|
|
762
767
|
CREATE TABLE session_summaries_new (
|
|
763
768
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
764
769
|
memory_session_id TEXT NOT NULL,
|
|
@@ -781,11 +786,11 @@ ${L.stack??""}
|
|
|
781
786
|
CREATE INDEX idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
782
787
|
CREATE INDEX idx_session_summaries_project ON session_summaries(project);
|
|
783
788
|
CREATE INDEX idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
784
|
-
`;try{e&&(this.db.run("DROP TRIGGER IF EXISTS observations_ai"),this.db.run("DROP TRIGGER IF EXISTS observations_ad"),this.db.run("DROP TRIGGER IF EXISTS observations_au"),this.db.run("DROP TABLE IF EXISTS observations_new"),this.recreateObservationsWithCascade(n,s,i
|
|
789
|
+
`;try{e&&(this.db.run("DROP TRIGGER IF EXISTS observations_ai"),this.db.run("DROP TRIGGER IF EXISTS observations_ad"),this.db.run("DROP TRIGGER IF EXISTS observations_au"),this.db.run("DROP TABLE IF EXISTS observations_new"),this.recreateObservationsWithCascade(n,s,i)),t&&(this.db.run("DROP TRIGGER IF EXISTS session_summaries_ai"),this.db.run("DROP TRIGGER IF EXISTS session_summaries_ad"),this.db.run("DROP TRIGGER IF EXISTS session_summaries_au"),this.db.run("DROP TABLE IF EXISTS session_summaries_new"),this.recreateSessionSummariesWithCascade(a,r,_)),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(21,new Date().toISOString()),this.db.run("COMMIT"),this.db.run("PRAGMA foreign_keys = ON"),c.debug("DB","Successfully added ON UPDATE CASCADE to FK constraints")}catch(E){throw this.db.run("ROLLBACK"),this.db.run("PRAGMA foreign_keys = ON"),E instanceof Error?E:new Error(String(E))}}recreateObservationsWithCascade(e,t,s){this.db.run(e);let i=this.carryLiveColumnsOntoNewTable("observations","observations_new",t).map(r=>`"${r}"`).join(", ");this.db.run(`INSERT INTO observations_new (${i}) SELECT ${i} FROM observations`),this.db.run("DROP TABLE observations"),this.db.run("ALTER TABLE observations_new RENAME TO observations"),this.db.run(s),this.recreateFtsTriggersIfIndexed("observations")}recreateSessionSummariesWithCascade(e,t,s){this.db.run(e);let i=this.carryLiveColumnsOntoNewTable("session_summaries","session_summaries_new",t).map(r=>`"${r}"`).join(", ");this.db.run(`INSERT INTO session_summaries_new (${i}) SELECT ${i} FROM session_summaries`),this.db.run("DROP TABLE session_summaries"),this.db.run("ALTER TABLE session_summaries_new RENAME TO session_summaries"),this.db.run(s),this.recreateFtsTriggersIfIndexed("session_summaries")}addObservationContentHashColumn(){if(this.db.query("PRAGMA table_info(observations)").all().some(s=>s.name==="content_hash")){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(22,new Date().toISOString());return}this.db.run("ALTER TABLE observations ADD COLUMN content_hash TEXT"),this.db.run("UPDATE observations SET content_hash = substr(hex(randomblob(8)), 1, 16) WHERE content_hash IS NULL"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_content_hash ON observations(content_hash, created_at_epoch)"),c.debug("DB","Added content_hash column to observations table with backfill and index"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(22,new Date().toISOString())}addSessionCustomTitleColumn(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(23),s=this.db.query("PRAGMA table_info(sdk_sessions)").all().some(n=>n.name==="custom_title");e&&s||(s||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN custom_title TEXT"),c.debug("DB","Added custom_title column to sdk_sessions table")),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(23,new Date().toISOString()))}addSessionPlatformSourceColumn(){let t=this.db.query("PRAGMA table_info(sdk_sessions)").all().some(r=>r.name==="platform_source"),n=this.db.query("PRAGMA index_list(sdk_sessions)").all().some(r=>r.name==="idx_sdk_sessions_platform_source");this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(24)&&t&&n||(t||(this.db.run(`ALTER TABLE sdk_sessions ADD COLUMN platform_source TEXT NOT NULL DEFAULT '${T}'`),c.debug("DB","Added platform_source column to sdk_sessions table")),this.db.run(`
|
|
785
790
|
UPDATE sdk_sessions
|
|
786
|
-
SET platform_source = '${
|
|
791
|
+
SET platform_source = '${T}'
|
|
787
792
|
WHERE platform_source IS NULL OR platform_source = ''
|
|
788
|
-
`),n||this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(24,new Date().toISOString()))}addObservationModelColumns(){let e=this.db.query("PRAGMA table_info(observations)").all(),t=e.some(n=>n.name==="generated_by_model"),s=e.some(n=>n.name==="relevance_count");t&&s||(t||this.db.run("ALTER TABLE observations ADD COLUMN generated_by_model TEXT"),s||this.db.run("ALTER TABLE observations ADD COLUMN relevance_count INTEGER DEFAULT 0"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(26,new Date().toISOString()))}ensureSDKSessionsObservedColumns(){let e=this.db.query("PRAGMA table_info(sdk_sessions)").all(),t=e.some(n=>n.name==="observed_model"),s=e.some(n=>n.name==="observed_billing");t&&s||(t||this.db.run("ALTER TABLE sdk_sessions ADD COLUMN observed_model TEXT"),s||this.db.run("ALTER TABLE sdk_sessions ADD COLUMN observed_billing TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(50,new Date().toISOString()))}ensureToolUsesTable(){
|
|
793
|
+
`),n||this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(24,new Date().toISOString()))}addObservationModelColumns(){let e=this.db.query("PRAGMA table_info(observations)").all(),t=e.some(n=>n.name==="generated_by_model"),s=e.some(n=>n.name==="relevance_count");t&&s||(t||this.db.run("ALTER TABLE observations ADD COLUMN generated_by_model TEXT"),s||this.db.run("ALTER TABLE observations ADD COLUMN relevance_count INTEGER DEFAULT 0"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(26,new Date().toISOString()))}ensureSDKSessionsObservedColumns(){let e=this.db.query("PRAGMA table_info(sdk_sessions)").all(),t=e.some(n=>n.name==="observed_model"),s=e.some(n=>n.name==="observed_billing");t&&s||(t||this.db.run("ALTER TABLE sdk_sessions ADD COLUMN observed_model TEXT"),s||this.db.run("ALTER TABLE sdk_sessions ADD COLUMN observed_billing TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(50,new Date().toISOString()))}ensureToolUsesTable(){gt(this.db),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(51,new Date().toISOString())}ensureWorkStateTable(){Lt(this.db),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(61,new Date().toISOString())}ensureProjectRecencyIndexes(){this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_project_nocase_recent ON observations(project COLLATE NOCASE, created_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_merged_into_nocase_recent ON observations(merged_into_project COLLATE NOCASE, created_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_project_nocase_recent ON session_summaries(project COLLATE NOCASE, created_at_epoch DESC)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_merged_into_nocase_recent ON session_summaries(merged_into_project COLLATE NOCASE, created_at_epoch DESC)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(63,new Date().toISOString())}ensureMergedIntoProjectCoveringIndexes(){this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_merged_into_nocase_project ON observations(merged_into_project COLLATE NOCASE, project)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_merged_into_nocase_project ON session_summaries(merged_into_project COLLATE NOCASE, project)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(64,new Date().toISOString())}ensureHookSpoolConsumedTable(){this.db.run(`
|
|
789
794
|
CREATE TABLE IF NOT EXISTS hook_spool_consumed (
|
|
790
795
|
entry_key TEXT PRIMARY KEY,
|
|
791
796
|
consumed_at_epoch_ms INTEGER NOT NULL
|
|
@@ -803,7 +808,7 @@ ${L.stack??""}
|
|
|
803
808
|
sent_at_epoch INTEGER,
|
|
804
809
|
UNIQUE(platform_source, content_session_id, project, route_key)
|
|
805
810
|
)
|
|
806
|
-
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_telegram_wrapups_platform_content ON telegram_wrapups(platform_source, content_session_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(52,new Date().toISOString())}ensureReinforcementColumns(){let e=this.db.query("PRAGMA table_info(observations)").all();e.some(t=>t.name==="reinforcement_dates")||this.db.run("ALTER TABLE observations ADD COLUMN reinforcement_dates TEXT"),e.some(t=>t.name==="last_reinforced")||this.db.run("ALTER TABLE observations ADD COLUMN last_reinforced TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(
|
|
811
|
+
`),this.db.run("CREATE INDEX IF NOT EXISTS idx_telegram_wrapups_platform_content ON telegram_wrapups(platform_source, content_session_id)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(52,new Date().toISOString())}ensureReinforcementColumns(){let e=this.db.query("PRAGMA table_info(observations)").all();e.some(t=>t.name==="reinforcement_dates")||this.db.run("ALTER TABLE observations ADD COLUMN reinforcement_dates TEXT"),e.some(t=>t.name==="last_reinforced")||this.db.run("ALTER TABLE observations ADD COLUMN last_reinforced TEXT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(gn,new Date().toISOString())}dropWriteOnlyUserPromptsFtsAndScopeFtsUpdateTriggers(){let e=this.db.prepare(`
|
|
807
812
|
SELECT name FROM sqlite_master
|
|
808
813
|
WHERE type = 'trigger'
|
|
809
814
|
AND name IN ('observations_au', 'session_summaries_au')
|
|
@@ -811,7 +816,7 @@ ${L.stack??""}
|
|
|
811
816
|
`).all().map(s=>s.name),t=this.db.prepare(`
|
|
812
817
|
SELECT name FROM sqlite_master
|
|
813
818
|
WHERE name IN ('user_prompts_fts', 'user_prompts_ai', 'user_prompts_ad', 'user_prompts_au')
|
|
814
|
-
`).all();if(e.length>0||t.length>0){this.db.run("BEGIN TRANSACTION");try{e.includes("observations_au")&&(this.db.run("DROP TRIGGER observations_au"),this.db.run(
|
|
819
|
+
`).all();if(e.length>0||t.length>0){this.db.run("BEGIN TRANSACTION");try{e.includes("observations_au")&&(this.db.run("DROP TRIGGER observations_au"),this.db.run(ae)),e.includes("session_summaries_au")&&(this.db.run("DROP TRIGGER session_summaries_au"),this.db.run(_e)),this.db.run("DROP TRIGGER IF EXISTS user_prompts_ai"),this.db.run("DROP TRIGGER IF EXISTS user_prompts_ad"),this.db.run("DROP TRIGGER IF EXISTS user_prompts_au"),this.db.run("DROP TABLE IF EXISTS user_prompts_fts"),this.db.run("COMMIT")}catch(s){throw this.db.run("ROLLBACK"),c.error("DB","Failed to scope FTS update triggers / drop user_prompts_fts, rolled back",{},s instanceof Error?s:new Error(String(s))),s}c.info("DB","Scoped FTS update triggers to indexed columns and dropped the write-only user_prompts_fts",{rescopedTriggers:e,droppedUserPromptsFts:t.length>0})}this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(54,new Date().toISOString())}ensureMergedIntoProjectColumns(){this.db.query("PRAGMA table_info(observations)").all().some(s=>s.name==="merged_into_project")||this.db.run("ALTER TABLE observations ADD COLUMN merged_into_project TEXT"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_merged_into ON observations(merged_into_project)"),this.db.query("PRAGMA table_info(session_summaries)").all().some(s=>s.name==="merged_into_project")||this.db.run("ALTER TABLE session_summaries ADD COLUMN merged_into_project TEXT"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_merged_into ON session_summaries(merged_into_project)")}requeuePromptsDeadLetteredForSize(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(60))return;let t="canonical content: body exceeds % UTF-8 bytes";this.db.transaction(()=>{let s=this.db.prepare(`
|
|
815
820
|
UPDATE user_prompts SET synced_at = NULL
|
|
816
821
|
WHERE synced_at = -1 AND origin_device_id IS NULL
|
|
817
822
|
AND CAST(id AS TEXT) IN (
|
|
@@ -820,7 +825,7 @@ ${L.stack??""}
|
|
|
820
825
|
)
|
|
821
826
|
`).run(t);this.db.prepare(`
|
|
822
827
|
DELETE FROM sync_dead_letter WHERE lane = 'content' AND kind = 'prompt' AND reason LIKE ?
|
|
823
|
-
`).run(t),s.changes>0&&
|
|
828
|
+
`).run(t),s.changes>0&&c.info("DB","Re-queued prompts quarantined for size before the cloud-sync prompt clamp",{prompts:s.changes}),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(60,new Date().toISOString())})()}ensureSessionProjectKeySourceColumn(){this.db.query("PRAGMA table_info(sdk_sessions)").all().some(t=>t.name==="project_key_source")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN project_key_source TEXT"),c.debug("DB","Added project_key_source column to sdk_sessions table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(59,new Date().toISOString())}ensureSessionCwdColumn(){this.db.query("PRAGMA table_info(sdk_sessions)").all().some(t=>t.name==="cwd")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN cwd TEXT"),c.debug("DB","Added cwd column to sdk_sessions table (#2864)")),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_cwd ON sdk_sessions(cwd)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(53,new Date().toISOString())}ensureProjectNocaseIndexes(){this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_project_nocase ON observations(project COLLATE NOCASE)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_merged_into_nocase ON observations(merged_into_project COLLATE NOCASE)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_project_nocase ON session_summaries(project COLLATE NOCASE)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_summaries_merged_into_nocase ON session_summaries(merged_into_project COLLATE NOCASE)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_sdk_sessions_project_nocase ON sdk_sessions(project COLLATE NOCASE)"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(55,new Date().toISOString())}ensureAdvisorCallsTable(){this.db.run(`
|
|
824
829
|
CREATE TABLE IF NOT EXISTS advisor_calls (
|
|
825
830
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
826
831
|
session_db_id INTEGER NOT NULL,
|
|
@@ -843,7 +848,7 @@ ${L.stack??""}
|
|
|
843
848
|
INSERT OR IGNORE INTO advisor_calls
|
|
844
849
|
(session_db_id, content_session_id, project, platform_source, tool_use_id, advisor_model, cwd, last_user_message, transcript_path, transcript_byte_offset, advice, occurred_at_epoch, created_at, created_at_epoch)
|
|
845
850
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
846
|
-
`).run(e.sessionDbId,e.contentSessionId,e.project,e.platformSource,e.toolUseId,e.advisorModel??null,e.cwd??null,e.lastUserMessage??null,e.transcriptPath??null,e.transcriptByteOffset??null,e.advice,e.occurredAtEpoch,t.toISOString(),t.getTime());return s.changes>0?{id:Number(s.lastInsertRowid),inserted:!0}:{id:this.db.prepare("SELECT id FROM advisor_calls WHERE tool_use_id = ?").get(e.toolUseId)?.id??0,inserted:!1}}getAdvisorCalls(e,t,s,n){let i="SELECT * FROM advisor_calls",
|
|
851
|
+
`).run(e.sessionDbId,e.contentSessionId,e.project,e.platformSource,e.toolUseId,e.advisorModel??null,e.cwd??null,e.lastUserMessage??null,e.transcriptPath??null,e.transcriptByteOffset??null,e.advice,e.occurredAtEpoch,t.toISOString(),t.getTime());return s.changes>0?{id:Number(s.lastInsertRowid),inserted:!0}:{id:this.db.prepare("SELECT id FROM advisor_calls WHERE tool_use_id = ?").get(e.toolUseId)?.id??0,inserted:!1}}getAdvisorCalls(e,t,s,n){let i="SELECT * FROM advisor_calls",r=[],a=[];s?(a.push("project = ?"),r.push(s)):(a.push("project != ?"),r.push(ee)),n&&(a.push("platform_source = ?"),r.push(n)),i+=` WHERE ${a.join(" AND ")}`,i+=" ORDER BY occurred_at_epoch DESC LIMIT ? OFFSET ?",r.push(t+1,e);let _=this.db.prepare(i).all(...r);return{items:_.slice(0,t),hasMore:_.length>t,offset:e,limit:t}}getAdvisorCallById(e){return this.db.prepare("SELECT * FROM advisor_calls WHERE id = ?").get(e)??null}addObservationSubagentColumns(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(27),t=this.db.query("PRAGMA table_info(observations)").all(),s=t.some(r=>r.name==="agent_type"),n=t.some(r=>r.name==="agent_id");s||this.db.run("ALTER TABLE observations ADD COLUMN agent_type TEXT"),n||this.db.run("ALTER TABLE observations ADD COLUMN agent_id TEXT"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_agent_type ON observations(agent_type)"),this.db.run("CREATE INDEX IF NOT EXISTS idx_observations_agent_id ON observations(agent_id)");let i=this.db.query("PRAGMA table_info(pending_messages)").all();if(i.length>0){let r=i.some(_=>_.name==="agent_type"),a=i.some(_=>_.name==="agent_id");r||this.db.run("ALTER TABLE pending_messages ADD COLUMN agent_type TEXT"),a||this.db.run("ALTER TABLE pending_messages ADD COLUMN agent_id TEXT")}e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(27,new Date().toISOString())}ensurePendingMessagesToolUseIdColumn(){if(this.db.query("SELECT name FROM sqlite_master WHERE type='table' AND name='pending_messages'").all().length===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(28,new Date().toISOString());return}this.db.query("PRAGMA table_info(pending_messages)").all().some(n=>n.name==="tool_use_id")||this.db.run("ALTER TABLE pending_messages ADD COLUMN tool_use_id TEXT"),this.db.run("BEGIN TRANSACTION");try{this.dedupePendingMessagesByToolUseId(),this.db.run("COMMIT")}catch(n){this.db.run("ROLLBACK");let i=n instanceof Error?n:new Error(String(n));throw c.error("DB","Failed to de-dupe pending_messages by tool_use_id, rolled back",{},i),n}}dedupePendingMessagesByToolUseId(){this.db.run(`
|
|
847
852
|
DELETE FROM pending_messages
|
|
848
853
|
WHERE id IN (
|
|
849
854
|
SELECT id
|
|
@@ -868,7 +873,7 @@ ${L.stack??""}
|
|
|
868
873
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
869
874
|
ON pending_messages(session_db_id, tool_use_id)
|
|
870
875
|
WHERE tool_use_id IS NOT NULL
|
|
871
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(28,new Date().toISOString())}addObservationsUniqueContentHashIndex(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(29))return;let t=this.db.query("PRAGMA table_info(observations)").all(),s=t.some(i=>i.name==="memory_session_id"),n=t.some(i=>i.name==="content_hash");if(!s||!n){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(29,new Date().toISOString());return}this.db.run("BEGIN TRANSACTION");try{this.dedupeObservationsByContentHash(),this.db.run("COMMIT")}catch(i){this.db.run("ROLLBACK");let
|
|
876
|
+
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(28,new Date().toISOString())}addObservationsUniqueContentHashIndex(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(29))return;let t=this.db.query("PRAGMA table_info(observations)").all(),s=t.some(i=>i.name==="memory_session_id"),n=t.some(i=>i.name==="content_hash");if(!s||!n){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(29,new Date().toISOString());return}this.db.run("BEGIN TRANSACTION");try{this.dedupeObservationsByContentHash(),this.db.run("COMMIT")}catch(i){this.db.run("ROLLBACK");let r=i instanceof Error?i:new Error(String(i));throw c.error("DB","Failed to de-dupe observations by content_hash, rolled back",{},r),i}}dedupeObservationsByContentHash(){this.db.run(`
|
|
872
877
|
UPDATE observations
|
|
873
878
|
SET content_hash = '__null_migration_' || id || '__'
|
|
874
879
|
WHERE content_hash IS NULL
|
|
@@ -889,7 +894,7 @@ ${L.stack??""}
|
|
|
889
894
|
`),this.db.run(`
|
|
890
895
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_observations_session_hash
|
|
891
896
|
ON observations(memory_session_id, content_hash)
|
|
892
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(29,new Date().toISOString())}addObservationsMetadataColumn(){this.db.query("PRAGMA table_info(observations)").all().some(s=>s.name==="metadata")||(this.db.run("ALTER TABLE observations ADD COLUMN metadata TEXT"),
|
|
897
|
+
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(29,new Date().toISOString())}addObservationsMetadataColumn(){this.db.query("PRAGMA table_info(observations)").all().some(s=>s.name==="metadata")||(this.db.run("ALTER TABLE observations ADD COLUMN metadata TEXT"),c.debug("DB","Added metadata column to observations table (#2116)")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(30,new Date().toISOString())}updateMemorySessionId(e,t){let s=this.db.prepare(`
|
|
893
898
|
SELECT memory_session_id
|
|
894
899
|
FROM sdk_sessions
|
|
895
900
|
WHERE id = ?
|
|
@@ -901,7 +906,7 @@ ${L.stack??""}
|
|
|
901
906
|
UPDATE tool_uses
|
|
902
907
|
SET memory_session_id = ?
|
|
903
908
|
WHERE session_db_id = ?
|
|
904
|
-
`).run(t,e)})(),t&&this.requeuePromptSync(e))}enqueueMutationOp(e,t){if(!this.syncOpsEnabled)return;let s=JSON.parse(JSON.stringify(t));if(s.op==="set_prompt_session"){let n=s.target;n?.origin_device_id===null&&(n.origin_device_id="self")}
|
|
909
|
+
`).run(t,e)})(),t&&this.requeuePromptSync(e))}enqueueMutationOp(e,t){if(!this.syncOpsEnabled)return;let s=JSON.parse(JSON.stringify(t));if(s.op==="set_prompt_session"){let n=s.target;n?.origin_device_id===null&&(n.origin_device_id="self")}Qe(s),t.op==="set_prompt_session"&&this.cachedStatement(`
|
|
905
910
|
DELETE FROM sync_outbox
|
|
906
911
|
WHERE json_valid(body)
|
|
907
912
|
AND json_extract(body, '$.op') = 'set_prompt_session'
|
|
@@ -910,7 +915,7 @@ ${L.stack??""}
|
|
|
910
915
|
`).run(t.target?.origin_device_id??null,String(t.target?.origin_local_id??"")),this.cachedStatement(`
|
|
911
916
|
INSERT INTO sync_outbox (op_uuid, rev, body, created_at_epoch)
|
|
912
917
|
VALUES (?, ?, ?, ?)
|
|
913
|
-
`).run((0,
|
|
918
|
+
`).run((0,he.randomUUID)(),String(e),JSON.stringify(t),Date.now())}requeuePromptSync(e){if(!this.syncOpsEnabled)return;let t=this.cachedStatement(`
|
|
914
919
|
SELECT memory_session_id, project, content_session_id, platform_source
|
|
915
920
|
FROM sdk_sessions WHERE id = ?
|
|
916
921
|
`).get(e);if(!t?.memory_session_id)return;this.db.transaction(()=>{let n=this.cachedStatement(`
|
|
@@ -919,7 +924,7 @@ ${L.stack??""}
|
|
|
919
924
|
`).all(e);if(n.length===0)return;let i=this.cachedStatement(`
|
|
920
925
|
UPDATE user_prompts SET sync_rev = ?, synced_at = NULL
|
|
921
926
|
WHERE id = ? AND origin_device_id IS NULL
|
|
922
|
-
`);for(let
|
|
927
|
+
`);for(let r of n){let a=ze(r.sync_rev);i.run(a,r.id),this.enqueueMutationOp(a,{op:"set_prompt_session",target:{origin_device_id:null,origin_local_id:r.id},fields:{memory_session_id:t.memory_session_id,project:t.project,content_session_id:t.content_session_id,platform_source:t.platform_source}})}})()}markSessionCompleted(e){let t=Date.now(),s=new Date(t).toISOString();this.db.prepare(`
|
|
923
928
|
UPDATE sdk_sessions
|
|
924
929
|
SET status = 'completed', completed_at = ?, completed_at_epoch = ?
|
|
925
930
|
WHERE id = ?
|
|
@@ -931,28 +936,28 @@ ${L.stack??""}
|
|
|
931
936
|
SELECT id, memory_session_id, worker_port FROM sdk_sessions WHERE id = ?
|
|
932
937
|
`).get(e);if(!n)throw new Error(`Session ${e} not found in sdk_sessions`);return n.memory_session_id===null?(this.db.prepare(`
|
|
933
938
|
UPDATE sdk_sessions SET memory_session_id = ? WHERE id = ?
|
|
934
|
-
`).run(t,e),this.requeuePromptSync(e),
|
|
939
|
+
`).run(t,e),this.requeuePromptSync(e),c.info("DB","Registered memory_session_id before storage (FK fix)",{sessionDbId:e,newId:t})):n.memory_session_id!==t&&c.debug("DB","Keeping the registered memory_session_id",{sessionDbId:e,registered:n.memory_session_id,offered:t}),typeof s=="number"&&n.worker_port!==s&&this.db.prepare(`
|
|
935
940
|
UPDATE sdk_sessions SET worker_port = ? WHERE id = ?
|
|
936
|
-
`).run(s,e),n.memory_session_id??t}getProjectReadKeys(e){return
|
|
941
|
+
`).run(s,e),n.memory_session_id??t}getProjectReadKeys(e){return dt(this.db,e)}getAllProjects(e){let t=e?b(e):void 0,s=`
|
|
937
942
|
SELECT DISTINCT project
|
|
938
943
|
FROM sdk_sessions
|
|
939
944
|
WHERE project IS NOT NULL AND project != ''
|
|
940
945
|
AND project != ?
|
|
941
|
-
`,n=[
|
|
946
|
+
`,n=[ee];return t&&(s+=" AND COALESCE(platform_source, ?) = ?",n.push(T,t)),s+=" ORDER BY project ASC",this.db.prepare(s).all(...n).map(r=>r.project)}getProjectCatalog(){let e=this.db.prepare(`
|
|
942
947
|
SELECT
|
|
943
|
-
COALESCE(platform_source, '${
|
|
948
|
+
COALESCE(platform_source, '${T}') as platform_source,
|
|
944
949
|
project,
|
|
945
950
|
MAX(started_at_epoch) as latest_epoch
|
|
946
951
|
FROM sdk_sessions
|
|
947
952
|
WHERE project IS NOT NULL AND project != ''
|
|
948
953
|
AND project != ?
|
|
949
|
-
GROUP BY COALESCE(platform_source, '${
|
|
954
|
+
GROUP BY COALESCE(platform_source, '${T}'), project
|
|
950
955
|
ORDER BY latest_epoch DESC
|
|
951
|
-
`).all(
|
|
956
|
+
`).all(ee),t=[],s=new Set,n={};for(let r of e){let a=b(r.platform_source);n[a]||(n[a]=[]),n[a].includes(r.project)||n[a].push(r.project),s.has(r.project)||(s.add(r.project),t.push(r.project))}let i=Tt(Object.keys(n));return{projects:t,sources:i,projectsBySource:Object.fromEntries(i.map(r=>[r,n[r]||[]]))}}getSessionCatalog(e={}){let t=Math.min(Math.max(Math.trunc(e.limit??Tn),1),Sn),s=Math.max(Math.trunc(e.offset??0),0),n=`
|
|
952
957
|
SELECT
|
|
953
958
|
s.content_session_id,
|
|
954
959
|
s.project,
|
|
955
|
-
COALESCE(s.platform_source, '${
|
|
960
|
+
COALESCE(s.platform_source, '${T}') as platform_source,
|
|
956
961
|
s.custom_title,
|
|
957
962
|
s.started_at_epoch,
|
|
958
963
|
(
|
|
@@ -963,16 +968,16 @@ ${L.stack??""}
|
|
|
963
968
|
FROM sdk_sessions s
|
|
964
969
|
WHERE s.project IS NOT NULL AND s.project != ''
|
|
965
970
|
AND s.project != ?
|
|
966
|
-
`,i=[
|
|
971
|
+
`,i=[ee];e.project&&(n+=" AND s.project = ?",i.push(e.project)),e.platformSource&&(n+=` AND COALESCE(s.platform_source, '${T}') = ?`,i.push(b(e.platformSource))),n+=" ORDER BY s.started_at_epoch DESC, s.id DESC LIMIT ? OFFSET ?",i.push(t+1,s);let r=this.db.prepare(n).all(...i);return{sessions:r.slice(0,t),hasMore:r.length>t}}getUserPromptById(e){return this.db.prepare(`
|
|
967
972
|
SELECT
|
|
968
973
|
up.*,
|
|
969
974
|
s.memory_session_id,
|
|
970
975
|
s.project,
|
|
971
|
-
COALESCE(s.platform_source, '${
|
|
976
|
+
COALESCE(s.platform_source, '${T}') as platform_source
|
|
972
977
|
FROM user_prompts up
|
|
973
978
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
974
979
|
WHERE up.id = ?
|
|
975
|
-
`).get(e)}findRecentDuplicateUserPrompt(e,t,s,n){return
|
|
980
|
+
`).get(e)}findRecentDuplicateUserPrompt(e,t,s,n){return Jt(this.db,e,ie(t),s,this.resolvePromptSessionDbId(e,n)??void 0)}getRecentSessionsWithStatus(e,t=3,s){let n=[e],i="";return s&&(i=`AND COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?`,n.push(b(s))),n.push(t),this.db.prepare(`
|
|
976
981
|
SELECT * FROM (
|
|
977
982
|
SELECT
|
|
978
983
|
s.memory_session_id,
|
|
@@ -995,7 +1000,7 @@ ${L.stack??""}
|
|
|
995
1000
|
SELECT 1
|
|
996
1001
|
FROM sdk_sessions s
|
|
997
1002
|
WHERE s.memory_session_id = observations.memory_session_id
|
|
998
|
-
AND COALESCE(NULLIF(s.platform_source, ''), '${
|
|
1003
|
+
AND COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?
|
|
999
1004
|
)
|
|
1000
1005
|
`,s.push(b(t))),this.db.prepare(`
|
|
1001
1006
|
SELECT title, subtitle, type, prompt_number
|
|
@@ -1008,24 +1013,24 @@ ${L.stack??""}
|
|
|
1008
1013
|
FROM observations o
|
|
1009
1014
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id
|
|
1010
1015
|
WHERE o.id = ?
|
|
1011
|
-
AND COALESCE(NULLIF(s.platform_source, ''), '${
|
|
1016
|
+
AND COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?
|
|
1012
1017
|
`).get(e,b(t))||null:this.db.prepare(`
|
|
1013
1018
|
SELECT *
|
|
1014
1019
|
FROM observations
|
|
1015
1020
|
WHERE id = ?
|
|
1016
|
-
`).get(e)||null}upsertToolUse(e){return
|
|
1021
|
+
`).get(e)||null}upsertToolUse(e){return Ot(this.db,e)}linkToolUsesToObservation(e){return ft(this.db,e)}getToolUsesByIds(e,t={}){return Nt(this.db,e,t)}queryToolUses(e={}){return bt(this.db,e)}appendWorkStateEntry(e){let t=It(this.db,e);return j({projects:[e.project]},"appendWorkStateEntry"),t}getWorkStateEntries(e,t){let s=ht(this.db,this.getProjectReadKeys(e),t),n=a=>a.replace(/[A-Z]/g,_=>_.toLowerCase()),i=new Set(e.map(n)),r=e.at(-1);return s.map(a=>r&&i.has(n(a.project))?{...a,scope_project:r}:a)}countToolUses(e={}){return Ct(this.db,e)}getObservationsByIds(e,t={}){if(e.length===0)return[];let{orderBy:s="date_desc",platformSource:n,type:i,concepts:r,files:a}=t,_=Ze(t.limit),E=w(t),d=s==="relevance",u=s==="date_asc"?"ASC":"DESC",l=d?"":`ORDER BY o.created_at_epoch ${u}, o.id ${u}`,p=_&&!d?"LIMIT ?":"",S=e.map(()=>"?").join(","),h=[...e],f=[];if(E.length>0){let g=x("o",E,{includeMerged:!0});f.push(g.sql),h.push(...g.params)}if(n&&(f.push(`COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?`),h.push(b(n))),i)if(Array.isArray(i)){let g=i.map(()=>"?").join(",");f.push(`o.type IN (${g})`),h.push(...i)}else f.push("o.type = ?"),h.push(i);if(r){let g=Array.isArray(r)?r:[r],D=g.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE value = ?)");h.push(...g),f.push(`(${D.join(" OR ")})`)}if(a){let g=Array.isArray(a)?a:[a],D=g.map(()=>"(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE value LIKE ? ESCAPE '\\') OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE value LIKE ? ESCAPE '\\'))");g.forEach(O=>{let v=O.replace(/[\\%_]/g,"\\$&");h.push(`%${v}%`,`%${v}%`)}),f.push(`(${D.join(" OR ")})`)}let C=f.length>0?`WHERE o.id IN (${S}) AND ${f.join(" AND ")}`:`WHERE o.id IN (${S})`;p&&h.push(_);let m=this.db.prepare(`
|
|
1017
1022
|
SELECT o.*
|
|
1018
1023
|
FROM observations o
|
|
1019
1024
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id
|
|
1020
|
-
${
|
|
1025
|
+
${C}
|
|
1021
1026
|
${l}
|
|
1022
|
-
${
|
|
1023
|
-
`).all(...
|
|
1027
|
+
${p}
|
|
1028
|
+
`).all(...h);if(!d)return m;let A=new Map(m.map(g=>[g.id,g])),y=e.map(g=>A.get(g)).filter(g=>!!g);return _?y.slice(0,_):y}getSummaryForSession(e,t){let s=[e],n="";return t&&(n=`
|
|
1024
1029
|
AND EXISTS (
|
|
1025
1030
|
SELECT 1
|
|
1026
1031
|
FROM sdk_sessions sdk
|
|
1027
1032
|
WHERE sdk.memory_session_id = session_summaries.memory_session_id
|
|
1028
|
-
AND COALESCE(NULLIF(sdk.platform_source, ''), '${
|
|
1033
|
+
AND COALESCE(NULLIF(sdk.platform_source, ''), '${T}') = ?
|
|
1029
1034
|
)
|
|
1030
1035
|
`,s.push(b(t))),this.db.prepare(`
|
|
1031
1036
|
SELECT
|
|
@@ -1039,7 +1044,7 @@ ${L.stack??""}
|
|
|
1039
1044
|
LIMIT 1
|
|
1040
1045
|
`).get(...s)||null}getSessionById(e){return this.db.prepare(`
|
|
1041
1046
|
SELECT id, content_session_id, memory_session_id, project,
|
|
1042
|
-
COALESCE(platform_source, '${
|
|
1047
|
+
COALESCE(platform_source, '${T}') as platform_source,
|
|
1043
1048
|
user_prompt, custom_title, status,
|
|
1044
1049
|
observed_model, observed_billing
|
|
1045
1050
|
FROM sdk_sessions
|
|
@@ -1051,11 +1056,11 @@ ${L.stack??""}
|
|
|
1051
1056
|
WHERE COALESCE(NULLIF(platform_source, ''), ?) = ?
|
|
1052
1057
|
AND content_session_id = ?
|
|
1053
1058
|
LIMIT 1
|
|
1054
|
-
`).get(
|
|
1059
|
+
`).get(T,b(t),e)?.id??null}claimTelegramWrapup({platformSource:e,contentSessionId:t,project:s,routeKey:n,summaryCreatedAtEpoch:i}){let r=Date.now();return this.db.prepare(`
|
|
1055
1060
|
INSERT OR IGNORE INTO telegram_wrapups
|
|
1056
1061
|
(platform_source, content_session_id, project, route_key, summary_created_at_epoch, status, claimed_at_epoch, sent_at_epoch)
|
|
1057
1062
|
VALUES (?, ?, ?, ?, ?, 'claimed', ?, NULL)
|
|
1058
|
-
`).run(b(e),t,s,n,i,
|
|
1063
|
+
`).run(b(e),t,s,n,i,r).changes===1?!0:this.db.prepare(`
|
|
1059
1064
|
UPDATE telegram_wrapups
|
|
1060
1065
|
SET summary_created_at_epoch = ?, claimed_at_epoch = ?, sent_at_epoch = NULL
|
|
1061
1066
|
WHERE platform_source = ?
|
|
@@ -1064,7 +1069,7 @@ ${L.stack??""}
|
|
|
1064
1069
|
AND route_key = ?
|
|
1065
1070
|
AND status = 'claimed'
|
|
1066
1071
|
AND claimed_at_epoch <= ?
|
|
1067
|
-
`).run(i,
|
|
1072
|
+
`).run(i,r,b(e),t,s,n,r-ds).changes===1}markTelegramWrapupSent({platformSource:e,contentSessionId:t,project:s,routeKey:n}){this.db.prepare(`
|
|
1068
1073
|
UPDATE telegram_wrapups
|
|
1069
1074
|
SET status = 'sent', sent_at_epoch = ?
|
|
1070
1075
|
WHERE platform_source = ?
|
|
@@ -1084,19 +1089,19 @@ ${L.stack??""}
|
|
|
1084
1089
|
SET observed_model = COALESCE(?, observed_model),
|
|
1085
1090
|
observed_billing = COALESCE(?, observed_billing)
|
|
1086
1091
|
WHERE id = ?
|
|
1087
|
-
`).run(t||null,s||null,e)}getSdkSessionsBySessionIds(e,t=[]){if(e.length===0&&t.length===0)return[];let s=[...new Set(e),...new Set(t)],n=new Map;for(let i=0;i<s.length;i+=500){let
|
|
1092
|
+
`).run(t||null,s||null,e)}getSdkSessionsBySessionIds(e,t=[]){if(e.length===0&&t.length===0)return[];let s=[...new Set(e),...new Set(t)],n=new Map;for(let i=0;i<s.length;i+=500){let r=s.slice(i,i+500),a=r.filter(u=>typeof u=="string"),_=r.filter(u=>typeof u=="number"),E=[];a.length&&E.push(`memory_session_id IN (${a.map(()=>"?").join(",")})`),_.length&&E.push(`id IN (SELECT session_db_id FROM user_prompts WHERE id IN (${_.map(()=>"?").join(",")}))`);let d=this.db.prepare(`
|
|
1088
1093
|
SELECT id, content_session_id, memory_session_id, project,
|
|
1089
|
-
COALESCE(platform_source, '${
|
|
1094
|
+
COALESCE(platform_source, '${T}') as platform_source,
|
|
1090
1095
|
user_prompt, custom_title,
|
|
1091
1096
|
started_at, started_at_epoch, completed_at, completed_at_epoch, status
|
|
1092
1097
|
FROM sdk_sessions
|
|
1093
1098
|
WHERE ${E.join(" OR ")}
|
|
1094
1099
|
ORDER BY started_at_epoch DESC
|
|
1095
|
-
`);for(let
|
|
1096
|
-
SELECT
|
|
1097
|
-
`).get(
|
|
1098
|
-
SELECT
|
|
1099
|
-
`).get(
|
|
1100
|
+
`);for(let u of d.all(...r))n.set(u.id,u)}return[...n.values()].sort((i,r)=>r.started_at_epoch-i.started_at_epoch)}getPromptNumberFromUserPrompts(e,t,s){let n=this.resolvePromptSessionDbId(e,t),i=n!==null?"session_db_id = ?":"content_session_id = ?",r=n!==null?n:e;return s!==void 0?this.db.prepare(`
|
|
1101
|
+
SELECT COALESCE(MAX(prompt_number), 0) as count FROM user_prompts WHERE ${i} AND created_at_epoch <= ?
|
|
1102
|
+
`).get(r,s).count:this.db.prepare(`
|
|
1103
|
+
SELECT COALESCE(MAX(prompt_number), 0) as count FROM user_prompts WHERE ${i}
|
|
1104
|
+
`).get(r).count}getLatestPromptTextFromUserPrompts(e,t){let s=this.resolvePromptSessionDbId(e,t),n=s!==null?"session_db_id = ?":"content_session_id = ?",i=s!==null?s:e;return this.db.prepare(`
|
|
1100
1105
|
SELECT prompt_text
|
|
1101
1106
|
FROM user_prompts
|
|
1102
1107
|
WHERE ${n}
|
|
@@ -1104,30 +1109,30 @@ ${L.stack??""}
|
|
|
1104
1109
|
AND length(trim(prompt_text)) > 0
|
|
1105
1110
|
ORDER BY prompt_number DESC, created_at_epoch DESC
|
|
1106
1111
|
LIMIT 1
|
|
1107
|
-
`).get(i)?.prompt_text??null}createSDKSession(e,t,s,n,i){let
|
|
1112
|
+
`).get(i)?.prompt_text??null}createSDKSession(e,t,s,n,i){let r=new Date,a=r.getTime(),_=i?b(i):T,E=ie(s);n&&this.validateSetTitleMutation(e,_,n);let d=this.db.prepare(`
|
|
1108
1113
|
SELECT id, platform_source
|
|
1109
1114
|
FROM sdk_sessions
|
|
1110
1115
|
WHERE COALESCE(NULLIF(platform_source, ''), ?) = ?
|
|
1111
1116
|
AND content_session_id = ?
|
|
1112
|
-
`).get(
|
|
1117
|
+
`).get(T,_,e);if(d){if(t&&this.db.prepare(`
|
|
1113
1118
|
UPDATE sdk_sessions SET project = ?
|
|
1114
1119
|
WHERE id = ? AND (project IS NULL OR project = '')
|
|
1115
|
-
`).run(t,
|
|
1120
|
+
`).run(t,d.id),E&&E!==We&&this.db.prepare(`
|
|
1116
1121
|
UPDATE sdk_sessions SET user_prompt = ?
|
|
1117
1122
|
WHERE id = ? AND (user_prompt IS NULL OR user_prompt = '' OR user_prompt = ?)
|
|
1118
|
-
`).run(E,
|
|
1123
|
+
`).run(E,d.id,We),n){let l=this.db.prepare("SELECT custom_title FROM sdk_sessions WHERE id = ?").get(d.id);l&&l.custom_title===null&&(this.db.prepare(`
|
|
1119
1124
|
UPDATE sdk_sessions SET custom_title = ?
|
|
1120
1125
|
WHERE id = ? AND custom_title IS NULL
|
|
1121
|
-
`).run(n,
|
|
1126
|
+
`).run(n,d.id),this.enqueueSetTitleOp(e,_,n))}return d.id}let u=this.db.prepare(`
|
|
1122
1127
|
INSERT INTO sdk_sessions
|
|
1123
1128
|
(content_session_id, memory_session_id, project, platform_source, user_prompt, custom_title, started_at, started_at_epoch, status)
|
|
1124
1129
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, 'active')
|
|
1125
|
-
`).run(e,t,_,E,n||null,
|
|
1130
|
+
`).run(e,t,_,E,n||null,r.toISOString(),a);return n&&this.enqueueSetTitleOp(e,_,n),Number(u.lastInsertRowid)}setSessionCwd(e,t,s){t.trim()&&this.db.prepare("UPDATE sdk_sessions SET cwd = ?, project_key_source = ? WHERE id = ? AND cwd IS NULL").run(t,s??null,e)}getSessionCwd(e){return this.db.prepare("SELECT cwd FROM sdk_sessions WHERE id = ?").get(e)?.cwd??null}enqueueSetTitleOp(e,t,s){let n=this.validateSetTitleMutation(e,t,s);this.enqueueMutationOp("1",n)}validateSetTitleMutation(e,t,s){let n={op:"set_title",target:{content_session_id:e,platform_source:t},fields:{custom_title:s}};return Qe(n),n}saveUserPrompt(e,t,s,n,i,r){let a=new Date,_=a.getTime(),E=ie(s),d=this.resolvePromptSessionDbId(e,n);return this.db.prepare(`
|
|
1126
1131
|
INSERT INTO user_prompts
|
|
1127
1132
|
(session_db_id, content_session_id, prompt_number, prompt_text, created_at, created_at_epoch, native_prompt_id, native_prompt_hash)
|
|
1128
1133
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
1129
|
-
`).run(
|
|
1130
|
-
WHERE session_db_id = ? AND native_prompt_id = ?`).get(t,s);if(_){if(_.native_prompt_hash!==a)throw new Error("Native prompt identity was reused with different text");return{id:_.id,promptNumber:_.prompt_number,duplicate:!0}}let E=this.getPromptNumberFromUserPrompts(e,t)+1;return this.reopenCompletedSession(t),{id:this.saveUserPrompt(e,E,
|
|
1134
|
+
`).run(d,e,t,E,a.toISOString(),_,i??null,r??null).lastInsertRowid}saveNativeUserPrompt(e,t,s,n,i=n){if(!s||s.length>256||/[\s\x00-\x1f\x7f]/.test(s))throw new Error("Invalid native prompt identity");let r=ie(n),a=(0,he.createHash)("sha256").update(fe(i).trim()).digest("hex");return this.db.transaction(()=>{let _=this.db.prepare(`SELECT id, prompt_number, native_prompt_hash FROM user_prompts
|
|
1135
|
+
WHERE session_db_id = ? AND native_prompt_id = ?`).get(t,s);if(_){if(_.native_prompt_hash!==a)throw new Error("Native prompt identity was reused with different text");return{id:_.id,promptNumber:_.prompt_number,duplicate:!0}}let E=this.getPromptNumberFromUserPrompts(e,t)+1;return this.reopenCompletedSession(t),{id:this.saveUserPrompt(e,E,r,t,s,a),promptNumber:E,duplicate:!1}}).immediate()}getUserPrompt(e,t,s){let n=this.resolvePromptSessionDbId(e,s);return n!==null?this.db.prepare(`
|
|
1131
1136
|
SELECT prompt_text
|
|
1132
1137
|
FROM user_prompts
|
|
1133
1138
|
WHERE session_db_id = ? AND prompt_number = ?
|
|
@@ -1137,12 +1142,12 @@ ${L.stack??""}
|
|
|
1137
1142
|
FROM user_prompts
|
|
1138
1143
|
WHERE content_session_id = ? AND prompt_number = ?
|
|
1139
1144
|
LIMIT 1
|
|
1140
|
-
`).get(e,t)?.prompt_text??null}dedupConfig(){let e=Y.loadFromFile(
|
|
1145
|
+
`).get(e,t)?.prompt_text??null}dedupConfig(){let e=Y.loadFromFile(pe),t=(n,i)=>{let r=Number(e[n]);return Number.isFinite(r)?r:i},s=(n,i)=>Math.trunc(t(n,i));return{enabled:e.CLAUDE_MEM_DEDUP_ENABLED==="true",cosineThreshold:t("CLAUDE_MEM_DEDUP_COSINE_THRESHOLD",.8),idfVetoDf:s("CLAUDE_MEM_DEDUP_IDF_VETO_DF",10),minSharedTokens:s("CLAUDE_MEM_DEDUP_MIN_SHARED_TOKENS",2),maxScan:s("CLAUDE_MEM_DEDUP_MAX_SCAN",2e3),maxBackfillRows:s("CLAUDE_MEM_DEDUP_MAX_BACKFILL_ROWS",5e4),minProjectDocs:s("CLAUDE_MEM_DEDUP_MIN_PROJECT_DOCS",10)}}listDedupCandidates(e,t=100,s){let n="SELECT c.id, c.project, c.method, c.score, c.status, c.created_at_epoch, c.observation_id, o1.title AS observation_title, c.duplicate_of_id, o2.title AS duplicate_of_title FROM observation_dedup_candidates c JOIN observations o1 ON o1.id = c.observation_id JOIN observations o2 ON o2.id = c.duplicate_of_id ",i="(? IS NULL OR c.status = ?) ",r="ORDER BY c.score DESC, c.id DESC LIMIT ?",a=s??null;return e?this.db.prepare(`${n}WHERE c.project = ? AND ${i}${r}`).all(e,a,a,t):this.db.prepare(`${n}WHERE ${i}${r}`).all(a,a,t)}resolveDedupCandidate(e,t){return this.db.prepare("UPDATE observation_dedup_candidates SET status = ? WHERE id = ?").run(t,e).changes>0}isDedupEnabled(){return this.dedupConfig().enabled}runDedupScan(){return Vt(this.db,this.dedupConfig())}maintainDedupOnInsert(e,t,s,n){Ht(this.db,e,s),Yt(this.db,e,n.minProjectDocs)&&qt(this.db,e,t,s,n)}storeObservation(e,t,s,n,i=0,r,a,_={}){if(!ke(s.title))throw new Error("storeObservation requires a non-empty title");let E=this.storeObservations(e,t,[s],null,n,i,r,a,_);return{id:E.observationIds[0],createdAtEpoch:E.createdAtEpoch,mergedIntoExisting:E.mergedIntoExisting[0]??!1}}storeSummary(e,t,s,n,i=0,r){let a=r??Date.now(),_=new Date(a).toISOString(),d=this.db.prepare(`
|
|
1141
1146
|
INSERT INTO session_summaries
|
|
1142
1147
|
(memory_session_id, project, request, investigated, learned, completed,
|
|
1143
1148
|
next_steps, files_read, files_edited, notes, prompt_number, discovery_tokens, created_at, created_at_epoch)
|
|
1144
1149
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1145
|
-
`).run(e,t,s.request,s.investigated,s.learned,s.completed,s.next_steps,JSON.stringify(s.files_read??[]),JSON.stringify(s.files_edited??[]),s.notes,n||null,i,_,a);return
|
|
1150
|
+
`).run(e,t,s.request,s.investigated,s.learned,s.completed,s.next_steps,JSON.stringify(s.files_read??[]),JSON.stringify(s.files_edited??[]),s.notes,n||null,i,_,a);return j({projects:[t]},"storeSummary"),{id:Number(d.lastInsertRowid),createdAtEpoch:a}}storeObservations(e,t,s,n,i,r=0,a,_,E={}){let d=a??Date.now(),u=new Date(d).toISOString(),l=mt(d),p=new Date(d),S=this.dedupConfig(),h=b(this.db.prepare("SELECT platform_source FROM sdk_sessions WHERE memory_session_id = ? LIMIT 1").get(e)?.platform_source),C=this.db.transaction(()=>{let R=[],m=[],A=[],y=this.db.prepare(`
|
|
1146
1151
|
INSERT INTO observations
|
|
1147
1152
|
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
|
1148
1153
|
files_read, files_modified, prompt_number, discovery_tokens, agent_type, agent_id, content_hash, created_at, created_at_epoch,
|
|
@@ -1150,30 +1155,30 @@ ${L.stack??""}
|
|
|
1150
1155
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1151
1156
|
ON CONFLICT(memory_session_id, content_hash) DO NOTHING
|
|
1152
1157
|
RETURNING id
|
|
1153
|
-
`),
|
|
1158
|
+
`),g=this.db.prepare("SELECT id FROM observations WHERE memory_session_id = ? AND content_hash = ?");for(let O of s){if(!ke(O.title)){c.debug("DB","Skipping observation with empty title");continue}let v=ut(e,O.title,O.narrative),de=ge(t,h,O.title,ne(O.agent_id,O.agent_type));if(S.enabled){let De=g.get(e,v);if(De){Se(this.db,De.id,p),R.push(De.id),m.push(!1);continue}let ce=E.skipTitleDedup?null:Gt(this.db,t,de);if(ce){this.db.prepare("UPDATE observations SET occurrence_count = occurrence_count + 1 WHERE id = ?").run(ce.id),Se(this.db,ce.id,p),R.push(ce.id),m.push(!0);continue}}let z=y.get(e,t,O.type,O.title,O.subtitle,JSON.stringify(O.facts),O.narrative,JSON.stringify(O.concepts),JSON.stringify(O.files_read),JSON.stringify(O.files_modified),i||null,r,O.agent_type??null,O.agent_id??null,v,u,d,_||null,O.metadata??null,de,l.dates,l.lastReinforced);if(z){S.enabled&&this.maintainDedupOnInsert(t,z.id,O.title,S),R.push(z.id),m.push(!1),A.push(z.id);continue}let Q=g.get(e,v);if(!Q)throw new Error(`storeObservations: ON CONFLICT without existing row for content_hash=${v}`);Se(this.db,Q.id,p),R.push(Q.id),m.push(!1)}let D=null;if(n){let O=cs(s),v=n.files_read??O.files_read,de=n.files_edited??O.files_edited,Q=this.db.prepare(`
|
|
1154
1159
|
INSERT INTO session_summaries
|
|
1155
1160
|
(memory_session_id, project, request, investigated, learned, completed,
|
|
1156
1161
|
next_steps, files_read, files_edited, notes, prompt_number, discovery_tokens, created_at, created_at_epoch)
|
|
1157
1162
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1158
|
-
`).run(e,t,n.request,n.investigated,n.learned,n.completed,n.next_steps,JSON.stringify(
|
|
1163
|
+
`).run(e,t,n.request,n.investigated,n.learned,n.completed,n.next_steps,JSON.stringify(v),JSON.stringify(de),n.notes,i||null,r,u,d);D=Number(Q.lastInsertRowid)}return{observationIds:R,mergedIntoExisting:m,insertedObservationIds:A,summaryId:D,createdAtEpoch:d}})();return j({projects:[t]},"storeObservations"),C}updateDiscoveryTokens(e,t,s){e.length===0&&t===null||this.db.transaction(()=>{let n=this.db.prepare("UPDATE observations SET discovery_tokens = ? WHERE id = ?");for(let i of e)n.run(s,i);t!==null&&this.db.prepare("UPDATE session_summaries SET discovery_tokens = ? WHERE id = ?").run(s,t)})()}getSessionSummariesByIds(e,t={}){if(e.length===0)return[];let{orderBy:s="date_desc",platformSource:n}=t,i=Ze(t.limit),r=w(t),a=s==="relevance",_=s==="date_asc"?"ASC":"DESC",E=a?"":`ORDER BY ss.created_at_epoch ${_}, ss.id ${_}`,d=i&&!a?"LIMIT ?":"",u=e.map(()=>"?").join(","),l=[...e],p=[];if(r.length>0){let m=x("ss",r,{includeMerged:!0});p.push(m.sql),l.push(...m.params)}n&&(p.push(`COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?`),l.push(b(n)));let S=p.length>0?`AND ${p.join(" AND ")}`:"";d&&l.push(i);let f=this.db.prepare(`
|
|
1159
1164
|
SELECT ss.*
|
|
1160
1165
|
FROM session_summaries ss
|
|
1161
1166
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = ss.memory_session_id
|
|
1162
|
-
WHERE ss.id IN (${
|
|
1163
|
-
${_}
|
|
1167
|
+
WHERE ss.id IN (${u}) ${S}
|
|
1164
1168
|
${E}
|
|
1165
|
-
|
|
1169
|
+
${d}
|
|
1170
|
+
`).all(...l);if(!a)return f;let C=new Map(f.map(m=>[m.id,m])),R=e.map(m=>C.get(m)).filter(m=>!!m);return i?R.slice(0,i):R}getUserPromptsByIds(e,t={}){if(e.length===0)return[];let{orderBy:s="date_desc",platformSource:n}=t,i=Ze(t.limit),r=w(t),a=s==="relevance",_=s==="date_asc"?"ASC":"DESC",E=a?"":`ORDER BY up.created_at_epoch ${_}, up.id ${_}`,d=i&&!a?"LIMIT ?":"",u=e.map(()=>"?").join(","),l=[...e],p=[];if(r.length>0){let m=x("s",r,{includeMerged:!1});p.push(m.sql),l.push(...m.params)}n&&(p.push(`COALESCE(NULLIF(s.platform_source, ''), '${T}') = ?`),l.push(b(n)));let S=p.length>0?`AND ${p.join(" AND ")}`:"";d&&l.push(i);let f=this.db.prepare(`
|
|
1166
1171
|
SELECT
|
|
1167
1172
|
up.*,
|
|
1168
1173
|
s.project,
|
|
1169
1174
|
s.memory_session_id,
|
|
1170
|
-
COALESCE(NULLIF(s.platform_source, ''), '${
|
|
1175
|
+
COALESCE(NULLIF(s.platform_source, ''), '${T}') as platform_source
|
|
1171
1176
|
FROM user_prompts up
|
|
1172
1177
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
1173
|
-
WHERE up.id IN (${
|
|
1174
|
-
${_}
|
|
1178
|
+
WHERE up.id IN (${u}) ${S}
|
|
1175
1179
|
${E}
|
|
1176
|
-
|
|
1180
|
+
${d}
|
|
1181
|
+
`).all(...l);if(!a)return f;let C=new Map(f.map(m=>[m.id,m])),R=e.map(m=>C.get(m)).filter(m=>!!m);return i?R.slice(0,i):R}getTimelineAroundTimestamp(e,t=10,s=10,n,i){return this.getTimelineAroundObservation(null,e,t,s,n,i)}getTimelineAroundObservation(e,t,s=10,n=10,i,r){let a=r?b(r):void 0,_=(A,y,g=!1)=>{let D=[],O=[];return i&&(g?(D.push(`(${A}.project COLLATE NOCASE = ? OR ${A}.merged_into_project COLLATE NOCASE = ?)`),O.push(i,i)):(D.push(`${A}.project COLLATE NOCASE = ?`),O.push(i))),a&&(D.push(`COALESCE(NULLIF(${y}.platform_source, ''), '${T}') = ?`),O.push(a)),{clause:D.length>0?`AND ${D.join(" AND ")}`:"",params:O}},E=_("o","src",!0),d=_("ss","src",!0),u=_("s","s"),l,p;if(e!==null){let A=`
|
|
1177
1182
|
SELECT o.id, o.created_at_epoch
|
|
1178
1183
|
FROM observations o
|
|
1179
1184
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
@@ -1187,7 +1192,7 @@ ${L.stack??""}
|
|
|
1187
1192
|
WHERE (o.created_at_epoch, o.id) >= (?, ?) ${E.clause}
|
|
1188
1193
|
ORDER BY o.created_at_epoch ASC
|
|
1189
1194
|
LIMIT ?
|
|
1190
|
-
`;try{let
|
|
1195
|
+
`;try{let g=this.db.prepare(A).all(t,e,...E.params,s+1),D=this.db.prepare(y).all(t,e,...E.params,n+1);if(g.length===0&&D.length===0)return{observations:[],sessions:[],prompts:[]};l=g.length>0?g[g.length-1].created_at_epoch:t,p=D.length>0?D[D.length-1].created_at_epoch:t}catch(g){return g instanceof Error?c.error("DB","Error getting boundary observations",{project:i},g):c.error("DB","Error getting boundary observations with non-Error",{},new Error(String(g))),{observations:[],sessions:[],prompts:[]}}}else{let A=`
|
|
1191
1196
|
SELECT o.created_at_epoch
|
|
1192
1197
|
FROM observations o
|
|
1193
1198
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
@@ -1201,58 +1206,58 @@ ${L.stack??""}
|
|
|
1201
1206
|
WHERE o.created_at_epoch > ? ${E.clause}
|
|
1202
1207
|
ORDER BY o.created_at_epoch ASC
|
|
1203
1208
|
LIMIT ?
|
|
1204
|
-
`;try{let
|
|
1209
|
+
`;try{let g=this.db.prepare(A).all(t,...E.params,s),D=this.db.prepare(y).all(t,...E.params,n);l=g.length>0?g[g.length-1].created_at_epoch:t,p=D.length>0?D[D.length-1].created_at_epoch:t}catch(g){return g instanceof Error?c.error("DB","Error getting boundary timestamps",{project:i},g):c.error("DB","Error getting boundary timestamps with non-Error",{},new Error(String(g))),{observations:[],sessions:[],prompts:[]}}}let S=`
|
|
1205
1210
|
SELECT o.*
|
|
1206
1211
|
FROM observations o
|
|
1207
1212
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
1208
1213
|
WHERE o.created_at_epoch >= ? AND o.created_at_epoch <= ? ${E.clause}
|
|
1209
1214
|
ORDER BY o.created_at_epoch ASC, o.id ASC
|
|
1210
|
-
`,
|
|
1215
|
+
`,h=`
|
|
1211
1216
|
SELECT ss.*
|
|
1212
1217
|
FROM session_summaries ss
|
|
1213
1218
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = ss.memory_session_id
|
|
1214
|
-
WHERE ss.created_at_epoch >= ? AND ss.created_at_epoch <= ? ${
|
|
1219
|
+
WHERE ss.created_at_epoch >= ? AND ss.created_at_epoch <= ? ${d.clause}
|
|
1215
1220
|
ORDER BY ss.created_at_epoch ASC, ss.id ASC
|
|
1216
1221
|
`,f=`
|
|
1217
|
-
SELECT up.*, s.project, s.memory_session_id, COALESCE(NULLIF(s.platform_source, ''), '${
|
|
1222
|
+
SELECT up.*, s.project, s.memory_session_id, COALESCE(NULLIF(s.platform_source, ''), '${T}') as platform_source
|
|
1218
1223
|
FROM user_prompts up
|
|
1219
1224
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
1220
|
-
WHERE up.created_at_epoch >= ? AND up.created_at_epoch <= ? ${
|
|
1225
|
+
WHERE up.created_at_epoch >= ? AND up.created_at_epoch <= ? ${u.clause}
|
|
1221
1226
|
ORDER BY up.created_at_epoch ASC, up.id ASC
|
|
1222
|
-
`,
|
|
1227
|
+
`,C=this.db.prepare(S).all(l,p,...E.params),R=this.db.prepare(h).all(l,p,...d.params),m=this.db.prepare(f).all(l,p,...u.params);return{observations:C,sessions:R.map(A=>({id:A.id,memory_session_id:A.memory_session_id,project:A.project,request:A.request,completed:A.completed,next_steps:A.next_steps,created_at:A.created_at,created_at_epoch:A.created_at_epoch})),prompts:m.map(A=>({id:A.id,content_session_id:A.content_session_id,prompt_number:A.prompt_number,prompt_text:A.prompt_text,project:A.project,platform_source:A.platform_source,created_at:A.created_at,created_at_epoch:A.created_at_epoch}))}}getOrCreateManualSession(e,t=T){let s=`manual-${e}`,n=`manual-content-${e}`;if(this.db.prepare("SELECT memory_session_id FROM sdk_sessions WHERE memory_session_id = ?").get(s))return t&&t!==T&&this.db.prepare("UPDATE sdk_sessions SET platform_source = ? WHERE memory_session_id = ?").run(t,s),s;let r=new Date;return this.db.prepare(`
|
|
1223
1228
|
INSERT INTO sdk_sessions (memory_session_id, content_session_id, project, platform_source, started_at, started_at_epoch, status)
|
|
1224
1229
|
VALUES (?, ?, ?, ?, ?, ?, 'active')
|
|
1225
|
-
`).run(s,n,e,
|
|
1230
|
+
`).run(s,n,e,T,r.toISOString(),r.getTime()),c.info("SESSION","Created manual session",{memorySessionId:s,project:e}),s}close(){this.db.close()}cachedStatement(e){let t=this.statementCache.get(e);return t||(t=this.db.prepare(e),this.statementCache.set(e,t)),t}importSdkSession(e){let t=b(e.platform_source),s=this.db.prepare(`SELECT id FROM sdk_sessions
|
|
1226
1231
|
WHERE platform_source = ? AND content_session_id = ?`).get(t,e.content_session_id);if(s)return{imported:!1,id:s.id};let n=e.custom_title??null;if(n!==null&&typeof n!="string")throw new TypeError("Imported custom_title must be a string or null");let i=this.db.prepare(`
|
|
1227
1232
|
INSERT INTO sdk_sessions (
|
|
1228
1233
|
content_session_id, memory_session_id, project, platform_source, user_prompt, custom_title,
|
|
1229
1234
|
started_at, started_at_epoch, completed_at, completed_at_epoch, status
|
|
1230
1235
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1231
|
-
`);return this.db.transaction(()=>({imported:!0,id:i.run(e.content_session_id,e.memory_session_id,e.project,t,e.user_prompt,n,e.started_at,e.started_at_epoch,e.completed_at,e.completed_at_epoch,e.status).lastInsertRowid}))()}importSessionSummary(e){if(typeof e?.memory_session_id!="string"||e.memory_session_id.trim()==="")return
|
|
1236
|
+
`);return this.db.transaction(()=>({imported:!0,id:i.run(e.content_session_id,e.memory_session_id,e.project,t,e.user_prompt,n,e.started_at,e.started_at_epoch,e.completed_at,e.completed_at_epoch,e.status).lastInsertRowid}))()}importSessionSummary(e){if(typeof e?.memory_session_id!="string"||e.memory_session_id.trim()==="")return c.warn("DB","Skipping imported session summary without memory_session_id",{project:typeof e?.project=="string"?e.project:null}),{imported:!1,id:0};let t=this.db.prepare(`SELECT id FROM session_summaries WHERE memory_session_id = ?
|
|
1232
1237
|
AND request IS ? AND investigated IS ? AND learned IS ? AND completed IS ?
|
|
1233
1238
|
AND next_steps IS ? AND files_read IS ? AND files_edited IS ? AND notes IS ?
|
|
1234
|
-
AND prompt_number IS ? AND created_at_epoch = ?`).get(e.memory_session_id,
|
|
1239
|
+
AND prompt_number IS ? AND created_at_epoch = ?`).get(e.memory_session_id,N(e.request),N(e.investigated),N(e.learned),N(e.completed),N(e.next_steps),N(e.files_read),N(e.files_edited),N(e.notes),e.prompt_number??null,e.created_at_epoch);if(t)return{imported:!1,id:t.id};let n=this.db.prepare(`
|
|
1235
1240
|
INSERT INTO session_summaries (
|
|
1236
1241
|
memory_session_id, project, request, investigated, learned,
|
|
1237
1242
|
completed, next_steps, files_read, files_edited, notes,
|
|
1238
1243
|
prompt_number, discovery_tokens, created_at, created_at_epoch
|
|
1239
1244
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1240
|
-
`).run(e.memory_session_id,e.project,
|
|
1245
|
+
`).run(e.memory_session_id,e.project,N(e.request),N(e.investigated),N(e.learned),N(e.completed),N(e.next_steps),N(e.files_read),N(e.files_edited),N(e.notes),e.prompt_number,e.discovery_tokens||0,e.created_at,e.created_at_epoch);return j({projects:[e.project]},"importSessionSummary"),{imported:!0,id:n.lastInsertRowid}}importObservation(e){if(typeof e?.memory_session_id!="string"||e.memory_session_id.trim()==="")return c.warn("DB","Skipping imported observation without memory_session_id",{title:typeof e?.title=="string"?e.title:null,type:typeof e?.type=="string"?e.type:null}),{imported:!1,id:0};let t=this.db.prepare(`
|
|
1241
1246
|
SELECT id FROM observations
|
|
1242
1247
|
WHERE memory_session_id = ? AND text IS ? AND type = ?
|
|
1243
1248
|
AND title IS ? AND subtitle IS ? AND facts IS ? AND narrative IS ?
|
|
1244
1249
|
AND concepts IS ? AND files_read IS ? AND files_modified IS ?
|
|
1245
1250
|
AND prompt_number IS ? AND agent_type IS ?
|
|
1246
1251
|
AND agent_id IS ? AND created_at_epoch = ?
|
|
1247
|
-
`).get(e.memory_session_id,
|
|
1252
|
+
`).get(e.memory_session_id,N(e.text),e.type,N(e.title),N(e.subtitle),N(e.facts),N(e.narrative),N(e.concepts),N(e.files_read),N(e.files_modified),e.prompt_number??null,e.agent_type??null,e.agent_id??null,e.created_at_epoch);if(t)return{imported:!1,id:t.id};let n=this.db.prepare(`
|
|
1248
1253
|
INSERT INTO observations (
|
|
1249
1254
|
memory_session_id, project, text, type, title, subtitle,
|
|
1250
1255
|
facts, narrative, concepts, files_read, files_modified,
|
|
1251
1256
|
prompt_number, discovery_tokens, agent_type, agent_id,
|
|
1252
1257
|
created_at, created_at_epoch
|
|
1253
1258
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1254
|
-
`).run(e.memory_session_id,e.project,
|
|
1255
|
-
SELECT id, content_session_id, COALESCE(NULLIF(platform_source, ''), '${
|
|
1259
|
+
`).run(e.memory_session_id,e.project,N(e.text),e.type,N(e.title),N(e.subtitle),N(e.facts),N(e.narrative),N(e.concepts),N(e.files_read),N(e.files_modified),e.prompt_number,e.discovery_tokens||0,e.agent_type??null,e.agent_id??null,e.created_at,e.created_at_epoch);return j({projects:[e.project]},"importObservation"),{imported:!0,id:n.lastInsertRowid}}rebuildObservationsFTSIndex(){this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='observations_fts'").all().length>0&&this.db.run("INSERT INTO observations_fts(observations_fts) VALUES('rebuild')")}importUserPrompt(e){let t=null,s=e.platform_source?b(e.platform_source):void 0;if(typeof e.session_db_id=="number"){let a=this.db.prepare(`
|
|
1260
|
+
SELECT id, content_session_id, COALESCE(NULLIF(platform_source, ''), '${T}') as platform_source
|
|
1256
1261
|
FROM sdk_sessions
|
|
1257
1262
|
WHERE id = ?
|
|
1258
1263
|
LIMIT 1
|
|
@@ -1264,5 +1269,5 @@ ${L.stack??""}
|
|
|
1264
1269
|
session_db_id, content_session_id, prompt_number, prompt_text,
|
|
1265
1270
|
created_at, created_at_epoch
|
|
1266
1271
|
) VALUES (?, ?, ?, ?, ?, ?)
|
|
1267
|
-
`).run(t,e.content_session_id,e.prompt_number,
|
|
1272
|
+
`).run(t,e.content_session_id,e.prompt_number,N(e.prompt_text),e.created_at,e.created_at_epoch).lastInsertRowid}}};0&&(module.exports={SessionStore,TELEGRAM_WRAPUP_CLAIM_STALE_AFTER_MS,rollupObservationFileLists});
|
|
1268
1273
|
//# sourceMappingURL=SessionStore.js.map
|