ahok-skill 1.3.1
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/.prettierrc +8 -0
- package/Dockerfile +59 -0
- package/RAW_SKILL.md +219 -0
- package/README.md +277 -0
- package/SKILL.md +58 -0
- package/bin/opm.js +268 -0
- package/data/openmemory.sqlite +0 -0
- package/data/openmemory.sqlite-shm +0 -0
- package/data/openmemory.sqlite-wal +0 -0
- package/dist/ai/graph.js +293 -0
- package/dist/ai/mcp.js +397 -0
- package/dist/cli.js +78 -0
- package/dist/core/cfg.js +87 -0
- package/dist/core/db.js +636 -0
- package/dist/core/memory.js +116 -0
- package/dist/core/migrate.js +227 -0
- package/dist/core/models.js +105 -0
- package/dist/core/telemetry.js +57 -0
- package/dist/core/types.js +2 -0
- package/dist/core/vector/postgres.js +52 -0
- package/dist/core/vector/valkey.js +246 -0
- package/dist/core/vector_store.js +2 -0
- package/dist/index.js +44 -0
- package/dist/memory/decay.js +301 -0
- package/dist/memory/embed.js +675 -0
- package/dist/memory/hsg.js +959 -0
- package/dist/memory/reflect.js +131 -0
- package/dist/memory/user_summary.js +99 -0
- package/dist/migrate.js +9 -0
- package/dist/ops/compress.js +255 -0
- package/dist/ops/dynamics.js +189 -0
- package/dist/ops/extract.js +333 -0
- package/dist/ops/ingest.js +214 -0
- package/dist/server/index.js +109 -0
- package/dist/server/middleware/auth.js +137 -0
- package/dist/server/routes/auth.js +186 -0
- package/dist/server/routes/compression.js +108 -0
- package/dist/server/routes/dashboard.js +399 -0
- package/dist/server/routes/docs.js +241 -0
- package/dist/server/routes/dynamics.js +312 -0
- package/dist/server/routes/ide.js +280 -0
- package/dist/server/routes/index.js +33 -0
- package/dist/server/routes/keys.js +132 -0
- package/dist/server/routes/langgraph.js +61 -0
- package/dist/server/routes/memory.js +213 -0
- package/dist/server/routes/sources.js +140 -0
- package/dist/server/routes/system.js +63 -0
- package/dist/server/routes/temporal.js +293 -0
- package/dist/server/routes/users.js +101 -0
- package/dist/server/routes/vercel.js +57 -0
- package/dist/server/server.js +211 -0
- package/dist/server.js +3 -0
- package/dist/sources/base.js +223 -0
- package/dist/sources/github.js +171 -0
- package/dist/sources/google_drive.js +166 -0
- package/dist/sources/google_sheets.js +112 -0
- package/dist/sources/google_slides.js +139 -0
- package/dist/sources/index.js +34 -0
- package/dist/sources/notion.js +165 -0
- package/dist/sources/onedrive.js +143 -0
- package/dist/sources/web_crawler.js +166 -0
- package/dist/temporal_graph/index.js +20 -0
- package/dist/temporal_graph/query.js +240 -0
- package/dist/temporal_graph/store.js +116 -0
- package/dist/temporal_graph/timeline.js +241 -0
- package/dist/temporal_graph/types.js +2 -0
- package/dist/utils/chunking.js +60 -0
- package/dist/utils/index.js +31 -0
- package/dist/utils/keyword.js +94 -0
- package/dist/utils/text.js +120 -0
- package/nodemon.json +7 -0
- package/package.json +50 -0
- package/references/api_reference.md +66 -0
- package/references/examples.md +45 -0
- package/src/ai/graph.ts +363 -0
- package/src/ai/mcp.ts +494 -0
- package/src/cli.ts +94 -0
- package/src/core/cfg.ts +110 -0
- package/src/core/db.ts +1052 -0
- package/src/core/memory.ts +99 -0
- package/src/core/migrate.ts +302 -0
- package/src/core/models.ts +107 -0
- package/src/core/telemetry.ts +47 -0
- package/src/core/types.ts +130 -0
- package/src/core/vector/postgres.ts +61 -0
- package/src/core/vector/valkey.ts +261 -0
- package/src/core/vector_store.ts +9 -0
- package/src/index.ts +5 -0
- package/src/memory/decay.ts +427 -0
- package/src/memory/embed.ts +707 -0
- package/src/memory/hsg.ts +1245 -0
- package/src/memory/reflect.ts +158 -0
- package/src/memory/user_summary.ts +110 -0
- package/src/migrate.ts +8 -0
- package/src/ops/compress.ts +296 -0
- package/src/ops/dynamics.ts +272 -0
- package/src/ops/extract.ts +360 -0
- package/src/ops/ingest.ts +286 -0
- package/src/server/index.ts +159 -0
- package/src/server/middleware/auth.ts +156 -0
- package/src/server/routes/auth.ts +223 -0
- package/src/server/routes/compression.ts +106 -0
- package/src/server/routes/dashboard.ts +420 -0
- package/src/server/routes/docs.ts +380 -0
- package/src/server/routes/dynamics.ts +516 -0
- package/src/server/routes/ide.ts +283 -0
- package/src/server/routes/index.ts +32 -0
- package/src/server/routes/keys.ts +131 -0
- package/src/server/routes/langgraph.ts +71 -0
- package/src/server/routes/memory.ts +440 -0
- package/src/server/routes/sources.ts +111 -0
- package/src/server/routes/system.ts +68 -0
- package/src/server/routes/temporal.ts +335 -0
- package/src/server/routes/users.ts +111 -0
- package/src/server/routes/vercel.ts +55 -0
- package/src/server/server.js +215 -0
- package/src/server.ts +1 -0
- package/src/sources/base.ts +257 -0
- package/src/sources/github.ts +156 -0
- package/src/sources/google_drive.ts +144 -0
- package/src/sources/google_sheets.ts +85 -0
- package/src/sources/google_slides.ts +115 -0
- package/src/sources/index.ts +19 -0
- package/src/sources/notion.ts +148 -0
- package/src/sources/onedrive.ts +131 -0
- package/src/sources/web_crawler.ts +161 -0
- package/src/temporal_graph/index.ts +4 -0
- package/src/temporal_graph/query.ts +299 -0
- package/src/temporal_graph/store.ts +156 -0
- package/src/temporal_graph/timeline.ts +319 -0
- package/src/temporal_graph/types.ts +41 -0
- package/src/utils/chunking.ts +66 -0
- package/src/utils/index.ts +25 -0
- package/src/utils/keyword.ts +137 -0
- package/src/utils/text.ts +115 -0
- package/tests/test_api_workspace_management.ts +413 -0
- package/tests/test_bulk_delete.ts +267 -0
- package/tests/test_omnibus.ts +166 -0
- package/tests/test_workspace_management.ts +278 -0
- package/tests/verify.ts +104 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { insert_fact, update_fact, invalidate_fact, delete_fact, apply_confidence_decay, get_active_facts_count, get_total_facts_count } from '../../temporal_graph/store'
|
|
2
|
+
import { query_facts_at_time, get_current_fact, query_facts_in_range, search_facts, get_facts_by_subject, get_related_facts } from '../../temporal_graph/query'
|
|
3
|
+
import { get_subject_timeline, get_predicate_timeline, get_changes_in_window, compare_time_points, get_change_frequency, get_volatile_facts } from '../../temporal_graph/timeline'
|
|
4
|
+
|
|
5
|
+
export const create_temporal_fact = async (req: any, res: any) => {
|
|
6
|
+
try {
|
|
7
|
+
const { subject, predicate, object, valid_from, confidence, metadata } = req.body
|
|
8
|
+
|
|
9
|
+
if (!subject || !predicate || !object) {
|
|
10
|
+
return res.status(400).json({ error: 'Missing required fields: subject, predicate, object' })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const valid_from_date = valid_from ? new Date(valid_from) : new Date()
|
|
14
|
+
const conf = confidence !== undefined ? Math.max(0, Math.min(1, confidence)) : 1.0
|
|
15
|
+
|
|
16
|
+
const id = await insert_fact(subject, predicate, object, valid_from_date, conf, metadata)
|
|
17
|
+
|
|
18
|
+
res.json({
|
|
19
|
+
id,
|
|
20
|
+
subject,
|
|
21
|
+
predicate,
|
|
22
|
+
object,
|
|
23
|
+
valid_from: valid_from_date.toISOString(),
|
|
24
|
+
confidence: conf,
|
|
25
|
+
message: 'Fact created successfully'
|
|
26
|
+
})
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('[TEMPORAL API] Error creating fact:', error)
|
|
29
|
+
res.status(500).json({ error: 'Failed to create fact' })
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
export const get_temporal_fact = async (req: any, res: any) => {
|
|
35
|
+
try {
|
|
36
|
+
const { subject, predicate, object, at, min_confidence } = req.query
|
|
37
|
+
|
|
38
|
+
if (!subject && !predicate && !object) {
|
|
39
|
+
return res.status(400).json({ error: 'At least one of subject, predicate, or object is required' })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const at_date = at ? new Date(at) : new Date()
|
|
43
|
+
const min_conf = min_confidence ? parseFloat(min_confidence) : 0.1
|
|
44
|
+
|
|
45
|
+
const facts = await query_facts_at_time(subject, predicate, object, at_date, min_conf)
|
|
46
|
+
|
|
47
|
+
res.json({
|
|
48
|
+
facts,
|
|
49
|
+
query: { subject, predicate, object, at: at_date.toISOString(), min_confidence: min_conf },
|
|
50
|
+
count: facts.length
|
|
51
|
+
})
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('[TEMPORAL API] Error querying facts:', error)
|
|
54
|
+
res.status(500).json({ error: 'Failed to query facts' })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export const get_current_temporal_fact = async (req: any, res: any) => {
|
|
60
|
+
try {
|
|
61
|
+
const { subject, predicate } = req.query
|
|
62
|
+
|
|
63
|
+
if (!subject || !predicate) {
|
|
64
|
+
return res.status(400).json({ error: 'Both subject and predicate are required' })
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const fact = await get_current_fact(subject, predicate)
|
|
68
|
+
|
|
69
|
+
if (!fact) {
|
|
70
|
+
return res.status(404).json({ error: 'No current fact found', subject, predicate })
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
res.json({ fact })
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('[TEMPORAL API] Error getting current fact:', error)
|
|
76
|
+
res.status(500).json({ error: 'Failed to get current fact' })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
export const get_entity_timeline = async (req: any, res: any) => {
|
|
82
|
+
try {
|
|
83
|
+
const { subject, predicate } = req.query
|
|
84
|
+
|
|
85
|
+
if (!subject) {
|
|
86
|
+
return res.status(400).json({ error: 'Subject parameter is required' })
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const timeline = await get_subject_timeline(subject, predicate)
|
|
90
|
+
|
|
91
|
+
res.json({
|
|
92
|
+
subject,
|
|
93
|
+
predicate,
|
|
94
|
+
timeline,
|
|
95
|
+
count: timeline.length
|
|
96
|
+
})
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error('[TEMPORAL API] Error getting timeline:', error)
|
|
99
|
+
res.status(500).json({ error: 'Failed to get timeline' })
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
export const get_predicate_history = async (req: any, res: any) => {
|
|
105
|
+
try {
|
|
106
|
+
const { predicate, from, to } = req.query
|
|
107
|
+
|
|
108
|
+
if (!predicate) {
|
|
109
|
+
return res.status(400).json({ error: 'Predicate parameter is required' })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const from_date = from ? new Date(from) : undefined
|
|
113
|
+
const to_date = to ? new Date(to) : undefined
|
|
114
|
+
|
|
115
|
+
const timeline = await get_predicate_timeline(predicate, from_date, to_date)
|
|
116
|
+
|
|
117
|
+
res.json({
|
|
118
|
+
predicate,
|
|
119
|
+
from: from_date?.toISOString(),
|
|
120
|
+
to: to_date?.toISOString(),
|
|
121
|
+
timeline,
|
|
122
|
+
count: timeline.length
|
|
123
|
+
})
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('[TEMPORAL API] Error getting predicate timeline:', error)
|
|
126
|
+
res.status(500).json({ error: 'Failed to get predicate timeline' })
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
export const update_temporal_fact = async (req: any, res: any) => {
|
|
132
|
+
try {
|
|
133
|
+
const { id } = req.params
|
|
134
|
+
const { confidence, metadata } = req.body
|
|
135
|
+
|
|
136
|
+
if (!id) {
|
|
137
|
+
return res.status(400).json({ error: 'Fact ID is required' })
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (confidence === undefined && metadata === undefined) {
|
|
141
|
+
return res.status(400).json({ error: 'At least one of confidence or metadata must be provided' })
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const conf = confidence !== undefined ? Math.max(0, Math.min(1, confidence)) : undefined
|
|
145
|
+
|
|
146
|
+
await update_fact(id, conf, metadata)
|
|
147
|
+
|
|
148
|
+
res.json({ id, confidence: conf, metadata, message: 'Fact updated successfully' })
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('[TEMPORAL API] Error updating fact:', error)
|
|
151
|
+
res.status(500).json({ error: 'Failed to update fact' })
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
export const invalidate_temporal_fact = async (req: any, res: any) => {
|
|
157
|
+
try {
|
|
158
|
+
const { id } = req.params
|
|
159
|
+
const { valid_to } = req.body
|
|
160
|
+
|
|
161
|
+
if (!id) {
|
|
162
|
+
return res.status(400).json({ error: 'Fact ID is required' })
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const valid_to_date = valid_to ? new Date(valid_to) : new Date()
|
|
166
|
+
|
|
167
|
+
await invalidate_fact(id, valid_to_date)
|
|
168
|
+
|
|
169
|
+
res.json({ id, valid_to: valid_to_date.toISOString(), message: 'Fact invalidated successfully' })
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error('[TEMPORAL API] Error invalidating fact:', error)
|
|
172
|
+
res.status(500).json({ error: 'Failed to invalidate fact' })
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
export const get_subject_facts = async (req: any, res: any) => {
|
|
178
|
+
try {
|
|
179
|
+
const { subject } = req.params
|
|
180
|
+
const { at, include_historical } = req.query
|
|
181
|
+
|
|
182
|
+
if (!subject) {
|
|
183
|
+
return res.status(400).json({ error: 'Subject parameter is required' })
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const at_date = at ? new Date(at) : undefined
|
|
187
|
+
const include_hist = include_historical === 'true'
|
|
188
|
+
|
|
189
|
+
const facts = await get_facts_by_subject(subject, at_date, include_hist)
|
|
190
|
+
|
|
191
|
+
res.json({
|
|
192
|
+
subject,
|
|
193
|
+
at: at_date?.toISOString(),
|
|
194
|
+
include_historical: include_hist,
|
|
195
|
+
facts,
|
|
196
|
+
count: facts.length
|
|
197
|
+
})
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error('[TEMPORAL API] Error getting subject facts:', error)
|
|
200
|
+
res.status(500).json({ error: 'Failed to get subject facts' })
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
export const search_temporal_facts = async (req: any, res: any) => {
|
|
206
|
+
try {
|
|
207
|
+
const { pattern, field = 'subject', at } = req.query
|
|
208
|
+
|
|
209
|
+
if (!pattern) {
|
|
210
|
+
return res.status(400).json({ error: 'Pattern parameter is required' })
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!['subject', 'predicate', 'object'].includes(field)) {
|
|
214
|
+
return res.status(400).json({ error: 'Field must be one of: subject, predicate, object' })
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const at_date = at ? new Date(at) : undefined
|
|
218
|
+
const facts = await search_facts(pattern, field as any, at_date)
|
|
219
|
+
|
|
220
|
+
res.json({
|
|
221
|
+
pattern,
|
|
222
|
+
field,
|
|
223
|
+
at: at_date?.toISOString(),
|
|
224
|
+
facts,
|
|
225
|
+
count: facts.length
|
|
226
|
+
})
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('[TEMPORAL API] Error searching facts:', error)
|
|
229
|
+
res.status(500).json({ error: 'Failed to search facts' })
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
export const get_temporal_stats = async (req: any, res: any) => {
|
|
235
|
+
try {
|
|
236
|
+
const active_facts = await get_active_facts_count()
|
|
237
|
+
const total_facts = await get_total_facts_count()
|
|
238
|
+
const historical_facts = total_facts - active_facts
|
|
239
|
+
|
|
240
|
+
res.json({
|
|
241
|
+
active_facts,
|
|
242
|
+
historical_facts,
|
|
243
|
+
total_facts,
|
|
244
|
+
historical_percentage: total_facts > 0 ? ((historical_facts / total_facts) * 100).toFixed(2) + '%' : '0%'
|
|
245
|
+
})
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.error('[TEMPORAL API] Error getting stats:', error)
|
|
248
|
+
res.status(500).json({ error: 'Failed to get statistics' })
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
export const apply_decay = async (req: any, res: any) => {
|
|
254
|
+
try {
|
|
255
|
+
const { decay_rate = 0.01 } = req.body
|
|
256
|
+
|
|
257
|
+
const updated = await apply_confidence_decay(decay_rate)
|
|
258
|
+
|
|
259
|
+
res.json({
|
|
260
|
+
decay_rate,
|
|
261
|
+
facts_updated: updated,
|
|
262
|
+
message: 'Confidence decay applied successfully'
|
|
263
|
+
})
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error('[TEMPORAL API] Error applying decay:', error)
|
|
266
|
+
res.status(500).json({ error: 'Failed to apply confidence decay' })
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
export const compare_facts = async (req: any, res: any) => {
|
|
272
|
+
try {
|
|
273
|
+
const { subject, time1, time2 } = req.query
|
|
274
|
+
|
|
275
|
+
if (!subject || !time1 || !time2) {
|
|
276
|
+
return res.status(400).json({ error: 'subject, time1, and time2 parameters are required' })
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const t1 = new Date(time1)
|
|
280
|
+
const t2 = new Date(time2)
|
|
281
|
+
|
|
282
|
+
const comparison = await compare_time_points(subject, t1, t2)
|
|
283
|
+
|
|
284
|
+
res.json({
|
|
285
|
+
subject,
|
|
286
|
+
time1: t1.toISOString(),
|
|
287
|
+
time2: t2.toISOString(),
|
|
288
|
+
...comparison,
|
|
289
|
+
summary: {
|
|
290
|
+
added: comparison.added.length,
|
|
291
|
+
removed: comparison.removed.length,
|
|
292
|
+
changed: comparison.changed.length,
|
|
293
|
+
unchanged: comparison.unchanged.length
|
|
294
|
+
}
|
|
295
|
+
})
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.error('[TEMPORAL API] Error comparing facts:', error)
|
|
298
|
+
res.status(500).json({ error: 'Failed to compare facts' })
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
export const get_most_volatile = async (req: any, res: any) => {
|
|
304
|
+
try {
|
|
305
|
+
const { subject, limit = 10 } = req.query
|
|
306
|
+
|
|
307
|
+
const volatile = await get_volatile_facts(subject, parseInt(limit))
|
|
308
|
+
|
|
309
|
+
res.json({
|
|
310
|
+
subject,
|
|
311
|
+
limit: parseInt(limit),
|
|
312
|
+
volatile_facts: volatile,
|
|
313
|
+
count: volatile.length
|
|
314
|
+
})
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error('[TEMPORAL API] Error getting volatile facts:', error)
|
|
317
|
+
res.status(500).json({ error: 'Failed to get volatile facts' })
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function temporal(app: any) {
|
|
322
|
+
app.post('/api/temporal/fact', create_temporal_fact)
|
|
323
|
+
app.get('/api/temporal/fact', get_temporal_fact)
|
|
324
|
+
app.get('/api/temporal/fact/current', get_current_temporal_fact)
|
|
325
|
+
app.patch('/api/temporal/fact/:id', update_temporal_fact)
|
|
326
|
+
app.delete('/api/temporal/fact/:id', invalidate_temporal_fact)
|
|
327
|
+
|
|
328
|
+
app.get('/api/temporal/timeline', get_entity_timeline)
|
|
329
|
+
app.get('/api/temporal/subject/:subject', get_subject_facts)
|
|
330
|
+
app.get('/api/temporal/search', search_temporal_facts)
|
|
331
|
+
app.get('/api/temporal/compare', compare_facts)
|
|
332
|
+
app.get('/api/temporal/stats', get_temporal_stats)
|
|
333
|
+
app.post('/api/temporal/decay', apply_decay)
|
|
334
|
+
app.get('/api/temporal/volatile', get_most_volatile)
|
|
335
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { q, vector_store } from "../../core/db";
|
|
2
|
+
import { p } from "../../utils";
|
|
3
|
+
import {
|
|
4
|
+
update_user_summary,
|
|
5
|
+
auto_update_user_summaries,
|
|
6
|
+
} from "../../memory/user_summary";
|
|
7
|
+
|
|
8
|
+
export const usr = (app: any) => {
|
|
9
|
+
app.get("/users/:user_id/summary", async (req: any, res: any) => {
|
|
10
|
+
try {
|
|
11
|
+
const { user_id } = req.params;
|
|
12
|
+
if (!user_id)
|
|
13
|
+
return res.status(400).json({ error: "user_id required" });
|
|
14
|
+
|
|
15
|
+
const user = await q.get_user.get(user_id);
|
|
16
|
+
if (!user) return res.status(404).json({ error: "user not found" });
|
|
17
|
+
|
|
18
|
+
res.json({
|
|
19
|
+
user_id: user.user_id,
|
|
20
|
+
summary: user.summary,
|
|
21
|
+
reflection_count: user.reflection_count,
|
|
22
|
+
updated_at: user.updated_at,
|
|
23
|
+
});
|
|
24
|
+
} catch (err: any) {
|
|
25
|
+
res.status(500).json({ error: err.message });
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
app.post(
|
|
30
|
+
"/users/:user_id/summary/regenerate",
|
|
31
|
+
async (req: any, res: any) => {
|
|
32
|
+
try {
|
|
33
|
+
const { user_id } = req.params;
|
|
34
|
+
if (!user_id)
|
|
35
|
+
return res.status(400).json({ err: "user_id required" });
|
|
36
|
+
|
|
37
|
+
await update_user_summary(user_id);
|
|
38
|
+
const user = await q.get_user.get(user_id);
|
|
39
|
+
|
|
40
|
+
res.json({
|
|
41
|
+
ok: true,
|
|
42
|
+
user_id,
|
|
43
|
+
summary: user?.summary,
|
|
44
|
+
reflection_count: user?.reflection_count,
|
|
45
|
+
});
|
|
46
|
+
} catch (err: any) {
|
|
47
|
+
res.status(500).json({ err: err.message });
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
app.post("/users/summaries/regenerate-all", async (req: any, res: any) => {
|
|
53
|
+
try {
|
|
54
|
+
const result = await auto_update_user_summaries();
|
|
55
|
+
res.json({ ok: true, updated: result.updated });
|
|
56
|
+
} catch (err: any) {
|
|
57
|
+
res.status(500).json({ err: err.message });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
app.get("/users/:user_id/memories", async (req: any, res: any) => {
|
|
62
|
+
try {
|
|
63
|
+
const { user_id } = req.params;
|
|
64
|
+
if (!user_id)
|
|
65
|
+
return res.status(400).json({ err: "user_id required" });
|
|
66
|
+
|
|
67
|
+
const l = req.query.l ? parseInt(req.query.l) : 100;
|
|
68
|
+
const u = req.query.u ? parseInt(req.query.u) : 0;
|
|
69
|
+
|
|
70
|
+
const r = await q.all_mem_by_user.all(user_id, l, u);
|
|
71
|
+
const i = r.map((x: any) => ({
|
|
72
|
+
id: x.id,
|
|
73
|
+
content: x.content,
|
|
74
|
+
tags: p(x.tags),
|
|
75
|
+
metadata: p(x.meta),
|
|
76
|
+
created_at: x.created_at,
|
|
77
|
+
updated_at: x.updated_at,
|
|
78
|
+
last_seen_at: x.last_seen_at,
|
|
79
|
+
salience: x.salience,
|
|
80
|
+
decay_lambda: x.decay_lambda,
|
|
81
|
+
primary_sector: x.primary_sector,
|
|
82
|
+
version: x.version,
|
|
83
|
+
}));
|
|
84
|
+
res.json({ user_id, items: i });
|
|
85
|
+
} catch (err: any) {
|
|
86
|
+
res.status(500).json({ err: err.message });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
app.delete("/users/:user_id/memories", async (req: any, res: any) => {
|
|
91
|
+
try {
|
|
92
|
+
const { user_id } = req.params;
|
|
93
|
+
if (!user_id)
|
|
94
|
+
return res.status(400).json({ err: "user_id required" });
|
|
95
|
+
|
|
96
|
+
const mems = await q.all_mem_by_user.all(user_id, 10000, 0);
|
|
97
|
+
let deleted = 0;
|
|
98
|
+
|
|
99
|
+
for (const m of mems) {
|
|
100
|
+
await q.del_mem.run(m.id);
|
|
101
|
+
await vector_store.deleteVectors(m.id);
|
|
102
|
+
await q.del_waypoints.run(m.id, m.id);
|
|
103
|
+
deleted++;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
res.json({ ok: true, deleted });
|
|
107
|
+
} catch (err: any) {
|
|
108
|
+
res.status(500).json({ err: err.message });
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { hsg_query, add_hsg_memory } from "../../memory/hsg";
|
|
2
|
+
import { j } from "../../utils";
|
|
3
|
+
|
|
4
|
+
export function vercel(app: any) {
|
|
5
|
+
// Simple memory query endpoint for Vercel AI SDK adapters
|
|
6
|
+
app.post("/query", async (req: any, res: any) => {
|
|
7
|
+
try {
|
|
8
|
+
const b = req.body || {};
|
|
9
|
+
const query: string = String(b.query || "").slice(0, 4000);
|
|
10
|
+
const user_id: string | undefined = b.user_id || req.query.user_id;
|
|
11
|
+
const k: number = Math.max(1, Math.min(32, Number(b.k) || 8));
|
|
12
|
+
if (!query) return res.status(400).json({ err: "query" });
|
|
13
|
+
|
|
14
|
+
const startTime: number | undefined = b.startTime ? Number(b.startTime) : undefined;
|
|
15
|
+
const endTime: number | undefined = b.endTime ? Number(b.endTime) : undefined;
|
|
16
|
+
const matches = await hsg_query(query, k, { user_id, startTime, endTime });
|
|
17
|
+
const lines = matches.map((m: any) => `- (${(m.score ?? 0).toFixed(2)}) ${m.content}`);
|
|
18
|
+
const result = lines.join("\n");
|
|
19
|
+
|
|
20
|
+
res.json({
|
|
21
|
+
query,
|
|
22
|
+
user_id: user_id || null,
|
|
23
|
+
k,
|
|
24
|
+
result,
|
|
25
|
+
matches: matches.map((m: any) => ({
|
|
26
|
+
id: m.id,
|
|
27
|
+
content: m.content,
|
|
28
|
+
score: m.score,
|
|
29
|
+
sectors: m.sectors,
|
|
30
|
+
primary_sector: m.primary_sector,
|
|
31
|
+
last_seen_at: m.last_seen_at,
|
|
32
|
+
})),
|
|
33
|
+
});
|
|
34
|
+
} catch (e: any) {
|
|
35
|
+
res.status(500).json({ err: "internal", msg: e?.message || String(e) });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Simple memory store endpoint for chat transcripts or summaries
|
|
40
|
+
app.post("/memories", async (req: any, res: any) => {
|
|
41
|
+
try {
|
|
42
|
+
const b = req.body || {};
|
|
43
|
+
const content: string = String(b.content || "").trim();
|
|
44
|
+
const user_id: string | undefined = b.user_id || req.query.user_id;
|
|
45
|
+
const tags: string[] = Array.isArray(b.tags) ? b.tags : [];
|
|
46
|
+
const metadata: any = b.metadata || undefined;
|
|
47
|
+
if (!content) return res.status(400).json({ err: "content" });
|
|
48
|
+
|
|
49
|
+
const r = await add_hsg_memory(content, j(tags), metadata, user_id);
|
|
50
|
+
res.json(r);
|
|
51
|
+
} catch (e: any) {
|
|
52
|
+
res.status(500).json({ err: "internal", msg: e?.message || String(e) });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|