@poprobertdaniel/openclaw-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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/dist/chunk-CRPEAZ44.cjs +1881 -0
  4. package/dist/chunk-CRPEAZ44.cjs.map +1 -0
  5. package/dist/chunk-JNWCMHOB.js +309 -0
  6. package/dist/chunk-JNWCMHOB.js.map +1 -0
  7. package/dist/chunk-JSQBXYDM.js +1881 -0
  8. package/dist/chunk-JSQBXYDM.js.map +1 -0
  9. package/dist/chunk-NHFPLDZK.js +236 -0
  10. package/dist/chunk-NHFPLDZK.js.map +1 -0
  11. package/dist/chunk-NMUPGLJW.cjs +752 -0
  12. package/dist/chunk-NMUPGLJW.cjs.map +1 -0
  13. package/dist/chunk-RFLG2CCR.js +752 -0
  14. package/dist/chunk-RFLG2CCR.js.map +1 -0
  15. package/dist/chunk-VXULEX3A.cjs +236 -0
  16. package/dist/chunk-VXULEX3A.cjs.map +1 -0
  17. package/dist/chunk-ZY2C2CJQ.cjs +309 -0
  18. package/dist/chunk-ZY2C2CJQ.cjs.map +1 -0
  19. package/dist/cli/index.cjs +764 -0
  20. package/dist/cli/index.cjs.map +1 -0
  21. package/dist/cli/index.d.cts +1 -0
  22. package/dist/cli/index.d.ts +1 -0
  23. package/dist/cli/index.js +764 -0
  24. package/dist/cli/index.js.map +1 -0
  25. package/dist/index.cjs +48 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.cts +790 -0
  28. package/dist/index.d.ts +790 -0
  29. package/dist/index.js +48 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/memory-service-6WDMF6KX.cjs +9 -0
  32. package/dist/memory-service-6WDMF6KX.cjs.map +1 -0
  33. package/dist/memory-service-GKEG6J2D.js +9 -0
  34. package/dist/memory-service-GKEG6J2D.js.map +1 -0
  35. package/dist/server-BTbRv-yX.d.cts +1199 -0
  36. package/dist/server-BTbRv-yX.d.ts +1199 -0
  37. package/dist/server.cjs +9 -0
  38. package/dist/server.cjs.map +1 -0
  39. package/dist/server.d.cts +2 -0
  40. package/dist/server.d.ts +2 -0
  41. package/dist/server.js +9 -0
  42. package/dist/server.js.map +1 -0
  43. package/docker/full.yml +45 -0
  44. package/docker/standard.yml +26 -0
  45. package/package.json +109 -0
  46. package/skill/SKILL.md +139 -0
  47. package/templates/.env.example +42 -0
  48. package/templates/docker-compose.full.yml +45 -0
  49. package/templates/docker-compose.standard.yml +26 -0
  50. package/templates/openclaw-memory.config.ts +49 -0
@@ -0,0 +1,752 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2
+
3
+
4
+
5
+ var _chunkCRPEAZ44cjs = require('./chunk-CRPEAZ44.cjs');
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+ var _chunkZY2C2CJQcjs = require('./chunk-ZY2C2CJQ.cjs');
14
+
15
+ // src/server.ts
16
+ var _url = require('url');
17
+ var _path = require('path'); var _path2 = _interopRequireDefault(_path);
18
+
19
+ // src/api/router.ts
20
+ var _elysia = require('elysia');
21
+ var _cors = require('@elysiajs/cors');
22
+
23
+ // src/api/memories.ts
24
+
25
+ function memoriesRoutes(orchestrator) {
26
+ return new (0, _elysia.Elysia)({ prefix: "/api/memories" }).post(
27
+ "/",
28
+ async ({ body, set }) => {
29
+ try {
30
+ const result = await orchestrator.createMemory(body);
31
+ set.status = 201;
32
+ return result;
33
+ } catch (error) {
34
+ set.status = 500;
35
+ return {
36
+ error: "Failed to create memory",
37
+ details: error instanceof Error ? error.message : String(error)
38
+ };
39
+ }
40
+ },
41
+ {
42
+ body: _elysia.t.Object({
43
+ agent_id: _elysia.t.String(),
44
+ scope: _elysia.t.Union([
45
+ _elysia.t.Literal("user"),
46
+ _elysia.t.Literal("agent"),
47
+ _elysia.t.Literal("global"),
48
+ _elysia.t.Literal("project"),
49
+ _elysia.t.Literal("session")
50
+ ]),
51
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
52
+ content: _elysia.t.String(),
53
+ tags: _elysia.t.Optional(_elysia.t.Array(_elysia.t.String())),
54
+ source: _elysia.t.Optional(
55
+ _elysia.t.Union([
56
+ _elysia.t.Literal("explicit"),
57
+ _elysia.t.Literal("derived"),
58
+ _elysia.t.Literal("observation"),
59
+ _elysia.t.Literal("conversation_summary"),
60
+ _elysia.t.Literal("entity_extraction"),
61
+ _elysia.t.Literal("daily_digest"),
62
+ _elysia.t.Literal("migration")
63
+ ])
64
+ ),
65
+ created_by: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
66
+ extract_entities: _elysia.t.Optional(_elysia.t.Boolean()),
67
+ expires_at: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String()))
68
+ })
69
+ }
70
+ ).get("/:id", ({ params, set }) => {
71
+ const memory = orchestrator.sqlite.getMemory(params.id);
72
+ if (!memory) {
73
+ set.status = 404;
74
+ return { error: "Memory not found" };
75
+ }
76
+ return memory;
77
+ }).put(
78
+ "/:id",
79
+ async ({ params, body, set }) => {
80
+ try {
81
+ const result = await orchestrator.updateMemory(
82
+ params.id,
83
+ body
84
+ );
85
+ if (!result) {
86
+ set.status = 404;
87
+ return { error: "Memory not found" };
88
+ }
89
+ return result;
90
+ } catch (error) {
91
+ set.status = 500;
92
+ return {
93
+ error: "Failed to update memory",
94
+ details: error instanceof Error ? error.message : String(error)
95
+ };
96
+ }
97
+ },
98
+ {
99
+ body: _elysia.t.Object({
100
+ content: _elysia.t.Optional(_elysia.t.String()),
101
+ tags: _elysia.t.Optional(_elysia.t.Array(_elysia.t.String())),
102
+ scope: _elysia.t.Optional(
103
+ _elysia.t.Union([
104
+ _elysia.t.Literal("user"),
105
+ _elysia.t.Literal("agent"),
106
+ _elysia.t.Literal("global"),
107
+ _elysia.t.Literal("project"),
108
+ _elysia.t.Literal("session")
109
+ ])
110
+ ),
111
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
112
+ expires_at: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
113
+ extract_entities: _elysia.t.Optional(_elysia.t.Boolean())
114
+ })
115
+ }
116
+ ).delete("/:id", async ({ params, set }) => {
117
+ try {
118
+ const deleted = await orchestrator.deleteMemory(params.id);
119
+ if (!deleted) {
120
+ set.status = 404;
121
+ return { error: "Memory not found" };
122
+ }
123
+ return { deleted: true, id: params.id };
124
+ } catch (error) {
125
+ set.status = 500;
126
+ return {
127
+ error: "Failed to delete memory",
128
+ details: error instanceof Error ? error.message : String(error)
129
+ };
130
+ }
131
+ }).get("/", ({ query }) => {
132
+ const memories = orchestrator.sqlite.listMemories({
133
+ agent_id: query.agent_id,
134
+ scope: query.scope,
135
+ subject_id: query.subject_id,
136
+ source: query.source,
137
+ tags: query.tags,
138
+ limit: query.limit ? parseInt(String(query.limit), 10) : void 0,
139
+ offset: query.offset ? parseInt(String(query.offset), 10) : void 0,
140
+ order: query.order || "desc"
141
+ });
142
+ return { memories, count: memories.length };
143
+ });
144
+ }
145
+
146
+ // src/api/search.ts
147
+
148
+ function searchRoutes(orchestrator) {
149
+ const searchEngine = new (0, _chunkCRPEAZ44cjs.SearchEngine)(orchestrator);
150
+ return new (0, _elysia.Elysia)({ prefix: "/api/search" }).post(
151
+ "/",
152
+ async ({ body, set }) => {
153
+ try {
154
+ const req = body;
155
+ if (!req.agent_id) req.cross_agent = true;
156
+ return await searchEngine.search(req);
157
+ } catch (error) {
158
+ set.status = 500;
159
+ return {
160
+ error: "Search failed",
161
+ details: error instanceof Error ? error.message : String(error)
162
+ };
163
+ }
164
+ },
165
+ {
166
+ body: _elysia.t.Object({
167
+ agent_id: _elysia.t.Optional(_elysia.t.String()),
168
+ query: _elysia.t.String(),
169
+ scopes: _elysia.t.Optional(
170
+ _elysia.t.Array(
171
+ _elysia.t.Union([
172
+ _elysia.t.Literal("user"),
173
+ _elysia.t.Literal("agent"),
174
+ _elysia.t.Literal("global"),
175
+ _elysia.t.Literal("project"),
176
+ _elysia.t.Literal("session")
177
+ ])
178
+ )
179
+ ),
180
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
181
+ limit: _elysia.t.Optional(_elysia.t.Number()),
182
+ include_graph: _elysia.t.Optional(_elysia.t.Boolean()),
183
+ cross_agent: _elysia.t.Optional(_elysia.t.Boolean()),
184
+ strategy: _elysia.t.Optional(
185
+ _elysia.t.Union([
186
+ _elysia.t.Literal("auto"),
187
+ _elysia.t.Literal("semantic"),
188
+ _elysia.t.Literal("fulltext"),
189
+ _elysia.t.Literal("graph"),
190
+ _elysia.t.Literal("all")
191
+ ])
192
+ )
193
+ })
194
+ }
195
+ ).post(
196
+ "/semantic",
197
+ async ({ body, set }) => {
198
+ try {
199
+ return await searchEngine.search({
200
+ ...body,
201
+ strategy: "semantic"
202
+ });
203
+ } catch (error) {
204
+ set.status = 500;
205
+ return {
206
+ error: "Semantic search failed",
207
+ details: error instanceof Error ? error.message : String(error)
208
+ };
209
+ }
210
+ },
211
+ {
212
+ body: _elysia.t.Object({
213
+ agent_id: _elysia.t.Optional(_elysia.t.String()),
214
+ query: _elysia.t.String(),
215
+ scopes: _elysia.t.Optional(
216
+ _elysia.t.Array(
217
+ _elysia.t.Union([
218
+ _elysia.t.Literal("user"),
219
+ _elysia.t.Literal("agent"),
220
+ _elysia.t.Literal("global"),
221
+ _elysia.t.Literal("project"),
222
+ _elysia.t.Literal("session")
223
+ ])
224
+ )
225
+ ),
226
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
227
+ limit: _elysia.t.Optional(_elysia.t.Number()),
228
+ cross_agent: _elysia.t.Optional(_elysia.t.Boolean())
229
+ })
230
+ }
231
+ ).post(
232
+ "/graph",
233
+ async ({ body, set }) => {
234
+ try {
235
+ return await searchEngine.search({
236
+ ...body,
237
+ strategy: "graph",
238
+ include_graph: true
239
+ });
240
+ } catch (error) {
241
+ set.status = 500;
242
+ return {
243
+ error: "Graph search failed",
244
+ details: error instanceof Error ? error.message : String(error)
245
+ };
246
+ }
247
+ },
248
+ {
249
+ body: _elysia.t.Object({
250
+ agent_id: _elysia.t.Optional(_elysia.t.String()),
251
+ query: _elysia.t.String(),
252
+ scopes: _elysia.t.Optional(
253
+ _elysia.t.Array(
254
+ _elysia.t.Union([
255
+ _elysia.t.Literal("user"),
256
+ _elysia.t.Literal("agent"),
257
+ _elysia.t.Literal("global"),
258
+ _elysia.t.Literal("project"),
259
+ _elysia.t.Literal("session")
260
+ ])
261
+ )
262
+ ),
263
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
264
+ limit: _elysia.t.Optional(_elysia.t.Number())
265
+ })
266
+ }
267
+ ).post(
268
+ "/fulltext",
269
+ async ({ body, set }) => {
270
+ try {
271
+ return await searchEngine.search({
272
+ ...body,
273
+ strategy: "fulltext",
274
+ include_graph: false
275
+ });
276
+ } catch (error) {
277
+ set.status = 500;
278
+ return {
279
+ error: "Fulltext search failed",
280
+ details: error instanceof Error ? error.message : String(error)
281
+ };
282
+ }
283
+ },
284
+ {
285
+ body: _elysia.t.Object({
286
+ agent_id: _elysia.t.Optional(_elysia.t.String()),
287
+ query: _elysia.t.String(),
288
+ scopes: _elysia.t.Optional(_elysia.t.Array(_elysia.t.String())),
289
+ subject_id: _elysia.t.Optional(_elysia.t.Nullable(_elysia.t.String())),
290
+ limit: _elysia.t.Optional(_elysia.t.Number())
291
+ })
292
+ }
293
+ );
294
+ }
295
+
296
+ // src/api/conversations.ts
297
+
298
+ function conversationRoutes(orchestrator, config) {
299
+ const summarizer = config.extraction ? new (0, _chunkCRPEAZ44cjs.ConversationSummarizer)({
300
+ apiKey: config.extraction.apiKey,
301
+ baseUrl: config.extraction.baseUrl,
302
+ model: config.extraction.model
303
+ }) : null;
304
+ return new (0, _elysia.Elysia)({ prefix: "/api/conversations" }).post(
305
+ "/log",
306
+ ({ body, set }) => {
307
+ try {
308
+ orchestrator.sqlite.appendConversationLog(body);
309
+ set.status = 201;
310
+ return { ok: true };
311
+ } catch (error) {
312
+ set.status = 500;
313
+ return {
314
+ error: "Failed to append conversation log",
315
+ details: error instanceof Error ? error.message : String(error)
316
+ };
317
+ }
318
+ },
319
+ {
320
+ body: _elysia.t.Object({
321
+ agent_id: _elysia.t.String(),
322
+ session_id: _elysia.t.String(),
323
+ user_id: _elysia.t.String(),
324
+ channel: _elysia.t.String(),
325
+ role: _elysia.t.Union([
326
+ _elysia.t.Literal("user"),
327
+ _elysia.t.Literal("assistant"),
328
+ _elysia.t.Literal("system")
329
+ ]),
330
+ content: _elysia.t.String(),
331
+ timestamp: _elysia.t.String()
332
+ })
333
+ }
334
+ ).post(
335
+ "/summarize",
336
+ async ({ body, set }) => {
337
+ if (!summarizer) {
338
+ set.status = 501;
339
+ return { error: "Summarization not available \u2014 extraction config required" };
340
+ }
341
+ try {
342
+ const { agent_id, session_id, user_id, channel, messages } = body;
343
+ const summary = await summarizer.summarize(messages);
344
+ if (!summary) {
345
+ set.status = 422;
346
+ return { error: "Failed to generate summary" };
347
+ }
348
+ const memoryReq = {
349
+ agent_id,
350
+ scope: "session",
351
+ subject_id: user_id,
352
+ content: summary,
353
+ tags: ["conversation_summary", channel, `session:${session_id}`],
354
+ source: "conversation_summary",
355
+ created_by: agent_id,
356
+ extract_entities: true
357
+ };
358
+ const result = await orchestrator.createMemory(memoryReq);
359
+ const response = {
360
+ memory_id: result.id,
361
+ summary,
362
+ entities_extracted: result.entities,
363
+ relationships_created: 0
364
+ };
365
+ set.status = 201;
366
+ return response;
367
+ } catch (error) {
368
+ set.status = 500;
369
+ return {
370
+ error: "Summarization failed",
371
+ details: error instanceof Error ? error.message : String(error)
372
+ };
373
+ }
374
+ },
375
+ {
376
+ body: _elysia.t.Object({
377
+ agent_id: _elysia.t.String(),
378
+ session_id: _elysia.t.String(),
379
+ user_id: _elysia.t.String(),
380
+ channel: _elysia.t.String(),
381
+ messages: _elysia.t.Array(
382
+ _elysia.t.Object({
383
+ role: _elysia.t.Union([
384
+ _elysia.t.Literal("user"),
385
+ _elysia.t.Literal("assistant"),
386
+ _elysia.t.Literal("system")
387
+ ]),
388
+ content: _elysia.t.String(),
389
+ timestamp: _elysia.t.String()
390
+ })
391
+ ),
392
+ reason: _elysia.t.Optional(_elysia.t.String())
393
+ })
394
+ }
395
+ );
396
+ }
397
+
398
+ // src/api/entities.ts
399
+
400
+ function entityRoutes(orchestrator) {
401
+ return new (0, _elysia.Elysia)({ prefix: "/api/entities" }).get("/:type", async ({ params, query, set }) => {
402
+ if (!orchestrator.age) {
403
+ set.status = 501;
404
+ return { error: "Graph layer not available \u2014 requires Full tier" };
405
+ }
406
+ try {
407
+ const entities = await orchestrator.age.listEntities(
408
+ params.type,
409
+ query.agent_id,
410
+ query.limit ? parseInt(String(query.limit), 10) : 50
411
+ );
412
+ return { entities, count: entities.length };
413
+ } catch (error) {
414
+ set.status = 500;
415
+ return {
416
+ error: "Failed to list entities",
417
+ details: error instanceof Error ? error.message : String(error)
418
+ };
419
+ }
420
+ }).get("/:type/:id", async ({ params, set }) => {
421
+ if (!orchestrator.age) {
422
+ set.status = 501;
423
+ return { error: "Graph layer not available \u2014 requires Full tier" };
424
+ }
425
+ try {
426
+ const result = await orchestrator.age.getEntityWithRelationships(
427
+ params.type,
428
+ params.id
429
+ );
430
+ if (!result.entity) {
431
+ set.status = 404;
432
+ return { error: "Entity not found" };
433
+ }
434
+ return result;
435
+ } catch (error) {
436
+ set.status = 500;
437
+ return {
438
+ error: "Failed to get entity",
439
+ details: error instanceof Error ? error.message : String(error)
440
+ };
441
+ }
442
+ }).get("/:type/:id/related", async ({ params, query, set }) => {
443
+ if (!orchestrator.age) {
444
+ set.status = 501;
445
+ return { error: "Graph layer not available \u2014 requires Full tier" };
446
+ }
447
+ try {
448
+ const depth = query.depth ? parseInt(String(query.depth), 10) : 2;
449
+ const related = await orchestrator.age.getRelatedEntities(
450
+ params.id,
451
+ depth
452
+ );
453
+ return { related, count: related.length };
454
+ } catch (error) {
455
+ set.status = 500;
456
+ return {
457
+ error: "Failed to get related entities",
458
+ details: error instanceof Error ? error.message : String(error)
459
+ };
460
+ }
461
+ }).post(
462
+ "/extract",
463
+ async ({ body, set }) => {
464
+ if (!orchestrator.entityExtractor) {
465
+ set.status = 501;
466
+ return { error: "Entity extraction not available \u2014 requires extraction config" };
467
+ }
468
+ try {
469
+ const result = await orchestrator.entityExtractor.extract(body.text);
470
+ return result;
471
+ } catch (error) {
472
+ set.status = 500;
473
+ return {
474
+ error: "Entity extraction failed",
475
+ details: error instanceof Error ? error.message : String(error)
476
+ };
477
+ }
478
+ },
479
+ {
480
+ body: _elysia.t.Object({
481
+ text: _elysia.t.String()
482
+ })
483
+ }
484
+ );
485
+ }
486
+
487
+ // src/api/admin.ts
488
+
489
+ var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
490
+
491
+ function adminRoutes(orchestrator) {
492
+ return new (0, _elysia.Elysia)().get("/api/health", async () => {
493
+ return await orchestrator.healthCheck();
494
+ }).post("/api/sync/retry", async ({ set }) => {
495
+ try {
496
+ const result = await orchestrator.retrySyncQueue();
497
+ return result;
498
+ } catch (error) {
499
+ set.status = 500;
500
+ return {
501
+ error: "Sync retry failed",
502
+ details: error instanceof Error ? error.message : String(error)
503
+ };
504
+ }
505
+ }).get("/api/sync/queue", () => {
506
+ const items = orchestrator.sqlite.getSyncQueue(100);
507
+ return { items, count: items.length };
508
+ }).post(
509
+ "/api/admin/migrate-markdown",
510
+ async ({ body, set }) => {
511
+ try {
512
+ const results = await migrateMarkdownFiles(orchestrator, body);
513
+ return results;
514
+ } catch (error) {
515
+ set.status = 500;
516
+ return {
517
+ error: "Migration failed",
518
+ details: error instanceof Error ? error.message : String(error)
519
+ };
520
+ }
521
+ },
522
+ {
523
+ body: _elysia.t.Object({
524
+ markdown_paths: _elysia.t.Array(_elysia.t.String()),
525
+ agent_id: _elysia.t.String(),
526
+ dry_run: _elysia.t.Optional(_elysia.t.Boolean())
527
+ })
528
+ }
529
+ ).post("/api/admin/daily-digest", async ({ set }) => {
530
+ set.status = 501;
531
+ return { error: "Not yet implemented" };
532
+ });
533
+ }
534
+ async function migrateMarkdownFiles(orchestrator, request) {
535
+ const { markdown_paths, agent_id, dry_run } = request;
536
+ let migrated = 0;
537
+ let skipped = 0;
538
+ const errors = [];
539
+ const memories = [];
540
+ for (const filePath of markdown_paths) {
541
+ try {
542
+ if (!_fs2.default.existsSync(filePath)) {
543
+ errors.push(`File not found: ${filePath}`);
544
+ skipped++;
545
+ continue;
546
+ }
547
+ const content = _fs2.default.readFileSync(filePath, "utf-8");
548
+ const fileName = _path2.default.basename(filePath, ".md");
549
+ const sections = parseMarkdownSections(content);
550
+ for (const section of sections) {
551
+ if (section.content.trim().length < 10) {
552
+ skipped++;
553
+ continue;
554
+ }
555
+ if (dry_run) {
556
+ memories.push({
557
+ id: "(dry-run)",
558
+ content_preview: section.content.slice(0, 100)
559
+ });
560
+ migrated++;
561
+ continue;
562
+ }
563
+ const scope = inferScope(section.heading, fileName);
564
+ const source = inferSource(fileName);
565
+ const tags = inferTags(section.heading, fileName);
566
+ const req = {
567
+ agent_id,
568
+ scope,
569
+ subject_id: null,
570
+ content: section.content.trim(),
571
+ tags,
572
+ source: source || "migration",
573
+ created_by: "migration",
574
+ extract_entities: true
575
+ };
576
+ try {
577
+ const result = await orchestrator.createMemory(req);
578
+ memories.push({
579
+ id: result.id,
580
+ content_preview: section.content.slice(0, 100)
581
+ });
582
+ migrated++;
583
+ } catch (error) {
584
+ errors.push(
585
+ `Failed to migrate section "${section.heading}": ${error instanceof Error ? error.message : String(error)}`
586
+ );
587
+ }
588
+ }
589
+ } catch (error) {
590
+ errors.push(
591
+ `Failed to process ${filePath}: ${error instanceof Error ? error.message : String(error)}`
592
+ );
593
+ }
594
+ }
595
+ return { migrated, skipped, errors, memories };
596
+ }
597
+ function parseMarkdownSections(markdown) {
598
+ const lines = markdown.split("\n");
599
+ const sections = [];
600
+ let currentHeading = "root";
601
+ let currentLevel = 0;
602
+ let currentContent = [];
603
+ for (const line of lines) {
604
+ const headingMatch = line.match(/^(#{1,3})\s+(.+)/);
605
+ if (headingMatch) {
606
+ if (currentContent.length > 0) {
607
+ sections.push({
608
+ heading: currentHeading,
609
+ content: currentContent.join("\n").trim(),
610
+ level: currentLevel
611
+ });
612
+ }
613
+ currentHeading = headingMatch[2].trim();
614
+ currentLevel = headingMatch[1].length;
615
+ currentContent = [];
616
+ } else {
617
+ currentContent.push(line);
618
+ }
619
+ }
620
+ if (currentContent.length > 0) {
621
+ sections.push({
622
+ heading: currentHeading,
623
+ content: currentContent.join("\n").trim(),
624
+ level: currentLevel
625
+ });
626
+ }
627
+ return sections;
628
+ }
629
+ function inferScope(heading, fileName) {
630
+ const h = heading.toLowerCase();
631
+ const f = fileName.toLowerCase();
632
+ if (h.includes("about") || h.includes("personal")) return "user";
633
+ if (h.includes("project")) return "project";
634
+ if (h.includes("agent")) return "agent";
635
+ if (h.includes("session") || f.match(/^\d{4}-\d{2}-\d{2}/)) return "session";
636
+ return "global";
637
+ }
638
+ function inferSource(fileName) {
639
+ if (fileName.match(/^\d{4}-\d{2}-\d{2}/)) return "daily_digest";
640
+ return "migration";
641
+ }
642
+ function inferTags(heading, fileName) {
643
+ const tags = ["migration"];
644
+ if (fileName.match(/^\d{4}-\d{2}-\d{2}/)) {
645
+ tags.push("daily", fileName);
646
+ }
647
+ if (heading !== "root") {
648
+ tags.push(heading.toLowerCase().replace(/[^a-z0-9]+/g, "-"));
649
+ }
650
+ return tags;
651
+ }
652
+
653
+ // src/api/router.ts
654
+ function createApp(orchestrator, config) {
655
+ const app = new (0, _elysia.Elysia)().use(_cors.cors.call(void 0, )).derive(({ headers, set, path: path2 }) => {
656
+ if (path2 === "/api/health") return {};
657
+ if (!config.auth.enabled || !config.auth.token) return {};
658
+ const authHeader = headers.authorization;
659
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
660
+ set.status = 401;
661
+ throw new (0, _chunkZY2C2CJQcjs.AuthError)("Missing or invalid Authorization header");
662
+ }
663
+ const token = authHeader.slice(7);
664
+ if (token !== config.auth.token) {
665
+ set.status = 403;
666
+ throw new (0, _chunkZY2C2CJQcjs.AuthError)("Invalid token");
667
+ }
668
+ return {};
669
+ }).onError(({ code, error, set }) => {
670
+ if (error instanceof _chunkZY2C2CJQcjs.AuthError) {
671
+ const status = error.message.includes("Invalid token") ? 403 : 401;
672
+ set.status = status;
673
+ return { error: error.message, code: error.code };
674
+ }
675
+ if (error instanceof _chunkZY2C2CJQcjs.NotFoundError) {
676
+ set.status = 404;
677
+ return { error: error.message, code: error.code };
678
+ }
679
+ if (error instanceof _chunkZY2C2CJQcjs.ValidationError) {
680
+ set.status = 400;
681
+ return { error: error.message, code: error.code, details: error.details };
682
+ }
683
+ if (error instanceof _chunkZY2C2CJQcjs.MemoryError) {
684
+ set.status = 500;
685
+ return { error: error.message, code: error.code };
686
+ }
687
+ if (code === "VALIDATION") {
688
+ const msg2 = error && "message" in error ? error.message : String(error);
689
+ set.status = 400;
690
+ return { error: "Validation error", details: msg2 };
691
+ }
692
+ const msg = error instanceof Error ? error.stack || error.message : String(error);
693
+ console.error(`[api] Unhandled error: ${msg}`);
694
+ set.status = 500;
695
+ return { error: "Internal server error" };
696
+ }).use(memoriesRoutes(orchestrator)).use(searchRoutes(orchestrator)).use(conversationRoutes(orchestrator, config)).use(entityRoutes(orchestrator)).use(adminRoutes(orchestrator));
697
+ return app;
698
+ }
699
+
700
+ // src/server.ts
701
+ async function createServer(configPath) {
702
+ const config = await _chunkZY2C2CJQcjs.loadConfig.call(void 0, configPath);
703
+ const orchestrator = new (0, _chunkCRPEAZ44cjs.StorageOrchestrator)(config);
704
+ await orchestrator.init();
705
+ const app = createApp(orchestrator, config);
706
+ return { app, orchestrator, config };
707
+ }
708
+ async function main() {
709
+ console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
710
+ console.log("\u2502 openclaw-memory service v0.1.0 \u2502");
711
+ console.log("\u2502 Triple-Layer Memory System \u2502");
712
+ console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
713
+ const { app, orchestrator, config } = await createServer();
714
+ console.log("[config]");
715
+ console.log(_chunkZY2C2CJQcjs.configSummary.call(void 0, config).split("\n").map((l) => ` ${l}`).join("\n"));
716
+ app.listen(config.port);
717
+ console.log(`[server] Listening on http://${config.host}:${config.port}`);
718
+ console.log(`[server] Health check: http://localhost:${config.port}/api/health`);
719
+ const shutdown = async () => {
720
+ console.log("\n[server] Shutting down...");
721
+ await orchestrator.close();
722
+ process.exit(0);
723
+ };
724
+ process.on("SIGINT", shutdown);
725
+ process.on("SIGTERM", shutdown);
726
+ }
727
+ function isMainModule() {
728
+ try {
729
+ if (typeof globalThis.Bun !== "undefined") {
730
+ const bun = globalThis.Bun;
731
+ return bun.main === _url.fileURLToPath.call(void 0, import.meta.url);
732
+ }
733
+ if (process.argv[1]) {
734
+ return _path.resolve.call(void 0, process.argv[1]) === _path.resolve.call(void 0, _url.fileURLToPath.call(void 0, import.meta.url));
735
+ }
736
+ return false;
737
+ } catch (e) {
738
+ return false;
739
+ }
740
+ }
741
+ if (isMainModule()) {
742
+ main().catch((error) => {
743
+ console.error("[fatal]", error);
744
+ process.exit(1);
745
+ });
746
+ }
747
+
748
+
749
+
750
+
751
+ exports.createApp = createApp; exports.createServer = createServer;
752
+ //# sourceMappingURL=chunk-NMUPGLJW.cjs.map