claude-mem 13.9.2 → 13.9.3
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/.codex-plugin/plugin.json +1 -1
- package/dist/npx-cli/index.js +401 -406
- package/dist/opencode-plugin/index.js +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/package.json +8 -32
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/bun.lock +0 -3
- package/plugin/package.json +1 -2
- package/plugin/scripts/context-generator.cjs +256 -411
- package/plugin/scripts/mcp-server.cjs +61 -61
- package/plugin/scripts/server-service.cjs +152 -163
- package/plugin/scripts/transcript-watcher.cjs +20 -22
- package/plugin/scripts/worker-service.cjs +555 -801
- package/plugin/ui/viewer-bundle.js +13 -13
- package/plugin/ui/viewer.html +1 -744
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let
|
|
1
|
+
"use strict";var ks=Object.create;var G=Object.defineProperty;var ws=Object.getOwnPropertyDescriptor;var Fs=Object.getOwnPropertyNames;var Ps=Object.getPrototypeOf,$s=Object.prototype.hasOwnProperty;var Xs=(n,e)=>{for(var s in e)G(n,s,{get:e[s],enumerable:!0})},Te=(n,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Fs(e))!$s.call(n,r)&&r!==s&&G(n,r,{get:()=>e[r],enumerable:!(t=ws(e,r))||t.enumerable});return n};var x=(n,e,s)=>(s=n!=null?ks(Ps(n)):{},Te(e||!n||!n.__esModule?G(s,"default",{value:n,enumerable:!0}):s,n)),Hs=n=>Te(G({},"__esModule",{value:!0}),n);var Tt={};Xs(Tt,{generateContext:()=>xs,generateContextWithStats:()=>le});module.exports=Hs(Tt);var vs=x(require("path"),1),ys=require("os"),Us=require("fs");var de=require("bun:sqlite");var f=require("path"),ee=require("os"),U=require("fs"),ge=require("url"),Ks={};function Gs(){return typeof __dirname<"u"?__dirname:(0,f.dirname)((0,ge.fileURLToPath)(Ks.url))}var Bs=Gs();function js(){if(process.env.CLAUDE_MEM_DATA_DIR)return process.env.CLAUDE_MEM_DATA_DIR;let n=(0,f.join)((0,ee.homedir)(),".claude-mem"),e=(0,f.join)(n,"settings.json");try{if((0,U.existsSync)(e)){let s=JSON.parse((0,U.readFileSync)(e,"utf-8")),t=s.env??s;if(t.CLAUDE_MEM_DATA_DIR)return t.CLAUDE_MEM_DATA_DIR}}catch{}return n}var I=js(),se=process.env.CLAUDE_CONFIG_DIR||(0,f.join)((0,ee.homedir)(),".claude"),ft=(0,f.join)(se,"plugins","marketplaces","thedotmack"),Ws=(0,f.join)(I,"logs"),Rt=(0,f.join)(I,"settings.json"),Se=(0,f.join)(I,"claude-mem.db"),Vs=(0,f.join)(I,"observer-sessions"),te=(0,f.basename)(Vs);function fe(n){(0,U.mkdirSync)(n,{recursive:!0})}function Re(){return(0,f.join)(Bs,"..")}var k={dataDir:()=>I,workerPid:()=>(0,f.join)(I,"worker.pid"),serverPid:()=>(0,f.join)(I,".server-beta.pid"),serverPort:()=>(0,f.join)(I,".server-beta.port"),serverRuntime:()=>(0,f.join)(I,".server-beta.runtime.json"),settings:()=>(0,f.join)(I,"settings.json"),database:()=>(0,f.join)(I,"claude-mem.db"),chroma:()=>(0,f.join)(I,"chroma"),combinedCerts:()=>(0,f.join)(I,"combined_certs.pem"),transcriptsConfig:()=>(0,f.join)(I,"transcript-watch.json"),transcriptsState:()=>(0,f.join)(I,"transcript-watch-state.json"),corpora:()=>(0,f.join)(I,"corpora"),supervisorRegistry:()=>(0,f.join)(I,"supervisor.json"),envFile:()=>(0,f.join)(I,".env"),logsDir:()=>Ws};var v=require("fs"),Oe=require("path");var Ys=null;function qs(n){return(Ys??process.stderr.write.bind(process.stderr))(n)}function re(n){qs(n)}var oe=(o=>(o[o.DEBUG=0]="DEBUG",o[o.INFO=1]="INFO",o[o.WARN=2]="WARN",o[o.ERROR=3]="ERROR",o[o.SILENT=4]="SILENT",o))(oe||{}),ne=null,ie=class{level=null;useColor;logFilePath=null;logFileInitialized=!1;constructor(){this.useColor=process.stdout.isTTY??!1}ensureLogFileInitialized(){if(!this.logFileInitialized){this.logFileInitialized=!0;try{let e=k.logsDir();(0,v.existsSync)(e)||(0,v.mkdirSync)(e,{recursive:!0});let s=new Date().toISOString().split("T")[0];this.logFilePath=(0,Oe.join)(e,`claude-mem-${s}.log`)}catch(e){console.error("[LOGGER] Failed to initialize log file:",e instanceof Error?e.message:String(e)),this.logFilePath=null}}}getLevel(){if(this.level===null)try{let e=k.settings();if((0,v.existsSync)(e)){let s=(0,v.readFileSync)(e,"utf-8"),r=(JSON.parse(s).CLAUDE_MEM_LOG_LEVEL||"INFO").toUpperCase();this.level=oe[r]??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}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}
|
|
2
|
+
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let s=Object.keys(e);return s.length===0?"{}":s.length<=3?JSON.stringify(e):`{${s.length} keys: ${s.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,s){if(!s)return e;let t=s;if(typeof s=="string")try{t=JSON.parse(s)}catch{t=s}if(e==="Bash"&&t.command)return`${e}(${t.command})`;if(t.file_path)return`${e}(${t.file_path})`;if(t.notebook_path)return`${e}(${t.notebook_path})`;if(e==="Glob"&&t.pattern)return`${e}(${t.pattern})`;if(e==="Grep"&&t.pattern)return`${e}(${t.pattern})`;if(t.url)return`${e}(${t.url})`;if(t.query)return`${e}(${t.query})`;if(e==="Task"){if(t.subagent_type)return`${e}(${t.subagent_type})`;if(t.description)return`${e}(${t.description})`}return e==="Skill"&&t.skill?`${e}(${t.skill})`:e==="LSP"&&t.operation?`${e}(${t.operation})`:e}formatTimestamp(e){let s=e.getFullYear(),t=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),o=String(e.getHours()).padStart(2,"0"),i=String(e.getMinutes()).padStart(2,"0"),a=String(e.getSeconds()).padStart(2,"0"),d=String(e.getMilliseconds()).padStart(3,"0");return`${s}-${t}-${r} ${o}:${i}:${a}.${d}`}log(e,s,t,r,o){if(e<this.getLevel())return;this.ensureLogFileInitialized();let i=this.formatTimestamp(new Date),a=oe[e].padEnd(5),d=s.padEnd(6),u="";r?.correlationId?u=`[${r.correlationId}] `:r?.sessionId&&(u=`[session-${r.sessionId}] `);let m="";if(o!=null)if(o instanceof Error)m=this.getLevel()===0?`
|
|
3
3
|
${o.message}
|
|
4
4
|
${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{m=`
|
|
5
|
-
`+JSON.stringify(o,null,2)}catch{m=" "+this.formatData(o)}else m=" "+this.formatData(o);let l="";if(r){let{sessionId:
|
|
6
|
-
`,"utf8")}catch(
|
|
7
|
-
|
|
8
|
-
`)}
|
|
9
|
-
`)
|
|
5
|
+
`+JSON.stringify(o,null,2)}catch{m=" "+this.formatData(o)}else m=" "+this.formatData(o);let l="";if(r){let{sessionId:T,memorySessionId:h,correlationId:b,...g}=r;Object.keys(g).length>0&&(l=` {${Object.entries(g).map(([C,y])=>`${C}=${y}`).join(", ")}}`)}let c=`[${i}] [${a}] [${d}] ${u}${t}${l}${m}`;if(this.logFilePath)try{(0,v.appendFileSync)(this.logFilePath,c+`
|
|
6
|
+
`,"utf8")}catch(T){let h=T instanceof Error?T:new Error(String(T));re(`[LOGGER] Failed to write to log file: ${h.message}
|
|
7
|
+
${h.stack??""}
|
|
8
|
+
`)}else re(c+`
|
|
9
|
+
`)}debug(e,s,t,r){this.log(0,e,s,t,r)}info(e,s,t,r){this.log(1,e,s,t,r)}warn(e,s,t,r){this.log(2,e,s,t,r)}setErrorSink(e){ne=e}error(e,s,t,r){this.log(3,e,s,t,r),this.routeErrorToSink(s,t,r)}routeErrorToSink(e,s,t){try{if(!ne||!(t instanceof Error))return;ne(t)}catch{}}dataIn(e,s,t,r){this.info(e,`\u2192 ${s}`,t,r)}dataOut(e,s,t,r){this.info(e,`\u2190 ${s}`,t,r)}success(e,s,t,r){this.info(e,`\u2713 ${s}`,t,r)}failure(e,s,t,r){this.error(e,`\u2717 ${s}`,t,r)}},_=new ie;var be=require("crypto");function he(n,e,s){return(0,be.createHash)("sha256").update([n||"",e||"",s||""].join("\0")).digest("hex").slice(0,16)}var p="claude";function Js(n){return n.trim().toLowerCase().replace(/\s+/g,"-")}function A(n){if(!n)return p;let e=Js(n);return e?e==="transcript"||e.includes("codex")?"codex":e.includes("cursor")?"cursor":e.includes("claude")?"claude":e:p}function Ne(n){let e=["claude","codex","cursor"];return[...n].sort((s,t)=>{let r=e.indexOf(s),o=e.indexOf(t);return r!==-1||o!==-1?r===-1?1:o===-1?-1:r-o:s.localeCompare(t)})}function Ie(n,e,s,t,r){let o=Date.now()-t,i=r!==void 0?"up.session_db_id = ?":"up.content_session_id = ?",a=r??e;return n.prepare(`
|
|
10
10
|
SELECT
|
|
11
11
|
up.*,
|
|
12
12
|
s.memory_session_id,
|
|
13
13
|
s.project,
|
|
14
|
-
COALESCE(s.platform_source, '${
|
|
14
|
+
COALESCE(s.platform_source, '${p}') as platform_source
|
|
15
15
|
FROM user_prompts up
|
|
16
16
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
17
17
|
WHERE ${i}
|
|
@@ -19,136 +19,136 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
19
19
|
AND up.created_at_epoch >= ?
|
|
20
20
|
ORDER BY up.created_at_epoch DESC
|
|
21
21
|
LIMIT 1
|
|
22
|
-
`).get(a,
|
|
22
|
+
`).get(a,s,o)??void 0}var Le=["private","claude-mem-context","system_instruction","system-instruction","persisted-output","system-reminder"],Ae=new RegExp(`<(${Le.join("|")})\\b[^>]*>[\\s\\S]*?</\\1>`,"g"),De=/<system-reminder>[\s\S]*?<\/system-reminder>/g,Ce=100;function Qs(n){let e=Object.fromEntries(Le.map(r=>[r,0]));Ae.lastIndex=0;let s=0,t=n.replace(Ae,(r,o)=>(e[o]=(e[o]??0)+1,s+=1,""));return s>Ce&&_.warn("SYSTEM","tag count exceeds limit",void 0,{tagCount:s,maxAllowed:Ce,contentLength:n.length}),{stripped:t.trim(),counts:e}}function Me(n){return Qs(n).stripped}var zs=["task-notification"],vt=new RegExp(`^\\s*<(${zs.join("|")})\\b[^>]*>(?:(?!<\\1\\b|</\\1\\b)[\\s\\S])*</\\1>\\s*$`),yt=256*1024;var ae=4e3;function B(n){let e=n.trim(),t=Me(n).trim()||e;return t.length<=ae?t:(_.debug("DB","Truncated stored prompt text to the configured cap",{originalLength:t.length,storedLength:ae}),`${t.slice(0,ae-1)}\u2026`)}var j=class{db;constructor(e=Se){e instanceof de.Database?this.db=e:(e!==":memory:"&&fe(I),this.db=new de.Database(e),this.db.run("PRAGMA journal_mode = WAL"),this.db.run("PRAGMA synchronous = NORMAL"),this.db.run("PRAGMA foreign_keys = ON"),this.db.run("PRAGMA journal_size_limit = 4194304")),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()}getIndexColumns(e){return this.db.query(`PRAGMA index_info(${JSON.stringify(e)})`).all().map(s=>s.name)}hasUniqueIndexOnColumns(e,s){return this.db.query(`PRAGMA index_list(${e})`).all().some(r=>{if(r.unique!==1)return!1;let o=this.getIndexColumns(r.name);return o.length===s.length&&o.every((i,a)=>i===s[a])})}resolvePromptSessionDbId(e,s,t){if(s!==void 0)return s;let r=t?A(t):void 0;return r?this.db.prepare(`
|
|
23
23
|
SELECT id
|
|
24
24
|
FROM sdk_sessions
|
|
25
25
|
WHERE COALESCE(NULLIF(platform_source, ''), ?) = ?
|
|
26
26
|
AND content_session_id = ?
|
|
27
27
|
LIMIT 1
|
|
28
|
-
`).get(
|
|
28
|
+
`).get(p,r,e)?.id??null:this.db.prepare(`
|
|
29
29
|
SELECT id
|
|
30
30
|
FROM sdk_sessions
|
|
31
31
|
WHERE content_session_id = ?
|
|
32
|
-
ORDER BY CASE COALESCE(NULLIF(platform_source, ''), '${
|
|
33
|
-
WHEN '${
|
|
32
|
+
ORDER BY CASE COALESCE(NULLIF(platform_source, ''), '${p}')
|
|
33
|
+
WHEN '${p}' THEN 0
|
|
34
34
|
ELSE 1
|
|
35
35
|
END, id
|
|
36
36
|
LIMIT 1
|
|
37
|
-
`).get(e)?.id??null}dropWorkerPidColumn(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(32),
|
|
37
|
+
`).get(e)?.id??null}dropWorkerPidColumn(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(32),t=this.db.query("PRAGMA table_info(pending_messages)").all().some(r=>r.name==="worker_pid");if(!(e&&!t)){if(t)try{this.db.run("DROP INDEX IF EXISTS idx_pending_messages_worker_pid"),this.db.run("ALTER TABLE pending_messages DROP COLUMN worker_pid"),_.debug("DB","Dropped worker_pid column and its index from pending_messages")}catch(r){_.warn("DB","Failed to drop worker_pid column from pending_messages",{},r instanceof Error?r:new Error(String(r)));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),s=this.hasUniqueIndexOnColumns("sdk_sessions",["content_session_id"]),t=this.hasUniqueIndexOnColumns("sdk_sessions",["platform_source","content_session_id"]),o=this.db.query("PRAGMA table_info(sdk_sessions)").all().some(i=>i.name==="platform_source");if(!(e&&!s&&t&&o)){if(o||this.db.run(`ALTER TABLE sdk_sessions ADD COLUMN platform_source TEXT NOT NULL DEFAULT '${p}'`),this.db.run(`
|
|
38
38
|
UPDATE sdk_sessions
|
|
39
|
-
SET platform_source = '${
|
|
39
|
+
SET platform_source = '${p}'
|
|
40
40
|
WHERE platform_source IS NULL OR platform_source = ''
|
|
41
|
-
`),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
41
|
+
`),s){this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildSdkSessionsWithCompositeIdentity(e),this.db.run("COMMIT")}catch(i){this.db.run("ROLLBACK");let a=i instanceof Error?i:new Error(String(i));throw _.error("DB","Failed to rebuild sdk_sessions with composite identity, rolled back",{},a),i}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(`
|
|
42
|
+
CREATE TABLE sdk_sessions_new (
|
|
43
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
44
|
+
content_session_id TEXT NOT NULL,
|
|
45
|
+
memory_session_id TEXT UNIQUE,
|
|
46
|
+
project TEXT NOT NULL,
|
|
47
|
+
platform_source TEXT NOT NULL DEFAULT '${p}',
|
|
48
|
+
user_prompt TEXT,
|
|
49
|
+
started_at TEXT NOT NULL,
|
|
50
|
+
started_at_epoch INTEGER NOT NULL,
|
|
51
|
+
completed_at TEXT,
|
|
52
|
+
completed_at_epoch INTEGER,
|
|
53
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'completed', 'failed')),
|
|
54
|
+
worker_port INTEGER,
|
|
55
|
+
prompt_counter INTEGER DEFAULT 0,
|
|
56
|
+
custom_title TEXT
|
|
57
|
+
)
|
|
58
|
+
`),this.db.run(`
|
|
59
|
+
INSERT INTO sdk_sessions_new (
|
|
60
|
+
id, content_session_id, memory_session_id, project, platform_source,
|
|
61
|
+
user_prompt, started_at, started_at_epoch, completed_at, completed_at_epoch,
|
|
62
|
+
status, worker_port, prompt_counter, custom_title
|
|
63
|
+
)
|
|
64
|
+
SELECT
|
|
65
|
+
id, content_session_id, memory_session_id, project,
|
|
66
|
+
COALESCE(NULLIF(platform_source, ''), '${p}'),
|
|
67
|
+
user_prompt, started_at, started_at_epoch, completed_at, completed_at_epoch,
|
|
68
|
+
status, worker_port, prompt_counter, custom_title
|
|
69
|
+
FROM sdk_sessions
|
|
70
|
+
`),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 r=this.db.query("PRAGMA table_info(user_prompts)").all().some(u=>u.name==="session_db_id"),i=this.db.query("PRAGMA foreign_key_list(user_prompts)").all().some(u=>u.table==="sdk_sessions"&&u.from==="content_session_id");if(e&&r&&!i)return;let a=this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='user_prompts_fts'").all().length>0,d=r?`COALESCE(up.session_db_id, (
|
|
71
71
|
SELECT s.id FROM sdk_sessions s
|
|
72
72
|
WHERE s.content_session_id = up.content_session_id
|
|
73
|
-
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${
|
|
74
|
-
WHEN '${
|
|
73
|
+
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${p}')
|
|
74
|
+
WHEN '${p}' THEN 0
|
|
75
75
|
ELSE 1
|
|
76
76
|
END, s.id
|
|
77
77
|
LIMIT 1
|
|
78
78
|
))`:`(
|
|
79
79
|
SELECT s.id FROM sdk_sessions s
|
|
80
80
|
WHERE s.content_session_id = up.content_session_id
|
|
81
|
-
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${
|
|
82
|
-
WHEN '${
|
|
81
|
+
ORDER BY CASE COALESCE(NULLIF(s.platform_source, ''), '${p}')
|
|
82
|
+
WHEN '${p}' THEN 0
|
|
83
83
|
ELSE 1
|
|
84
84
|
END, s.id
|
|
85
85
|
LIMIT 1
|
|
86
|
-
)`;this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{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(`
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
86
|
+
)`;this.db.run("PRAGMA foreign_keys = OFF"),this.db.run("BEGIN TRANSACTION");try{this.rebuildUserPromptsWithSessionDbId(e,d,a),this.db.run("COMMIT")}catch(u){this.db.run("ROLLBACK");let m=u instanceof Error?u:new Error(String(u));throw _.error("DB","Failed to rebuild user_prompts with session_db_id, rolled back",{},m),u}finally{this.db.run("PRAGMA foreign_keys = ON")}}rebuildUserPromptsWithSessionDbId(e,s,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(`
|
|
87
|
+
CREATE TABLE user_prompts_new (
|
|
88
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
89
|
+
session_db_id INTEGER,
|
|
90
|
+
content_session_id TEXT NOT NULL,
|
|
91
|
+
prompt_number INTEGER NOT NULL,
|
|
92
|
+
prompt_text TEXT NOT NULL,
|
|
93
|
+
created_at TEXT NOT NULL,
|
|
94
|
+
created_at_epoch INTEGER NOT NULL,
|
|
95
|
+
FOREIGN KEY(session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
|
96
|
+
)
|
|
97
|
+
`),this.db.run(`
|
|
98
|
+
INSERT INTO user_prompts_new (
|
|
99
|
+
id, session_db_id, content_session_id, prompt_number,
|
|
100
|
+
prompt_text, created_at, created_at_epoch
|
|
101
|
+
)
|
|
102
|
+
SELECT
|
|
103
|
+
up.id,
|
|
104
|
+
${s},
|
|
105
|
+
up.content_session_id,
|
|
106
|
+
up.prompt_number,
|
|
107
|
+
up.prompt_text,
|
|
108
|
+
up.created_at,
|
|
109
|
+
up.created_at_epoch
|
|
110
|
+
FROM user_prompts up
|
|
111
|
+
`),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)"),t&&(this.db.run(`
|
|
112
|
+
CREATE TRIGGER user_prompts_ai AFTER INSERT ON user_prompts BEGIN
|
|
113
|
+
INSERT INTO user_prompts_fts(rowid, prompt_text)
|
|
114
|
+
VALUES (new.id, new.prompt_text);
|
|
115
|
+
END;
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
CREATE TRIGGER user_prompts_ad AFTER DELETE ON user_prompts BEGIN
|
|
118
|
+
INSERT INTO user_prompts_fts(user_prompts_fts, rowid, prompt_text)
|
|
119
|
+
VALUES('delete', old.id, old.prompt_text);
|
|
120
|
+
END;
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
)
|
|
145
|
-
WHERE duplicate_rank > 1
|
|
122
|
+
CREATE TRIGGER user_prompts_au AFTER UPDATE ON user_prompts BEGIN
|
|
123
|
+
INSERT INTO user_prompts_fts(user_prompts_fts, rowid, prompt_text)
|
|
124
|
+
VALUES('delete', old.id, old.prompt_text);
|
|
125
|
+
INSERT INTO user_prompts_fts(rowid, prompt_text)
|
|
126
|
+
VALUES (new.id, new.prompt_text);
|
|
127
|
+
END;
|
|
128
|
+
`),this.db.run("INSERT INTO user_prompts_fts(user_prompts_fts) VALUES('rebuild')")),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 t=this.hasUniqueIndexOnColumns("pending_messages",["session_db_id","tool_use_id"]);if(!(e&&t)){this.db.run("BEGIN TRANSACTION");try{this.recreatePendingSessionToolUniqueIndex(e),this.db.run("COMMIT")}catch(r){this.db.run("ROLLBACK");let o=r instanceof Error?r:new Error(String(r));throw _.error("DB","Failed to recreate ux_pending_session_tool index, rolled back",{},o),r}}}recreatePendingSessionToolUniqueIndex(e){this.db.run("DROP INDEX IF EXISTS ux_pending_session_tool"),this.db.run(`
|
|
129
|
+
DELETE FROM pending_messages
|
|
130
|
+
WHERE id IN (
|
|
131
|
+
SELECT id
|
|
132
|
+
FROM (
|
|
133
|
+
SELECT id,
|
|
134
|
+
ROW_NUMBER() OVER (
|
|
135
|
+
PARTITION BY session_db_id, tool_use_id
|
|
136
|
+
ORDER BY CASE status
|
|
137
|
+
WHEN 'processing' THEN 0
|
|
138
|
+
WHEN 'pending' THEN 1
|
|
139
|
+
ELSE 2
|
|
140
|
+
END, id
|
|
141
|
+
) AS duplicate_rank
|
|
142
|
+
FROM pending_messages
|
|
143
|
+
WHERE tool_use_id IS NOT NULL
|
|
146
144
|
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
WHERE duplicate_rank > 1
|
|
146
|
+
)
|
|
147
|
+
`),this.db.run(`
|
|
148
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
149
|
+
ON pending_messages(session_db_id, tool_use_id)
|
|
150
|
+
WHERE tool_use_id IS NOT NULL
|
|
151
|
+
`),e||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(35,new Date().toISOString())}dropDeadPendingMessagesColumns(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(31),s=this.db.query("PRAGMA table_info(pending_messages)").all(),t=new Set(s.map(i=>i.name)),o=["retry_count","failed_at_epoch","completed_at_epoch"].filter(i=>t.has(i));if(!(e&&o.length===0)){if(o.length>0){this.db.run("BEGIN TRANSACTION");try{this.db.run("DELETE FROM pending_messages WHERE status NOT IN ('pending', 'processing')");for(let i of o)this.db.run(`ALTER TABLE pending_messages DROP COLUMN ${i}`),_.debug("DB",`Dropped dead column ${i} 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(i){this.db.run("ROLLBACK"),_.warn("DB","Failed to drop dead columns from pending_messages",{},i instanceof Error?i:new Error(String(i)));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(`
|
|
152
152
|
CREATE TABLE IF NOT EXISTS schema_versions (
|
|
153
153
|
id INTEGER PRIMARY KEY,
|
|
154
154
|
version INTEGER UNIQUE NOT NULL,
|
|
@@ -213,7 +213,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
213
213
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
214
214
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_project ON session_summaries(project);
|
|
215
215
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
216
|
-
`),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(
|
|
216
|
+
`),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(t=>t.name==="worker_port")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),_.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"),_.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"),_.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"),_.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())}removeSessionSummariesUniqueConstraint(){if(!this.db.query("PRAGMA index_list(session_summaries)").all().some(t=>t.unique===1&&t.origin!=="pk")){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString());return}_.debug("DB","Removing UNIQUE constraint from session_summaries.memory_session_id"),this.db.run("BEGIN TRANSACTION"),this.db.run("DROP TABLE IF EXISTS session_summaries_new"),this.db.run(`
|
|
217
217
|
CREATE TABLE session_summaries_new (
|
|
218
218
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
219
219
|
memory_session_id TEXT NOT NULL,
|
|
@@ -241,7 +241,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
241
241
|
CREATE INDEX idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
242
242
|
CREATE INDEX idx_session_summaries_project ON session_summaries(project);
|
|
243
243
|
CREATE INDEX idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
244
|
-
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString()),
|
|
244
|
+
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(7,new Date().toISOString()),_.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(r=>r.name==="title")){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString());return}_.debug("DB","Adding hierarchical fields to observations table"),this.db.run(`
|
|
245
245
|
ALTER TABLE observations ADD COLUMN title TEXT;
|
|
246
246
|
ALTER TABLE observations ADD COLUMN subtitle TEXT;
|
|
247
247
|
ALTER TABLE observations ADD COLUMN facts TEXT;
|
|
@@ -249,7 +249,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
249
249
|
ALTER TABLE observations ADD COLUMN concepts TEXT;
|
|
250
250
|
ALTER TABLE observations ADD COLUMN files_read TEXT;
|
|
251
251
|
ALTER TABLE observations ADD COLUMN files_modified TEXT;
|
|
252
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString()),
|
|
252
|
+
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(8,new Date().toISOString()),_.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 t=this.db.query("PRAGMA table_info(observations)").all().find(r=>r.name==="text");if(!t||t.notnull===0){this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString());return}_.debug("DB","Making observations.text nullable"),this.db.run("BEGIN TRANSACTION"),this.db.run("DROP TABLE IF EXISTS observations_new"),this.db.run(`
|
|
253
253
|
CREATE TABLE observations_new (
|
|
254
254
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
255
255
|
memory_session_id TEXT NOT NULL,
|
|
@@ -279,7 +279,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
279
279
|
CREATE INDEX idx_observations_project ON observations(project);
|
|
280
280
|
CREATE INDEX idx_observations_type ON observations(type);
|
|
281
281
|
CREATE INDEX idx_observations_created ON observations(created_at_epoch DESC);
|
|
282
|
-
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString()),
|
|
282
|
+
`),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(9,new Date().toISOString()),_.debug("DB","Successfully made observations.text nullable")}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}_.debug("DB","Creating user_prompts table with FTS5 support"),this.db.run("BEGIN TRANSACTION"),this.db.run(`
|
|
283
283
|
CREATE TABLE user_prompts (
|
|
284
284
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
285
285
|
session_db_id INTEGER,
|
|
@@ -297,7 +297,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
297
297
|
CREATE INDEX idx_user_prompts_prompt_number ON user_prompts(prompt_number);
|
|
298
298
|
CREATE INDEX idx_user_prompts_lookup ON user_prompts(session_db_id, prompt_number);
|
|
299
299
|
CREATE INDEX idx_user_prompts_content_lookup ON user_prompts(content_session_id, prompt_number);
|
|
300
|
-
`);let
|
|
300
|
+
`);let t=`
|
|
301
301
|
CREATE VIRTUAL TABLE user_prompts_fts USING fts5(
|
|
302
302
|
prompt_text,
|
|
303
303
|
content='user_prompts',
|
|
@@ -320,7 +320,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
320
320
|
INSERT INTO user_prompts_fts(rowid, prompt_text)
|
|
321
321
|
VALUES (new.id, new.prompt_text);
|
|
322
322
|
END;
|
|
323
|
-
`;try{this.db.run(
|
|
323
|
+
`;try{this.db.run(t),this.db.run(r)}catch(o){o instanceof Error?_.warn("DB","FTS5 not available \u2014 user_prompts_fts skipped (search uses ChromaDB)",{},o):_.warn("DB","FTS5 not available \u2014 user_prompts_fts skipped (search uses ChromaDB)",{},new Error(String(o))),this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(10,new Date().toISOString()),_.debug("DB","Created user_prompts table (without FTS5)");return}this.db.run("COMMIT"),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(10,new Date().toISOString()),_.debug("DB","Successfully created user_prompts table")}ensureDiscoveryTokensColumn(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(11))return;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"),_.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"),_.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}_.debug("DB","Creating pending_messages table"),this.db.run(`
|
|
324
324
|
CREATE TABLE pending_messages (
|
|
325
325
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
326
326
|
session_db_id INTEGER NOT NULL,
|
|
@@ -337,9 +337,9 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
337
337
|
created_at_epoch INTEGER NOT NULL,
|
|
338
338
|
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
|
339
339
|
)
|
|
340
|
-
`),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()),
|
|
341
|
-
metadata TEXT`:"",i=
|
|
342
|
-
content_hash TEXT`:"",d=r?", content_hash":"",
|
|
340
|
+
`),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()),_.debug("DB","pending_messages table created successfully")}renameSessionIdColumns(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(17))return;_.debug("DB","Checking session ID columns for semantic clarity rename");let s=0,t=(r,o,i)=>{let a=this.db.query(`PRAGMA table_info(${r})`).all(),d=a.some(m=>m.name===o);return a.some(m=>m.name===i)?!1:d?(this.db.run(`ALTER TABLE ${r} RENAME COLUMN ${o} TO ${i}`),_.debug("DB",`Renamed ${r}.${o} to ${i}`),!0):(_.warn("DB",`Column ${o} not found in ${r}, skipping rename`),!1)};t("sdk_sessions","claude_session_id","content_session_id")&&s++,t("sdk_sessions","sdk_session_id","memory_session_id")&&s++,t("pending_messages","claude_session_id","content_session_id")&&s++,t("observations","sdk_session_id","memory_session_id")&&s++,t("session_summaries","sdk_session_id","memory_session_id")&&s++,t("user_prompts","claude_session_id","content_session_id")&&s++,this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(17,new Date().toISOString()),s>0?_.debug("DB",`Successfully renamed ${s} session ID columns`):_.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(r=>r.name==="failed_at_epoch")||(this.db.run("ALTER TABLE pending_messages ADD COLUMN failed_at_epoch INTEGER"),_.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(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(21))return;_.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"),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");let s=this.db.query("PRAGMA table_info(observations)").all(),t=s.some(S=>S.name==="metadata"),r=s.some(S=>S.name==="content_hash"),o=t?`,
|
|
341
|
+
metadata TEXT`:"",i=t?", metadata":"",a=r?`,
|
|
342
|
+
content_hash TEXT`:"",d=r?", content_hash":"",u=`
|
|
343
343
|
CREATE TABLE observations_new (
|
|
344
344
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
345
345
|
memory_session_id TEXT NOT NULL,
|
|
@@ -370,7 +370,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
370
370
|
CREATE INDEX idx_observations_project ON observations(project);
|
|
371
371
|
CREATE INDEX idx_observations_type ON observations(type);
|
|
372
372
|
CREATE INDEX idx_observations_created ON observations(created_at_epoch DESC);
|
|
373
|
-
`,
|
|
373
|
+
`,c=`
|
|
374
374
|
CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN
|
|
375
375
|
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
|
376
376
|
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
|
@@ -387,7 +387,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
387
387
|
INSERT INTO observations_fts(rowid, title, subtitle, narrative, text, facts, concepts)
|
|
388
388
|
VALUES (new.id, new.title, new.subtitle, new.narrative, new.text, new.facts, new.concepts);
|
|
389
389
|
END;
|
|
390
|
-
`;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");let
|
|
390
|
+
`;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");let T=`
|
|
391
391
|
CREATE TABLE session_summaries_new (
|
|
392
392
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
393
393
|
memory_session_id TEXT NOT NULL,
|
|
@@ -406,17 +406,17 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
406
406
|
created_at_epoch INTEGER NOT NULL,
|
|
407
407
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
|
408
408
|
)
|
|
409
|
-
`,
|
|
409
|
+
`,h=`
|
|
410
410
|
INSERT INTO session_summaries_new
|
|
411
411
|
SELECT id, memory_session_id, project, request, investigated, learned,
|
|
412
412
|
completed, next_steps, files_read, files_edited, notes,
|
|
413
413
|
prompt_number, discovery_tokens, created_at, created_at_epoch
|
|
414
414
|
FROM session_summaries
|
|
415
|
-
`,
|
|
415
|
+
`,b=`
|
|
416
416
|
CREATE INDEX idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
417
417
|
CREATE INDEX idx_session_summaries_project ON session_summaries(project);
|
|
418
418
|
CREATE INDEX idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
419
|
-
`,
|
|
419
|
+
`,g=`
|
|
420
420
|
CREATE TRIGGER IF NOT EXISTS session_summaries_ai AFTER INSERT ON session_summaries BEGIN
|
|
421
421
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
422
422
|
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
@@ -433,169 +433,97 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
433
433
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
|
434
434
|
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
|
435
435
|
END;
|
|
436
|
-
`;try{this.recreateObservationsWithCascade(
|
|
436
|
+
`;try{this.recreateObservationsWithCascade(u,m,l,c),this.recreateSessionSummariesWithCascade(T,h,b,g),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"),_.debug("DB","Successfully added ON UPDATE CASCADE to FK constraints")}catch(S){throw this.db.run("ROLLBACK"),this.db.run("PRAGMA foreign_keys = ON"),S instanceof Error?S:new Error(String(S))}}recreateObservationsWithCascade(e,s,t,r){this.db.run(e),this.db.run(s),this.db.run("DROP TABLE observations"),this.db.run("ALTER TABLE observations_new RENAME TO observations"),this.db.run(t),this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='observations_fts'").all().length>0&&this.db.run(r)}recreateSessionSummariesWithCascade(e,s,t,r){this.db.run(e),this.db.run(s),this.db.run("DROP TABLE session_summaries"),this.db.run("ALTER TABLE session_summaries_new RENAME TO session_summaries"),this.db.run(t),this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='session_summaries_fts'").all().length>0&&this.db.run(r)}addObservationContentHashColumn(){if(this.db.query("PRAGMA table_info(observations)").all().some(t=>t.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)"),_.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(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(23))return;this.db.query("PRAGMA table_info(sdk_sessions)").all().some(r=>r.name==="custom_title")||(this.db.run("ALTER TABLE sdk_sessions ADD COLUMN custom_title TEXT"),_.debug("DB","Added custom_title column to sdk_sessions table")),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(23,new Date().toISOString())}addSessionPlatformSourceColumn(){let s=this.db.query("PRAGMA table_info(sdk_sessions)").all().some(i=>i.name==="platform_source"),r=this.db.query("PRAGMA index_list(sdk_sessions)").all().some(i=>i.name==="idx_sdk_sessions_platform_source");this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(24)&&s&&r||(s||(this.db.run(`ALTER TABLE sdk_sessions ADD COLUMN platform_source TEXT NOT NULL DEFAULT '${p}'`),_.debug("DB","Added platform_source column to sdk_sessions table")),this.db.run(`
|
|
437
437
|
UPDATE sdk_sessions
|
|
438
|
-
SET platform_source = '${
|
|
438
|
+
SET platform_source = '${p}'
|
|
439
439
|
WHERE platform_source IS NULL OR platform_source = ''
|
|
440
|
-
`),r||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(),
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
)
|
|
457
|
-
WHERE duplicate_rank > 1
|
|
440
|
+
`),r||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(),s=e.some(r=>r.name==="generated_by_model"),t=e.some(r=>r.name==="relevance_count");s&&t||(s||this.db.run("ALTER TABLE observations ADD COLUMN generated_by_model TEXT"),t||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()))}ensureMergedIntoProjectColumns(){this.db.query("PRAGMA table_info(observations)").all().some(t=>t.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(t=>t.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)")}addObservationSubagentColumns(){let e=this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(27),s=this.db.query("PRAGMA table_info(observations)").all(),t=s.some(i=>i.name==="agent_type"),r=s.some(i=>i.name==="agent_id");t||this.db.run("ALTER TABLE observations ADD COLUMN agent_type TEXT"),r||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 o=this.db.query("PRAGMA table_info(pending_messages)").all();if(o.length>0){let i=o.some(d=>d.name==="agent_type"),a=o.some(d=>d.name==="agent_id");i||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(r=>r.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(r){this.db.run("ROLLBACK");let o=r instanceof Error?r:new Error(String(r));throw _.error("DB","Failed to de-dupe pending_messages by tool_use_id, rolled back",{},o),r}}dedupePendingMessagesByToolUseId(){this.db.run(`
|
|
441
|
+
DELETE FROM pending_messages
|
|
442
|
+
WHERE id IN (
|
|
443
|
+
SELECT id
|
|
444
|
+
FROM (
|
|
445
|
+
SELECT id,
|
|
446
|
+
ROW_NUMBER() OVER (
|
|
447
|
+
PARTITION BY session_db_id, tool_use_id
|
|
448
|
+
ORDER BY CASE status
|
|
449
|
+
WHEN 'processing' THEN 0
|
|
450
|
+
WHEN 'pending' THEN 1
|
|
451
|
+
ELSE 2
|
|
452
|
+
END, id
|
|
453
|
+
) AS duplicate_rank
|
|
454
|
+
FROM pending_messages
|
|
455
|
+
WHERE tool_use_id IS NOT NULL
|
|
458
456
|
)
|
|
459
|
-
|
|
460
|
-
-- tool_use_id is optional for summaries and legacy rows; enforce de-dupe
|
|
461
|
-
-- only for rows that came from a concrete tool-use event.
|
|
462
|
-
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
463
|
-
ON pending_messages(session_db_id, tool_use_id)
|
|
464
|
-
WHERE tool_use_id IS NOT NULL
|
|
465
|
-
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(28,new Date().toISOString()),this.db.run("COMMIT")}catch(r){throw this.db.run("ROLLBACK"),r}}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(o=>o.name==="memory_session_id"),r=t.some(o=>o.name==="content_hash");if(!s||!r){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.db.run(`
|
|
466
|
-
UPDATE observations
|
|
467
|
-
SET content_hash = '__null_migration_' || id || '__'
|
|
468
|
-
WHERE content_hash IS NULL
|
|
469
|
-
`),this.db.run(`
|
|
470
|
-
DELETE FROM observations
|
|
471
|
-
WHERE id IN (
|
|
472
|
-
SELECT id
|
|
473
|
-
FROM (
|
|
474
|
-
SELECT id,
|
|
475
|
-
ROW_NUMBER() OVER (
|
|
476
|
-
PARTITION BY memory_session_id, content_hash
|
|
477
|
-
ORDER BY id
|
|
478
|
-
) AS duplicate_rank
|
|
479
|
-
FROM observations
|
|
480
|
-
)
|
|
481
|
-
WHERE duplicate_rank > 1
|
|
457
|
+
WHERE duplicate_rank > 1
|
|
482
458
|
)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
459
|
+
`),this.db.run(`
|
|
460
|
+
-- tool_use_id is optional for summaries and legacy rows; enforce de-dupe
|
|
461
|
+
-- only for rows that came from a concrete tool-use event.
|
|
462
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
463
|
+
ON pending_messages(session_db_id, tool_use_id)
|
|
464
|
+
WHERE tool_use_id IS NOT NULL
|
|
465
|
+
`),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 s=this.db.query("PRAGMA table_info(observations)").all(),t=s.some(o=>o.name==="memory_session_id"),r=s.some(o=>o.name==="content_hash");if(!t||!r){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(o){this.db.run("ROLLBACK");let i=o instanceof Error?o:new Error(String(o));throw _.error("DB","Failed to de-dupe observations by content_hash, rolled back",{},i),o}}dedupeObservationsByContentHash(){this.db.run(`
|
|
466
|
+
UPDATE observations
|
|
467
|
+
SET content_hash = '__null_migration_' || id || '__'
|
|
468
|
+
WHERE content_hash IS NULL
|
|
469
|
+
`),this.db.run(`
|
|
470
|
+
DELETE FROM observations
|
|
471
|
+
WHERE id IN (
|
|
472
|
+
SELECT id
|
|
473
|
+
FROM (
|
|
474
|
+
SELECT id,
|
|
475
|
+
ROW_NUMBER() OVER (
|
|
476
|
+
PARTITION BY memory_session_id, content_hash
|
|
477
|
+
ORDER BY id
|
|
478
|
+
) AS duplicate_rank
|
|
479
|
+
FROM observations
|
|
480
|
+
)
|
|
481
|
+
WHERE duplicate_rank > 1
|
|
482
|
+
)
|
|
483
|
+
`),this.db.run(`
|
|
484
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_observations_session_hash
|
|
485
|
+
ON observations(memory_session_id, content_hash)
|
|
486
|
+
`),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(t=>t.name==="metadata")||(this.db.run("ALTER TABLE observations ADD COLUMN metadata TEXT"),_.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,s){this.db.prepare(`
|
|
487
487
|
UPDATE sdk_sessions
|
|
488
488
|
SET memory_session_id = ?
|
|
489
489
|
WHERE id = ?
|
|
490
|
-
`).run(
|
|
490
|
+
`).run(s,e)}markSessionCompleted(e){let s=Date.now(),t=new Date(s).toISOString();this.db.prepare(`
|
|
491
491
|
UPDATE sdk_sessions
|
|
492
492
|
SET status = 'completed', completed_at = ?, completed_at_epoch = ?
|
|
493
493
|
WHERE id = ?
|
|
494
|
-
`).run(s,
|
|
494
|
+
`).run(t,s,e)}ensureMemorySessionIdRegistered(e,s,t){let r=this.db.prepare(`
|
|
495
495
|
SELECT id, memory_session_id, worker_port FROM sdk_sessions WHERE id = ?
|
|
496
|
-
`).get(e);if(!r)throw new Error(`Session ${e} not found in sdk_sessions`);r.memory_session_id!==
|
|
496
|
+
`).get(e);if(!r)throw new Error(`Session ${e} not found in sdk_sessions`);r.memory_session_id!==s&&(this.db.prepare(`
|
|
497
497
|
UPDATE sdk_sessions SET memory_session_id = ? WHERE id = ?
|
|
498
|
-
`).run(
|
|
498
|
+
`).run(s,e),_.info("DB","Registered memory_session_id before storage (FK fix)",{sessionDbId:e,oldId:r.memory_session_id,newId:s})),typeof t=="number"&&r.worker_port!==t&&this.db.prepare(`
|
|
499
499
|
UPDATE sdk_sessions SET worker_port = ? WHERE id = ?
|
|
500
|
-
`).run(
|
|
501
|
-
SELECT
|
|
502
|
-
request, investigated, learned, completed, next_steps,
|
|
503
|
-
files_read, files_edited, notes, prompt_number, created_at
|
|
504
|
-
FROM session_summaries
|
|
505
|
-
WHERE project = ?
|
|
506
|
-
ORDER BY created_at_epoch DESC
|
|
507
|
-
LIMIT ?
|
|
508
|
-
`).all(e,t)}getRecentSummariesWithSessionInfo(e,t=3){return this.db.prepare(`
|
|
509
|
-
SELECT
|
|
510
|
-
memory_session_id, request, learned, completed, next_steps,
|
|
511
|
-
prompt_number, created_at
|
|
512
|
-
FROM session_summaries
|
|
513
|
-
WHERE project = ?
|
|
514
|
-
ORDER BY created_at_epoch DESC
|
|
515
|
-
LIMIT ?
|
|
516
|
-
`).all(e,t)}getRecentObservations(e,t=20){return this.db.prepare(`
|
|
517
|
-
SELECT type, text, prompt_number, created_at
|
|
518
|
-
FROM observations
|
|
519
|
-
WHERE project = ?
|
|
520
|
-
ORDER BY created_at_epoch DESC
|
|
521
|
-
LIMIT ?
|
|
522
|
-
`).all(e,t)}getAllRecentObservations(e=100){return this.db.prepare(`
|
|
523
|
-
SELECT
|
|
524
|
-
o.id,
|
|
525
|
-
o.type,
|
|
526
|
-
o.title,
|
|
527
|
-
o.subtitle,
|
|
528
|
-
o.text,
|
|
529
|
-
o.project,
|
|
530
|
-
COALESCE(s.platform_source, '${c}') as platform_source,
|
|
531
|
-
o.prompt_number,
|
|
532
|
-
o.created_at,
|
|
533
|
-
o.created_at_epoch
|
|
534
|
-
FROM observations o
|
|
535
|
-
LEFT JOIN sdk_sessions s ON o.memory_session_id = s.memory_session_id
|
|
536
|
-
ORDER BY o.created_at_epoch DESC
|
|
537
|
-
LIMIT ?
|
|
538
|
-
`).all(e)}getAllRecentSummaries(e=50){return this.db.prepare(`
|
|
539
|
-
SELECT
|
|
540
|
-
ss.id,
|
|
541
|
-
ss.request,
|
|
542
|
-
ss.investigated,
|
|
543
|
-
ss.learned,
|
|
544
|
-
ss.completed,
|
|
545
|
-
ss.next_steps,
|
|
546
|
-
ss.files_read,
|
|
547
|
-
ss.files_edited,
|
|
548
|
-
ss.notes,
|
|
549
|
-
ss.project,
|
|
550
|
-
COALESCE(s.platform_source, '${c}') as platform_source,
|
|
551
|
-
ss.prompt_number,
|
|
552
|
-
ss.created_at,
|
|
553
|
-
ss.created_at_epoch
|
|
554
|
-
FROM session_summaries ss
|
|
555
|
-
LEFT JOIN sdk_sessions s ON ss.memory_session_id = s.memory_session_id
|
|
556
|
-
ORDER BY ss.created_at_epoch DESC
|
|
557
|
-
LIMIT ?
|
|
558
|
-
`).all(e)}getAllRecentUserPrompts(e=100){return this.db.prepare(`
|
|
559
|
-
SELECT
|
|
560
|
-
up.id,
|
|
561
|
-
up.content_session_id,
|
|
562
|
-
s.project,
|
|
563
|
-
COALESCE(s.platform_source, '${c}') as platform_source,
|
|
564
|
-
up.prompt_number,
|
|
565
|
-
up.prompt_text,
|
|
566
|
-
up.created_at,
|
|
567
|
-
up.created_at_epoch
|
|
568
|
-
FROM user_prompts up
|
|
569
|
-
LEFT JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
570
|
-
ORDER BY up.created_at_epoch DESC
|
|
571
|
-
LIMIT ?
|
|
572
|
-
`).all(e)}getAllProjects(e){let t=e?N(e):void 0,s=`
|
|
500
|
+
`).run(t,e)}getAllProjects(e){let s=e?A(e):void 0,t=`
|
|
573
501
|
SELECT DISTINCT project
|
|
574
502
|
FROM sdk_sessions
|
|
575
503
|
WHERE project IS NOT NULL AND project != ''
|
|
576
504
|
AND project != ?
|
|
577
|
-
`,r=[
|
|
505
|
+
`,r=[te];return s&&(t+=" AND COALESCE(platform_source, ?) = ?",r.push(p,s)),t+=" ORDER BY project ASC",this.db.prepare(t).all(...r).map(i=>i.project)}getProjectCatalog(){let e=this.db.prepare(`
|
|
578
506
|
SELECT
|
|
579
|
-
COALESCE(platform_source, '${
|
|
507
|
+
COALESCE(platform_source, '${p}') as platform_source,
|
|
580
508
|
project,
|
|
581
509
|
MAX(started_at_epoch) as latest_epoch
|
|
582
510
|
FROM sdk_sessions
|
|
583
511
|
WHERE project IS NOT NULL AND project != ''
|
|
584
512
|
AND project != ?
|
|
585
|
-
GROUP BY COALESCE(platform_source, '${
|
|
513
|
+
GROUP BY COALESCE(platform_source, '${p}'), project
|
|
586
514
|
ORDER BY latest_epoch DESC
|
|
587
|
-
`).all(
|
|
515
|
+
`).all(te),s=[],t=new Set,r={};for(let i of e){let a=A(i.platform_source);r[a]||(r[a]=[]),r[a].includes(i.project)||r[a].push(i.project),t.has(i.project)||(t.add(i.project),s.push(i.project))}let o=Ne(Object.keys(r));return{projects:s,sources:o,projectsBySource:Object.fromEntries(o.map(i=>[i,r[i]||[]]))}}getLatestUserPrompt(e,s){let t=this.resolvePromptSessionDbId(e,s),r=t!==null?"up.session_db_id = ?":"up.content_session_id = ?",o=t!==null?t:e;return this.db.prepare(`
|
|
588
516
|
SELECT
|
|
589
517
|
up.*,
|
|
590
518
|
s.memory_session_id,
|
|
591
519
|
s.project,
|
|
592
|
-
COALESCE(s.platform_source, '${
|
|
520
|
+
COALESCE(s.platform_source, '${p}') as platform_source
|
|
593
521
|
FROM user_prompts up
|
|
594
522
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
595
523
|
WHERE ${r}
|
|
596
524
|
ORDER BY up.created_at_epoch DESC
|
|
597
525
|
LIMIT 1
|
|
598
|
-
`).get(o)}findRecentDuplicateUserPrompt(e,t,
|
|
526
|
+
`).get(o)}findRecentDuplicateUserPrompt(e,s,t,r){return Ie(this.db,e,B(s),t,this.resolvePromptSessionDbId(e,r)??void 0)}getRecentSessionsWithStatus(e,s=3,t){let r=[e],o="";return t&&(o=`AND COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?`,r.push(A(t))),r.push(s),this.db.prepare(`
|
|
599
527
|
SELECT * FROM (
|
|
600
528
|
SELECT
|
|
601
529
|
s.memory_session_id,
|
|
@@ -613,44 +541,44 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
613
541
|
LIMIT ?
|
|
614
542
|
)
|
|
615
543
|
ORDER BY started_at_epoch ASC
|
|
616
|
-
`).all(...r)}getObservationsForSession(e,
|
|
544
|
+
`).all(...r)}getObservationsForSession(e,s){let t=[e],r="";return s&&(r=`
|
|
617
545
|
AND EXISTS (
|
|
618
546
|
SELECT 1
|
|
619
547
|
FROM sdk_sessions s
|
|
620
548
|
WHERE s.memory_session_id = observations.memory_session_id
|
|
621
|
-
AND COALESCE(NULLIF(s.platform_source, ''), '${
|
|
549
|
+
AND COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?
|
|
622
550
|
)
|
|
623
|
-
`,
|
|
551
|
+
`,t.push(A(s))),this.db.prepare(`
|
|
624
552
|
SELECT title, subtitle, type, prompt_number
|
|
625
553
|
FROM observations
|
|
626
554
|
WHERE memory_session_id = ?
|
|
627
555
|
${r}
|
|
628
556
|
ORDER BY created_at_epoch ASC
|
|
629
|
-
`).all(...
|
|
557
|
+
`).all(...t)}getObservationById(e,s){return s?this.db.prepare(`
|
|
630
558
|
SELECT o.*
|
|
631
559
|
FROM observations o
|
|
632
560
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id
|
|
633
561
|
WHERE o.id = ?
|
|
634
|
-
AND COALESCE(NULLIF(s.platform_source, ''), '${
|
|
635
|
-
`).get(e,
|
|
562
|
+
AND COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?
|
|
563
|
+
`).get(e,A(s))||null:this.db.prepare(`
|
|
636
564
|
SELECT *
|
|
637
565
|
FROM observations
|
|
638
566
|
WHERE id = ?
|
|
639
|
-
`).get(e)||null}getObservationsByIds(e,
|
|
567
|
+
`).get(e)||null}getObservationsByIds(e,s={}){if(e.length===0)return[];let{orderBy:t="date_desc",limit:r,project:o,platformSource:i,type:a,concepts:d,files:u}=s,m=t==="relevance",l=m?"":`ORDER BY o.created_at_epoch ${t==="date_asc"?"ASC":"DESC"}`,c=r&&!m?`LIMIT ${r}`:"",T=e.map(()=>"?").join(","),h=[...e],b=[];if(o&&(b.push("o.project = ?"),h.push(o)),i&&(b.push(`COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?`),h.push(A(i))),a)if(Array.isArray(a)){let N=a.map(()=>"?").join(",");b.push(`o.type IN (${N})`),h.push(...a)}else b.push("o.type = ?"),h.push(a);if(d){let N=Array.isArray(d)?d:[d],O=N.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE value = ?)");h.push(...N),b.push(`(${O.join(" OR ")})`)}if(u){let N=Array.isArray(u)?u:[u],O=N.map(()=>"(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE value LIKE ?) OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE value LIKE ?))");N.forEach(L=>{h.push(`%${L}%`,`%${L}%`)}),b.push(`(${O.join(" OR ")})`)}let g=b.length>0?`WHERE o.id IN (${T}) AND ${b.join(" AND ")}`:`WHERE o.id IN (${T})`,C=this.db.prepare(`
|
|
640
568
|
SELECT o.*
|
|
641
569
|
FROM observations o
|
|
642
570
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = o.memory_session_id
|
|
643
|
-
${
|
|
571
|
+
${g}
|
|
644
572
|
${l}
|
|
645
|
-
${
|
|
646
|
-
`).all(...
|
|
573
|
+
${c}
|
|
574
|
+
`).all(...h);if(!m)return C;let y=new Map(C.map(N=>[N.id,N])),R=e.map(N=>y.get(N)).filter(N=>!!N);return r?R.slice(0,r):R}getSummaryForSession(e,s){let t=[e],r="";return s&&(r=`
|
|
647
575
|
AND EXISTS (
|
|
648
576
|
SELECT 1
|
|
649
577
|
FROM sdk_sessions sdk
|
|
650
578
|
WHERE sdk.memory_session_id = session_summaries.memory_session_id
|
|
651
|
-
AND COALESCE(NULLIF(sdk.platform_source, ''), '${
|
|
579
|
+
AND COALESCE(NULLIF(sdk.platform_source, ''), '${p}') = ?
|
|
652
580
|
)
|
|
653
|
-
`,
|
|
581
|
+
`,t.push(A(s))),this.db.prepare(`
|
|
654
582
|
SELECT
|
|
655
583
|
request, investigated, learned, completed, next_steps,
|
|
656
584
|
files_read, files_edited, notes, prompt_number, created_at,
|
|
@@ -660,258 +588,175 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
660
588
|
${r}
|
|
661
589
|
ORDER BY created_at_epoch DESC
|
|
662
590
|
LIMIT 1
|
|
663
|
-
`).get(...
|
|
664
|
-
SELECT files_read, files_modified
|
|
665
|
-
FROM observations
|
|
666
|
-
WHERE memory_session_id = ?
|
|
667
|
-
`).all(e),r=new Set,o=new Set;for(let i of s)de(i.files_read).forEach(a=>r.add(a)),de(i.files_modified).forEach(a=>o.add(a));return{filesRead:Array.from(r),filesModified:Array.from(o)}}getSessionById(e){return this.db.prepare(`
|
|
591
|
+
`).get(...t)||null}getSessionById(e){return this.db.prepare(`
|
|
668
592
|
SELECT id, content_session_id, memory_session_id, project,
|
|
669
|
-
COALESCE(platform_source, '${
|
|
593
|
+
COALESCE(platform_source, '${p}') as platform_source,
|
|
670
594
|
user_prompt, custom_title, status
|
|
671
595
|
FROM sdk_sessions
|
|
672
596
|
WHERE id = ?
|
|
673
597
|
LIMIT 1
|
|
674
|
-
`).get(e)||null}getSdkSessionsBySessionIds(e){if(e.length===0)return[];let
|
|
598
|
+
`).get(e)||null}getSdkSessionsBySessionIds(e){if(e.length===0)return[];let s=e.map(()=>"?").join(",");return this.db.prepare(`
|
|
675
599
|
SELECT id, content_session_id, memory_session_id, project,
|
|
676
|
-
COALESCE(platform_source, '${
|
|
600
|
+
COALESCE(platform_source, '${p}') as platform_source,
|
|
677
601
|
user_prompt, custom_title,
|
|
678
602
|
started_at, started_at_epoch, completed_at, completed_at_epoch, status
|
|
679
603
|
FROM sdk_sessions
|
|
680
|
-
WHERE memory_session_id IN (${
|
|
604
|
+
WHERE memory_session_id IN (${s})
|
|
681
605
|
ORDER BY started_at_epoch DESC
|
|
682
|
-
`).all(...e)}getPromptNumberFromUserPrompts(e,
|
|
606
|
+
`).all(...e)}getPromptNumberFromUserPrompts(e,s){let t=this.resolvePromptSessionDbId(e,s);return t!==null?this.db.prepare(`
|
|
683
607
|
SELECT COUNT(*) as count FROM user_prompts WHERE session_db_id = ?
|
|
684
|
-
`).get(
|
|
608
|
+
`).get(t).count:this.db.prepare(`
|
|
685
609
|
SELECT COUNT(*) as count FROM user_prompts WHERE content_session_id = ?
|
|
686
|
-
`).get(e).count}createSDKSession(e,t,
|
|
610
|
+
`).get(e).count}createSDKSession(e,s,t,r,o){let i=new Date,a=i.getTime(),d=o?A(o):p,u=B(t),m=this.db.prepare(`
|
|
687
611
|
SELECT id, platform_source
|
|
688
612
|
FROM sdk_sessions
|
|
689
613
|
WHERE COALESCE(NULLIF(platform_source, ''), ?) = ?
|
|
690
614
|
AND content_session_id = ?
|
|
691
|
-
`).get(
|
|
615
|
+
`).get(p,d,e);if(m)return s&&this.db.prepare(`
|
|
692
616
|
UPDATE sdk_sessions SET project = ?
|
|
693
617
|
WHERE id = ? AND (project IS NULL OR project = '')
|
|
694
|
-
`).run(
|
|
618
|
+
`).run(s,m.id),r&&this.db.prepare(`
|
|
695
619
|
UPDATE sdk_sessions SET custom_title = ?
|
|
696
620
|
WHERE id = ? AND custom_title IS NULL
|
|
697
|
-
`).run(
|
|
621
|
+
`).run(r,m.id),m.id;let l=this.db.prepare(`
|
|
698
622
|
INSERT INTO sdk_sessions
|
|
699
623
|
(content_session_id, memory_session_id, project, platform_source, user_prompt, custom_title, started_at, started_at_epoch, status)
|
|
700
624
|
VALUES (?, NULL, ?, ?, ?, ?, ?, ?, 'active')
|
|
701
|
-
`).run(e,
|
|
625
|
+
`).run(e,s,d,u,r||null,i.toISOString(),a);return Number(l.lastInsertRowid)}saveUserPrompt(e,s,t,r){let o=new Date,i=o.getTime(),a=B(t),d=this.resolvePromptSessionDbId(e,r);return this.db.prepare(`
|
|
702
626
|
INSERT INTO user_prompts
|
|
703
627
|
(session_db_id, content_session_id, prompt_number, prompt_text, created_at, created_at_epoch)
|
|
704
628
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
705
|
-
`).run(d,e,
|
|
629
|
+
`).run(d,e,s,a,o.toISOString(),i).lastInsertRowid}getUserPrompt(e,s,t){let r=this.resolvePromptSessionDbId(e,t);return r!==null?this.db.prepare(`
|
|
706
630
|
SELECT prompt_text
|
|
707
631
|
FROM user_prompts
|
|
708
632
|
WHERE session_db_id = ? AND prompt_number = ?
|
|
709
633
|
LIMIT 1
|
|
710
|
-
`).get(r,
|
|
634
|
+
`).get(r,s)?.prompt_text??null:this.db.prepare(`
|
|
711
635
|
SELECT prompt_text
|
|
712
636
|
FROM user_prompts
|
|
713
637
|
WHERE content_session_id = ? AND prompt_number = ?
|
|
714
638
|
LIMIT 1
|
|
715
|
-
`).get(e,
|
|
716
|
-
INSERT INTO observations
|
|
717
|
-
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
|
718
|
-
files_read, files_modified, prompt_number, discovery_tokens, agent_type, agent_id, content_hash, created_at, created_at_epoch,
|
|
719
|
-
generated_by_model, metadata)
|
|
720
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
721
|
-
ON CONFLICT(memory_session_id, content_hash) DO NOTHING
|
|
722
|
-
RETURNING id, created_at_epoch
|
|
723
|
-
`).get(e,t,s.type,s.title,s.subtitle,JSON.stringify(s.facts),s.narrative,JSON.stringify(s.concepts),JSON.stringify(s.files_read),JSON.stringify(s.files_modified),r||null,o,s.agent_type??null,s.agent_id??null,m,_,d,a||null,s.metadata??null);if(p)return{id:p.id,createdAtEpoch:p.created_at_epoch};let g=this.db.prepare("SELECT id, created_at_epoch FROM observations WHERE memory_session_id = ? AND content_hash = ?").get(e,m);if(!g)throw new Error(`storeObservation: ON CONFLICT without existing row for content_hash=${m}`);return{id:g.id,createdAtEpoch:g.created_at_epoch}}storeSummary(e,t,s,r,o=0,i){let a=i??Date.now(),d=new Date(a).toISOString(),m=this.db.prepare(`
|
|
639
|
+
`).get(e,s)?.prompt_text??null}storeObservation(e,s,t,r,o=0,i,a){let d=this.storeObservations(e,s,[t],null,r,o,i,a);return{id:d.observationIds[0],createdAtEpoch:d.createdAtEpoch}}storeSummary(e,s,t,r,o=0,i){let a=i??Date.now(),d=new Date(a).toISOString(),m=this.db.prepare(`
|
|
724
640
|
INSERT INTO session_summaries
|
|
725
641
|
(memory_session_id, project, request, investigated, learned, completed,
|
|
726
642
|
next_steps, notes, prompt_number, discovery_tokens, created_at, created_at_epoch)
|
|
727
643
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
728
|
-
`).run(e,t
|
|
644
|
+
`).run(e,s,t.request,t.investigated,t.learned,t.completed,t.next_steps,t.notes,r||null,o,d,a);return{id:Number(m.lastInsertRowid),createdAtEpoch:a}}storeObservations(e,s,t,r,o,i=0,a,d){let u=a??Date.now(),m=new Date(u).toISOString();return this.db.transaction(()=>{let c=[],T=this.db.prepare(`
|
|
729
645
|
INSERT INTO observations
|
|
730
646
|
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
|
731
647
|
files_read, files_modified, prompt_number, discovery_tokens, agent_type, agent_id, content_hash, created_at, created_at_epoch,
|
|
732
|
-
generated_by_model)
|
|
733
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
648
|
+
generated_by_model, metadata)
|
|
649
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
734
650
|
ON CONFLICT(memory_session_id, content_hash) DO NOTHING
|
|
735
651
|
RETURNING id
|
|
736
|
-
`),
|
|
652
|
+
`),h=this.db.prepare("SELECT id FROM observations WHERE memory_session_id = ? AND content_hash = ?");for(let g of t){let S=he(e,g.title,g.narrative),C=T.get(e,s,g.type,g.title,g.subtitle,JSON.stringify(g.facts),g.narrative,JSON.stringify(g.concepts),JSON.stringify(g.files_read),JSON.stringify(g.files_modified),o||null,i,g.agent_type??null,g.agent_id??null,S,m,u,d||null,g.metadata??null);if(C){c.push(C.id);continue}let y=h.get(e,S);if(!y)throw new Error(`storeObservations: ON CONFLICT without existing row for content_hash=${S}`);c.push(y.id)}let b=null;if(r){let S=this.db.prepare(`
|
|
737
653
|
INSERT INTO session_summaries
|
|
738
654
|
(memory_session_id, project, request, investigated, learned, completed,
|
|
739
655
|
next_steps, notes, prompt_number, discovery_tokens, created_at, created_at_epoch)
|
|
740
656
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
741
|
-
`).run(e,
|
|
657
|
+
`).run(e,s,r.request,r.investigated,r.learned,r.completed,r.next_steps,r.notes,o||null,i,m,u);b=Number(S.lastInsertRowid)}return{observationIds:c,summaryId:b,createdAtEpoch:u}})()}getSessionSummariesByIds(e,s={}){if(e.length===0)return[];let{orderBy:t="date_desc",limit:r,project:o,platformSource:i}=s,a=t==="relevance",d=a?"":`ORDER BY ss.created_at_epoch ${t==="date_asc"?"ASC":"DESC"}`,u=r&&!a?`LIMIT ${r}`:"",m=e.map(()=>"?").join(","),l=[...e],c=[];o&&(c.push("ss.project = ?"),l.push(o)),i&&(c.push(`COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?`),l.push(A(i)));let T=c.length>0?`AND ${c.join(" AND ")}`:"",b=this.db.prepare(`
|
|
742
658
|
SELECT ss.*
|
|
743
659
|
FROM session_summaries ss
|
|
744
660
|
LEFT JOIN sdk_sessions s ON s.memory_session_id = ss.memory_session_id
|
|
745
|
-
WHERE ss.id IN (${m}) ${
|
|
661
|
+
WHERE ss.id IN (${m}) ${T}
|
|
746
662
|
${d}
|
|
747
|
-
${
|
|
748
|
-
`).all(...l);if(!a)return
|
|
663
|
+
${u}
|
|
664
|
+
`).all(...l);if(!a)return b;let g=new Map(b.map(C=>[C.id,C])),S=e.map(C=>g.get(C)).filter(C=>!!C);return r?S.slice(0,r):S}getUserPromptsByIds(e,s={}){if(e.length===0)return[];let{orderBy:t="date_desc",limit:r,project:o,platformSource:i}=s,a=t==="relevance",d=a?"":`ORDER BY up.created_at_epoch ${t==="date_asc"?"ASC":"DESC"}`,u=r?`LIMIT ${r}`:"",m=e.map(()=>"?").join(","),l=[...e],c=[];o&&(c.push("s.project = ?"),l.push(o)),i&&(c.push(`COALESCE(NULLIF(s.platform_source, ''), '${p}') = ?`),l.push(A(i)));let T=c.length>0?`AND ${c.join(" AND ")}`:"",b=this.db.prepare(`
|
|
749
665
|
SELECT
|
|
750
666
|
up.*,
|
|
751
667
|
s.project,
|
|
752
668
|
s.memory_session_id,
|
|
753
|
-
COALESCE(NULLIF(s.platform_source, ''), '${
|
|
669
|
+
COALESCE(NULLIF(s.platform_source, ''), '${p}') as platform_source
|
|
754
670
|
FROM user_prompts up
|
|
755
671
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
756
|
-
WHERE up.id IN (${m}) ${
|
|
672
|
+
WHERE up.id IN (${m}) ${T}
|
|
757
673
|
${d}
|
|
758
|
-
${
|
|
759
|
-
`).all(...l);if(!a)return
|
|
674
|
+
${u}
|
|
675
|
+
`).all(...l);if(!a)return b;let g=new Map(b.map(S=>[S.id,S]));return e.map(S=>g.get(S)).filter(S=>!!S)}getTimelineAroundTimestamp(e,s=10,t=10,r,o){return this.getTimelineAroundObservation(null,e,s,t,r,o)}getTimelineAroundObservation(e,s,t=10,r=10,o,i){let a=i?A(i):void 0,d=(R,N)=>{let O=[],L=[];return o&&(O.push(`${R}.project = ?`),L.push(o)),a&&(O.push(`COALESCE(NULLIF(${N}.platform_source, ''), '${p}') = ?`),L.push(a)),{clause:O.length>0?`AND ${O.join(" AND ")}`:"",params:L}},u=d("o","src"),m=d("ss","src"),l=d("s","s"),c,T;if(e!==null){let R=`
|
|
760
676
|
SELECT o.id, o.created_at_epoch
|
|
761
677
|
FROM observations o
|
|
762
678
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
763
|
-
WHERE o.id <= ? ${
|
|
679
|
+
WHERE o.id <= ? ${u.clause}
|
|
764
680
|
ORDER BY o.id DESC
|
|
765
681
|
LIMIT ?
|
|
766
|
-
`,
|
|
682
|
+
`,N=`
|
|
767
683
|
SELECT o.id, o.created_at_epoch
|
|
768
684
|
FROM observations o
|
|
769
685
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
770
|
-
WHERE o.id >= ? ${
|
|
686
|
+
WHERE o.id >= ? ${u.clause}
|
|
771
687
|
ORDER BY o.id ASC
|
|
772
688
|
LIMIT ?
|
|
773
|
-
`;try{let
|
|
689
|
+
`;try{let O=this.db.prepare(R).all(e,...u.params,t+1),L=this.db.prepare(N).all(e,...u.params,r+1);if(O.length===0&&L.length===0)return{observations:[],sessions:[],prompts:[]};c=O.length>0?O[O.length-1].created_at_epoch:s,T=L.length>0?L[L.length-1].created_at_epoch:s}catch(O){return O instanceof Error?_.error("DB","Error getting boundary observations",{project:o},O):_.error("DB","Error getting boundary observations with non-Error",{},new Error(String(O))),{observations:[],sessions:[],prompts:[]}}}else{let R=`
|
|
774
690
|
SELECT o.created_at_epoch
|
|
775
691
|
FROM observations o
|
|
776
692
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
777
|
-
WHERE o.created_at_epoch <= ? ${
|
|
693
|
+
WHERE o.created_at_epoch <= ? ${u.clause}
|
|
778
694
|
ORDER BY o.created_at_epoch DESC
|
|
779
695
|
LIMIT ?
|
|
780
|
-
`,
|
|
696
|
+
`,N=`
|
|
781
697
|
SELECT o.created_at_epoch
|
|
782
698
|
FROM observations o
|
|
783
699
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
784
|
-
WHERE o.created_at_epoch >= ? ${
|
|
700
|
+
WHERE o.created_at_epoch >= ? ${u.clause}
|
|
785
701
|
ORDER BY o.created_at_epoch ASC
|
|
786
702
|
LIMIT ?
|
|
787
|
-
`;try{let
|
|
703
|
+
`;try{let O=this.db.prepare(R).all(s,...u.params,t),L=this.db.prepare(N).all(s,...u.params,r+1);if(O.length===0&&L.length===0)return{observations:[],sessions:[],prompts:[]};c=O.length>0?O[O.length-1].created_at_epoch:s,T=L.length>0?L[L.length-1].created_at_epoch:s}catch(O){return O instanceof Error?_.error("DB","Error getting boundary timestamps",{project:o},O):_.error("DB","Error getting boundary timestamps with non-Error",{},new Error(String(O))),{observations:[],sessions:[],prompts:[]}}}let h=`
|
|
788
704
|
SELECT o.*
|
|
789
705
|
FROM observations o
|
|
790
706
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = o.memory_session_id
|
|
791
|
-
WHERE o.created_at_epoch >= ? AND o.created_at_epoch <= ? ${
|
|
707
|
+
WHERE o.created_at_epoch >= ? AND o.created_at_epoch <= ? ${u.clause}
|
|
792
708
|
ORDER BY o.created_at_epoch ASC
|
|
793
|
-
`,
|
|
709
|
+
`,b=`
|
|
794
710
|
SELECT ss.*
|
|
795
711
|
FROM session_summaries ss
|
|
796
712
|
LEFT JOIN sdk_sessions src ON src.memory_session_id = ss.memory_session_id
|
|
797
713
|
WHERE ss.created_at_epoch >= ? AND ss.created_at_epoch <= ? ${m.clause}
|
|
798
714
|
ORDER BY ss.created_at_epoch ASC
|
|
799
|
-
`,
|
|
800
|
-
SELECT up.*, s.project, s.memory_session_id, COALESCE(NULLIF(s.platform_source, ''), '${
|
|
715
|
+
`,g=`
|
|
716
|
+
SELECT up.*, s.project, s.memory_session_id, COALESCE(NULLIF(s.platform_source, ''), '${p}') as platform_source
|
|
801
717
|
FROM user_prompts up
|
|
802
718
|
JOIN sdk_sessions s ON up.session_db_id = s.id
|
|
803
719
|
WHERE up.created_at_epoch >= ? AND up.created_at_epoch <= ? ${l.clause}
|
|
804
720
|
ORDER BY up.created_at_epoch ASC
|
|
805
|
-
`,S=this.db.prepare(
|
|
806
|
-
SELECT
|
|
807
|
-
p.id,
|
|
808
|
-
p.content_session_id,
|
|
809
|
-
p.prompt_number,
|
|
810
|
-
p.prompt_text,
|
|
811
|
-
s.project,
|
|
812
|
-
p.created_at,
|
|
813
|
-
p.created_at_epoch
|
|
814
|
-
FROM user_prompts p
|
|
815
|
-
LEFT JOIN sdk_sessions s ON p.session_db_id = s.id
|
|
816
|
-
WHERE p.id = ?
|
|
817
|
-
LIMIT 1
|
|
818
|
-
`).get(e)||null}getPromptsByIds(e){if(e.length===0)return[];let t=e.map(()=>"?").join(",");return this.db.prepare(`
|
|
819
|
-
SELECT
|
|
820
|
-
p.id,
|
|
821
|
-
p.content_session_id,
|
|
822
|
-
p.prompt_number,
|
|
823
|
-
p.prompt_text,
|
|
824
|
-
s.project,
|
|
825
|
-
p.created_at,
|
|
826
|
-
p.created_at_epoch
|
|
827
|
-
FROM user_prompts p
|
|
828
|
-
LEFT JOIN sdk_sessions s ON p.session_db_id = s.id
|
|
829
|
-
WHERE p.id IN (${t})
|
|
830
|
-
ORDER BY p.created_at_epoch DESC
|
|
831
|
-
`).all(...e)}getOrCreateManualSession(e){let t=`manual-${e}`,s=`manual-content-${e}`;if(this.db.prepare("SELECT memory_session_id FROM sdk_sessions WHERE memory_session_id = ?").get(t))return t;let o=new Date;return this.db.prepare(`
|
|
721
|
+
`,S=this.db.prepare(h).all(c,T,...u.params),C=this.db.prepare(b).all(c,T,...m.params),y=this.db.prepare(g).all(c,T,...l.params);return{observations:S,sessions:C.map(R=>({id:R.id,memory_session_id:R.memory_session_id,project:R.project,request:R.request,completed:R.completed,next_steps:R.next_steps,created_at:R.created_at,created_at_epoch:R.created_at_epoch})),prompts:y.map(R=>({id:R.id,content_session_id:R.content_session_id,prompt_number:R.prompt_number,prompt_text:R.prompt_text,project:R.project,platform_source:R.platform_source,created_at:R.created_at,created_at_epoch:R.created_at_epoch}))}}getOrCreateManualSession(e){let s=`manual-${e}`,t=`manual-content-${e}`;if(this.db.prepare("SELECT memory_session_id FROM sdk_sessions WHERE memory_session_id = ?").get(s))return s;let o=new Date;return this.db.prepare(`
|
|
832
722
|
INSERT INTO sdk_sessions (memory_session_id, content_session_id, project, platform_source, started_at, started_at_epoch, status)
|
|
833
723
|
VALUES (?, ?, ?, ?, ?, ?, 'active')
|
|
834
|
-
`).run(t,
|
|
835
|
-
WHERE platform_source = ? AND content_session_id = ?`).get(
|
|
724
|
+
`).run(s,t,e,p,o.toISOString(),o.getTime()),_.info("SESSION","Created manual session",{memorySessionId:s,project:e}),s}close(){this.db.close()}importSdkSession(e){let s=A(e.platform_source),t=this.db.prepare(`SELECT id FROM sdk_sessions
|
|
725
|
+
WHERE platform_source = ? AND content_session_id = ?`).get(s,e.content_session_id);return t?{imported:!1,id:t.id}:{imported:!0,id:this.db.prepare(`
|
|
836
726
|
INSERT INTO sdk_sessions (
|
|
837
727
|
content_session_id, memory_session_id, project, platform_source, user_prompt,
|
|
838
728
|
started_at, started_at_epoch, completed_at, completed_at_epoch, status
|
|
839
729
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
840
|
-
`).run(e.content_session_id,e.memory_session_id,e.project,
|
|
730
|
+
`).run(e.content_session_id,e.memory_session_id,e.project,s,e.user_prompt,e.started_at,e.started_at_epoch,e.completed_at,e.completed_at_epoch,e.status).lastInsertRowid}}importSessionSummary(e){let s=this.db.prepare("SELECT id FROM session_summaries WHERE memory_session_id = ?").get(e.memory_session_id);return s?{imported:!1,id:s.id}:{imported:!0,id:this.db.prepare(`
|
|
841
731
|
INSERT INTO session_summaries (
|
|
842
732
|
memory_session_id, project, request, investigated, learned,
|
|
843
733
|
completed, next_steps, files_read, files_edited, notes,
|
|
844
734
|
prompt_number, discovery_tokens, created_at, created_at_epoch
|
|
845
735
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
846
|
-
`).run(e.memory_session_id,e.project,e.request,e.investigated,e.learned,e.completed,e.next_steps,e.files_read,e.files_edited,e.notes,e.prompt_number,e.discovery_tokens||0,e.created_at,e.created_at_epoch).lastInsertRowid}}importObservation(e){let
|
|
736
|
+
`).run(e.memory_session_id,e.project,e.request,e.investigated,e.learned,e.completed,e.next_steps,e.files_read,e.files_edited,e.notes,e.prompt_number,e.discovery_tokens||0,e.created_at,e.created_at_epoch).lastInsertRowid}}importObservation(e){let s=this.db.prepare(`
|
|
847
737
|
SELECT id FROM observations
|
|
848
738
|
WHERE memory_session_id = ? AND title = ? AND created_at_epoch = ?
|
|
849
|
-
`).get(e.memory_session_id,e.title,e.created_at_epoch);return
|
|
739
|
+
`).get(e.memory_session_id,e.title,e.created_at_epoch);return s?{imported:!1,id:s.id}:{imported:!0,id:this.db.prepare(`
|
|
850
740
|
INSERT INTO observations (
|
|
851
741
|
memory_session_id, project, text, type, title, subtitle,
|
|
852
742
|
facts, narrative, concepts, files_read, files_modified,
|
|
853
743
|
prompt_number, discovery_tokens, agent_type, agent_id,
|
|
854
744
|
created_at, created_at_epoch
|
|
855
745
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
856
|
-
`).run(e.memory_session_id,e.project,e.text,e.type,e.title,e.subtitle,e.facts,e.narrative,e.concepts,e.files_read,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).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
|
|
857
|
-
SELECT id, content_session_id, COALESCE(NULLIF(platform_source, ''), '${
|
|
746
|
+
`).run(e.memory_session_id,e.project,e.text,e.type,e.title,e.subtitle,e.facts,e.narrative,e.concepts,e.files_read,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).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 s=null,t=e.platform_source?A(e.platform_source):void 0;if(typeof e.session_db_id=="number"){let a=this.db.prepare(`
|
|
747
|
+
SELECT id, content_session_id, COALESCE(NULLIF(platform_source, ''), '${p}') as platform_source
|
|
858
748
|
FROM sdk_sessions
|
|
859
749
|
WHERE id = ?
|
|
860
750
|
LIMIT 1
|
|
861
|
-
`).get(e.session_db_id);a&&a.content_session_id===e.content_session_id&&(!
|
|
751
|
+
`).get(e.session_db_id);a&&a.content_session_id===e.content_session_id&&(!t||A(a.platform_source)===t)&&(s=a.id)}s===null&&(s=this.resolvePromptSessionDbId(e.content_session_id,void 0,t));let r=this.db.prepare(`
|
|
862
752
|
SELECT id FROM user_prompts
|
|
863
|
-
WHERE ${
|
|
864
|
-
`).get(
|
|
753
|
+
WHERE ${s!==null?"session_db_id = ?":"content_session_id = ?"} AND prompt_number = ?
|
|
754
|
+
`).get(s??e.content_session_id,e.prompt_number);return r?{imported:!1,id:r.id}:{imported:!0,id:this.db.prepare(`
|
|
865
755
|
INSERT INTO user_prompts (
|
|
866
756
|
session_db_id, content_session_id, prompt_number, prompt_text,
|
|
867
757
|
created_at, created_at_epoch
|
|
868
758
|
) VALUES (?, ?, ?, ?, ?, ?)
|
|
869
|
-
`).run(t,e.content_session_id,e.prompt_number,e.prompt_text,e.created_at,e.created_at_epoch).lastInsertRowid}}};var ke=require("os"),Fe=k(require("path"),1),we=require("child_process");var Y=require("fs"),V=k(require("path"),1);var w={isWorktree:!1,worktreeName:null,parentRepoPath:null,parentProjectName:null};function xe(n){let e=V.default.join(n,".git"),t;try{t=(0,Y.statSync)(e)}catch(m){return m instanceof Error&&m.code!=="ENOENT"&&E.warn("GIT","Unexpected error checking .git",{error:m instanceof Error?m.message:String(m)}),w}if(!t.isFile())return w;let s;try{s=(0,Y.readFileSync)(e,"utf-8").trim()}catch(m){return E.warn("GIT","Failed to read .git file",{error:m instanceof Error?m.message:String(m)}),w}let r=s.match(/^gitdir:\s*(.+)$/);if(!r)return w;let i=r[1].match(/^(.+)[/\\]\.git[/\\]worktrees[/\\]([^/\\]+)$/);if(!i)return w;let a=i[1],d=V.default.basename(n),_=V.default.basename(a);return{isWorktree:!0,worktreeName:d,parentRepoPath:a,parentProjectName:_}}function Pe(n){return n==="~"||n.startsWith("~/")?n.replace(/^~/,(0,ke.homedir)()):n}function ds(n){try{return(0,we.execFileSync)("git",["rev-parse","--show-toplevel"],{cwd:n,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch{return null}}function _s(n){if(!n||n.trim()==="")return E.warn("PROJECT_NAME","Empty cwd provided, using fallback",{cwd:n}),"unknown-project";let e=Pe(n),s=ds(e)??e,r=Fe.default.basename(s);if(r===""){if(process.platform==="win32"){let i=n.match(/^([A-Z]):\\/i);if(i){let d=`drive-${i[1].toUpperCase()}`;return E.info("PROJECT_NAME","Drive root detected",{cwd:n,projectName:d}),d}}return E.warn("PROJECT_NAME","Root directory detected, using fallback",{cwd:n}),"unknown-project"}return r}function $e(n){let e=_s(n);if(!n)return{primary:e,parent:null,isWorktree:!1,allProjects:[e]};let t=Pe(n),s=xe(t);if(s.isWorktree&&s.parentProjectName){let r=`${s.parentProjectName}/${e}`;return{primary:r,parent:s.parentProjectName,isWorktree:!0,allProjects:[s.parentProjectName,r]}}return{primary:e,parent:null,isWorktree:!1,allProjects:[e]}}var M=require("fs"),P=require("path"),me=require("os");var Ee={DEFAULT:3e5,HEALTH_CHECK:3e3,API_REQUEST:3e4,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,WORKER_STARTUP_WAIT:1e3,PRE_RESTART_SETTLE_DELAY:2e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function He(n){return process.platform==="win32"?Math.round(n*Ee.WINDOWS_MULTIPLIER):n}var q=class{static DEFAULTS={CLAUDE_MEM_MODEL:"claude-haiku-4-5-20251001",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_WORKER_PORT:String(37700+(process.getuid?.()??77)%100),CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_API_TIMEOUT_MS:String(He(Ee.API_REQUEST)),CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_PROVIDER:"claude",CLAUDE_MEM_CLAUDE_AUTH_METHOD:"subscription",CLAUDE_MEM_GEMINI_API_KEY:"",CLAUDE_MEM_GEMINI_MODEL:"gemini-2.5-flash-lite",CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED:"true",CLAUDE_MEM_OPENROUTER_API_KEY:"",CLAUDE_MEM_OPENROUTER_MODEL:"xiaomi/mimo-v2-flash:free",CLAUDE_MEM_OPENROUTER_BASE_URL:"",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_DATA_DIR:(0,P.join)((0,me.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",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_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_SHOW_TERMINAL_OUTPUT:"true",CLAUDE_MEM_WELCOME_HINT_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,P.join)((0,me.homedir)(),".claude-mem","transcript-watch.json"),CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION:"false",CLAUDE_MEM_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD:"3",CLAUDE_MEM_EXCLUDED_PROJECTS:"",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_TELEGRAM_ENABLED:"true",CLAUDE_MEM_TELEGRAM_BOT_TOKEN:"",CLAUDE_MEM_TELEGRAM_CHAT_ID:"",CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:"security_alert",CLAUDE_MEM_TELEGRAM_TRIGGER_CONCEPTS:"",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:""};static getAllDefaults(){return{...this.DEFAULTS}}static get(e){return process.env[e]??this.DEFAULTS[e]}static getInt(e){let t=this.get(e);return parseInt(t,10)}static getBool(e){let t=this.get(e);return t==="true"||t===!0}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,M.existsSync)(e)){let a=this.getAllDefaults();try{let d=(0,P.dirname)(e);(0,M.existsSync)(d)||(0,M.mkdirSync)(d,{recursive:!0}),(0,M.writeFileSync)(e,JSON.stringify(a,null,2),"utf-8"),console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(d){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,d instanceof Error?d.message:String(d))}return t?this.applyEnvOverrides(a):a}let s=(0,M.readFileSync)(e,"utf-8"),r=JSON.parse(s.replace(/^\uFEFF/,"")),o=r;if(r.env&&typeof r.env=="object"){o=r.env;try{(0,M.writeFileSync)(e,JSON.stringify(o,null,2),"utf-8"),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(a){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,a instanceof Error?a.message:String(a))}}let i={...this.DEFAULTS};for(let a of Object.keys(this.DEFAULTS))o[a]!==void 0&&(i[a]=o[a]);return t?this.applyEnvOverrides(i):i}catch(s){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,s instanceof Error?s.message:String(s));let r=this.getAllDefaults();return t?this.applyEnvOverrides(r):r}}};var $=require("fs"),K=require("path");var D=class n{static instance=null;activeMode=null;modesDir;constructor(){let e=Ie(),t=[...process.env.CLAUDE_MEM_MODES_DIR?[process.env.CLAUDE_MEM_MODES_DIR]:[],(0,K.join)(e,"modes"),(0,K.join)(e,"..","plugin","modes")],s=t.find(r=>(0,$.existsSync)(r));this.modesDir=s||t[0]}static getInstance(){return n.instance||(n.instance=new n),n.instance}parseInheritance(e){let t=e.split("--");if(t.length===1)return{hasParent:!1,parentId:"",overrideId:""};if(t.length>2)throw new Error(`Invalid mode inheritance: ${e}. Only one level of inheritance supported (parent--override)`);return{hasParent:!0,parentId:t[0],overrideId:e}}isPlainObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}deepMerge(e,t){let s={...e};for(let r in t){let o=t[r],i=e[r];this.isPlainObject(o)&&this.isPlainObject(i)?s[r]=this.deepMerge(i,o):s[r]=o}return s}loadModeFile(e){let t=(0,K.join)(this.modesDir,`${e}.json`);if(!(0,$.existsSync)(t))throw new Error(`Mode file not found: ${t}`);let s=(0,$.readFileSync)(t,"utf-8");return JSON.parse(s)}loadMode(e){let t=this.parseInheritance(e);if(!t.hasParent)try{let d=this.loadModeFile(e);return this.activeMode=d,E.debug("SYSTEM",`Loaded mode: ${d.name} (${e})`,void 0,{types:d.observation_types.map(_=>_.id),concepts:d.observation_concepts.map(_=>_.id)}),d}catch(d){if(d instanceof Error?E.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{message:d.message}):E.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{error:String(d)}),e==="code")throw new Error("Critical: code.json mode file missing");return this.loadMode("code")}let{parentId:s,overrideId:r}=t,o;try{o=this.loadMode(s)}catch(d){d instanceof Error?E.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{message:d.message}):E.warn("WORKER",`Parent mode '${s}' not found for ${e}, falling back to 'code'`,{error:String(d)}),o=this.loadMode("code")}let i;try{i=this.loadModeFile(r),E.debug("SYSTEM",`Loaded override file: ${r} for parent ${s}`)}catch(d){return d instanceof Error?E.warn("WORKER",`Override file '${r}' not found, using parent mode '${s}' only`,{message:d.message}):E.warn("WORKER",`Override file '${r}' not found, using parent mode '${s}' only`,{error:String(d)}),this.activeMode=o,o}if(!i)return E.warn("SYSTEM",`Invalid override file: ${r}, using parent mode '${s}' only`),this.activeMode=o,o;let a=this.deepMerge(o,i);return this.activeMode=a,E.debug("SYSTEM",`Loaded mode with inheritance: ${a.name} (${e} = ${s} + ${r})`,void 0,{parent:s,override:r,types:a.observation_types.map(d=>d.id),concepts:a.observation_concepts.map(d=>d.id)}),a}getActiveMode(){if(!this.activeMode)throw new Error("No mode loaded. Call loadMode() first.");return this.activeMode}getObservationTypes(){return this.getActiveMode().observation_types}getTypeIcon(e){return this.getObservationTypes().find(s=>s.id===e)?.emoji||"\u{1F4DD}"}getWorkEmoji(e){return this.getObservationTypes().find(s=>s.id===e)?.work_emoji||"\u{1F4DD}"}};function Xe(){let n=F.settings(),e=q.loadFromFile(n),t=D.getInstance().getActiveMode(),s=new Set(t.observation_types.map(o=>o.id)),r=new Set(t.observation_concepts.map(o=>o.id));return{totalObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_OBSERVATIONS,10),fullObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_FULL_COUNT,10),sessionCount:parseInt(e.CLAUDE_MEM_CONTEXT_SESSION_COUNT,10),showReadTokens:e.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS==="true",showWorkTokens:e.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS==="true",showSavingsAmount:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT==="true",showSavingsPercent:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT==="true",observationTypes:s,observationConcepts:r,fullObservationField:e.CLAUDE_MEM_CONTEXT_FULL_FIELD,showLastSummary:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY==="true",showLastMessage:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE==="true"}}var u={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"},Ge=4,pe=1;function je(n){let e=(n.title?.length||0)+(n.subtitle?.length||0)+(n.narrative?.length||0)+JSON.stringify(n.facts||[]).length;return Math.ceil(e/Ge)}function ce(n){let e=n.length,t=n.reduce((i,a)=>i+je(a),0),s=n.reduce((i,a)=>i+(a.discovery_tokens||0),0),r=s-t,o=s>0?Math.round(r/s*100):0;return{totalObservations:e,totalReadTokens:t,totalDiscoveryTokens:s,savings:r,savingsPercent:o}}function us(n){return D.getInstance().getWorkEmoji(n)}function H(n,e){let t=je(n),s=n.discovery_tokens||0,r=us(n.type),o=s>0?`${r} ${s.toLocaleString()}`:"-";return{readTokens:t,discoveryTokens:s,discoveryDisplay:o,workEmoji:r}}function J(n){return n.showReadTokens||n.showWorkTokens||n.showSavingsAmount||n.showSavingsPercent}var Be=k(require("path"),1),Q=require("fs");function We(n,e,t,s){let r=Array.from(t.observationTypes),o=r.map(()=>"?").join(","),i=Array.from(t.observationConcepts),a=i.map(()=>"?").join(",");return n.db.prepare(`
|
|
870
|
-
SELECT
|
|
871
|
-
o.id,
|
|
872
|
-
o.memory_session_id,
|
|
873
|
-
COALESCE(s.platform_source, 'claude') as platform_source,
|
|
874
|
-
o.type,
|
|
875
|
-
o.title,
|
|
876
|
-
o.subtitle,
|
|
877
|
-
o.narrative,
|
|
878
|
-
o.facts,
|
|
879
|
-
o.concepts,
|
|
880
|
-
o.files_read,
|
|
881
|
-
o.files_modified,
|
|
882
|
-
o.discovery_tokens,
|
|
883
|
-
o.created_at,
|
|
884
|
-
o.created_at_epoch
|
|
885
|
-
FROM observations o
|
|
886
|
-
LEFT JOIN sdk_sessions s ON o.memory_session_id = s.memory_session_id
|
|
887
|
-
WHERE (o.project = ? OR o.merged_into_project = ?)
|
|
888
|
-
AND (? IS NULL OR s.platform_source = ?)
|
|
889
|
-
AND type IN (${o})
|
|
890
|
-
AND EXISTS (
|
|
891
|
-
SELECT 1 FROM json_each(o.concepts)
|
|
892
|
-
WHERE value IN (${a})
|
|
893
|
-
)
|
|
894
|
-
ORDER BY o.created_at_epoch DESC
|
|
895
|
-
LIMIT ?
|
|
896
|
-
`).all(e,e,s??null,s??null,...r,...i,t.totalObservationCount)}function Ve(n,e,t,s){return n.db.prepare(`
|
|
897
|
-
SELECT
|
|
898
|
-
ss.id,
|
|
899
|
-
ss.memory_session_id,
|
|
900
|
-
COALESCE(s.platform_source, 'claude') as platform_source,
|
|
901
|
-
ss.request,
|
|
902
|
-
ss.investigated,
|
|
903
|
-
ss.learned,
|
|
904
|
-
ss.completed,
|
|
905
|
-
ss.next_steps,
|
|
906
|
-
ss.created_at,
|
|
907
|
-
ss.created_at_epoch
|
|
908
|
-
FROM session_summaries ss
|
|
909
|
-
LEFT JOIN sdk_sessions s ON ss.memory_session_id = s.memory_session_id
|
|
910
|
-
WHERE (ss.project = ? OR ss.merged_into_project = ?)
|
|
911
|
-
AND (? IS NULL OR s.platform_source = ?)
|
|
912
|
-
ORDER BY ss.created_at_epoch DESC
|
|
913
|
-
LIMIT ?
|
|
914
|
-
`).all(e,e,s??null,s??null,t.sessionCount+pe)}function Ye(n,e,t,s){let r=Array.from(t.observationTypes),o=r.map(()=>"?").join(","),i=Array.from(t.observationConcepts),a=i.map(()=>"?").join(","),d=e.map(()=>"?").join(",");return n.db.prepare(`
|
|
759
|
+
`).run(s,e.content_session_id,e.prompt_number,e.prompt_text,e.created_at,e.created_at_epoch).lastInsertRowid}}};var ye=require("os"),Ue=x(require("path"),1),xe=require("child_process");var V=require("fs"),W=x(require("path"),1);var w={isWorktree:!1,worktreeName:null,parentRepoPath:null,parentProjectName:null};function ve(n){let e=W.default.join(n,".git"),s;try{s=(0,V.statSync)(e)}catch(m){return m instanceof Error&&m.code!=="ENOENT"&&_.warn("GIT","Unexpected error checking .git",{error:m instanceof Error?m.message:String(m)}),w}if(!s.isFile())return w;let t;try{t=(0,V.readFileSync)(e,"utf-8").trim()}catch(m){return _.warn("GIT","Failed to read .git file",{error:m instanceof Error?m.message:String(m)}),w}let r=t.match(/^gitdir:\s*(.+)$/);if(!r)return w;let i=r[1].match(/^(.+)[/\\]\.git[/\\]worktrees[/\\]([^/\\]+)$/);if(!i)return w;let a=i[1],d=W.default.basename(n),u=W.default.basename(a);return{isWorktree:!0,worktreeName:d,parentRepoPath:a,parentProjectName:u}}function ke(n){return n==="~"||n.startsWith("~/")?n.replace(/^~/,(0,ye.homedir)()):n}function Zs(n){try{return(0,xe.execFileSync)("git",["rev-parse","--show-toplevel"],{cwd:n,encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()||null}catch(e){let s=e instanceof Error?e:new Error(String(e));return _.debug("PROJECT_NAME","git rev-parse failed, falling back to basename",{dir:n},s),null}}function et(n){if(!n||n.trim()==="")return _.warn("PROJECT_NAME","Empty cwd provided, using fallback",{cwd:n}),"unknown-project";let e=ke(n),t=Zs(e)??e,r=Ue.default.basename(t);if(r===""){if(process.platform==="win32"){let i=n.match(/^([A-Z]):\\/i);if(i){let d=`drive-${i[1].toUpperCase()}`;return _.info("PROJECT_NAME","Drive root detected",{cwd:n,projectName:d}),d}}return _.warn("PROJECT_NAME","Root directory detected, using fallback",{cwd:n}),"unknown-project"}return r}function we(n){let e=et(n);if(!n)return{primary:e,parent:null,isWorktree:!1,allProjects:[e]};let s=ke(n),t=ve(s);if(t.isWorktree&&t.parentProjectName){let r=`${t.parentProjectName}/${e}`;return{primary:r,parent:t.parentProjectName,isWorktree:!0,allProjects:[t.parentProjectName,r]}}return{primary:e,parent:null,isWorktree:!1,allProjects:[e]}}var M=require("fs"),F=require("path"),Ee=require("os");var _e={HEALTH_CHECK:3e3,API_REQUEST:3e4,HOOK_READINESS_WAIT:1e4,POST_SPAWN_WAIT:15e3,READINESS_WAIT:3e4,PORT_IN_USE_WAIT:3e3,POWERSHELL_COMMAND:1e4,WINDOWS_MULTIPLIER:1.5};function Fe(n){return process.platform==="win32"?Math.round(n*_e.WINDOWS_MULTIPLIER):n}var K=class{static DEFAULTS={CLAUDE_MEM_MODEL:"claude-haiku-4-5-20251001",CLAUDE_MEM_CONTEXT_OBSERVATIONS:"50",CLAUDE_MEM_WORKER_PORT:String(37700+(process.getuid?.()??77)%100),CLAUDE_MEM_WORKER_HOST:"127.0.0.1",CLAUDE_MEM_API_TIMEOUT_MS:String(Fe(_e.API_REQUEST)),CLAUDE_MEM_SKIP_TOOLS:"ListMcpResourcesTool,SlashCommand,Skill,TodoWrite,AskUserQuestion",CLAUDE_MEM_PROVIDER:"claude",CLAUDE_MEM_CLAUDE_AUTH_METHOD:"subscription",CLAUDE_MEM_GEMINI_API_KEY:"",CLAUDE_MEM_GEMINI_MODEL:"gemini-2.5-flash-lite",CLAUDE_MEM_GEMINI_RATE_LIMITING_ENABLED:"true",CLAUDE_MEM_OPENROUTER_API_KEY:"",CLAUDE_MEM_OPENROUTER_MODEL:"xiaomi/mimo-v2-flash:free",CLAUDE_MEM_OPENROUTER_BASE_URL:"",CLAUDE_MEM_OPENROUTER_SITE_URL:"",CLAUDE_MEM_OPENROUTER_APP_NAME:"claude-mem",CLAUDE_MEM_DATA_DIR:(0,F.join)((0,Ee.homedir)(),".claude-mem"),CLAUDE_MEM_LOG_LEVEL:"INFO",CLAUDE_MEM_PYTHON_VERSION:"3.13",CLAUDE_CODE_PATH:"",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_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_SHOW_TERMINAL_OUTPUT:"true",CLAUDE_MEM_WELCOME_HINT_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,F.join)((0,Ee.homedir)(),".claude-mem","transcript-watch.json"),CLAUDE_MEM_CODEX_TRANSCRIPT_INGESTION:"false",CLAUDE_MEM_MAX_CONCURRENT_AGENTS:"2",CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD:"3",CLAUDE_MEM_EXCLUDED_PROJECTS:"",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_TELEGRAM_ENABLED:"true",CLAUDE_MEM_TELEGRAM_BOT_TOKEN:"",CLAUDE_MEM_TELEGRAM_CHAT_ID:"",CLAUDE_MEM_TELEGRAM_TRIGGER_TYPES:"security_alert",CLAUDE_MEM_TELEGRAM_TRIGGER_CONCEPTS:"",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:""};static getAllDefaults(){return{...this.DEFAULTS}}static get(e){return process.env[e]??this.DEFAULTS[e]}static getInt(e){let s=this.get(e);return parseInt(s,10)}static applyEnvOverrides(e){let s={...e};for(let t of Object.keys(this.DEFAULTS))process.env[t]!==void 0&&(s[t]=process.env[t]);return s}static loadFromFile(e,s=!0){try{if(!(0,M.existsSync)(e)){let a=this.getAllDefaults();try{let d=(0,F.dirname)(e);(0,M.existsSync)(d)||(0,M.mkdirSync)(d,{recursive:!0}),(0,M.writeFileSync)(e,JSON.stringify(a,null,2),"utf-8"),console.warn("[SETTINGS] Created settings file with defaults:",e)}catch(d){console.warn("[SETTINGS] Failed to create settings file, using in-memory defaults:",e,d instanceof Error?d.message:String(d))}return s?this.applyEnvOverrides(a):a}let t=(0,M.readFileSync)(e,"utf-8"),r=JSON.parse(t.replace(/^\uFEFF/,"")),o=r;if(r.env&&typeof r.env=="object"){o=r.env;try{(0,M.writeFileSync)(e,JSON.stringify(o,null,2),"utf-8"),console.warn("[SETTINGS] Migrated settings file from nested to flat schema:",e)}catch(a){console.warn("[SETTINGS] Failed to auto-migrate settings file:",e,a instanceof Error?a.message:String(a))}}let i={...this.DEFAULTS};for(let a of Object.keys(this.DEFAULTS))o[a]!==void 0&&(i[a]=o[a]);return s?this.applyEnvOverrides(i):i}catch(t){console.warn("[SETTINGS] Failed to load settings, using defaults:",e,t instanceof Error?t.message:String(t));let r=this.getAllDefaults();return s?this.applyEnvOverrides(r):r}}};var P=require("fs"),Y=require("path");var D=class n{static instance=null;activeMode=null;modesDir;constructor(){let e=Re(),s=[...process.env.CLAUDE_MEM_MODES_DIR?[process.env.CLAUDE_MEM_MODES_DIR]:[],(0,Y.join)(e,"modes"),(0,Y.join)(e,"..","plugin","modes")],t=s.find(r=>(0,P.existsSync)(r));this.modesDir=t||s[0]}static getInstance(){return n.instance||(n.instance=new n),n.instance}parseInheritance(e){let s=e.split("--");if(s.length===1)return{hasParent:!1,parentId:"",overrideId:""};if(s.length>2)throw new Error(`Invalid mode inheritance: ${e}. Only one level of inheritance supported (parent--override)`);return{hasParent:!0,parentId:s[0],overrideId:e}}isPlainObject(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}deepMerge(e,s){let t={...e};for(let r in s){let o=s[r],i=e[r];this.isPlainObject(o)&&this.isPlainObject(i)?t[r]=this.deepMerge(i,o):t[r]=o}return t}loadModeFile(e){let s=(0,Y.join)(this.modesDir,`${e}.json`);if(!(0,P.existsSync)(s))throw new Error(`Mode file not found: ${s}`);let t=(0,P.readFileSync)(s,"utf-8");return JSON.parse(t)}loadMode(e){let s=this.parseInheritance(e);if(!s.hasParent)try{let d=this.loadModeFile(e);return this.activeMode=d,_.debug("SYSTEM",`Loaded mode: ${d.name} (${e})`,void 0,{types:d.observation_types.map(u=>u.id),concepts:d.observation_concepts.map(u=>u.id)}),d}catch(d){if(d instanceof Error?_.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{message:d.message}):_.warn("WORKER",`Mode file not found: ${e}, falling back to 'code'`,{error:String(d)}),e==="code")throw new Error("Critical: code.json mode file missing");return this.loadMode("code")}let{parentId:t,overrideId:r}=s,o;try{o=this.loadMode(t)}catch(d){d instanceof Error?_.warn("WORKER",`Parent mode '${t}' not found for ${e}, falling back to 'code'`,{message:d.message}):_.warn("WORKER",`Parent mode '${t}' not found for ${e}, falling back to 'code'`,{error:String(d)}),o=this.loadMode("code")}let i;try{i=this.loadModeFile(r),_.debug("SYSTEM",`Loaded override file: ${r} for parent ${t}`)}catch(d){return d instanceof Error?_.warn("WORKER",`Override file '${r}' not found, using parent mode '${t}' only`,{message:d.message}):_.warn("WORKER",`Override file '${r}' not found, using parent mode '${t}' only`,{error:String(d)}),this.activeMode=o,o}if(!i)return _.warn("SYSTEM",`Invalid override file: ${r}, using parent mode '${t}' only`),this.activeMode=o,o;let a=this.deepMerge(o,i);return this.activeMode=a,_.debug("SYSTEM",`Loaded mode with inheritance: ${a.name} (${e} = ${t} + ${r})`,void 0,{parent:t,override:r,types:a.observation_types.map(d=>d.id),concepts:a.observation_concepts.map(d=>d.id)}),a}getActiveMode(){if(!this.activeMode)throw new Error("No mode loaded. Call loadMode() first.");return this.activeMode}getObservationTypes(){return this.getActiveMode().observation_types}getTypeIcon(e){return this.getObservationTypes().find(t=>t.id===e)?.emoji||"\u{1F4DD}"}getWorkEmoji(e){return this.getObservationTypes().find(t=>t.id===e)?.work_emoji||"\u{1F4DD}"}};function Pe(){let n=k.settings(),e=K.loadFromFile(n),s=D.getInstance().getActiveMode(),t=new Set(s.observation_types.map(o=>o.id)),r=new Set(s.observation_concepts.map(o=>o.id));return{totalObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_OBSERVATIONS,10),fullObservationCount:parseInt(e.CLAUDE_MEM_CONTEXT_FULL_COUNT,10),sessionCount:parseInt(e.CLAUDE_MEM_CONTEXT_SESSION_COUNT,10),showReadTokens:e.CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS==="true",showWorkTokens:e.CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS==="true",showSavingsAmount:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT==="true",showSavingsPercent:e.CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT==="true",observationTypes:t,observationConcepts:r,fullObservationField:e.CLAUDE_MEM_CONTEXT_FULL_FIELD,showLastSummary:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY==="true",showLastMessage:e.CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE==="true"}}var E={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",gray:"\x1B[90m",red:"\x1B[31m"},$e=4,Xe=1;function He(n){let e=(n.title?.length||0)+(n.subtitle?.length||0)+(n.narrative?.length||0)+JSON.stringify(n.facts||[]).length;return Math.ceil(e/$e)}function ue(n){let e=n.length,s=n.reduce((i,a)=>i+He(a),0),t=n.reduce((i,a)=>i+(a.discovery_tokens||0),0),r=t-s,o=t>0?Math.round(r/t*100):0;return{totalObservations:e,totalReadTokens:s,totalDiscoveryTokens:t,savings:r,savingsPercent:o}}function st(n){return D.getInstance().getWorkEmoji(n)}function $(n,e){let s=He(n),t=n.discovery_tokens||0,r=st(n.type),o=t>0?`${r} ${t.toLocaleString()}`:"-";return{readTokens:s,discoveryTokens:t,discoveryDisplay:o,workEmoji:r}}function q(n){return n.showReadTokens||n.showWorkTokens||n.showSavingsAmount||n.showSavingsPercent}var Ge=x(require("path"),1),J=require("fs");function Be(n,e,s,t){let r=Array.from(s.observationTypes),o=r.map(()=>"?").join(","),i=Array.from(s.observationConcepts),a=i.map(()=>"?").join(","),d=e.map(()=>"?").join(",");return n.db.prepare(`
|
|
915
760
|
SELECT
|
|
916
761
|
o.id,
|
|
917
762
|
o.memory_session_id,
|
|
@@ -940,7 +785,7 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
940
785
|
)
|
|
941
786
|
ORDER BY o.created_at_epoch DESC
|
|
942
787
|
LIMIT ?
|
|
943
|
-
`).all(...e,...e,
|
|
788
|
+
`).all(...e,...e,t??null,t??null,...r,...i,s.totalObservationCount)}function je(n,e,s,t){let r=e.map(()=>"?").join(",");return n.db.prepare(`
|
|
944
789
|
SELECT
|
|
945
790
|
ss.id,
|
|
946
791
|
ss.memory_session_id,
|
|
@@ -960,14 +805,14 @@ ${o.stack}`:` ${o.message}`;else if(this.getLevel()===0&&typeof o=="object")try{
|
|
|
960
805
|
AND (? IS NULL OR s.platform_source = ?)
|
|
961
806
|
ORDER BY ss.created_at_epoch DESC
|
|
962
807
|
LIMIT ?
|
|
963
|
-
`).all(...e,...e,
|
|
964
|
-
`).filter(r=>r.trim());return{assistantMessage:
|
|
808
|
+
`).all(...e,...e,t??null,t??null,s.sessionCount+Xe)}function tt(n){return n.replace(/[/.]/g,"-")}function rt(n){if(!n.includes('"type":"assistant"'))return null;let e=JSON.parse(n);if(e.type==="assistant"&&e.message?.content&&Array.isArray(e.message.content)){let s="";for(let t of e.message.content)t.type==="text"&&(s+=t.text);if(s=s.replace(De,"").trim(),s)return s}return null}function nt(n){for(let e=n.length-1;e>=0;e--)try{let s=rt(n[e]);if(s)return s}catch(s){s instanceof Error?_.debug("WORKER","Skipping malformed transcript line",{lineIndex:e},s):_.debug("WORKER","Skipping malformed transcript line",{lineIndex:e,error:String(s)});continue}return""}function ot(n){try{if(!(0,J.existsSync)(n))return{assistantMessage:""};let e=(0,J.readFileSync)(n,"utf-8").trim();if(!e)return{assistantMessage:""};let s=e.split(`
|
|
809
|
+
`).filter(r=>r.trim());return{assistantMessage:nt(s)}}catch(e){return e instanceof Error?_.failure("WORKER","Failed to extract prior messages from transcript",{transcriptPath:n},e):_.warn("WORKER","Failed to extract prior messages from transcript",{transcriptPath:n,error:String(e)}),{assistantMessage:""}}}function We(n,e,s,t){if(!e.showLastMessage||n.length===0)return{assistantMessage:""};let r=n.find(d=>d.memory_session_id!==s);if(!r)return{assistantMessage:""};let o=r.memory_session_id,i=tt(t),a=Ge.default.join(se,"projects",i,`${o}.jsonl`);return ot(a)}function Ve(n,e){let s=e[0]?.id;return n.map((t,r)=>{let o=r===0?null:e[r+1];return{...t,displayEpoch:o?o.created_at_epoch:t.created_at_epoch,displayTime:o?o.created_at:t.created_at,shouldShowLink:t.id!==s}})}function Ke(n,e){let s=[...n.map(t=>({type:"observation",data:t})),...e.map(t=>({type:"summary",data:t}))];return s.sort((t,r)=>{let o=t.type==="observation"?t.data.created_at_epoch:t.data.displayEpoch,i=r.type==="observation"?r.data.created_at_epoch:r.data.displayEpoch;return o-i}),s}function Ye(n,e){return new Set(n.slice(0,e).map(s=>s.id))}function qe(){let n=new Date,e=n.toLocaleDateString("en-CA"),s=n.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0}).toLowerCase().replace(" ",""),t=n.toLocaleTimeString("en-US",{timeZoneName:"short"}).split(" ").pop();return`${e} ${s} ${t}`}function Je(n){return[`# [${n}] recent context, ${qe()}`,""]}function Qe(){return[`Legend: \u{1F3AF}session ${D.getInstance().getActiveMode().observation_types.map(s=>`${s.emoji}${s.id}`).join(" ")}`,"Format: ID TIME TYPE TITLE","Fetch details: get_observations([IDs]) | Search: mem-search skill",""]}function ze(n,e){let s=[],t=[`${n.totalObservations} obs (${n.totalReadTokens.toLocaleString()}t read)`,`${n.totalDiscoveryTokens.toLocaleString()}t work`];return n.totalDiscoveryTokens>0&&(e.showSavingsAmount||e.showSavingsPercent)&&(e.showSavingsPercent?t.push(`${n.savingsPercent}% savings`):e.showSavingsAmount&&t.push(`${n.savings.toLocaleString()}t saved`)),s.push(`Stats: ${t.join(" | ")}`),s.push(""),s}function Ze(n){return[`### ${n}`]}function es(n){return n.toLowerCase().replace(" am","a").replace(" pm","p")}function ss(n,e,s){let t=n.title||"Untitled",r=D.getInstance().getTypeIcon(n.type),o=e?es(e):'"';return`${n.id} ${o} ${r} ${t}`}function ts(n,e,s,t){let r=[],o=n.title||"Untitled",i=D.getInstance().getTypeIcon(n.type),a=e?es(e):'"',{readTokens:d,discoveryDisplay:u}=$(n,t);r.push(`**${n.id}** ${a} ${i} **${o}**`),s&&r.push(s);let m=[];return t.showReadTokens&&m.push(`~${d}t`),t.showWorkTokens&&m.push(u),m.length>0&&r.push(m.join(" ")),r.push(""),r}function rs(n,e){return[`S${n.id} ${n.request||"Session started"} (${e})`]}function X(n,e){return e?[`**${n}**: ${e}`,""]:[]}function ns(n){return n.assistantMessage?["","---","","**Previously**","",`A: ${n.assistantMessage}`,""]:[]}function os(n,e){return["",`Access ${Math.round(n/1e3)}k tokens of past work via get_observations([IDs]) or mem-search skill.`]}function is(n){return`# [${n}] recent context, ${qe()}
|
|
965
810
|
|
|
966
|
-
No previous sessions found.`}function
|
|
967
|
-
${
|
|
968
|
-
${
|
|
811
|
+
No previous sessions found.`}function as(){let n=new Date,e=n.toLocaleDateString("en-CA"),s=n.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0}).toLowerCase().replace(" ",""),t=n.toLocaleTimeString("en-US",{timeZoneName:"short"}).split(" ").pop();return`${e} ${s} ${t}`}function ds(n){return["",`${E.bright}${E.cyan}[${n}] recent context, ${as()}${E.reset}`,`${E.gray}${"\u2500".repeat(60)}${E.reset}`,""]}function _s(){let e=D.getInstance().getActiveMode().observation_types.map(s=>`${s.emoji} ${s.id}`).join(" | ");return[`${E.dim}Legend: session-request | ${e}${E.reset}`,""]}function Es(){return[`${E.bright}Column Key${E.reset}`,`${E.dim} Read: Tokens to read this observation (cost to learn it now)${E.reset}`,`${E.dim} Work: Tokens spent on work that produced this record ( research, building, deciding)${E.reset}`,""]}function us(){return[`${E.dim}Context Index: This semantic index (titles, types, files, tokens) is usually sufficient to understand past work.${E.reset}`,"",`${E.dim}When you need implementation details, rationale, or debugging context:${E.reset}`,`${E.dim} - Fetch by ID: get_observations([IDs]) for observations visible in this index${E.reset}`,`${E.dim} - Search history: Use the mem-search skill for past decisions, bugs, and deeper research${E.reset}`,`${E.dim} - Trust this index over re-reading code for past decisions and learnings${E.reset}`,""]}function ms(n,e){let s=[];if(s.push(`${E.bright}${E.cyan}Context Economics${E.reset}`),s.push(`${E.dim} Loading: ${n.totalObservations} observations (${n.totalReadTokens.toLocaleString()} tokens to read)${E.reset}`),s.push(`${E.dim} Work investment: ${n.totalDiscoveryTokens.toLocaleString()} tokens spent on research, building, and decisions${E.reset}`),n.totalDiscoveryTokens>0&&(e.showSavingsAmount||e.showSavingsPercent)){let t=" Your savings: ";e.showSavingsAmount&&e.showSavingsPercent?t+=`${n.savings.toLocaleString()} tokens (${n.savingsPercent}% reduction from reuse)`:e.showSavingsAmount?t+=`${n.savings.toLocaleString()} tokens`:t+=`${n.savingsPercent}% reduction from reuse`,s.push(`${E.green}${t}${E.reset}`)}return s.push(""),s}function ps(n){return[`${E.bright}${E.cyan}${n}${E.reset}`,""]}function cs(n){return[`${E.dim}${n}${E.reset}`]}function ls(n,e,s,t){let r=n.title||"Untitled",o=D.getInstance().getTypeIcon(n.type),{readTokens:i,discoveryTokens:a,workEmoji:d}=$(n,t),u=s?`${E.dim}${e}${E.reset}`:" ".repeat(e.length),m=t.showReadTokens&&i>0?`${E.dim}(~${i}t)${E.reset}`:"",l=t.showWorkTokens&&a>0?`${E.dim}(${d} ${a.toLocaleString()}t)${E.reset}`:"";return` ${E.dim}#${n.id}${E.reset} ${u} ${o} ${r} ${m} ${l}`}function Ts(n,e,s,t,r){let o=[],i=n.title||"Untitled",a=D.getInstance().getTypeIcon(n.type),{readTokens:d,discoveryTokens:u,workEmoji:m}=$(n,r),l=s?`${E.dim}${e}${E.reset}`:" ".repeat(e.length),c=r.showReadTokens&&d>0?`${E.dim}(~${d}t)${E.reset}`:"",T=r.showWorkTokens&&u>0?`${E.dim}(${m} ${u.toLocaleString()}t)${E.reset}`:"";return o.push(` ${E.dim}#${n.id}${E.reset} ${l} ${a} ${E.bright}${i}${E.reset}`),t&&o.push(` ${E.dim}${t}${E.reset}`),(c||T)&&o.push(` ${c} ${T}`),o.push(""),o}function gs(n,e){let s=`${n.request||"Session started"} (${e})`;return[`${E.yellow}#S${n.id}${E.reset} ${s}`,""]}function H(n,e,s){return e?[`${s}${n}:${E.reset} ${e}`,""]:[]}function Ss(n){return n.assistantMessage?["","---","",`${E.bright}${E.magenta}Previously${E.reset}`,"",`${E.dim}A: ${n.assistantMessage}${E.reset}`,""]:[]}function fs(n,e){let s=Math.round(n/1e3);return["",`${E.dim}Access ${s}k tokens of past research & decisions for just ${e.toLocaleString()}t. Use the claude-mem skill to access memories by ID.${E.reset}`]}function Rs(n){return`
|
|
812
|
+
${E.bright}${E.cyan}[${n}] recent context, ${as()}${E.reset}
|
|
813
|
+
${E.gray}${"\u2500".repeat(60)}${E.reset}
|
|
969
814
|
|
|
970
|
-
${
|
|
971
|
-
`}function
|
|
972
|
-
`):null}function
|
|
973
|
-
`).trimEnd()}var
|
|
815
|
+
${E.dim}No previous sessions found for this project yet.${E.reset}
|
|
816
|
+
`}function Os(n,e,s,t){let r=[];return t?r.push(...ds(n)):r.push(...Je(n)),t?r.push(..._s()):r.push(...Qe()),t&&(r.push(...Es()),r.push(...us())),q(s)&&(t?r.push(...ms(e,s)):r.push(...ze(e,s))),r}var me=x(require("path"),1);function Z(n){if(!n)return[];try{let e=JSON.parse(n);return Array.isArray(e)?e:[]}catch(e){return _.debug("PARSER","Failed to parse JSON array, using empty fallback",{preview:n?.substring(0,50)},e instanceof Error?e:new Error(String(e))),[]}}function pe(n){return new Date(n).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",hour12:!0})}function ce(n){return new Date(n).toLocaleString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0})}function hs(n){return new Date(n).toLocaleString("en-US",{month:"short",day:"numeric",year:"numeric"})}function bs(n,e){return me.default.isAbsolute(n)?me.default.relative(e,n):n}function Ns(n,e,s){let t=Z(n);if(t.length>0)return bs(t[0],e);if(s){let r=Z(s);if(r.length>0)return bs(r[0],e)}return"General"}function it(n){let e=new Map;for(let t of n){let r=t.type==="observation"?t.data.created_at:t.data.displayTime,o=hs(r);e.has(o)||e.set(o,[]),e.get(o).push(t)}let s=Array.from(e.entries()).sort((t,r)=>{let o=new Date(t[0]).getTime(),i=new Date(r[0]).getTime();return o-i});return new Map(s)}function Is(n,e){return e.fullObservationField==="narrative"?n.narrative:n.facts?Z(n.facts).join(`
|
|
817
|
+
`):null}function at(n,e,s,t){let r=[];r.push(...Ze(n));let o="";for(let i of e)if(i.type==="summary"){let a=i.data,d=pe(a.displayTime);r.push(...rs(a,d))}else{let a=i.data,d=ce(a.created_at),m=d!==o?d:"";if(o=d,s.has(a.id)){let c=Is(a,t);r.push(...ts(a,m,c,t))}else r.push(ss(a,m,t))}return r}function dt(n,e,s,t,r){let o=[];o.push(...ps(n));let i=null,a="";for(let d of e)if(d.type==="summary"){i=null,a="";let u=d.data,m=pe(u.displayTime);o.push(...gs(u,m))}else{let u=d.data,m=Ns(u.files_modified,r,u.files_read),l=ce(u.created_at),c=l!==a;a=l;let T=s.has(u.id);if(m!==i&&(o.push(...cs(m)),i=m),T){let h=Is(u,t);o.push(...Ts(u,l,c,h,t))}else o.push(ls(u,l,c,t))}return o.push(""),o}function _t(n,e,s,t,r,o){return o?dt(n,e,s,t,r):at(n,e,s,t)}function As(n,e,s,t,r){let o=[],i=it(n);for(let[a,d]of i)o.push(..._t(a,d,e,s,t,r));return o}function Cs(n,e,s){return!(!n.showLastSummary||!e||!!!(e.investigated||e.learned||e.completed||e.next_steps)||s&&e.created_at_epoch<=s.created_at_epoch)}function Ls(n,e){let s=[];return e?(s.push(...H("Investigated",n.investigated,E.blue)),s.push(...H("Learned",n.learned,E.yellow)),s.push(...H("Completed",n.completed,E.green)),s.push(...H("Next Steps",n.next_steps,E.magenta))):(s.push(...X("Investigated",n.investigated)),s.push(...X("Learned",n.learned)),s.push(...X("Completed",n.completed)),s.push(...X("Next Steps",n.next_steps))),s}function Ds(n,e){return e?Ss(n):ns(n)}function Ms(n,e,s){return!q(e)||n.totalDiscoveryTokens<=0||n.savings<=0?[]:s?fs(n.totalDiscoveryTokens,n.totalReadTokens):os(n.totalDiscoveryTokens,n.totalReadTokens)}var Et=vs.default.join((0,ys.homedir)(),".claude","plugins","marketplaces","thedotmack","plugin",".install-version");function ut(){try{return new j}catch(n){if(n instanceof Error&&n.code==="ERR_DLOPEN_FAILED"){try{(0,Us.unlinkSync)(Et)}catch(e){e instanceof Error?_.debug("WORKER","Marker file cleanup failed (may not exist)",{},e):_.debug("WORKER","Marker file cleanup failed (may not exist)",{error:String(e)})}return _.error("WORKER","Native module rebuild needed - restart Claude Code to auto-fix"),null}throw n}}function mt(n,e){return e?Rs(n):is(n)}function pt(n,e,s,t,r,o,i){let a=[],d=ue(e);a.push(...Os(n,d,t,i));let u=s.slice(0,t.sessionCount),m=Ve(u,s),l=Ke(e,m),c=Ye(e,t.fullObservationCount);a.push(...As(l,c,t,r,i));let T=s[0],h=e[0];Cs(t,T,h)&&a.push(...Ls(T,i));let b=We(e,t,o,r);return a.push(...Ds(b,i)),a.push(...Ms(d,t,i)),a.join(`
|
|
818
|
+
`).trimEnd()}var ct=new Set(["bugfix","discovery","decision","refactor"]);function lt(n,e,s){let t=ue(n),r={bugfix:0,discovery:0,decision:0,refactor:0,other:0},o=new Set,i=Number.POSITIVE_INFINITY;for(let d of n){let u=ct.has(d.type)?d.type:"other";r[u]++,d.memory_session_id&&o.add(d.memory_session_id),d.created_at_epoch&&d.created_at_epoch<i&&(i=d.created_at_epoch)}let a=Number.isFinite(i)?Math.max(0,Math.floor((Date.now()-i)/864e5)):0;return{observation_count:n.length,session_count:o.size,timeline_depth_days:a,has_session_summary:e.length>0,obs_type_bugfix:r.bugfix,obs_type_discovery:r.discovery,obs_type_decision:r.decision,obs_type_refactor:r.refactor,obs_type_other:r.other,tokens_injected:t.totalReadTokens,tokens_saved_vs_naive:t.savings,search_strategy:s?"full":"timeline"}}async function le(n,e=!1){let s=Pe(),t=n?.cwd??process.cwd(),r=we(t),o=n?.projects?.length?n.projects:r.allProjects,i=o[o.length-1]??r.primary;n?.full&&(s.totalObservationCount=999999,s.sessionCount=999999);let a=ut();if(!a)return{text:"",stats:null};try{let d=n?.platformSource?A(n.platformSource):void 0,u=o.length>1?o:[i],m=Be(a,u,s,d),l=je(a,u,s,d);return m.length===0&&l.length===0?{text:mt(i,e),stats:null}:{text:pt(i,m,l,s,t,n?.session_id,e),stats:lt(m,l,!!n?.full)}}finally{a.close()}}async function xs(n,e=!1){return(await le(n,e)).text}0&&(module.exports={generateContext,generateContextWithStats});
|