feat(SessionStore): auto-create session records if missing

- Added functionality to automatically create a session record in the database if it does not exist when storing observations or session summaries.
- Updated `storeObservation` and `storeSummary` methods to include checks for existing session records and insert new records as needed.
- Added logging for auto-created session records for better traceability.
This commit is contained in:
Alex Newman
2025-10-21 22:13:13 -04:00
parent 726f167ebf
commit f7f62ef3f3
10 changed files with 254 additions and 99 deletions
+23 -11
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import q from"path";import j from"better-sqlite3";import{join as m,dirname as M,basename as V}from"path";import{homedir as A}from"os";import{existsSync as Z,mkdirSync as X}from"fs";import{fileURLToPath as F}from"url";function P(){return typeof __dirname<"u"?__dirname:M(F(import.meta.url))}var G=P(),l=process.env.CLAUDE_MEM_DATA_DIR||m(A(),".claude-mem"),S=process.env.CLAUDE_CONFIG_DIR||m(A(),".claude"),se=m(l,"archives"),te=m(l,"logs"),re=m(l,"trash"),ne=m(l,"backups"),ie=m(l,"settings.json"),v=m(l,"claude-mem.db"),oe=m(S,"settings.json"),ae=m(S,"commands"),pe=m(S,"CLAUDE.md");function D(d){X(d,{recursive:!0})}function x(){return m(G,"..","..")}var b=(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))(b||{}),N=class{level;useColor;constructor(){let e=process.env.CLAUDE_MEM_LOG_LEVEL?.toUpperCase()||"INFO";this.level=b[e]??1,this.useColor=process.stdout.isTTY??!1}correlationId(e,t){return`obs-${e}-${t}`}sessionId(e){return`session-${e}`}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.level===0?`${e.message}
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?JSON.stringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;try{let r=typeof t=="string"?JSON.parse(t):t;if(e==="Bash"&&r.command){let n=r.command.length>50?r.command.substring(0,50)+"...":r.command;return`${e}(${n})`}if(e==="Read"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}if(e==="Edit"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}if(e==="Write"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}return e}catch{return e}}log(e,t,r,n,o){if(e<this.level)return;let p=new Date().toISOString().replace("T"," ").substring(0,23),s=b[e].padEnd(5),c=t.padEnd(6),_="";n?.correlationId?_=`[${n.correlationId}] `:n?.sessionId&&(_=`[session-${n.sessionId}] `);let a="";o!=null&&(this.level===0&&typeof o=="object"?a=`
`+JSON.stringify(o,null,2):a=" "+this.formatData(o));let E="";if(n){let{sessionId:T,sdkSessionId:f,correlationId:$,...h}=n;Object.keys(h).length>0&&(E=` {${Object.entries(h).map(([U,w])=>`${U}=${w}`).join(", ")}}`)}let u=`[${p}] [${s}] [${c}] ${_}${r}${E}${a}`;e===3?console.error(u):console.log(u)}debug(e,t,r,n){this.log(0,e,t,r,n)}info(e,t,r,n){this.log(1,e,t,r,n)}warn(e,t,r,n){this.log(2,e,t,r,n)}error(e,t,r,n){this.log(3,e,t,r,n)}dataIn(e,t,r,n){this.info(e,`\u2192 ${t}`,r,n)}dataOut(e,t,r,n){this.info(e,`\u2190 ${t}`,r,n)}success(e,t,r,n){this.info(e,`\u2713 ${t}`,r,n)}failure(e,t,r,n){this.error(e,`\u2717 ${t}`,r,n)}timing(e,t,r,n){this.info(e,`\u23F1 ${t}`,n,{duration:`${r}ms`})}},y=new N;var g=class{db;constructor(){D(l),this.db=new j(v),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.initializeSchema(),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields(),this.makeObservationsTextNullable(),this.createUserPromptsTable()}initializeSchema(){try{this.db.exec(`
import q from"path";import j from"better-sqlite3";import{join as m,dirname as M,basename as V}from"path";import{homedir as A}from"os";import{existsSync as Z,mkdirSync as X}from"fs";import{fileURLToPath as F}from"url";function P(){return typeof __dirname<"u"?__dirname:M(F(import.meta.url))}var G=P(),l=process.env.CLAUDE_MEM_DATA_DIR||m(A(),".claude-mem"),S=process.env.CLAUDE_CONFIG_DIR||m(A(),".claude"),se=m(l,"archives"),te=m(l,"logs"),re=m(l,"trash"),ne=m(l,"backups"),ie=m(l,"settings.json"),v=m(l,"claude-mem.db"),oe=m(S,"settings.json"),ae=m(S,"commands"),de=m(S,"CLAUDE.md");function x(p){X(p,{recursive:!0})}function D(){return m(G,"..","..")}var b=(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))(b||{}),N=class{level;useColor;constructor(){let e=process.env.CLAUDE_MEM_LOG_LEVEL?.toUpperCase()||"INFO";this.level=b[e]??1,this.useColor=process.stdout.isTTY??!1}correlationId(e,t){return`obs-${e}-${t}`}sessionId(e){return`session-${e}`}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.level===0?`${e.message}
${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Object.keys(e);return t.length===0?"{}":t.length<=3?JSON.stringify(e):`{${t.length} keys: ${t.slice(0,3).join(", ")}...}`}return String(e)}formatTool(e,t){if(!t)return e;try{let r=typeof t=="string"?JSON.parse(t):t;if(e==="Bash"&&r.command){let n=r.command.length>50?r.command.substring(0,50)+"...":r.command;return`${e}(${n})`}if(e==="Read"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}if(e==="Edit"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}if(e==="Write"&&r.file_path){let n=r.file_path.split("/").pop()||r.file_path;return`${e}(${n})`}return e}catch{return e}}log(e,t,r,n,o){if(e<this.level)return;let d=new Date().toISOString().replace("T"," ").substring(0,23),s=b[e].padEnd(5),c=t.padEnd(6),_="";n?.correlationId?_=`[${n.correlationId}] `:n?.sessionId&&(_=`[session-${n.sessionId}] `);let a="";o!=null&&(this.level===0&&typeof o=="object"?a=`
`+JSON.stringify(o,null,2):a=" "+this.formatData(o));let E="";if(n){let{sessionId:T,sdkSessionId:f,correlationId:$,...h}=n;Object.keys(h).length>0&&(E=` {${Object.entries(h).map(([U,w])=>`${U}=${w}`).join(", ")}}`)}let u=`[${d}] [${s}] [${c}] ${_}${r}${E}${a}`;e===3?console.error(u):console.log(u)}debug(e,t,r,n){this.log(0,e,t,r,n)}info(e,t,r,n){this.log(1,e,t,r,n)}warn(e,t,r,n){this.log(2,e,t,r,n)}error(e,t,r,n){this.log(3,e,t,r,n)}dataIn(e,t,r,n){this.info(e,`\u2192 ${t}`,r,n)}dataOut(e,t,r,n){this.info(e,`\u2190 ${t}`,r,n)}success(e,t,r,n){this.info(e,`\u2713 ${t}`,r,n)}failure(e,t,r,n){this.error(e,`\u2717 ${t}`,r,n)}timing(e,t,r,n){this.info(e,`\u23F1 ${t}`,n,{duration:`${r}ms`})}},y=new N;var g=class{db;constructor(){x(l),this.db=new j(v),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.initializeSchema(),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint(),this.addObservationHierarchicalFields(),this.makeObservationsTextNullable(),this.createUserPromptsTable()}initializeSchema(){try{this.db.exec(`
CREATE TABLE IF NOT EXISTS schema_versions (
id INTEGER PRIMARY KEY,
version INTEGER UNIQUE NOT NULL,
@@ -222,7 +222,7 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
SELECT files_read, files_modified
FROM observations
WHERE sdk_session_id = ?
`).all(e),n=new Set,o=new Set;for(let p of r){if(p.files_read)try{let s=JSON.parse(p.files_read);Array.isArray(s)&&s.forEach(c=>n.add(c))}catch{}if(p.files_modified)try{let s=JSON.parse(p.files_modified);Array.isArray(s)&&s.forEach(c=>o.add(c))}catch{}}return{filesRead:Array.from(n),filesModified:Array.from(o)}}getSessionById(e){return this.db.prepare(`
`).all(e),n=new Set,o=new Set;for(let d of r){if(d.files_read)try{let s=JSON.parse(d.files_read);Array.isArray(s)&&s.forEach(c=>n.add(c))}catch{}if(d.files_modified)try{let s=JSON.parse(d.files_modified);Array.isArray(s)&&s.forEach(c=>o.add(c))}catch{}}return{filesRead:Array.from(n),filesModified:Array.from(o)}}getSessionById(e){return this.db.prepare(`
SELECT id, sdk_session_id, project, user_prompt
FROM sdk_sessions
WHERE id = ?
@@ -272,17 +272,29 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
INSERT INTO user_prompts
(claude_session_id, prompt_number, prompt_text, created_at, created_at_epoch)
VALUES (?, ?, ?, ?, ?)
`).run(e,t,r,n.toISOString(),o).lastInsertRowid}storeObservation(e,t,r,n){let o=new Date,p=o.getTime();this.db.prepare(`
`).run(e,t,r,n.toISOString(),o).lastInsertRowid}storeObservation(e,t,r,n){let o=new Date,d=o.getTime();this.db.prepare(`
SELECT id FROM sdk_sessions WHERE sdk_session_id = ?
`).get(e)||(this.db.prepare(`
INSERT INTO sdk_sessions
(claude_session_id, sdk_session_id, project, started_at, started_at_epoch, status)
VALUES (?, ?, ?, ?, ?, 'active')
`).run(e,e,t,o.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`)),this.db.prepare(`
INSERT INTO observations
(sdk_session_id, project, type, title, subtitle, facts, narrative, concepts,
files_read, files_modified, prompt_number, created_at, created_at_epoch)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(e,t,r.type,r.title,r.subtitle,JSON.stringify(r.facts),r.narrative,JSON.stringify(r.concepts),JSON.stringify(r.files_read),JSON.stringify(r.files_modified),n||null,o.toISOString(),p)}storeSummary(e,t,r,n){let o=new Date,p=o.getTime();this.db.prepare(`
`).run(e,t,r.type,r.title,r.subtitle,JSON.stringify(r.facts),r.narrative,JSON.stringify(r.concepts),JSON.stringify(r.files_read),JSON.stringify(r.files_modified),n||null,o.toISOString(),d)}storeSummary(e,t,r,n){let o=new Date,d=o.getTime();this.db.prepare(`
SELECT id FROM sdk_sessions WHERE sdk_session_id = ?
`).get(e)||(this.db.prepare(`
INSERT INTO sdk_sessions
(claude_session_id, sdk_session_id, project, started_at, started_at_epoch, status)
VALUES (?, ?, ?, ?, ?, 'active')
`).run(e,e,t,o.toISOString(),d),console.error(`[SessionStore] Auto-created session record for session_id: ${e}`)),this.db.prepare(`
INSERT INTO session_summaries
(sdk_session_id, project, request, investigated, learned, completed,
next_steps, notes, prompt_number, created_at, created_at_epoch)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`).run(e,t,r.request,r.investigated,r.learned,r.completed,r.next_steps,r.notes,n||null,o.toISOString(),p)}markSessionCompleted(e){let t=new Date,r=t.getTime();this.db.prepare(`
`).run(e,t,r.request,r.investigated,r.learned,r.completed,r.next_steps,r.notes,n||null,o.toISOString(),d)}markSessionCompleted(e){let t=new Date,r=t.getTime();this.db.prepare(`
UPDATE sdk_sessions
SET status = 'completed', completed_at = ?, completed_at_epoch = ?
WHERE id = ?
@@ -294,13 +306,13 @@ ${e.stack}`:e.message;if(Array.isArray(e))return`[${e.length} items]`;let t=Obje
UPDATE sdk_sessions
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
WHERE status = 'active'
`).run(e.toISOString(),t).changes}close(){this.db.close()}};import R from"path";import{existsSync as I}from"fs";import{spawn as W}from"child_process";var B=parseInt(process.env.CLAUDE_MEM_WORKER_PORT||"37777",10),H=`http://127.0.0.1:${B}/health`;async function k(){try{return(await fetch(H,{signal:AbortSignal.timeout(500)})).ok}catch{return!1}}async function C(){try{if(await k())return!0;console.error("[claude-mem] Worker not responding, starting...");let d=x(),e=R.join(d,"plugin","scripts","worker-service.cjs");if(!I(e))return console.error(`[claude-mem] Worker service not found at ${e}`),!1;let t=R.join(d,"ecosystem.config.cjs"),r=R.join(d,"node_modules",".bin","pm2");if(!I(r))throw new Error(`PM2 binary not found at ${r}. This is a bundled dependency - try running: npm install`);if(!I(t))throw new Error(`PM2 ecosystem config not found at ${t}. Plugin installation may be corrupted.`);let n=W(r,["start",t],{detached:!0,stdio:"ignore",cwd:d});n.on("error",o=>{throw new Error(`Failed to spawn PM2: ${o.message}`)}),n.unref(),console.error("[claude-mem] Worker started with PM2");for(let o=0;o<3;o++)if(await new Promise(p=>setTimeout(p,500)),await k())return console.error("[claude-mem] Worker is healthy"),!0;return console.error("[claude-mem] Worker failed to become healthy after startup"),!1}catch(d){return console.error(`[claude-mem] Failed to start worker: ${d.message}`),!1}}var i={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"};function O(d,e=!1,t=!1){C();let r=d?.cwd??process.cwd(),n=r?q.basename(r):"unknown-project",o=new g;try{let p=o.getRecentSummariesWithSessionInfo(n,3);if(p.length===0)return e?`
`).run(e.toISOString(),t).changes}close(){this.db.close()}};import R from"path";import{existsSync as I}from"fs";import{spawn as W}from"child_process";var H=parseInt(process.env.CLAUDE_MEM_WORKER_PORT||"37777",10),B=`http://127.0.0.1:${H}/health`;async function k(){try{return(await fetch(B,{signal:AbortSignal.timeout(500)})).ok}catch{return!1}}async function C(){try{if(await k())return!0;console.error("[claude-mem] Worker not responding, starting...");let p=D(),e=R.join(p,"plugin","scripts","worker-service.cjs");if(!I(e))return console.error(`[claude-mem] Worker service not found at ${e}`),!1;let t=R.join(p,"ecosystem.config.cjs"),r=R.join(p,"node_modules",".bin","pm2");if(!I(r))throw new Error(`PM2 binary not found at ${r}. This is a bundled dependency - try running: npm install`);if(!I(t))throw new Error(`PM2 ecosystem config not found at ${t}. Plugin installation may be corrupted.`);let n=W(r,["start",t],{detached:!0,stdio:"ignore",cwd:p});n.on("error",o=>{throw new Error(`Failed to spawn PM2: ${o.message}`)}),n.unref(),console.error("[claude-mem] Worker started with PM2");for(let o=0;o<3;o++)if(await new Promise(d=>setTimeout(d,500)),await k())return console.error("[claude-mem] Worker is healthy"),!0;return console.error("[claude-mem] Worker failed to become healthy after startup"),!1}catch(p){return console.error(`[claude-mem] Failed to start worker: ${p.message}`),!1}}var i={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"};function O(p,e=!1,t=!1){C();let r=p?.cwd??process.cwd(),n=r?q.basename(r):"unknown-project",o=new g;try{let d=o.getRecentSummariesWithSessionInfo(n,3);if(d.length===0)return e?`
${i.bright}${i.cyan}\u{1F4DD} [${n}] recent context${i.reset}
${i.gray}${"\u2500".repeat(60)}${i.reset}
${i.dim}No previous summaries found for this project yet.${i.reset}
`:`# [${n}] recent context
No previous summaries found for this project yet.`;let s=[];if(t){if(e?(s.push(""),s.push(`${i.bright}${i.cyan}\u{1F4DD} [${n}] recent context${i.reset}`),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push(`# [${n}] recent context`),s.push("")),p.length>1){e?(s.push(`${i.bright}${i.dim}Previous Requests:${i.reset}`),s.push("")):(s.push("**Previous Requests:**"),s.push(""));for(let T=p.length-1;T>=1;T--){let f=p[T],h=new Date(f.created_at).toLocaleString();e?s.push(`${i.dim}\u2022 ${h}:${i.reset} ${f.request||"(no request)"}`):s.push(`- ${h}: ${f.request||"(no request)"}`)}e?(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push(""),s.push("---"),s.push(""))}let a=p[0];a.request&&(e?(s.push(`${i.bright}${i.yellow}Request:${i.reset} ${a.request}`),s.push("")):(s.push(`**Request:** ${a.request}`),s.push(""))),a.learned&&(e?(s.push(`${i.bright}${i.blue}Learned:${i.reset} ${a.learned}`),s.push("")):(s.push(`**Learned:** ${a.learned}`),s.push(""))),a.completed&&(e?(s.push(`${i.bright}${i.green}Completed:${i.reset} ${a.completed}`),s.push("")):(s.push(`**Completed:** ${a.completed}`),s.push(""))),a.next_steps&&(e?(s.push(`${i.bright}${i.magenta}Next Steps:${i.reset} ${a.next_steps}`),s.push("")):(s.push(`**Next Steps:** ${a.next_steps}`),s.push("")));let E=o.getFilesForSession(a.sdk_session_id);E.filesRead.length>0&&(e?s.push(`${i.dim}Files Read: ${E.filesRead.join(", ")}${i.reset}`):s.push(`**Files Read:** ${E.filesRead.join(", ")}`)),E.filesModified.length>0&&(e?s.push(`${i.dim}Files Modified: ${E.filesModified.join(", ")}${i.reset}`):s.push(`**Files Modified:** ${E.filesModified.join(", ")}`));let u=new Date(a.created_at).toLocaleString();return e?s.push(`${i.dim}Date: ${u}${i.reset}`):s.push(`**Date:** ${u}`),e&&(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)),s.join(`
`)}e?(s.push(""),s.push(`${i.bright}${i.cyan}\u{1F4DD} [${n}] recent context${i.reset}`),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)):(s.push(`# [${n}] recent context`),s.push(""));let c=null,_=!0;for(let a of p){c!==null&&a.sdk_session_id!==c?e?(s.push(""),s.push(`${i.dim}${"\u2500".repeat(23)} New Session ${"\u2500".repeat(24)}${i.reset}`),s.push("")):(s.push(""),s.push("--- New Session ---"),s.push("")):_?e&&s.push(""):e?(s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push("---"),s.push("")),_=!1,a.request&&(e?(s.push(`${i.bright}${i.yellow}Request:${i.reset} ${a.request}`),s.push("")):(s.push(`**Request:** ${a.request}`),s.push(""))),a.learned&&(e?(s.push(`${i.bright}${i.blue}Learned:${i.reset} ${a.learned}`),s.push("")):(s.push(`**Learned:** ${a.learned}`),s.push(""))),a.completed&&(e?(s.push(`${i.bright}${i.green}Completed:${i.reset} ${a.completed}`),s.push("")):(s.push(`**Completed:** ${a.completed}`),s.push(""))),a.next_steps&&(e?(s.push(`${i.bright}${i.magenta}Next Steps:${i.reset} ${a.next_steps}`),s.push("")):(s.push(`**Next Steps:** ${a.next_steps}`),s.push("")));let u=o.getFilesForSession(a.sdk_session_id);u.filesRead.length>0&&(e?s.push(`${i.dim}Files Read: ${u.filesRead.join(", ")}${i.reset}`):s.push(`**Files Read:** ${u.filesRead.join(", ")}`)),u.filesModified.length>0&&(e?s.push(`${i.dim}Files Modified: ${u.filesModified.join(", ")}${i.reset}`):s.push(`**Files Modified:** ${u.filesModified.join(", ")}`));let T=new Date(a.created_at).toLocaleString();e?s.push(`${i.dim}Date: ${T}${i.reset}`):s.push(`**Date:** ${T}`),e||s.push(""),c=a.sdk_session_id}return e&&(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)),s.join(`
`)}finally{o.close()}}import{stdin as L}from"process";try{let d=process.argv.includes("--index");if(L.isTTY){let e=O(void 0,!0,d);console.log(e),process.exit(0)}else{let e="";L.on("data",t=>e+=t),L.on("end",()=>{let t=e.trim()?JSON.parse(e):void 0,n={hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:O(t,!1,d)}};console.log(JSON.stringify(n)),process.exit(0)})}}catch(d){console.error(`[claude-mem context-hook error: ${d.message}]`),process.exit(0)}
No previous summaries found for this project yet.`;let s=[];if(t){if(e?(s.push(""),s.push(`${i.bright}${i.cyan}\u{1F4DD} [${n}] recent context${i.reset}`),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push(`# [${n}] recent context`),s.push("")),d.length>1){e?(s.push(`${i.bright}${i.dim}Previous Requests:${i.reset}`),s.push("")):(s.push("**Previous Requests:**"),s.push(""));for(let T=d.length-1;T>=1;T--){let f=d[T],h=new Date(f.created_at).toLocaleString();e?s.push(`${i.dim}\u2022 ${h}:${i.reset} ${f.request||"(no request)"}`):s.push(`- ${h}: ${f.request||"(no request)"}`)}e?(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push(""),s.push("---"),s.push(""))}let a=d[0];a.request&&(e?(s.push(`${i.bright}${i.yellow}Request:${i.reset} ${a.request}`),s.push("")):(s.push(`**Request:** ${a.request}`),s.push(""))),a.learned&&(e?(s.push(`${i.bright}${i.blue}Learned:${i.reset} ${a.learned}`),s.push("")):(s.push(`**Learned:** ${a.learned}`),s.push(""))),a.completed&&(e?(s.push(`${i.bright}${i.green}Completed:${i.reset} ${a.completed}`),s.push("")):(s.push(`**Completed:** ${a.completed}`),s.push(""))),a.next_steps&&(e?(s.push(`${i.bright}${i.magenta}Next Steps:${i.reset} ${a.next_steps}`),s.push("")):(s.push(`**Next Steps:** ${a.next_steps}`),s.push("")));let E=o.getFilesForSession(a.sdk_session_id);E.filesRead.length>0&&(e?s.push(`${i.dim}Files Read: ${E.filesRead.join(", ")}${i.reset}`):s.push(`**Files Read:** ${E.filesRead.join(", ")}`)),E.filesModified.length>0&&(e?s.push(`${i.dim}Files Modified: ${E.filesModified.join(", ")}${i.reset}`):s.push(`**Files Modified:** ${E.filesModified.join(", ")}`));let u=new Date(a.created_at).toLocaleString();return e?s.push(`${i.dim}Date: ${u}${i.reset}`):s.push(`**Date:** ${u}`),e&&(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)),s.join(`
`)}e?(s.push(""),s.push(`${i.bright}${i.cyan}\u{1F4DD} [${n}] recent context${i.reset}`),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)):(s.push(`# [${n}] recent context`),s.push(""));let c=null,_=!0;for(let a of d){c!==null&&a.sdk_session_id!==c?e?(s.push(""),s.push(`${i.dim}${"\u2500".repeat(23)} New Session ${"\u2500".repeat(24)}${i.reset}`),s.push("")):(s.push(""),s.push("--- New Session ---"),s.push("")):_?e&&s.push(""):e?(s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`),s.push("")):(s.push("---"),s.push("")),_=!1,a.request&&(e?(s.push(`${i.bright}${i.yellow}Request:${i.reset} ${a.request}`),s.push("")):(s.push(`**Request:** ${a.request}`),s.push(""))),a.learned&&(e?(s.push(`${i.bright}${i.blue}Learned:${i.reset} ${a.learned}`),s.push("")):(s.push(`**Learned:** ${a.learned}`),s.push(""))),a.completed&&(e?(s.push(`${i.bright}${i.green}Completed:${i.reset} ${a.completed}`),s.push("")):(s.push(`**Completed:** ${a.completed}`),s.push(""))),a.next_steps&&(e?(s.push(`${i.bright}${i.magenta}Next Steps:${i.reset} ${a.next_steps}`),s.push("")):(s.push(`**Next Steps:** ${a.next_steps}`),s.push("")));let u=o.getFilesForSession(a.sdk_session_id);u.filesRead.length>0&&(e?s.push(`${i.dim}Files Read: ${u.filesRead.join(", ")}${i.reset}`):s.push(`**Files Read:** ${u.filesRead.join(", ")}`)),u.filesModified.length>0&&(e?s.push(`${i.dim}Files Modified: ${u.filesModified.join(", ")}${i.reset}`):s.push(`**Files Modified:** ${u.filesModified.join(", ")}`));let T=new Date(a.created_at).toLocaleString();e?s.push(`${i.dim}Date: ${T}${i.reset}`):s.push(`**Date:** ${T}`),e||s.push(""),c=a.sdk_session_id}return e&&(s.push(""),s.push(`${i.gray}${"\u2500".repeat(60)}${i.reset}`)),s.join(`
`)}finally{o.close()}}import{stdin as L}from"process";try{let p=process.argv.includes("--index");if(L.isTTY){let e=O(void 0,!0,p);console.log(e),process.exit(0)}else{let e="";L.on("data",t=>e+=t),L.on("end",()=>{let t=e.trim()?JSON.parse(e):void 0,n={hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:O(t,!1,p)}};console.log(JSON.stringify(n)),process.exit(0)})}}catch(p){console.error(`[claude-mem context-hook error: ${p.message}]`),process.exit(0)}