get-claudia 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -102
- package/assets/claudia-install.gif +0 -0
- package/memory-daemon/claudia_memory/config.py +16 -3
- package/memory-daemon/claudia_memory/database.py +44 -0
- package/memory-daemon/claudia_memory/mcp/server.py +358 -4
- package/memory-daemon/claudia_memory/schema.sql +4 -0
- package/memory-daemon/claudia_memory/services/consolidate.py +56 -0
- package/memory-daemon/claudia_memory/services/recall.py +251 -95
- package/memory-daemon/tests/test_fts_hybrid.py +182 -0
- package/memory-daemon/tests/test_session_context.py +356 -0
- package/package.json +1 -1
- package/template-v2/.claude/commands/capture-meeting.md +9 -13
- package/template-v2/.claude/commands/morning-brief.md +15 -13
- package/template-v2/.claude/commands/weekly-review.md +6 -4
- package/template-v2/.claude/hooks/hooks.json +3 -2
- package/template-v2/.claude/rules/claudia-principles.md +16 -0
- package/template-v2/.claude/skills/memory-manager.md +48 -0
- package/template-v2/.claude/skills/risk-surfacer.md +4 -0
- package/template-v2/CLAUDE.md +11 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<a href="https://python.org"><img src="https://img.shields.io/badge/python-%3E%3D3.10-blue?style=flat-square" alt="Python"></a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
<h3 align="center">An AI
|
|
13
|
+
<h3 align="center">An AI thinking partner who learns how you work.</h3>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<em>"Busy work is my job. Judgment is yours."</em>
|
|
@@ -22,13 +22,58 @@ Created by <a href="https://github.com/kbanc85">Kamil Banc</a> · <a href="https
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## The Problem
|
|
26
|
+
|
|
27
|
+
You finish a call and forget to follow up. You promise a deliverable on Friday and lose track of it by Wednesday. You meet someone important, and three weeks later you can't remember what you talked about. You juggle four clients, two projects, and a growing pipeline, and the context lives scattered across notes, emails, and your memory.
|
|
28
|
+
|
|
29
|
+
AI tools can draft emails and summarize documents. But none of them actually *know* you. None of them remember last Tuesday's conversation, track the commitment you made to Sarah, or warn you that you haven't talked to your best client in three weeks.
|
|
30
|
+
|
|
31
|
+
That's the gap Claudia fills.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
25
35
|
## What Is Claudia?
|
|
26
36
|
|
|
27
|
-
Claudia is an open-source
|
|
37
|
+
Claudia is an open-source AI thinking partner that runs inside [Claude Code](https://docs.anthropic.com/en/docs/claude-code). She remembers your conversations, tracks your relationships, catches commitments you make, and adapts to match how you actually work.
|
|
38
|
+
|
|
39
|
+
Not a chatbot. Not a task manager. Not another inbox. She's a thinking partner with memory that compounds over time.
|
|
28
40
|
|
|
29
41
|
Everything runs locally. Your data stays on your machine.
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## See It in Action
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Claudia: Hey there. I'm Claudia. What's your name?
|
|
49
|
+
|
|
50
|
+
You: Sarah
|
|
51
|
+
|
|
52
|
+
Claudia: Nice to meet you, Sarah. What do you do?
|
|
53
|
+
|
|
54
|
+
You: I'm a fractional CMO. I work with 4 clients right now.
|
|
55
|
+
|
|
56
|
+
Claudia: Got it. What are your top priorities?
|
|
57
|
+
|
|
58
|
+
You: Client deliverables, growing my pipeline, and not dropping balls
|
|
59
|
+
|
|
60
|
+
Claudia: Based on what you've shared, here's how I'd organize things:
|
|
61
|
+
|
|
62
|
+
clients/ [one folder per client]
|
|
63
|
+
people/ [key relationships]
|
|
64
|
+
context/ [commitments, waiting-on items]
|
|
65
|
+
|
|
66
|
+
And I'll set up commands for your work:
|
|
67
|
+
/morning-brief, /client-status, /meeting-prep
|
|
68
|
+
|
|
69
|
+
Want me to create this?
|
|
70
|
+
|
|
71
|
+
You: Yes, do it
|
|
72
|
+
|
|
73
|
+
Claudia: Done. Try '/morning-brief' tomorrow, or tell me about a client.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
From here, every conversation builds on the last. She remembers.
|
|
32
77
|
|
|
33
78
|
---
|
|
34
79
|
|
|
@@ -38,16 +83,20 @@ Everything runs locally. Your data stays on your machine.
|
|
|
38
83
|
npx get-claudia
|
|
39
84
|
```
|
|
40
85
|
|
|
41
|
-
|
|
86
|
+
<p align="center">
|
|
87
|
+
<img src="assets/claudia-install.gif" alt="Installing Claudia" width="600">
|
|
88
|
+
</p>
|
|
89
|
+
|
|
90
|
+
The installer walks you through everything: creates your workspace, installs the memory system, and optionally sets up a local language model. Then:
|
|
42
91
|
|
|
43
92
|
```bash
|
|
44
93
|
cd claudia
|
|
45
94
|
claude
|
|
46
95
|
```
|
|
47
96
|
|
|
48
|
-
Say hi. She'll introduce herself and learn about you in a natural conversation. Within a few
|
|
97
|
+
Say hi. She'll introduce herself and learn about you in a natural conversation. Within a few sessions, she'll have a personalized workspace, commands, and workflows tailored to your role.
|
|
49
98
|
|
|
50
|
-
**Requirements:** [Claude Code](https://docs.anthropic.com/en/docs/claude-code), Node.js 14+, Python 3.10+ (for memory
|
|
99
|
+
**Requirements:** [Claude Code](https://docs.anthropic.com/en/docs/claude-code), Node.js 14+, Python 3.10+ (for memory)
|
|
51
100
|
|
|
52
101
|
**Already have Claudia?** Upgrade from any version:
|
|
53
102
|
```bash
|
|
@@ -59,68 +108,51 @@ This upgrades framework files while preserving your data (context/, people/, pro
|
|
|
59
108
|
|
|
60
109
|
---
|
|
61
110
|
|
|
62
|
-
##
|
|
111
|
+
## What She Actually Does
|
|
63
112
|
|
|
64
|
-
|
|
113
|
+
Claudia isn't a list of features. She's a set of outcomes:
|
|
65
114
|
|
|
66
|
-
|
|
115
|
+
- **Catches your commitments.** Say "I'll send that proposal by Friday" in conversation, and she'll track it. On Friday morning, she'll remind you.
|
|
116
|
+
- **Remembers your relationships.** Mention Sarah from Acme, and Claudia surfaces what she knows: last conversation, open commitments, communication frequency, sentiment.
|
|
117
|
+
- **Warns you before things slip.** Haven't talked to your best client in three weeks? Overdue on a deliverable? She surfaces it without being asked.
|
|
118
|
+
- **Processes your meetings.** Paste a transcript. She pulls out decisions, action items, and follow-ups, then stores them where they belong.
|
|
119
|
+
- **Adapts to how you work.** She notices patterns ("You draft LinkedIn posts almost daily. Want me to add a quick command for that?") and suggests improvements to her own workflow.
|
|
67
120
|
|
|
68
|
-
|
|
69
|
-
- **Per-project isolation** so work memories don't mix with personal projects
|
|
70
|
-
- **Session narratives** that capture tone, emotional context, and unresolved threads
|
|
71
|
-
- **Source provenance** for tracing any fact back to the email, transcript, or conversation it came from
|
|
121
|
+
---
|
|
72
122
|
|
|
73
|
-
|
|
123
|
+
## Who It's For
|
|
74
124
|
|
|
75
|
-
|
|
125
|
+
Claudia detects your work style during setup and generates structure that fits:
|
|
76
126
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| **Risk Surfacer** | Proactively warns about overdue items, cooling relationships, capacity issues |
|
|
83
|
-
| **Memory Manager** | Handles session startup, shutdown, and cross-session persistence |
|
|
84
|
-
| **Capability Suggester** | Notices repeated tasks and offers to create commands for them |
|
|
85
|
-
| **Onboarding** | First-run discovery that generates your personalized workspace |
|
|
86
|
-
| **Structure Generator** | Creates folder structures and commands matched to your archetype |
|
|
127
|
+
- **Consultant** -- Multiple clients, deliverables, proposals, pipeline tracking
|
|
128
|
+
- **Executive** -- Direct reports, initiatives, leadership, board prep
|
|
129
|
+
- **Founder** -- Investors, team, product, fundraising cycles
|
|
130
|
+
- **Solo Professional** -- Mix of clients and projects, wearing many hats
|
|
131
|
+
- **Creator** -- Audience growth, content calendar, collaborations
|
|
87
132
|
|
|
88
|
-
|
|
133
|
+
Each gets custom folder structures, commands, and templates.
|
|
89
134
|
|
|
90
|
-
|
|
135
|
+
---
|
|
91
136
|
|
|
92
|
-
|
|
93
|
-
- Choose your model: Qwen3-4B (recommended), SmolLM3-3B, or Llama 3.2-3B
|
|
94
|
-
- Falls back gracefully when no model is installed
|
|
137
|
+
## How She Gets Smarter
|
|
95
138
|
|
|
96
|
-
|
|
139
|
+
Claudia suggests improvements as she learns your patterns:
|
|
97
140
|
|
|
98
|
-
|
|
141
|
+
> "I notice you draft LinkedIn posts almost daily. Want me to add a `/linkedin-quick` command?"
|
|
99
142
|
|
|
100
|
-
|
|
101
|
-
|-----------|--------------|
|
|
102
|
-
| **Consultant** | Multiple clients, deliverables, proposals, pipeline |
|
|
103
|
-
| **Executive** | Direct reports, initiatives, leadership, board prep |
|
|
104
|
-
| **Founder** | Investors, team, product, fundraising |
|
|
105
|
-
| **Solo Professional** | Mix of clients and projects, wearing many hats |
|
|
106
|
-
| **Creator** | Audience, content calendar, collaborations |
|
|
143
|
+
> "You often ask about project status on Mondays. Should I add that to your morning brief?"
|
|
107
144
|
|
|
108
|
-
|
|
145
|
+
> "You've mentioned being stretched thin in three conversations this week."
|
|
109
146
|
|
|
110
|
-
|
|
147
|
+
She challenges constructively, surfaces what you might be missing, and adapts her structure to fit how your work actually evolves.
|
|
111
148
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
| `/draft-reply` | Email response drafts in your voice |
|
|
120
|
-
| `/follow-up-draft [person]` | Post-meeting thank-you and summary |
|
|
121
|
-
| `/new-person [name]` | Create a relationship file |
|
|
122
|
-
| `/pipeline-review` | Active deals, capacity, pipeline health |
|
|
123
|
-
| `/accountability-check` | Outstanding commitments and waiting-on items |
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Privacy and Safety
|
|
152
|
+
|
|
153
|
+
- **Fully local.** Memory, embeddings, and cognitive tools run on your machine. No external APIs for data storage.
|
|
154
|
+
- **No external actions without approval.** Every email, calendar event, and external action requires your explicit "yes." Non-negotiable, enforced at the framework level.
|
|
155
|
+
- **Your data is yours.** Memories live in `~/.claudia/memory/` as SQLite databases. Context lives in readable markdown files. Delete anything, anytime.
|
|
124
156
|
|
|
125
157
|
---
|
|
126
158
|
|
|
@@ -130,11 +162,11 @@ Claudia has two layers:
|
|
|
130
162
|
|
|
131
163
|
**Template layer** (markdown) defines who she is. Skills, commands, rules, and identity files that Claude reads on startup. This is what makes her Claudia rather than generic Claude.
|
|
132
164
|
|
|
133
|
-
**Memory system** (Python) defines what she remembers. A daemon running locally with SQLite, vector embeddings
|
|
165
|
+
**Memory system** (Python) defines what she remembers. A daemon running locally with SQLite, vector embeddings, and three service layers:
|
|
134
166
|
|
|
135
|
-
- **Remember** stores facts, entities, and relationships with embeddings for semantic search
|
|
136
|
-
- **Recall** retrieves memories using hybrid ranking (vector similarity + importance + recency)
|
|
137
|
-
- **Consolidate** runs in the background: decaying old memories, detecting patterns, generating predictions
|
|
167
|
+
- **Remember** -- stores facts, entities, and relationships with embeddings for semantic search
|
|
168
|
+
- **Recall** -- retrieves memories using hybrid ranking (vector similarity + importance + recency)
|
|
169
|
+
- **Consolidate** -- runs in the background: decaying old memories, detecting patterns, generating predictions
|
|
138
170
|
|
|
139
171
|
```
|
|
140
172
|
You talk to Claude Code
|
|
@@ -155,73 +187,71 @@ Memory daemon processes locally: SQLite + vector search + Ollama
|
|
|
155
187
|
Everything stays on your machine
|
|
156
188
|
```
|
|
157
189
|
|
|
158
|
-
For
|
|
190
|
+
For full technical diagrams, see [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
159
191
|
|
|
160
192
|
---
|
|
161
193
|
|
|
162
|
-
##
|
|
163
|
-
|
|
164
|
-
When you first run `claude`, she introduces herself:
|
|
194
|
+
## Key Commands
|
|
165
195
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
196
|
+
| Command | What It Does |
|
|
197
|
+
|---------|-------------|
|
|
198
|
+
| `/morning-brief` | What needs attention today: commitments, meetings, warnings |
|
|
199
|
+
| `/meeting-prep [person]` | One-page briefing before a call |
|
|
200
|
+
| `/capture-meeting` | Process notes into decisions, commitments, action items |
|
|
201
|
+
| `/what-am-i-missing` | Surface risks, overdue items, cooling relationships |
|
|
202
|
+
| `/weekly-review` | Guided reflection across relationships and projects |
|
|
203
|
+
| `/accountability-check` | Outstanding commitments and waiting-on items |
|
|
169
204
|
|
|
170
|
-
|
|
205
|
+
<details>
|
|
206
|
+
<summary>All commands</summary>
|
|
171
207
|
|
|
172
|
-
|
|
173
|
-
|
|
208
|
+
| Command | What It Does |
|
|
209
|
+
|---------|-------------|
|
|
210
|
+
| `/draft-reply` | Email response drafts in your voice |
|
|
211
|
+
| `/follow-up-draft [person]` | Post-meeting thank-you and summary |
|
|
212
|
+
| `/new-person [name]` | Create a relationship file |
|
|
213
|
+
| `/pipeline-review` | Active deals, capacity, pipeline health |
|
|
174
214
|
|
|
175
|
-
|
|
215
|
+
</details>
|
|
176
216
|
|
|
177
|
-
|
|
217
|
+
---
|
|
178
218
|
|
|
179
|
-
|
|
219
|
+
## Advanced: Memory System
|
|
180
220
|
|
|
181
|
-
Claudia
|
|
221
|
+
Claudia's memory goes beyond chat history. She stores facts, preferences, commitments, and observations in a local SQLite database with 384-dimensional vector embeddings (via [Ollama](https://ollama.com) and the all-minilm:l6-v2 model).
|
|
182
222
|
|
|
183
|
-
|
|
184
|
-
[one folder per client]
|
|
185
|
-
people/
|
|
186
|
-
[key relationships]
|
|
187
|
-
context/
|
|
188
|
-
commitments.md
|
|
189
|
-
waiting.md
|
|
223
|
+
**Semantic search** uses a 60/30/10 scoring formula: 60% vector similarity, 30% importance weighting, 10% recency. Accessing a memory boosts it (rehearsal effect), so frequently referenced facts stay prominent.
|
|
190
224
|
|
|
191
|
-
|
|
192
|
-
/morning-brief, /client-status, /meeting-prep
|
|
225
|
+
**Per-project isolation** keeps work memories separate from personal projects. Each workspace gets its own database, keyed by folder path hash.
|
|
193
226
|
|
|
194
|
-
|
|
227
|
+
**Session narratives** capture tone, emotional context, and unresolved threads, so Claudia understands not just what happened but how the conversation felt.
|
|
195
228
|
|
|
196
|
-
|
|
229
|
+
**Source provenance** traces any fact back to the email, transcript, or conversation it came from.
|
|
197
230
|
|
|
198
|
-
|
|
199
|
-
or tell me about one of your clients.
|
|
200
|
-
```
|
|
231
|
+
**Eight built-in skills** activate automatically based on context:
|
|
201
232
|
|
|
202
|
-
|
|
233
|
+
| Skill | What It Does |
|
|
234
|
+
|-------|-------------|
|
|
235
|
+
| **Commitment Detector** | Catches promises in conversation. "I'll send that by Friday" triggers tracking |
|
|
236
|
+
| **Relationship Tracker** | Surfaces context when people are mentioned. Tracks contact frequency, sentiment |
|
|
237
|
+
| **Pattern Recognizer** | Notices recurring themes after 3+ observations |
|
|
238
|
+
| **Risk Surfacer** | Warns about overdue items, cooling relationships, capacity issues |
|
|
239
|
+
| **Memory Manager** | Handles session startup, shutdown, and cross-session persistence |
|
|
240
|
+
| **Capability Suggester** | Notices repeated tasks and offers to create commands for them |
|
|
241
|
+
| **Onboarding** | First-run discovery that generates your personalized workspace |
|
|
242
|
+
| **Structure Generator** | Creates folder structures and commands matched to your archetype |
|
|
203
243
|
|
|
204
244
|
---
|
|
205
245
|
|
|
206
|
-
##
|
|
207
|
-
|
|
208
|
-
Claudia suggests improvements as she learns your patterns:
|
|
209
|
-
|
|
210
|
-
> "I notice you draft LinkedIn posts almost daily. Want me to add a `/linkedin-quick` command?"
|
|
211
|
-
|
|
212
|
-
> "You often ask about project status on Mondays. Should I add that to your morning brief?"
|
|
213
|
-
|
|
214
|
-
> "You've mentioned being stretched thin in three conversations this week."
|
|
246
|
+
## Advanced: Cognitive Tools
|
|
215
247
|
|
|
216
|
-
|
|
248
|
+
Paste a meeting transcript or email. Instead of Claude parsing it token by token, a local language model extracts structured data (entities, facts, commitments, action items) in seconds. Claude then reviews the output and applies judgment.
|
|
217
249
|
|
|
218
|
-
|
|
250
|
+
- Runs locally via [Ollama](https://ollama.com), no API keys needed
|
|
251
|
+
- Choose your model during install: Qwen3-4B (recommended), SmolLM3-3B, or Llama 3.2-3B
|
|
252
|
+
- Falls back gracefully when no model is installed (Claude handles extraction directly)
|
|
219
253
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
- **Fully local.** Memory, embeddings, and cognitive tools run on your machine. No external APIs (unless you choose to use Claude Code's cloud connection for the main conversation).
|
|
223
|
-
- **No external actions without approval.** Every email, calendar event, and external action requires your explicit "yes." This is non-negotiable and enforced at the framework level.
|
|
224
|
-
- **Your data is yours.** Memories live in `~/.claudia/memory/` as SQLite databases. Context lives in readable markdown files. Delete anything, anytime.
|
|
254
|
+
Four specialized extraction modes: **meeting** (participants, decisions, action items), **email** (sender, recipients, tone, action items), **document** (key points, entities, relationships), and **general** (facts, commitments, entities).
|
|
225
255
|
|
|
226
256
|
---
|
|
227
257
|
|
|
Binary file
|
|
@@ -35,9 +35,10 @@ class MemoryConfig:
|
|
|
35
35
|
|
|
36
36
|
# Search settings
|
|
37
37
|
max_recall_results: int = 20
|
|
38
|
-
vector_weight: float = 0.
|
|
39
|
-
importance_weight: float = 0.
|
|
40
|
-
recency_weight: float = 0.
|
|
38
|
+
vector_weight: float = 0.50 # Weight for vector similarity in ranking
|
|
39
|
+
importance_weight: float = 0.25 # Weight for importance score
|
|
40
|
+
recency_weight: float = 0.10 # Weight for recency
|
|
41
|
+
fts_weight: float = 0.15 # Weight for FTS5 full-text search match
|
|
41
42
|
|
|
42
43
|
# Health check
|
|
43
44
|
health_port: int = 3848
|
|
@@ -83,6 +84,14 @@ class MemoryConfig:
|
|
|
83
84
|
config.pattern_detection_interval_hours = data["pattern_detection_interval_hours"]
|
|
84
85
|
if "max_recall_results" in data:
|
|
85
86
|
config.max_recall_results = data["max_recall_results"]
|
|
87
|
+
if "vector_weight" in data:
|
|
88
|
+
config.vector_weight = data["vector_weight"]
|
|
89
|
+
if "importance_weight" in data:
|
|
90
|
+
config.importance_weight = data["importance_weight"]
|
|
91
|
+
if "recency_weight" in data:
|
|
92
|
+
config.recency_weight = data["recency_weight"]
|
|
93
|
+
if "fts_weight" in data:
|
|
94
|
+
config.fts_weight = data["fts_weight"]
|
|
86
95
|
if "health_port" in data:
|
|
87
96
|
config.health_port = data["health_port"]
|
|
88
97
|
if "log_path" in data:
|
|
@@ -119,6 +128,10 @@ class MemoryConfig:
|
|
|
119
128
|
"consolidation_interval_hours": self.consolidation_interval_hours,
|
|
120
129
|
"pattern_detection_interval_hours": self.pattern_detection_interval_hours,
|
|
121
130
|
"max_recall_results": self.max_recall_results,
|
|
131
|
+
"vector_weight": self.vector_weight,
|
|
132
|
+
"importance_weight": self.importance_weight,
|
|
133
|
+
"recency_weight": self.recency_weight,
|
|
134
|
+
"fts_weight": self.fts_weight,
|
|
122
135
|
"health_port": self.health_port,
|
|
123
136
|
"log_path": str(self.log_path),
|
|
124
137
|
}
|
|
@@ -259,6 +259,50 @@ class Database:
|
|
|
259
259
|
conn.commit()
|
|
260
260
|
logger.info("Applied migration 3: episodic memory provenance")
|
|
261
261
|
|
|
262
|
+
if current_version < 4:
|
|
263
|
+
# Migration 4: Add FTS5 full-text search table and auto-sync triggers
|
|
264
|
+
try:
|
|
265
|
+
conn.execute(
|
|
266
|
+
"""CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
267
|
+
content,
|
|
268
|
+
content=memories,
|
|
269
|
+
content_rowid=id,
|
|
270
|
+
tokenize='porter unicode61'
|
|
271
|
+
)"""
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
# Auto-sync triggers
|
|
275
|
+
conn.execute(
|
|
276
|
+
"""CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
277
|
+
INSERT INTO memories_fts(rowid, content) VALUES (new.id, new.content);
|
|
278
|
+
END"""
|
|
279
|
+
)
|
|
280
|
+
conn.execute(
|
|
281
|
+
"""CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
282
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.id, old.content);
|
|
283
|
+
END"""
|
|
284
|
+
)
|
|
285
|
+
conn.execute(
|
|
286
|
+
"""CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
287
|
+
INSERT INTO memories_fts(memories_fts, rowid, content) VALUES ('delete', old.id, old.content);
|
|
288
|
+
INSERT INTO memories_fts(rowid, content) VALUES (new.id, new.content);
|
|
289
|
+
END"""
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Backfill existing memories into FTS5 index
|
|
293
|
+
conn.execute(
|
|
294
|
+
"INSERT INTO memories_fts(rowid, content) SELECT id, content FROM memories"
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
conn.execute(
|
|
298
|
+
"INSERT OR IGNORE INTO schema_migrations (version, description) VALUES (4, 'Add FTS5 full-text search table and auto-sync triggers for hybrid search')"
|
|
299
|
+
)
|
|
300
|
+
conn.commit()
|
|
301
|
+
logger.info("Applied migration 4: FTS5 hybrid search")
|
|
302
|
+
except Exception as e:
|
|
303
|
+
logger.warning(f"Migration 4 (FTS5) failed: {e}. FTS5 may not be available.")
|
|
304
|
+
# FTS5 is optional; the system degrades gracefully without it
|
|
305
|
+
|
|
262
306
|
def execute(
|
|
263
307
|
self, sql: str, params: Tuple = (), fetch: bool = False
|
|
264
308
|
) -> Optional[List[sqlite3.Row]]:
|