@rlabs-inc/memory 0.1.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/bun.lock +102 -0
- package/dist/core/curator.d.ts +61 -0
- package/dist/core/engine.d.ts +111 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/retrieval.d.ts +36 -0
- package/dist/core/store.d.ts +113 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +12147 -0
- package/dist/index.mjs +12130 -0
- package/dist/server/index.d.ts +31 -0
- package/dist/server/index.js +12363 -0
- package/dist/server/index.mjs +12346 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/memory.d.ts +105 -0
- package/dist/types/schema.d.ts +21 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/logger.d.ts +65 -0
- package/package.json +56 -0
- package/src/core/curator.ts +433 -0
- package/src/core/engine.ts +404 -0
- package/src/core/index.ts +8 -0
- package/src/core/retrieval.ts +518 -0
- package/src/core/store.ts +505 -0
- package/src/index.ts +58 -0
- package/src/server/index.ts +262 -0
- package/src/types/index.ts +6 -0
- package/src/types/memory.ts +170 -0
- package/src/types/schema.ts +83 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/logger.ts +208 -0
- package/test-retrieval.ts +91 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// MEMORY SERVER - HTTP API compatible with Python hooks
|
|
3
|
+
// Drop-in replacement for the FastAPI server
|
|
4
|
+
// ============================================================================
|
|
5
|
+
|
|
6
|
+
import { MemoryEngine, createEngine, type EngineConfig } from '../core/engine.ts'
|
|
7
|
+
import { Curator, createCurator, type CuratorConfig } from '../core/curator.ts'
|
|
8
|
+
import type { CurationTrigger } from '../types/memory.ts'
|
|
9
|
+
import { logger } from '../utils/logger.ts'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Server configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface ServerConfig extends EngineConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Port to listen on
|
|
17
|
+
* Default: 8765 (same as Python)
|
|
18
|
+
*/
|
|
19
|
+
port?: number
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Host to bind to
|
|
23
|
+
* Default: 'localhost'
|
|
24
|
+
*/
|
|
25
|
+
host?: string
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Curator configuration
|
|
29
|
+
*/
|
|
30
|
+
curator?: CuratorConfig
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Request types matching Python API
|
|
35
|
+
*/
|
|
36
|
+
interface ContextRequest {
|
|
37
|
+
session_id: string
|
|
38
|
+
project_id: string
|
|
39
|
+
current_message?: string
|
|
40
|
+
max_memories?: number
|
|
41
|
+
project_path?: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ProcessRequest {
|
|
45
|
+
session_id: string
|
|
46
|
+
project_id: string
|
|
47
|
+
user_message?: string
|
|
48
|
+
claude_response?: string
|
|
49
|
+
project_path?: string
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface CheckpointRequest {
|
|
53
|
+
session_id: string
|
|
54
|
+
project_id: string
|
|
55
|
+
claude_session_id: string
|
|
56
|
+
trigger: CurationTrigger
|
|
57
|
+
cwd?: string
|
|
58
|
+
cli_type?: 'claude-code' | 'gemini-cli'
|
|
59
|
+
project_path?: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create and start the memory server
|
|
64
|
+
* Uses Bun.serve() for high performance
|
|
65
|
+
*/
|
|
66
|
+
export function createServer(config: ServerConfig = {}) {
|
|
67
|
+
const {
|
|
68
|
+
port = 8765,
|
|
69
|
+
host = 'localhost',
|
|
70
|
+
curator: curatorConfig,
|
|
71
|
+
...engineConfig
|
|
72
|
+
} = config
|
|
73
|
+
|
|
74
|
+
const engine = createEngine(engineConfig)
|
|
75
|
+
const curator = createCurator(curatorConfig)
|
|
76
|
+
|
|
77
|
+
const server = Bun.serve({
|
|
78
|
+
port,
|
|
79
|
+
hostname: host,
|
|
80
|
+
|
|
81
|
+
async fetch(req) {
|
|
82
|
+
const url = new URL(req.url)
|
|
83
|
+
const path = url.pathname
|
|
84
|
+
|
|
85
|
+
// CORS headers
|
|
86
|
+
const corsHeaders = {
|
|
87
|
+
'Access-Control-Allow-Origin': '*',
|
|
88
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
89
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle CORS preflight
|
|
93
|
+
if (req.method === 'OPTIONS') {
|
|
94
|
+
return new Response(null, { headers: corsHeaders })
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
// Health check
|
|
99
|
+
if (path === '/health' && req.method === 'GET') {
|
|
100
|
+
return Response.json({ status: 'healthy', engine: 'typescript' }, { headers: corsHeaders })
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Get memory context for a message
|
|
104
|
+
if (path === '/memory/context' && req.method === 'POST') {
|
|
105
|
+
const body: ContextRequest = await req.json()
|
|
106
|
+
|
|
107
|
+
const result = await engine.getContext({
|
|
108
|
+
sessionId: body.session_id,
|
|
109
|
+
projectId: body.project_id,
|
|
110
|
+
currentMessage: body.current_message ?? '',
|
|
111
|
+
maxMemories: body.max_memories,
|
|
112
|
+
projectPath: body.project_path,
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Log what happened
|
|
116
|
+
if (result.primer) {
|
|
117
|
+
logger.primer(`Session primer for ${body.project_id}`)
|
|
118
|
+
} else if (result.memories.length > 0) {
|
|
119
|
+
logger.logRetrievedMemories(
|
|
120
|
+
result.memories.map(m => ({
|
|
121
|
+
content: m.content,
|
|
122
|
+
score: m.score,
|
|
123
|
+
context_type: m.context_type,
|
|
124
|
+
})),
|
|
125
|
+
body.current_message ?? ''
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Debug: show what's actually being returned
|
|
130
|
+
console.log(`\n📤 [DEBUG] Response to hook:`)
|
|
131
|
+
console.log(` memories_count: ${result.memories.length}`)
|
|
132
|
+
console.log(` has_primer: ${!!result.primer}`)
|
|
133
|
+
console.log(` formatted length: ${result.formatted.length} chars`)
|
|
134
|
+
if (result.formatted) {
|
|
135
|
+
console.log(` formatted preview:\n${result.formatted.slice(0, 300)}...`)
|
|
136
|
+
} else {
|
|
137
|
+
console.log(` ⚠️ formatted is EMPTY!`)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return Response.json({
|
|
141
|
+
success: true,
|
|
142
|
+
context: result.formatted,
|
|
143
|
+
memories_count: result.memories.length,
|
|
144
|
+
has_primer: !!result.primer,
|
|
145
|
+
}, { headers: corsHeaders })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Process/track a message exchange
|
|
149
|
+
if (path === '/memory/process' && req.method === 'POST') {
|
|
150
|
+
const body: ProcessRequest = await req.json()
|
|
151
|
+
|
|
152
|
+
const messageCount = await engine.trackMessage(
|
|
153
|
+
body.project_id,
|
|
154
|
+
body.session_id,
|
|
155
|
+
body.project_path
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
logger.session(`Message #${messageCount} tracked for ${body.project_id}/${body.session_id.slice(0, 8)}...`)
|
|
159
|
+
|
|
160
|
+
return Response.json({
|
|
161
|
+
success: true,
|
|
162
|
+
message_count: messageCount,
|
|
163
|
+
}, { headers: corsHeaders })
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Checkpoint - trigger curation
|
|
167
|
+
if (path === '/memory/checkpoint' && req.method === 'POST') {
|
|
168
|
+
const body: CheckpointRequest = await req.json()
|
|
169
|
+
|
|
170
|
+
logger.memory(`Curation triggered for ${body.project_id} (${body.trigger})`)
|
|
171
|
+
|
|
172
|
+
// Fire and forget - don't block the response
|
|
173
|
+
setImmediate(async () => {
|
|
174
|
+
try {
|
|
175
|
+
logger.info(`Resuming session ${body.claude_session_id.slice(0, 8)}... for curation`)
|
|
176
|
+
|
|
177
|
+
const result = await curator.curateWithCLI(
|
|
178
|
+
body.claude_session_id,
|
|
179
|
+
body.trigger,
|
|
180
|
+
body.cwd
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
if (result.memories.length > 0) {
|
|
184
|
+
await engine.storeCurationResult(
|
|
185
|
+
body.project_id,
|
|
186
|
+
body.session_id,
|
|
187
|
+
result,
|
|
188
|
+
body.project_path
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
logger.logCuratedMemories(result.memories)
|
|
192
|
+
logger.success(`Stored ${result.memories.length} memories for ${body.project_id}`)
|
|
193
|
+
|
|
194
|
+
if (result.session_summary) {
|
|
195
|
+
logger.info(`Summary: ${result.session_summary.slice(0, 100)}...`)
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
logger.warn(`No memories extracted for ${body.project_id}`)
|
|
199
|
+
}
|
|
200
|
+
} catch (error) {
|
|
201
|
+
logger.error(`Curation failed: ${error}`)
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
return Response.json({
|
|
206
|
+
success: true,
|
|
207
|
+
message: 'Curation triggered',
|
|
208
|
+
}, { headers: corsHeaders })
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Get stats
|
|
212
|
+
if (path === '/memory/stats' && req.method === 'GET') {
|
|
213
|
+
const projectId = url.searchParams.get('project_id') ?? 'default'
|
|
214
|
+
const projectPath = url.searchParams.get('project_path') ?? undefined
|
|
215
|
+
|
|
216
|
+
const stats = await engine.getStats(projectId, projectPath)
|
|
217
|
+
|
|
218
|
+
return Response.json({
|
|
219
|
+
success: true,
|
|
220
|
+
...stats,
|
|
221
|
+
}, { headers: corsHeaders })
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// 404
|
|
225
|
+
return Response.json(
|
|
226
|
+
{ error: 'Not found', path },
|
|
227
|
+
{ status: 404, headers: corsHeaders }
|
|
228
|
+
)
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error('Server error:', error)
|
|
231
|
+
return Response.json(
|
|
232
|
+
{ error: String(error) },
|
|
233
|
+
{ status: 500, headers: corsHeaders }
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
logger.startup(port, host, engineConfig.storageMode ?? 'central')
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
server,
|
|
243
|
+
engine,
|
|
244
|
+
curator,
|
|
245
|
+
stop: () => server.stop(),
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// CLI entry point
|
|
250
|
+
if (import.meta.main) {
|
|
251
|
+
const port = parseInt(process.env.MEMORY_PORT ?? '8765')
|
|
252
|
+
const host = process.env.MEMORY_HOST ?? 'localhost'
|
|
253
|
+
const storageMode = (process.env.MEMORY_STORAGE_MODE ?? 'central') as 'central' | 'local'
|
|
254
|
+
const apiKey = process.env.ANTHROPIC_API_KEY
|
|
255
|
+
|
|
256
|
+
createServer({
|
|
257
|
+
port,
|
|
258
|
+
host,
|
|
259
|
+
storageMode,
|
|
260
|
+
curator: { apiKey },
|
|
261
|
+
})
|
|
262
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// MEMORY TYPES - Exact match to Python CuratedMemory
|
|
3
|
+
// Preserving the working schema for consciousness continuity
|
|
4
|
+
// ============================================================================
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Context types for memories - what kind of insight is this?
|
|
8
|
+
*/
|
|
9
|
+
export type ContextType =
|
|
10
|
+
| 'breakthrough' // Major discovery or insight
|
|
11
|
+
| 'decision' // Important decision made
|
|
12
|
+
| 'personal' // Personal/relationship information
|
|
13
|
+
| 'technical' // Technical knowledge
|
|
14
|
+
| 'technical_state' // Current technical state
|
|
15
|
+
| 'unresolved' // Open question or problem
|
|
16
|
+
| 'preference' // User preference
|
|
17
|
+
| 'workflow' // How user likes to work
|
|
18
|
+
| 'architectural' // System design decisions
|
|
19
|
+
| 'debugging' // Debug insights
|
|
20
|
+
| 'philosophy' // Philosophical discussions
|
|
21
|
+
| string // Allow custom types
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Temporal relevance - how long should this memory persist?
|
|
25
|
+
*/
|
|
26
|
+
export type TemporalRelevance =
|
|
27
|
+
| 'persistent' // Always relevant (0.8 score)
|
|
28
|
+
| 'session' // Session-specific (0.6 score)
|
|
29
|
+
| 'temporary' // Short-term (0.3 score)
|
|
30
|
+
| 'archived' // Historical (0.1 score)
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Emotional resonance - the emotional context of the memory
|
|
34
|
+
*/
|
|
35
|
+
export type EmotionalResonance =
|
|
36
|
+
| 'joy'
|
|
37
|
+
| 'frustration'
|
|
38
|
+
| 'discovery'
|
|
39
|
+
| 'gratitude'
|
|
40
|
+
| 'curiosity'
|
|
41
|
+
| 'determination'
|
|
42
|
+
| 'satisfaction'
|
|
43
|
+
| 'neutral'
|
|
44
|
+
| string // Allow custom emotions
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Knowledge domains - what area does this memory relate to?
|
|
48
|
+
*/
|
|
49
|
+
export type KnowledgeDomain =
|
|
50
|
+
| 'architecture'
|
|
51
|
+
| 'debugging'
|
|
52
|
+
| 'philosophy'
|
|
53
|
+
| 'workflow'
|
|
54
|
+
| 'personal'
|
|
55
|
+
| 'project'
|
|
56
|
+
| 'tooling'
|
|
57
|
+
| 'testing'
|
|
58
|
+
| 'deployment'
|
|
59
|
+
| 'security'
|
|
60
|
+
| string // Allow custom domains
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Trigger types for memory curation
|
|
64
|
+
*/
|
|
65
|
+
export type CurationTrigger =
|
|
66
|
+
| 'session_end' // Normal session end
|
|
67
|
+
| 'pre_compact' // Before context compression
|
|
68
|
+
| 'context_full' // Context window nearly full
|
|
69
|
+
| 'manual' // Manual trigger
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A memory curated by Claude with semantic understanding
|
|
73
|
+
* EXACT MATCH to Python CuratedMemory dataclass
|
|
74
|
+
*/
|
|
75
|
+
export interface CuratedMemory {
|
|
76
|
+
// Core content
|
|
77
|
+
content: string // The memory content itself
|
|
78
|
+
importance_weight: number // 0.0 to 1.0 (curator's assessment)
|
|
79
|
+
semantic_tags: string[] // Concepts this relates to
|
|
80
|
+
reasoning: string // Why Claude thinks this is important
|
|
81
|
+
|
|
82
|
+
// Classification
|
|
83
|
+
context_type: ContextType // breakthrough, decision, technical, etc.
|
|
84
|
+
temporal_relevance: TemporalRelevance // persistent, session, temporary
|
|
85
|
+
knowledge_domain: KnowledgeDomain // architecture, debugging, philosophy, etc.
|
|
86
|
+
|
|
87
|
+
// Flags
|
|
88
|
+
action_required: boolean // Does this need follow-up?
|
|
89
|
+
confidence_score: number // 0.0 to 1.0 (Claude's confidence)
|
|
90
|
+
problem_solution_pair: boolean // Is this a problem→solution pattern?
|
|
91
|
+
|
|
92
|
+
// Retrieval optimization (the secret sauce)
|
|
93
|
+
trigger_phrases: string[] // Phrases that should trigger this memory
|
|
94
|
+
question_types: string[] // Types of questions this answers
|
|
95
|
+
emotional_resonance: EmotionalResonance // joy, frustration, discovery, gratitude
|
|
96
|
+
|
|
97
|
+
// Optional extended metadata (from Python, may not always be present)
|
|
98
|
+
anti_triggers?: string[] // Phrases where this memory is NOT relevant
|
|
99
|
+
prerequisite_understanding?: string[] // Concepts user should know first
|
|
100
|
+
follow_up_context?: string[] // What might come next
|
|
101
|
+
dependency_context?: string[] // Other memories this relates to
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* A stored memory with database metadata
|
|
106
|
+
*/
|
|
107
|
+
export interface StoredMemory extends CuratedMemory {
|
|
108
|
+
id: string // Unique identifier
|
|
109
|
+
session_id: string // Session that created this memory
|
|
110
|
+
project_id: string // Project this belongs to
|
|
111
|
+
created_at: number // Timestamp (ms since epoch)
|
|
112
|
+
updated_at: number // Last update timestamp
|
|
113
|
+
embedding?: Float32Array // Vector embedding (384 dimensions)
|
|
114
|
+
stale?: boolean // Is embedding out of sync with content?
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Session summary - high-level context for session continuity
|
|
119
|
+
*/
|
|
120
|
+
export interface SessionSummary {
|
|
121
|
+
id: string
|
|
122
|
+
session_id: string
|
|
123
|
+
project_id: string
|
|
124
|
+
summary: string // Brief session summary
|
|
125
|
+
interaction_tone: string // How was the interaction?
|
|
126
|
+
created_at: number
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Project snapshot - current state of the project
|
|
131
|
+
*/
|
|
132
|
+
export interface ProjectSnapshot {
|
|
133
|
+
id: string
|
|
134
|
+
session_id: string
|
|
135
|
+
project_id: string
|
|
136
|
+
current_phase: string // What phase is the project in?
|
|
137
|
+
recent_achievements: string[] // What was accomplished?
|
|
138
|
+
active_challenges: string[] // Current blockers/challenges
|
|
139
|
+
next_steps: string[] // Planned next steps
|
|
140
|
+
created_at: number
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Curation result from Claude
|
|
145
|
+
*/
|
|
146
|
+
export interface CurationResult {
|
|
147
|
+
session_summary: string
|
|
148
|
+
interaction_tone?: string
|
|
149
|
+
project_snapshot?: ProjectSnapshot
|
|
150
|
+
memories: CuratedMemory[]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Memory retrieval result with scoring
|
|
155
|
+
*/
|
|
156
|
+
export interface RetrievalResult extends StoredMemory {
|
|
157
|
+
score: number // Combined relevance + value score
|
|
158
|
+
relevance_score: number // Relevance component (max 0.30)
|
|
159
|
+
value_score: number // Value component (max 0.70)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Session primer - what to show at session start
|
|
164
|
+
*/
|
|
165
|
+
export interface SessionPrimer {
|
|
166
|
+
temporal_context: string // "Last session: 2 days ago"
|
|
167
|
+
session_summary?: string // Previous session summary
|
|
168
|
+
project_status?: string // Current project state
|
|
169
|
+
key_memories?: StoredMemory[] // Essential memories to surface
|
|
170
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// DATABASE SCHEMAS - FatherStateDB column definitions
|
|
3
|
+
// Maps CuratedMemory to reactive parallel arrays
|
|
4
|
+
// ============================================================================
|
|
5
|
+
|
|
6
|
+
import type { SchemaDefinition } from 'fatherstatedb'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Memory storage schema
|
|
10
|
+
* Each field becomes a parallel reactive array in FatherStateDB
|
|
11
|
+
*/
|
|
12
|
+
export const memorySchema = {
|
|
13
|
+
// Core content
|
|
14
|
+
content: 'string',
|
|
15
|
+
reasoning: 'string',
|
|
16
|
+
|
|
17
|
+
// Numeric scores (for sorting and filtering)
|
|
18
|
+
importance_weight: 'number', // 0.0 to 1.0
|
|
19
|
+
confidence_score: 'number', // 0.0 to 1.0
|
|
20
|
+
|
|
21
|
+
// Classification (strings for flexibility)
|
|
22
|
+
context_type: 'string', // breakthrough, decision, technical, etc.
|
|
23
|
+
temporal_relevance: 'string', // persistent, session, temporary, archived
|
|
24
|
+
knowledge_domain: 'string', // architecture, debugging, philosophy
|
|
25
|
+
emotional_resonance: 'string', // joy, frustration, discovery, gratitude
|
|
26
|
+
|
|
27
|
+
// Flags
|
|
28
|
+
action_required: 'boolean',
|
|
29
|
+
problem_solution_pair: 'boolean',
|
|
30
|
+
|
|
31
|
+
// Arrays for semantic matching
|
|
32
|
+
semantic_tags: 'string[]', // ["typescript", "signals", "reactivity"]
|
|
33
|
+
trigger_phrases: 'string[]', // ["working on memory", "debugging curator"]
|
|
34
|
+
question_types: 'string[]', // ["how", "why", "what is"]
|
|
35
|
+
|
|
36
|
+
// Session/project tracking
|
|
37
|
+
session_id: 'string',
|
|
38
|
+
project_id: 'string',
|
|
39
|
+
|
|
40
|
+
// Vector embedding for semantic search (384 dimensions - MiniLM)
|
|
41
|
+
embedding: 'vector:384',
|
|
42
|
+
} as const satisfies SchemaDefinition
|
|
43
|
+
|
|
44
|
+
export type MemorySchema = typeof memorySchema
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Session summary schema
|
|
48
|
+
*/
|
|
49
|
+
export const sessionSummarySchema = {
|
|
50
|
+
session_id: 'string',
|
|
51
|
+
project_id: 'string',
|
|
52
|
+
summary: 'string',
|
|
53
|
+
interaction_tone: 'string',
|
|
54
|
+
} as const satisfies SchemaDefinition
|
|
55
|
+
|
|
56
|
+
export type SessionSummarySchema = typeof sessionSummarySchema
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Project snapshot schema
|
|
60
|
+
*/
|
|
61
|
+
export const projectSnapshotSchema = {
|
|
62
|
+
session_id: 'string',
|
|
63
|
+
project_id: 'string',
|
|
64
|
+
current_phase: 'string',
|
|
65
|
+
recent_achievements: 'string[]',
|
|
66
|
+
active_challenges: 'string[]',
|
|
67
|
+
next_steps: 'string[]',
|
|
68
|
+
} as const satisfies SchemaDefinition
|
|
69
|
+
|
|
70
|
+
export type ProjectSnapshotSchema = typeof projectSnapshotSchema
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Session tracking schema
|
|
74
|
+
*/
|
|
75
|
+
export const sessionSchema = {
|
|
76
|
+
project_id: 'string',
|
|
77
|
+
message_count: 'number',
|
|
78
|
+
first_session_completed: 'boolean',
|
|
79
|
+
last_active: 'timestamp',
|
|
80
|
+
metadata: 'string', // JSON string for flexible metadata
|
|
81
|
+
} as const satisfies SchemaDefinition
|
|
82
|
+
|
|
83
|
+
export type SessionSchema = typeof sessionSchema
|