chore: bump version to 9.1.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "claude-mem",
|
"name": "claude-mem",
|
||||||
"version": "9.1.0",
|
"version": "9.1.1",
|
||||||
"source": "./plugin",
|
"source": "./plugin",
|
||||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-mem",
|
"name": "claude-mem",
|
||||||
"version": "9.1.0",
|
"version": "9.1.1",
|
||||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"claude",
|
"claude",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-mem",
|
"name": "claude-mem",
|
||||||
"version": "9.1.0",
|
"version": "9.1.1",
|
||||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Alex Newman"
|
"name": "Alex Newman"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "claude-mem-plugin",
|
"name": "claude-mem-plugin",
|
||||||
"version": "9.1.0",
|
"version": "9.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ ${o.stack}`:` ${o.message}`:this.getLevel()===0&&typeof o=="object"?u=`
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
text TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery')),
|
type TEXT NOT NULL,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
created_at_epoch INTEGER NOT NULL,
|
created_at_epoch INTEGER NOT NULL,
|
||||||
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
@@ -110,7 +110,7 @@ ${o.stack}`:` ${o.message}`:this.getLevel()===0&&typeof o=="object"?u=`
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT,
|
text TEXT,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
|
type TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
subtitle TEXT,
|
subtitle TEXT,
|
||||||
facts TEXT,
|
facts TEXT,
|
||||||
@@ -192,13 +192,13 @@ ${o.stack}`:` ${o.message}`:this.getLevel()===0&&typeof o=="object"?u=`
|
|||||||
completed_at_epoch INTEGER,
|
completed_at_epoch INTEGER,
|
||||||
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
`),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()),m.debug("DB","pending_messages table created successfully")}renameSessionIdColumns(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(17))return;m.debug("DB","Checking session ID columns for semantic clarity rename");let t=0,s=(n,o,i)=>{let a=this.db.query(`PRAGMA table_info(${n})`).all(),d=a.some(u=>u.name===o);return a.some(u=>u.name===i)?!1:d?(this.db.run(`ALTER TABLE ${n} RENAME COLUMN ${o} TO ${i}`),m.debug("DB",`Renamed ${n}.${o} to ${i}`),!0):(m.warn("DB",`Column ${o} not found in ${n}, skipping rename`),!1)};s("sdk_sessions","claude_session_id","content_session_id")&&t++,s("sdk_sessions","sdk_session_id","memory_session_id")&&t++,s("pending_messages","claude_session_id","content_session_id")&&t++,s("observations","sdk_session_id","memory_session_id")&&t++,s("session_summaries","sdk_session_id","memory_session_id")&&t++,s("user_prompts","claude_session_id","content_session_id")&&t++,this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(17,new Date().toISOString()),t>0?m.debug("DB",`Successfully renamed ${t} session ID columns`):m.debug("DB","No session ID column renames needed (already up to date)")}repairSessionIdColumnRename(){this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(19)||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(19,new Date().toISOString())}addFailedAtEpochColumn(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(20))return;this.db.query("PRAGMA table_info(pending_messages)").all().some(n=>n.name==="failed_at_epoch")||(this.db.run("ALTER TABLE pending_messages ADD COLUMN failed_at_epoch INTEGER"),m.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)){m.debug("DB","Adding ON UPDATE CASCADE to FK constraints on observations and session_summaries"),this.db.run("BEGIN TRANSACTION");try{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(`
|
`),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()),m.debug("DB","pending_messages table created successfully")}renameSessionIdColumns(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(17))return;m.debug("DB","Checking session ID columns for semantic clarity rename");let t=0,s=(n,o,i)=>{let a=this.db.query(`PRAGMA table_info(${n})`).all(),d=a.some(u=>u.name===o);return a.some(u=>u.name===i)?!1:d?(this.db.run(`ALTER TABLE ${n} RENAME COLUMN ${o} TO ${i}`),m.debug("DB",`Renamed ${n}.${o} to ${i}`),!0):(m.warn("DB",`Column ${o} not found in ${n}, skipping rename`),!1)};s("sdk_sessions","claude_session_id","content_session_id")&&t++,s("sdk_sessions","sdk_session_id","memory_session_id")&&t++,s("pending_messages","claude_session_id","content_session_id")&&t++,s("observations","sdk_session_id","memory_session_id")&&t++,s("session_summaries","sdk_session_id","memory_session_id")&&t++,s("user_prompts","claude_session_id","content_session_id")&&t++,this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(17,new Date().toISOString()),t>0?m.debug("DB",`Successfully renamed ${t} session ID columns`):m.debug("DB","No session ID column renames needed (already up to date)")}repairSessionIdColumnRename(){this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(19)||this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(19,new Date().toISOString())}addFailedAtEpochColumn(){if(this.db.prepare("SELECT version FROM schema_versions WHERE version = ?").get(20))return;this.db.query("PRAGMA table_info(pending_messages)").all().some(n=>n.name==="failed_at_epoch")||(this.db.run("ALTER TABLE pending_messages ADD COLUMN failed_at_epoch INTEGER"),m.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)){m.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");try{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(`
|
||||||
CREATE TABLE observations_new (
|
CREATE TABLE observations_new (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT,
|
text TEXT,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
|
type TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
subtitle TEXT,
|
subtitle TEXT,
|
||||||
facts TEXT,
|
facts TEXT,
|
||||||
@@ -286,7 +286,7 @@ ${o.stack}`:` ${o.message}`:this.getLevel()===0&&typeof o=="object"?u=`
|
|||||||
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
INSERT INTO session_summaries_fts(rowid, request, investigated, learned, completed, next_steps, notes)
|
||||||
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
VALUES (new.id, new.request, new.investigated, new.learned, new.completed, new.next_steps, new.notes);
|
||||||
END;
|
END;
|
||||||
`),this.db.prepare("INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)").run(21,new Date().toISOString()),this.db.run("COMMIT"),m.debug("DB","Successfully added ON UPDATE CASCADE to FK constraints")}catch(t){throw this.db.run("ROLLBACK"),t}}}updateMemorySessionId(e,t){this.db.prepare(`
|
`),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"),m.debug("DB","Successfully added ON UPDATE CASCADE to FK constraints")}catch(t){throw this.db.run("ROLLBACK"),this.db.run("PRAGMA foreign_keys = ON"),t}}}updateMemorySessionId(e,t){this.db.prepare(`
|
||||||
UPDATE sdk_sessions
|
UPDATE sdk_sessions
|
||||||
SET memory_session_id = ?
|
SET memory_session_id = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,141 @@
|
|||||||
|
---
|
||||||
|
name: mem-search
|
||||||
|
description: Search claude-mem's persistent cross-session memory database. Use when user asks "did we already solve this?", "how did we do X last time?", or needs work from previous sessions.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Memory Search
|
||||||
|
|
||||||
|
Search past work across all sessions. Simple workflow: search -> filter -> fetch.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
Use when users ask about PREVIOUS sessions (not current conversation):
|
||||||
|
|
||||||
|
- "Did we already fix this?"
|
||||||
|
- "How did we solve X last time?"
|
||||||
|
- "What happened last week?"
|
||||||
|
|
||||||
|
## 3-Layer Workflow (ALWAYS Follow)
|
||||||
|
|
||||||
|
**NEVER fetch full details without filtering first. 10x token savings.**
|
||||||
|
|
||||||
|
### Step 1: Search - Get Index with IDs
|
||||||
|
|
||||||
|
Use the `search` MCP tool:
|
||||||
|
|
||||||
|
```
|
||||||
|
search(query="authentication", limit=20, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** Table with IDs, timestamps, types, titles (~50-100 tokens/result)
|
||||||
|
|
||||||
|
```
|
||||||
|
| ID | Time | T | Title | Read |
|
||||||
|
|----|------|---|-------|------|
|
||||||
|
| #11131 | 3:48 PM | 🟣 | Added JWT authentication | ~75 |
|
||||||
|
| #10942 | 2:15 PM | 🔴 | Fixed auth token expiration | ~50 |
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `query` (string) - Search term
|
||||||
|
- `limit` (number) - Max results, default 20, max 100
|
||||||
|
- `project` (string) - Project name filter
|
||||||
|
- `type` (string, optional) - "observations", "sessions", or "prompts"
|
||||||
|
- `obs_type` (string, optional) - Comma-separated: bugfix, feature, decision, discovery, change
|
||||||
|
- `dateStart` (string, optional) - YYYY-MM-DD or epoch ms
|
||||||
|
- `dateEnd` (string, optional) - YYYY-MM-DD or epoch ms
|
||||||
|
- `offset` (number, optional) - Skip N results
|
||||||
|
- `orderBy` (string, optional) - "date_desc" (default), "date_asc", "relevance"
|
||||||
|
|
||||||
|
### Step 2: Timeline - Get Context Around Interesting Results
|
||||||
|
|
||||||
|
Use the `timeline` MCP tool:
|
||||||
|
|
||||||
|
```
|
||||||
|
timeline(anchor=11131, depth_before=3, depth_after=3, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
Or find anchor automatically from query:
|
||||||
|
|
||||||
|
```
|
||||||
|
timeline(query="authentication", depth_before=3, depth_after=3, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Returns:** `depth_before + 1 + depth_after` items in chronological order with observations, sessions, and prompts interleaved around the anchor.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `anchor` (number, optional) - Observation ID to center around
|
||||||
|
- `query` (string, optional) - Find anchor automatically if anchor not provided
|
||||||
|
- `depth_before` (number, optional) - Items before anchor, default 5, max 20
|
||||||
|
- `depth_after` (number, optional) - Items after anchor, default 5, max 20
|
||||||
|
- `project` (string) - Project name filter
|
||||||
|
|
||||||
|
### Step 3: Fetch - Get Full Details ONLY for Filtered IDs
|
||||||
|
|
||||||
|
Review titles from Step 1 and context from Step 2. Pick relevant IDs. Discard the rest.
|
||||||
|
|
||||||
|
Use the `get_observations` MCP tool:
|
||||||
|
|
||||||
|
```
|
||||||
|
get_observations(ids=[11131, 10942])
|
||||||
|
```
|
||||||
|
|
||||||
|
**ALWAYS use `get_observations` for 2+ observations - single request vs N requests.**
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `ids` (array of numbers, required) - Observation IDs to fetch
|
||||||
|
- `orderBy` (string, optional) - "date_desc" (default), "date_asc"
|
||||||
|
- `limit` (number, optional) - Max observations to return
|
||||||
|
- `project` (string, optional) - Project name filter
|
||||||
|
|
||||||
|
**Returns:** Complete observation objects with title, subtitle, narrative, facts, concepts, files (~500-1000 tokens each)
|
||||||
|
|
||||||
|
## Saving Memories
|
||||||
|
|
||||||
|
Use the `save_memory` MCP tool to store manual observations:
|
||||||
|
|
||||||
|
```
|
||||||
|
save_memory(text="Important discovery about the auth system", title="Auth Architecture", project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
|
||||||
|
- `text` (string, required) - Content to remember
|
||||||
|
- `title` (string, optional) - Short title, auto-generated if omitted
|
||||||
|
- `project` (string, optional) - Project name, defaults to "claude-mem"
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
**Find recent bug fixes:**
|
||||||
|
|
||||||
|
```
|
||||||
|
search(query="bug", type="observations", obs_type="bugfix", limit=20, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Find what happened last week:**
|
||||||
|
|
||||||
|
```
|
||||||
|
search(type="observations", dateStart="2025-11-11", limit=20, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Understand context around a discovery:**
|
||||||
|
|
||||||
|
```
|
||||||
|
timeline(anchor=11131, depth_before=5, depth_after=5, project="my-project")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Batch fetch details:**
|
||||||
|
|
||||||
|
```
|
||||||
|
get_observations(ids=[11131, 10942, 10855], orderBy="date_desc")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why This Workflow?
|
||||||
|
|
||||||
|
- **Search index:** ~50-100 tokens per result
|
||||||
|
- **Full observation:** ~500-1000 tokens each
|
||||||
|
- **Batch fetch:** 1 HTTP request vs N individual requests
|
||||||
|
- **10x token savings** by filtering before fetching
|
||||||
@@ -99,7 +99,7 @@ export class SessionStore {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
text TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery')),
|
type TEXT NOT NULL,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
created_at_epoch INTEGER NOT NULL,
|
created_at_epoch INTEGER NOT NULL,
|
||||||
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
@@ -342,7 +342,7 @@ export class SessionStore {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT,
|
text TEXT,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
|
type TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
subtitle TEXT,
|
subtitle TEXT,
|
||||||
facts TEXT,
|
facts TEXT,
|
||||||
@@ -661,6 +661,8 @@ export class SessionStore {
|
|||||||
|
|
||||||
logger.debug('DB', 'Adding ON UPDATE CASCADE to FK constraints on observations and session_summaries');
|
logger.debug('DB', 'Adding ON UPDATE CASCADE to FK constraints on observations and session_summaries');
|
||||||
|
|
||||||
|
// PRAGMA foreign_keys must be set outside a transaction
|
||||||
|
this.db.run('PRAGMA foreign_keys = OFF');
|
||||||
this.db.run('BEGIN TRANSACTION');
|
this.db.run('BEGIN TRANSACTION');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -679,7 +681,7 @@ export class SessionStore {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT,
|
text TEXT,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
|
type TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
subtitle TEXT,
|
subtitle TEXT,
|
||||||
facts TEXT,
|
facts TEXT,
|
||||||
@@ -813,10 +815,12 @@ export class SessionStore {
|
|||||||
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(21, new Date().toISOString());
|
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('COMMIT');
|
||||||
|
this.db.run('PRAGMA foreign_keys = ON');
|
||||||
|
|
||||||
logger.debug('DB', 'Successfully added ON UPDATE CASCADE to FK constraints');
|
logger.debug('DB', 'Successfully added ON UPDATE CASCADE to FK constraints');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.db.run('ROLLBACK');
|
this.db.run('ROLLBACK');
|
||||||
|
this.db.run('PRAGMA foreign_keys = ON');
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ export const migration004: Migration = {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
text TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery')),
|
type TEXT NOT NULL,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
created_at_epoch INTEGER NOT NULL,
|
created_at_epoch INTEGER NOT NULL,
|
||||||
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export class MigrationRunner {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
text TEXT NOT NULL,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery')),
|
type TEXT NOT NULL,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
created_at_epoch INTEGER NOT NULL,
|
created_at_epoch INTEGER NOT NULL,
|
||||||
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id) ON DELETE CASCADE
|
||||||
@@ -325,7 +325,7 @@ export class MigrationRunner {
|
|||||||
memory_session_id TEXT NOT NULL,
|
memory_session_id TEXT NOT NULL,
|
||||||
project TEXT NOT NULL,
|
project TEXT NOT NULL,
|
||||||
text TEXT,
|
text TEXT,
|
||||||
type TEXT NOT NULL CHECK(type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
|
type TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
subtitle TEXT,
|
subtitle TEXT,
|
||||||
facts TEXT,
|
facts TEXT,
|
||||||
|
|||||||
@@ -235,13 +235,7 @@ export class WorkerService {
|
|||||||
* Register all route handlers with the server
|
* Register all route handlers with the server
|
||||||
*/
|
*/
|
||||||
private registerRoutes(): void {
|
private registerRoutes(): void {
|
||||||
// Standard routes
|
// IMPORTANT: Middleware must be registered BEFORE routes (Express processes in order)
|
||||||
this.server.registerRoutes(new ViewerRoutes(this.sseBroadcaster, this.dbManager, this.sessionManager));
|
|
||||||
this.server.registerRoutes(new SessionRoutes(this.sessionManager, this.dbManager, this.sdkAgent, this.geminiAgent, this.openRouterAgent, this.sessionEventBroadcaster, this));
|
|
||||||
this.server.registerRoutes(new DataRoutes(this.paginationHelper, this.dbManager, this.sessionManager, this.sseBroadcaster, this, this.startTime));
|
|
||||||
this.server.registerRoutes(new SettingsRoutes(this.settingsManager));
|
|
||||||
this.server.registerRoutes(new LogsRoutes());
|
|
||||||
this.server.registerRoutes(new MemoryRoutes(this.dbManager, 'claude-mem'));
|
|
||||||
|
|
||||||
// Early handler for /api/context/inject — fail open if not yet initialized
|
// Early handler for /api/context/inject — fail open if not yet initialized
|
||||||
this.server.app.get('/api/context/inject', async (req, res, next) => {
|
this.server.app.get('/api/context/inject', async (req, res, next) => {
|
||||||
@@ -255,7 +249,7 @@ export class WorkerService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Guard ALL /api/* routes during initialization — wait for DB with timeout
|
// Guard ALL /api/* routes during initialization — wait for DB with timeout
|
||||||
// Exceptions: /api/health, /api/readiness, /api/version (handled by Server.ts core routes before this middleware)
|
// Exceptions: /api/health, /api/readiness, /api/version (handled by Server.ts core routes)
|
||||||
// and /api/context/inject (handled above with fail-open)
|
// and /api/context/inject (handled above with fail-open)
|
||||||
this.server.app.use('/api', async (req, res, next) => {
|
this.server.app.use('/api', async (req, res, next) => {
|
||||||
if (this.initializationCompleteFlag) {
|
if (this.initializationCompleteFlag) {
|
||||||
@@ -279,6 +273,14 @@ export class WorkerService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Standard routes (registered AFTER guard middleware)
|
||||||
|
this.server.registerRoutes(new ViewerRoutes(this.sseBroadcaster, this.dbManager, this.sessionManager));
|
||||||
|
this.server.registerRoutes(new SessionRoutes(this.sessionManager, this.dbManager, this.sdkAgent, this.geminiAgent, this.openRouterAgent, this.sessionEventBroadcaster, this));
|
||||||
|
this.server.registerRoutes(new DataRoutes(this.paginationHelper, this.dbManager, this.sessionManager, this.sseBroadcaster, this, this.startTime));
|
||||||
|
this.server.registerRoutes(new SettingsRoutes(this.settingsManager));
|
||||||
|
this.server.registerRoutes(new LogsRoutes());
|
||||||
|
this.server.registerRoutes(new MemoryRoutes(this.dbManager, 'claude-mem'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user