Refactor database hooks to add new session tracking features
- Introduced `getSessionById` method in HooksDatabase to retrieve session details by ID. - Updated context, new, save, and summary hooks to utilize the new `getSessionById` method. - Enhanced session management by adding `worker_port` and `prompt_counter` columns to relevant tables. - Improved logging in WorkerService to provide clearer output during session initialization and processing. - Removed redundant error logging in favor of more informative console logs.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
import D from"path";import R from"better-sqlite3";import{join as m,dirname as N,basename as v}from"path";import{homedir as h}from"os";import{existsSync as O,mkdirSync as S}from"fs";var d=process.env.CLAUDE_MEM_DATA_DIR||m(h(),".claude-mem"),E=process.env.CLAUDE_CONFIG_DIR||m(h(),".claude"),w=m(d,"archives"),U=m(d,"logs"),P=m(d,"trash"),H=m(d,"backups"),M=m(d,"settings.json"),T=m(d,"claude-mem.db"),j=m(E,"settings.json"),$=m(E,"commands"),W=m(E,"CLAUDE.md");function f(p){S(p,{recursive:!0})}var l=class{db;constructor(){f(d),this.db=new R(T),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(t=>t.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(c=>c.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(c=>c.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(c=>c.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let n=this.db.pragma("index_list(session_summaries)").some(c=>c.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(t=>t.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
import D from"path";import R from"better-sqlite3";import{join as p,dirname as N,basename as L}from"path";import{homedir as h}from"os";import{existsSync as O,mkdirSync as S}from"fs";var d=process.env.CLAUDE_MEM_DATA_DIR||p(h(),".claude-mem"),E=process.env.CLAUDE_CONFIG_DIR||p(h(),".claude"),w=p(d,"archives"),U=p(d,"logs"),P=p(d,"trash"),H=p(d,"backups"),M=p(d,"settings.json"),T=p(d,"claude-mem.db"),j=p(E,"settings.json"),W=p(E,"commands"),$=p(E,"CLAUDE.md");function f(m){S(m,{recursive:!0})}var l=class{db;constructor(){f(d),this.db=new R(T),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),this.ensureWorkerPortColumn(),this.ensurePromptTrackingColumns(),this.removeSessionSummariesUniqueConstraint()}ensureWorkerPortColumn(){try{this.db.pragma("table_info(sdk_sessions)").some(t=>t.name==="worker_port")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN worker_port INTEGER"),console.error("[HooksDatabase] Added worker_port column to sdk_sessions table"))}catch(e){console.error("[HooksDatabase] Migration error:",e.message)}}ensurePromptTrackingColumns(){try{this.db.pragma("table_info(sdk_sessions)").some(c=>c.name==="prompt_counter")||(this.db.exec("ALTER TABLE sdk_sessions ADD COLUMN prompt_counter INTEGER DEFAULT 0"),console.error("[HooksDatabase] Added prompt_counter column to sdk_sessions table")),this.db.pragma("table_info(observations)").some(c=>c.name==="prompt_number")||(this.db.exec("ALTER TABLE observations ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to observations table")),this.db.pragma("table_info(session_summaries)").some(c=>c.name==="prompt_number")||(this.db.exec("ALTER TABLE session_summaries ADD COLUMN prompt_number INTEGER"),console.error("[HooksDatabase] Added prompt_number column to session_summaries table"));let n=this.db.pragma("index_list(session_summaries)").some(c=>c.unique===1)}catch(e){console.error("[HooksDatabase] Prompt tracking migration error:",e.message)}}removeSessionSummariesUniqueConstraint(){try{if(!this.db.pragma("index_list(session_summaries)").some(t=>t.unique===1))return;console.error("[HooksDatabase] Removing UNIQUE constraint from session_summaries.sdk_session_id..."),this.db.exec("BEGIN TRANSACTION");try{this.db.exec(`
|
||||
CREATE TABLE session_summaries_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sdk_session_id TEXT NOT NULL,
|
||||
@@ -41,7 +41,12 @@ import D from"path";import R from"better-sqlite3";import{join as m,dirname as N,
|
||||
WHERE project = ?
|
||||
ORDER BY created_at_epoch DESC
|
||||
LIMIT ?
|
||||
`).all(e,s)}findActiveSDKSession(e){return this.db.prepare(`
|
||||
`).all(e,s)}getSessionById(e){return this.db.prepare(`
|
||||
SELECT id, sdk_session_id, project, user_prompt
|
||||
FROM sdk_sessions
|
||||
WHERE id = ?
|
||||
LIMIT 1
|
||||
`).get(e)||null}findActiveSDKSession(e){return this.db.prepare(`
|
||||
SELECT id, sdk_session_id, project, worker_port
|
||||
FROM sdk_sessions
|
||||
WHERE claude_session_id = ? AND status = 'active'
|
||||
@@ -67,11 +72,11 @@ import D from"path";import R from"better-sqlite3";import{join as m,dirname as N,
|
||||
INSERT INTO sdk_sessions
|
||||
(claude_session_id, project, user_prompt, started_at, started_at_epoch, status)
|
||||
VALUES (?, ?, ?, ?, ?, 'active')
|
||||
`).run(e,s,t,i.toISOString(),a).lastInsertRowid}updateSDKSessionId(e,s){this.db.prepare(`
|
||||
`).run(e,s,t,i.toISOString(),a).lastInsertRowid}updateSDKSessionId(e,s){return this.db.prepare(`
|
||||
UPDATE sdk_sessions
|
||||
SET sdk_session_id = ?
|
||||
WHERE id = ? AND sdk_session_id IS NULL
|
||||
`).run(s,e).changes===0&&console.error(`[HooksDatabase] Skipped updating sdk_session_id for session ${e} - already set (prevents FOREIGN KEY constraint violation)`)}setWorkerPort(e,s){this.db.prepare(`
|
||||
`).run(s,e).changes===0?(console.error(`[HooksDatabase] Skipped updating sdk_session_id for session ${e} - already set (prevents FOREIGN KEY constraint violation)`),!1):!0}setWorkerPort(e,s){this.db.prepare(`
|
||||
UPDATE sdk_sessions
|
||||
SET worker_port = ?
|
||||
WHERE id = ?
|
||||
@@ -101,8 +106,8 @@ import D from"path";import R from"better-sqlite3";import{join as m,dirname as N,
|
||||
UPDATE sdk_sessions
|
||||
SET status = 'failed', completed_at = ?, completed_at_epoch = ?
|
||||
WHERE status = 'active'
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function g(p){let e=p?.cwd??process.cwd(),s=e?D.basename(e):"unknown-project",t=new l;try{let i=t.getRecentSummaries(s,5),a=t.getRecentObservations(s,20);if(i.length===0&&a.length===0){console.log(`# Recent Session Context
|
||||
`).run(e.toISOString(),s).changes}close(){this.db.close()}};function g(m){let e=m?.cwd??process.cwd(),s=e?D.basename(e):"unknown-project",t=new l;try{let i=t.getRecentSummaries(s,5),a=t.getRecentObservations(s,20);if(i.length===0&&a.length===0){console.log(`# Recent Session Context
|
||||
|
||||
No previous sessions found for this project yet.`);return}let r=[];if(r.push("# Recent Session Context"),r.push(""),a.length>0){r.push(`## Recent Observations (${a.length})`),r.push("");let n={};for(let o of a)n[o.type]||(n[o.type]=[]),n[o.type].push({text:o.text,prompt_number:o.prompt_number,created_at:o.created_at});let c=["feature","bugfix","refactor","discovery","decision"];for(let o of c)if(n[o]&&n[o].length>0){r.push(`### ${o.charAt(0).toUpperCase()+o.slice(1)}s`);for(let _ of n[o]){let k=_.prompt_number?` (prompt #${_.prompt_number})`:"";r.push(`- ${_.text}${k}`)}r.push("")}}if(i.length===0){console.log(r.join(`
|
||||
`));return}r.push("## Recent Sessions"),r.push("");let u=i.length===1?"session":"sessions";r.push(`Showing last ${i.length} ${u} for **${s}**:`),r.push("");for(let n of i){r.push("---"),r.push("");let c=n.prompt_number?` (Prompt #${n.prompt_number})`:"";if(r.push(`**Summary${c}**`),r.push(""),n.request&&r.push(`**Request:** ${n.request}`),n.completed&&r.push(`**Completed:** ${n.completed}`),n.learned&&r.push(`**Learned:** ${n.learned}`),n.next_steps&&r.push(`**Next Steps:** ${n.next_steps}`),n.files_read)try{let o=JSON.parse(n.files_read);Array.isArray(o)&&o.length>0&&r.push(`**Files Read:** ${o.join(", ")}`)}catch{n.files_read.trim()&&r.push(`**Files Read:** ${n.files_read}`)}if(n.files_edited)try{let o=JSON.parse(n.files_edited);Array.isArray(o)&&o.length>0&&r.push(`**Files Edited:** ${o.join(", ")}`)}catch{n.files_edited.trim()&&r.push(`**Files Edited:** ${n.files_edited}`)}r.push(`**Date:** ${n.created_at.split("T")[0]}`),r.push("")}console.log(r.join(`
|
||||
`))}finally{t.close()}}import{stdin as b}from"process";try{if(b.isTTY)g();else{let p="";b.on("data",e=>p+=e),b.on("end",()=>{let e=p.trim()?JSON.parse(p):void 0;g(e)})}}catch(p){console.error(`[claude-mem context-hook error: ${p.message}]`),process.exit(0)}
|
||||
`))}finally{t.close()}}import{stdin as b}from"process";try{if(b.isTTY)g();else{let m="";b.on("data",e=>m+=e),b.on("end",()=>{let e=m.trim()?JSON.parse(m):void 0;g(e)})}}catch(m){console.error(`[claude-mem context-hook error: ${m.message}]`),process.exit(0)}
|
||||
|
||||
Reference in New Issue
Block a user