agent-world 0.11.1 → 0.12.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 +17 -7
- package/dist/cli/commands.d.ts +109 -0
- package/dist/cli/commands.js +2024 -0
- package/dist/cli/display.d.ts +124 -0
- package/dist/cli/display.js +381 -0
- package/dist/cli/hitl.d.ts +33 -0
- package/dist/cli/hitl.js +81 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/stream.d.ts +41 -0
- package/dist/cli/stream.js +222 -0
- package/dist/core/activity-tracker.d.ts +16 -0
- package/dist/core/activity-tracker.d.ts.map +1 -0
- package/dist/core/activity-tracker.js +91 -0
- package/dist/core/activity-tracker.js.map +1 -0
- package/dist/core/ai-commands.d.ts +16 -0
- package/dist/core/ai-commands.d.ts.map +1 -0
- package/dist/core/ai-commands.js +24 -0
- package/dist/core/ai-commands.js.map +1 -0
- package/dist/core/ai-sdk-patch.d.ts +24 -0
- package/dist/core/ai-sdk-patch.d.ts.map +1 -0
- package/dist/core/ai-sdk-patch.js +169 -0
- package/dist/core/ai-sdk-patch.js.map +1 -0
- package/dist/core/anthropic-direct.d.ts +52 -0
- package/dist/core/anthropic-direct.d.ts.map +1 -0
- package/dist/core/anthropic-direct.js +301 -0
- package/dist/core/anthropic-direct.js.map +1 -0
- package/dist/core/approval-cache.d.ts +104 -0
- package/dist/core/approval-cache.d.ts.map +1 -0
- package/dist/core/approval-cache.js +150 -0
- package/dist/core/approval-cache.js.map +1 -0
- package/dist/core/chat-constants.d.ts +20 -0
- package/dist/core/chat-constants.d.ts.map +1 -0
- package/dist/core/chat-constants.js +22 -0
- package/dist/core/chat-constants.js.map +1 -0
- package/dist/core/create-agent-tool.d.ts +66 -0
- package/dist/core/create-agent-tool.d.ts.map +1 -0
- package/dist/core/create-agent-tool.js +212 -0
- package/dist/core/create-agent-tool.js.map +1 -0
- package/dist/core/events/approval-checker.d.ts +61 -0
- package/dist/core/events/approval-checker.d.ts.map +1 -0
- package/dist/core/events/approval-checker.js +226 -0
- package/dist/core/events/approval-checker.js.map +1 -0
- package/dist/core/events/index.d.ts +25 -0
- package/dist/core/events/index.d.ts.map +1 -0
- package/dist/core/events/index.js +30 -0
- package/dist/core/events/index.js.map +1 -0
- package/dist/core/events/memory-manager.d.ts +73 -0
- package/dist/core/events/memory-manager.d.ts.map +1 -0
- package/dist/core/events/memory-manager.js +1218 -0
- package/dist/core/events/memory-manager.js.map +1 -0
- package/dist/core/events/mention-logic.d.ts +39 -0
- package/dist/core/events/mention-logic.d.ts.map +1 -0
- package/dist/core/events/mention-logic.js +163 -0
- package/dist/core/events/mention-logic.js.map +1 -0
- package/dist/core/events/orchestrator.d.ts +69 -0
- package/dist/core/events/orchestrator.d.ts.map +1 -0
- package/dist/core/events/orchestrator.js +883 -0
- package/dist/core/events/orchestrator.js.map +1 -0
- package/dist/core/events/persistence.d.ts +41 -0
- package/dist/core/events/persistence.d.ts.map +1 -0
- package/dist/core/events/persistence.js +296 -0
- package/dist/core/events/persistence.js.map +1 -0
- package/dist/core/events/publishers.d.ts +81 -0
- package/dist/core/events/publishers.d.ts.map +1 -0
- package/dist/core/events/publishers.js +272 -0
- package/dist/core/events/publishers.js.map +1 -0
- package/dist/core/events/subscribers.d.ts +45 -0
- package/dist/core/events/subscribers.d.ts.map +1 -0
- package/dist/core/events/subscribers.js +288 -0
- package/dist/core/events/subscribers.js.map +1 -0
- package/dist/core/events/tool-bridge-logging.d.ts +28 -0
- package/dist/core/events/tool-bridge-logging.d.ts.map +1 -0
- package/dist/core/events/tool-bridge-logging.js +94 -0
- package/dist/core/events/tool-bridge-logging.js.map +1 -0
- package/dist/core/events-metadata.d.ts +72 -0
- package/dist/core/events-metadata.d.ts.map +1 -0
- package/dist/core/events-metadata.js +167 -0
- package/dist/core/events-metadata.js.map +1 -0
- package/dist/core/events.d.ts +186 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +1248 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/export.d.ts +106 -0
- package/dist/core/export.d.ts.map +1 -0
- package/dist/core/export.js +705 -0
- package/dist/core/export.js.map +1 -0
- package/dist/core/file-tools.d.ts +114 -0
- package/dist/core/file-tools.d.ts.map +1 -0
- package/dist/core/file-tools.js +370 -0
- package/dist/core/file-tools.js.map +1 -0
- package/dist/core/google-direct.d.ts +58 -0
- package/dist/core/google-direct.d.ts.map +1 -0
- package/dist/core/google-direct.js +298 -0
- package/dist/core/google-direct.js.map +1 -0
- package/dist/core/hitl.d.ts +54 -0
- package/dist/core/hitl.d.ts.map +1 -0
- package/dist/core/hitl.js +153 -0
- package/dist/core/hitl.js.map +1 -0
- package/dist/core/index.d.ts +59 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +70 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/llm-config.d.ts +128 -0
- package/dist/core/llm-config.d.ts.map +1 -0
- package/dist/core/llm-config.js +164 -0
- package/dist/core/llm-config.js.map +1 -0
- package/dist/core/llm-manager.d.ts +163 -0
- package/dist/core/llm-manager.d.ts.map +1 -0
- package/dist/core/llm-manager.js +669 -0
- package/dist/core/llm-manager.js.map +1 -0
- package/dist/core/load-skill-tool.d.ts +55 -0
- package/dist/core/load-skill-tool.d.ts.map +1 -0
- package/dist/core/load-skill-tool.js +468 -0
- package/dist/core/load-skill-tool.js.map +1 -0
- package/dist/core/logger.d.ts +88 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +358 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/managers.d.ts +131 -0
- package/dist/core/managers.d.ts.map +1 -0
- package/dist/core/managers.js +1223 -0
- package/dist/core/managers.js.map +1 -0
- package/dist/core/mcp-server-registry.d.ts +304 -0
- package/dist/core/mcp-server-registry.d.ts.map +1 -0
- package/dist/core/mcp-server-registry.js +1769 -0
- package/dist/core/mcp-server-registry.js.map +1 -0
- package/dist/core/mcp-tools.d.ts +56 -0
- package/dist/core/mcp-tools.d.ts.map +1 -0
- package/dist/core/mcp-tools.js +186 -0
- package/dist/core/mcp-tools.js.map +1 -0
- package/dist/core/message-prep.d.ts +81 -0
- package/dist/core/message-prep.d.ts.map +1 -0
- package/dist/core/message-prep.js +223 -0
- package/dist/core/message-prep.js.map +1 -0
- package/dist/core/message-processing-control.d.ts +54 -0
- package/dist/core/message-processing-control.d.ts.map +1 -0
- package/dist/core/message-processing-control.js +139 -0
- package/dist/core/message-processing-control.js.map +1 -0
- package/dist/core/openai-direct.d.ts +80 -0
- package/dist/core/openai-direct.d.ts.map +1 -0
- package/dist/core/openai-direct.js +374 -0
- package/dist/core/openai-direct.js.map +1 -0
- package/dist/core/shell-cmd-tool.d.ts +235 -0
- package/dist/core/shell-cmd-tool.d.ts.map +1 -0
- package/dist/core/shell-cmd-tool.js +1157 -0
- package/dist/core/shell-cmd-tool.js.map +1 -0
- package/dist/core/shell-process-registry.d.ts +88 -0
- package/dist/core/shell-process-registry.d.ts.map +1 -0
- package/dist/core/shell-process-registry.js +309 -0
- package/dist/core/shell-process-registry.js.map +1 -0
- package/dist/core/skill-registry.d.ts +75 -0
- package/dist/core/skill-registry.d.ts.map +1 -0
- package/dist/core/skill-registry.js +369 -0
- package/dist/core/skill-registry.js.map +1 -0
- package/dist/core/skill-script-runner.d.ts +89 -0
- package/dist/core/skill-script-runner.d.ts.map +1 -0
- package/dist/core/skill-script-runner.js +274 -0
- package/dist/core/skill-script-runner.js.map +1 -0
- package/dist/core/skill-selector.d.ts +65 -0
- package/dist/core/skill-selector.d.ts.map +1 -0
- package/dist/core/skill-selector.js +190 -0
- package/dist/core/skill-selector.js.map +1 -0
- package/dist/core/skill-settings.d.ts +20 -0
- package/dist/core/skill-settings.d.ts.map +1 -0
- package/dist/core/skill-settings.js +40 -0
- package/dist/core/skill-settings.js.map +1 -0
- package/dist/core/storage/agent-storage.d.ts +134 -0
- package/dist/core/storage/agent-storage.d.ts.map +1 -0
- package/dist/core/storage/agent-storage.js +498 -0
- package/dist/core/storage/agent-storage.js.map +1 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts +100 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js +494 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/index.d.ts +31 -0
- package/dist/core/storage/eventStorage/index.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/index.js +31 -0
- package/dist/core/storage/eventStorage/index.js.map +1 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +87 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js +244 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +45 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.js +301 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/types.d.ts +142 -0
- package/dist/core/storage/eventStorage/types.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/types.js +43 -0
- package/dist/core/storage/eventStorage/types.js.map +1 -0
- package/dist/core/storage/eventStorage/validation.d.ts +30 -0
- package/dist/core/storage/eventStorage/validation.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/validation.js +68 -0
- package/dist/core/storage/eventStorage/validation.js.map +1 -0
- package/dist/core/storage/legacy-migrations.d.ts +45 -0
- package/dist/core/storage/legacy-migrations.d.ts.map +1 -0
- package/dist/core/storage/legacy-migrations.js +295 -0
- package/dist/core/storage/legacy-migrations.js.map +1 -0
- package/dist/core/storage/memory-storage.d.ts +105 -0
- package/dist/core/storage/memory-storage.d.ts.map +1 -0
- package/dist/core/storage/memory-storage.js +415 -0
- package/dist/core/storage/memory-storage.js.map +1 -0
- package/dist/core/storage/migration-runner.d.ts +96 -0
- package/dist/core/storage/migration-runner.d.ts.map +1 -0
- package/dist/core/storage/migration-runner.js +306 -0
- package/dist/core/storage/migration-runner.js.map +1 -0
- package/dist/core/storage/queue-storage.d.ts +147 -0
- package/dist/core/storage/queue-storage.d.ts.map +1 -0
- package/dist/core/storage/queue-storage.js +290 -0
- package/dist/core/storage/queue-storage.js.map +1 -0
- package/dist/core/storage/skill-storage.d.ts +136 -0
- package/dist/core/storage/skill-storage.d.ts.map +1 -0
- package/dist/core/storage/skill-storage.js +474 -0
- package/dist/core/storage/skill-storage.js.map +1 -0
- package/dist/core/storage/sqlite-schema.d.ts +95 -0
- package/dist/core/storage/sqlite-schema.d.ts.map +1 -0
- package/dist/core/storage/sqlite-schema.js +156 -0
- package/dist/core/storage/sqlite-schema.js.map +1 -0
- package/dist/core/storage/sqlite-storage.d.ts +146 -0
- package/dist/core/storage/sqlite-storage.d.ts.map +1 -0
- package/dist/core/storage/sqlite-storage.js +709 -0
- package/dist/core/storage/sqlite-storage.js.map +1 -0
- package/dist/core/storage/storage-factory.d.ts +61 -0
- package/dist/core/storage/storage-factory.d.ts.map +1 -0
- package/dist/core/storage/storage-factory.js +794 -0
- package/dist/core/storage/storage-factory.js.map +1 -0
- package/dist/core/storage/validation.d.ts +36 -0
- package/dist/core/storage/validation.d.ts.map +1 -0
- package/dist/core/storage/validation.js +79 -0
- package/dist/core/storage/validation.js.map +1 -0
- package/dist/core/storage/world-storage.d.ts +114 -0
- package/dist/core/storage/world-storage.d.ts.map +1 -0
- package/dist/core/storage/world-storage.js +378 -0
- package/dist/core/storage/world-storage.js.map +1 -0
- package/dist/core/subscription.d.ts +43 -0
- package/dist/core/subscription.d.ts.map +1 -0
- package/dist/core/subscription.js +227 -0
- package/dist/core/subscription.js.map +1 -0
- package/dist/core/tool-utils.d.ts +80 -0
- package/dist/core/tool-utils.d.ts.map +1 -0
- package/dist/core/tool-utils.js +273 -0
- package/dist/core/tool-utils.js.map +1 -0
- package/dist/core/types.d.ts +595 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +158 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/utils.d.ts +138 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +478 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/core/world-class.d.ts +43 -0
- package/dist/core/world-class.d.ts.map +1 -0
- package/dist/core/world-class.js +90 -0
- package/dist/core/world-class.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/public/assets/agent-sprites-DJFgj-zP.png +0 -0
- package/dist/public/assets/border-KHK37r8y.svg +83 -0
- package/dist/public/assets/index-C9kPXL6G.css +1 -0
- package/dist/public/assets/index-DOQEHGWt.js +96 -0
- package/dist/public/index.html +21 -0
- package/dist/server/api.d.ts +2 -0
- package/dist/server/api.js +1124 -0
- package/dist/server/index.d.ts +29 -0
- package/dist/server/sse-handler.d.ts +62 -0
- package/dist/server/sse-handler.js +234 -0
- package/package.json +15 -3
- package/scripts/launch-electron.js +0 -58
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based Event Storage Implementation
|
|
3
|
+
*
|
|
4
|
+
* JSON-based event storage suitable for serverless environments and low-overhead persistence.
|
|
5
|
+
* Each world/chat combination is stored in a separate JSON file for efficient access patterns.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - JSON format for readable event storage
|
|
9
|
+
* - One file per world/chat combination for easy cleanup
|
|
10
|
+
* - Automatic sequence number generation per world/chat
|
|
11
|
+
* - Support for time-based and sequence-based pagination
|
|
12
|
+
* - Event type filtering
|
|
13
|
+
* - Duplicate event ID handling (silently ignores duplicates)
|
|
14
|
+
* - Write locking to prevent concurrent write corruption
|
|
15
|
+
* - No database dependencies
|
|
16
|
+
* - Suitable for serverless and file-based deployments
|
|
17
|
+
*
|
|
18
|
+
* Implementation:
|
|
19
|
+
* - Uses JSON format for human-readable event storage
|
|
20
|
+
* - Maintains sequence counters in memory with file-based initialization
|
|
21
|
+
* - File structure: baseDir/worldId/events/chatId.json
|
|
22
|
+
* - World-scoped storage: events stored within each world's directory
|
|
23
|
+
* - Checks for duplicate IDs before insertion (matches SQLite INSERT OR IGNORE behavior)
|
|
24
|
+
* - Write lock manager ensures atomic file operations per file path
|
|
25
|
+
*
|
|
26
|
+
* Cascade Delete Behavior:
|
|
27
|
+
* - Deleting a world directory removes all events for that world
|
|
28
|
+
* - Deleting a chat file removes all events for that chat
|
|
29
|
+
*
|
|
30
|
+
* Changes:
|
|
31
|
+
* - 2026-02-08: Fixed write lock queueing bug that allowed concurrent writes after first waiter
|
|
32
|
+
* - 2026-02-08: Switched event file writes to atomic temp-file + rename to avoid partial read/write races
|
|
33
|
+
* - 2026-02-08: Added recovery for valid JSON arrays with trailing corruption bytes and auto-rewrite repair
|
|
34
|
+
* - 2026-02-06: Added write lock manager to prevent concurrent write corruption during rapid event saves
|
|
35
|
+
* - 2025-11-09: Fixed file paths to be world-scoped (baseDir/worldId/events/) instead of storage root
|
|
36
|
+
* - 2025-11-03: Added duplicate event ID detection to prevent constraint violations
|
|
37
|
+
*/
|
|
38
|
+
import type { EventStorage, StoredEvent, GetEventsOptions } from './types.js';
|
|
39
|
+
/**
|
|
40
|
+
* File storage configuration
|
|
41
|
+
*/
|
|
42
|
+
export interface FileEventStorageConfig {
|
|
43
|
+
baseDir: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* File-backed event storage implementation
|
|
47
|
+
*/
|
|
48
|
+
export declare class FileEventStorage implements EventStorage {
|
|
49
|
+
private baseDir;
|
|
50
|
+
private seqCounters;
|
|
51
|
+
constructor(config: FileEventStorageConfig);
|
|
52
|
+
/**
|
|
53
|
+
* Get context key for sequence counter
|
|
54
|
+
*/
|
|
55
|
+
private getContextKey;
|
|
56
|
+
/**
|
|
57
|
+
* Get the next sequence number for a world/chat context
|
|
58
|
+
*/
|
|
59
|
+
private getNextSeq;
|
|
60
|
+
/**
|
|
61
|
+
* Save a single event
|
|
62
|
+
*/
|
|
63
|
+
saveEvent(event: StoredEvent): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Save multiple events in batch
|
|
66
|
+
* Note: This method generates sequence numbers sequentially to avoid race conditions
|
|
67
|
+
*/
|
|
68
|
+
saveEvents(events: StoredEvent[]): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Get events for a specific world and chat with filtering
|
|
71
|
+
*/
|
|
72
|
+
getEventsByWorldAndChat(worldId: string, chatId: string | null, options?: GetEventsOptions): Promise<StoredEvent[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Delete all events for a specific world and chat
|
|
75
|
+
*/
|
|
76
|
+
deleteEventsByWorldAndChat(worldId: string, chatId: string | null): Promise<number>;
|
|
77
|
+
/**
|
|
78
|
+
* Delete all events for a specific world (all chats)
|
|
79
|
+
*/
|
|
80
|
+
deleteEventsByWorld(worldId: string): Promise<number>;
|
|
81
|
+
/**
|
|
82
|
+
* Get the latest sequence number for a world/chat context
|
|
83
|
+
* Returns 0 if no events exist
|
|
84
|
+
*/
|
|
85
|
+
getLatestSeq(worldId: string, chatId: string | null): Promise<number>;
|
|
86
|
+
/**
|
|
87
|
+
* Get events within a specific sequence range (inclusive)
|
|
88
|
+
*/
|
|
89
|
+
getEventRange(worldId: string, chatId: string | null, fromSeq: number, toSeq: number): Promise<StoredEvent[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Compact a specific event file (remove deleted events, rewrite file)
|
|
92
|
+
* This is useful after bulk deletions to reclaim space
|
|
93
|
+
*/
|
|
94
|
+
compact(worldId: string, chatId: string | null): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a new file-backed event storage instance
|
|
98
|
+
*/
|
|
99
|
+
export declare function createFileEventStorage(config: FileEventStorageConfig): EventStorage;
|
|
100
|
+
//# sourceMappingURL=fileEventStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileEventStorage.d.ts","sourceRoot":"","sources":["../../../../core/storage/eventStorage/fileEventStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9E;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAyND;;GAEG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAA6B;gBAEpC,MAAM,EAAE,sBAAsB;IAI1C;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;YACW,UAAU;IAoBxB;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkClD;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDtD;;OAEG;IACG,uBAAuB,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC;IAyCzB;;OAEG;IACG,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBzF;;OAEG;IACG,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8C3D;;;OAGG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3E;;OAEG;IACG,aAAa,CACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,EAAE,CAAC;IAuBzB;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAarE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,YAAY,CAEnF"}
|
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based Event Storage Implementation
|
|
3
|
+
*
|
|
4
|
+
* JSON-based event storage suitable for serverless environments and low-overhead persistence.
|
|
5
|
+
* Each world/chat combination is stored in a separate JSON file for efficient access patterns.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - JSON format for readable event storage
|
|
9
|
+
* - One file per world/chat combination for easy cleanup
|
|
10
|
+
* - Automatic sequence number generation per world/chat
|
|
11
|
+
* - Support for time-based and sequence-based pagination
|
|
12
|
+
* - Event type filtering
|
|
13
|
+
* - Duplicate event ID handling (silently ignores duplicates)
|
|
14
|
+
* - Write locking to prevent concurrent write corruption
|
|
15
|
+
* - No database dependencies
|
|
16
|
+
* - Suitable for serverless and file-based deployments
|
|
17
|
+
*
|
|
18
|
+
* Implementation:
|
|
19
|
+
* - Uses JSON format for human-readable event storage
|
|
20
|
+
* - Maintains sequence counters in memory with file-based initialization
|
|
21
|
+
* - File structure: baseDir/worldId/events/chatId.json
|
|
22
|
+
* - World-scoped storage: events stored within each world's directory
|
|
23
|
+
* - Checks for duplicate IDs before insertion (matches SQLite INSERT OR IGNORE behavior)
|
|
24
|
+
* - Write lock manager ensures atomic file operations per file path
|
|
25
|
+
*
|
|
26
|
+
* Cascade Delete Behavior:
|
|
27
|
+
* - Deleting a world directory removes all events for that world
|
|
28
|
+
* - Deleting a chat file removes all events for that chat
|
|
29
|
+
*
|
|
30
|
+
* Changes:
|
|
31
|
+
* - 2026-02-08: Fixed write lock queueing bug that allowed concurrent writes after first waiter
|
|
32
|
+
* - 2026-02-08: Switched event file writes to atomic temp-file + rename to avoid partial read/write races
|
|
33
|
+
* - 2026-02-08: Added recovery for valid JSON arrays with trailing corruption bytes and auto-rewrite repair
|
|
34
|
+
* - 2026-02-06: Added write lock manager to prevent concurrent write corruption during rapid event saves
|
|
35
|
+
* - 2025-11-09: Fixed file paths to be world-scoped (baseDir/worldId/events/) instead of storage root
|
|
36
|
+
* - 2025-11-03: Added duplicate event ID detection to prevent constraint violations
|
|
37
|
+
*/
|
|
38
|
+
import * as fs from 'fs/promises';
|
|
39
|
+
import * as path from 'path';
|
|
40
|
+
import { existsSync } from 'fs';
|
|
41
|
+
import { validateEventForPersistence } from './validation.js';
|
|
42
|
+
/**
|
|
43
|
+
* Get file path for a world/chat combination
|
|
44
|
+
*/
|
|
45
|
+
function getEventFilePath(baseDir, worldId, chatId) {
|
|
46
|
+
const chatIdStr = chatId ?? 'null';
|
|
47
|
+
return path.join(baseDir, worldId, 'events', `${chatIdStr}.json`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get directory path for a world's events
|
|
51
|
+
*/
|
|
52
|
+
function getWorldEventsDir(baseDir, worldId) {
|
|
53
|
+
return path.join(baseDir, worldId, 'events');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Ensure directory exists
|
|
57
|
+
*/
|
|
58
|
+
async function ensureDir(dir) {
|
|
59
|
+
try {
|
|
60
|
+
await fs.mkdir(dir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// Ignore if directory already exists
|
|
64
|
+
if (error.code !== 'EEXIST') {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract first complete JSON array from content.
|
|
71
|
+
* Returns null if no complete array exists.
|
|
72
|
+
*/
|
|
73
|
+
function extractFirstJsonArray(content) {
|
|
74
|
+
const start = content.indexOf('[');
|
|
75
|
+
if (start !== 0) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
let depth = 0;
|
|
79
|
+
let inString = false;
|
|
80
|
+
let isEscaped = false;
|
|
81
|
+
for (let i = start; i < content.length; i++) {
|
|
82
|
+
const ch = content[i];
|
|
83
|
+
if (inString) {
|
|
84
|
+
if (isEscaped) {
|
|
85
|
+
isEscaped = false;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (ch === '\\') {
|
|
89
|
+
isEscaped = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (ch === '"') {
|
|
93
|
+
inString = false;
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (ch === '"') {
|
|
98
|
+
inString = true;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (ch === '[') {
|
|
102
|
+
depth += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (ch === ']') {
|
|
106
|
+
depth -= 1;
|
|
107
|
+
if (depth === 0) {
|
|
108
|
+
return content.slice(start, i + 1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse event file content, allowing recovery when valid JSON has trailing bytes.
|
|
116
|
+
*/
|
|
117
|
+
function parseEventFileContent(content) {
|
|
118
|
+
const trimmed = content.trim();
|
|
119
|
+
if (!trimmed) {
|
|
120
|
+
return { events: [], recoveredFromTrailingData: false };
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(trimmed);
|
|
124
|
+
if (!Array.isArray(parsed)) {
|
|
125
|
+
throw new Error('Expected JSON array');
|
|
126
|
+
}
|
|
127
|
+
return { events: parsed, recoveredFromTrailingData: false };
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const recoveredJson = extractFirstJsonArray(trimmed);
|
|
131
|
+
if (!recoveredJson) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
const trailing = trimmed.slice(recoveredJson.length).trim();
|
|
135
|
+
if (!trailing) {
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
const parsed = JSON.parse(recoveredJson);
|
|
139
|
+
if (!Array.isArray(parsed)) {
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
return { events: parsed, recoveredFromTrailingData: true };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Read all events from a JSON file
|
|
147
|
+
*/
|
|
148
|
+
async function readEventsFromFile(filePath) {
|
|
149
|
+
if (!existsSync(filePath)) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
154
|
+
if (!content.trim()) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const parsed = parseEventFileContent(content);
|
|
158
|
+
const events = parsed.events.map(event => ({
|
|
159
|
+
...event,
|
|
160
|
+
createdAt: new Date(event.createdAt)
|
|
161
|
+
}));
|
|
162
|
+
if (parsed.recoveredFromTrailingData) {
|
|
163
|
+
console.warn('[FileEventStorage] Recovered event file with trailing data:', filePath);
|
|
164
|
+
try {
|
|
165
|
+
await writeEventsToFile(filePath, events);
|
|
166
|
+
}
|
|
167
|
+
catch (rewriteError) {
|
|
168
|
+
console.error('[FileEventStorage] Failed to rewrite recovered event file:', filePath, rewriteError);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return events;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error('[FileEventStorage] Failed to read events from file:', filePath, error);
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Write events to a JSON file atomically
|
|
180
|
+
*/
|
|
181
|
+
async function writeEventsToFile(filePath, events) {
|
|
182
|
+
const content = JSON.stringify(events, null, 2);
|
|
183
|
+
const tempFilePath = `${filePath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
184
|
+
try {
|
|
185
|
+
await fs.writeFile(tempFilePath, content, 'utf-8');
|
|
186
|
+
await fs.rename(tempFilePath, filePath);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
try {
|
|
190
|
+
await fs.unlink(tempFilePath);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Ignore cleanup failures for temp files
|
|
194
|
+
}
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* File write lock manager to prevent concurrent writes to the same file
|
|
200
|
+
*/
|
|
201
|
+
class WriteLockManager {
|
|
202
|
+
locks = new Map();
|
|
203
|
+
/**
|
|
204
|
+
* Execute a write operation with exclusive file lock
|
|
205
|
+
*/
|
|
206
|
+
async withLock(filePath, operation) {
|
|
207
|
+
const previousTail = this.locks.get(filePath) ?? Promise.resolve();
|
|
208
|
+
let releaseCurrent;
|
|
209
|
+
const currentLock = new Promise((resolve) => {
|
|
210
|
+
releaseCurrent = resolve;
|
|
211
|
+
});
|
|
212
|
+
const queueTail = previousTail.then(() => currentLock);
|
|
213
|
+
this.locks.set(filePath, queueTail);
|
|
214
|
+
await previousTail;
|
|
215
|
+
try {
|
|
216
|
+
return await operation();
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
releaseCurrent();
|
|
220
|
+
if (this.locks.get(filePath) === queueTail) {
|
|
221
|
+
this.locks.delete(filePath);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const writeLockManager = new WriteLockManager();
|
|
227
|
+
/**
|
|
228
|
+
* File-backed event storage implementation
|
|
229
|
+
*/
|
|
230
|
+
export class FileEventStorage {
|
|
231
|
+
baseDir;
|
|
232
|
+
seqCounters = new Map();
|
|
233
|
+
constructor(config) {
|
|
234
|
+
this.baseDir = config.baseDir;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get context key for sequence counter
|
|
238
|
+
*/
|
|
239
|
+
getContextKey(worldId, chatId) {
|
|
240
|
+
return `${worldId}:${chatId ?? 'null'}`;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get the next sequence number for a world/chat context
|
|
244
|
+
*/
|
|
245
|
+
async getNextSeq(worldId, chatId) {
|
|
246
|
+
const key = this.getContextKey(worldId, chatId);
|
|
247
|
+
// Check cache first
|
|
248
|
+
if (this.seqCounters.has(key)) {
|
|
249
|
+
const current = this.seqCounters.get(key);
|
|
250
|
+
const next = current + 1;
|
|
251
|
+
this.seqCounters.set(key, next);
|
|
252
|
+
return next;
|
|
253
|
+
}
|
|
254
|
+
// Load from file to find max seq
|
|
255
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
256
|
+
const events = await readEventsFromFile(filePath);
|
|
257
|
+
const maxSeq = events.reduce((max, e) => Math.max(max, e.seq ?? 0), 0);
|
|
258
|
+
const next = maxSeq + 1;
|
|
259
|
+
this.seqCounters.set(key, next);
|
|
260
|
+
return next;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Save a single event
|
|
264
|
+
*/
|
|
265
|
+
async saveEvent(event) {
|
|
266
|
+
// Validate event metadata before persistence
|
|
267
|
+
validateEventForPersistence(event);
|
|
268
|
+
const eventsDir = getWorldEventsDir(this.baseDir, event.worldId);
|
|
269
|
+
await ensureDir(eventsDir);
|
|
270
|
+
const filePath = getEventFilePath(this.baseDir, event.worldId, event.chatId);
|
|
271
|
+
// Use lock to prevent concurrent writes to the same file
|
|
272
|
+
await writeLockManager.withLock(filePath, async () => {
|
|
273
|
+
// Read existing events
|
|
274
|
+
const existingEvents = await readEventsFromFile(filePath);
|
|
275
|
+
// Check for duplicate ID - skip if already exists
|
|
276
|
+
const existingEvent = existingEvents.find(e => e.id === event.id);
|
|
277
|
+
if (existingEvent) {
|
|
278
|
+
// Silently ignore duplicate event ID (matches SQLite INSERT OR IGNORE behavior)
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Auto-generate sequence number if not provided
|
|
282
|
+
const seq = event.seq ?? await this.getNextSeq(event.worldId, event.chatId);
|
|
283
|
+
const storedEvent = {
|
|
284
|
+
...event,
|
|
285
|
+
seq
|
|
286
|
+
};
|
|
287
|
+
existingEvents.push(storedEvent);
|
|
288
|
+
await writeEventsToFile(filePath, existingEvents);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Save multiple events in batch
|
|
293
|
+
* Note: This method generates sequence numbers sequentially to avoid race conditions
|
|
294
|
+
*/
|
|
295
|
+
async saveEvents(events) {
|
|
296
|
+
// Group events by world/chat
|
|
297
|
+
const groupedEvents = new Map();
|
|
298
|
+
for (const event of events) {
|
|
299
|
+
const key = this.getContextKey(event.worldId, event.chatId);
|
|
300
|
+
if (!groupedEvents.has(key)) {
|
|
301
|
+
groupedEvents.set(key, []);
|
|
302
|
+
}
|
|
303
|
+
groupedEvents.get(key).push(event);
|
|
304
|
+
}
|
|
305
|
+
// Process each group sequentially to avoid race conditions with seq generation
|
|
306
|
+
for (const [key, groupEvents] of groupedEvents.entries()) {
|
|
307
|
+
const [worldId, chatIdStr] = key.split(':');
|
|
308
|
+
const chatId = chatIdStr === 'null' ? null : chatIdStr;
|
|
309
|
+
const eventsDir = getWorldEventsDir(this.baseDir, worldId);
|
|
310
|
+
await ensureDir(eventsDir);
|
|
311
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
312
|
+
// Use lock to prevent concurrent writes to the same file
|
|
313
|
+
await writeLockManager.withLock(filePath, async () => {
|
|
314
|
+
// Read existing events
|
|
315
|
+
const existingEvents = await readEventsFromFile(filePath);
|
|
316
|
+
const existingIds = new Set(existingEvents.map(e => e.id));
|
|
317
|
+
// Generate seq numbers sequentially and filter out duplicates
|
|
318
|
+
const eventsWithSeq = [];
|
|
319
|
+
for (const event of groupEvents) {
|
|
320
|
+
// Validate event metadata before persistence
|
|
321
|
+
validateEventForPersistence(event);
|
|
322
|
+
// Skip if duplicate ID exists
|
|
323
|
+
if (existingIds.has(event.id)) {
|
|
324
|
+
continue; // Silently ignore duplicate
|
|
325
|
+
}
|
|
326
|
+
const seq = event.seq ?? await this.getNextSeq(worldId, chatId);
|
|
327
|
+
eventsWithSeq.push({ ...event, seq });
|
|
328
|
+
}
|
|
329
|
+
// Append new events and write back
|
|
330
|
+
existingEvents.push(...eventsWithSeq);
|
|
331
|
+
await writeEventsToFile(filePath, existingEvents);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get events for a specific world and chat with filtering
|
|
337
|
+
*/
|
|
338
|
+
async getEventsByWorldAndChat(worldId, chatId, options = {}) {
|
|
339
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
340
|
+
let events = await readEventsFromFile(filePath);
|
|
341
|
+
// Apply filters
|
|
342
|
+
if (options.sinceSeq !== undefined) {
|
|
343
|
+
events = events.filter(e => (e.seq ?? 0) > options.sinceSeq);
|
|
344
|
+
}
|
|
345
|
+
if (options.sinceTime !== undefined) {
|
|
346
|
+
events = events.filter(e => e.createdAt > options.sinceTime);
|
|
347
|
+
}
|
|
348
|
+
if (options.types && options.types.length > 0) {
|
|
349
|
+
const typeSet = new Set(options.types);
|
|
350
|
+
events = events.filter(e => typeSet.has(e.type));
|
|
351
|
+
}
|
|
352
|
+
// Sort by sequence and time
|
|
353
|
+
events.sort((a, b) => {
|
|
354
|
+
const seqA = a.seq ?? 0;
|
|
355
|
+
const seqB = b.seq ?? 0;
|
|
356
|
+
if (seqA !== seqB) {
|
|
357
|
+
return seqA - seqB;
|
|
358
|
+
}
|
|
359
|
+
return a.createdAt.getTime() - b.createdAt.getTime();
|
|
360
|
+
});
|
|
361
|
+
// Apply order (reverse if desc)
|
|
362
|
+
if (options.order === 'desc') {
|
|
363
|
+
events.reverse();
|
|
364
|
+
}
|
|
365
|
+
// Apply limit
|
|
366
|
+
if (options.limit && options.limit > 0) {
|
|
367
|
+
events = events.slice(0, options.limit);
|
|
368
|
+
}
|
|
369
|
+
return events;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Delete all events for a specific world and chat
|
|
373
|
+
*/
|
|
374
|
+
async deleteEventsByWorldAndChat(worldId, chatId) {
|
|
375
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
376
|
+
if (!existsSync(filePath)) {
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
const events = await readEventsFromFile(filePath);
|
|
380
|
+
const count = events.length;
|
|
381
|
+
// Delete the file
|
|
382
|
+
await fs.unlink(filePath);
|
|
383
|
+
// Clear sequence counter
|
|
384
|
+
const key = this.getContextKey(worldId, chatId);
|
|
385
|
+
this.seqCounters.delete(key);
|
|
386
|
+
return count;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Delete all events for a specific world (all chats)
|
|
390
|
+
*/
|
|
391
|
+
async deleteEventsByWorld(worldId) {
|
|
392
|
+
const eventsDir = getWorldEventsDir(this.baseDir, worldId);
|
|
393
|
+
if (!existsSync(eventsDir)) {
|
|
394
|
+
return 0;
|
|
395
|
+
}
|
|
396
|
+
let totalDeleted = 0;
|
|
397
|
+
try {
|
|
398
|
+
// Read all files in the events directory
|
|
399
|
+
const files = await fs.readdir(eventsDir);
|
|
400
|
+
for (const file of files) {
|
|
401
|
+
if (file.endsWith('.json')) {
|
|
402
|
+
const filePath = path.join(eventsDir, file);
|
|
403
|
+
const events = await readEventsFromFile(filePath);
|
|
404
|
+
totalDeleted += events.length;
|
|
405
|
+
await fs.unlink(filePath);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// Remove the events directory if empty
|
|
409
|
+
try {
|
|
410
|
+
await fs.rmdir(eventsDir);
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
// Ignore if directory is not empty or doesn't exist
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
console.error('[FileEventStorage] Error deleting events for world:', worldId, error);
|
|
418
|
+
}
|
|
419
|
+
// Clear sequence counters for this world
|
|
420
|
+
const keysToDelete = [];
|
|
421
|
+
for (const key of this.seqCounters.keys()) {
|
|
422
|
+
if (key.startsWith(`${worldId}:`)) {
|
|
423
|
+
keysToDelete.push(key);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
for (const key of keysToDelete) {
|
|
427
|
+
this.seqCounters.delete(key);
|
|
428
|
+
}
|
|
429
|
+
return totalDeleted;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Get the latest sequence number for a world/chat context
|
|
433
|
+
* Returns 0 if no events exist
|
|
434
|
+
*/
|
|
435
|
+
async getLatestSeq(worldId, chatId) {
|
|
436
|
+
const key = this.getContextKey(worldId, chatId);
|
|
437
|
+
// Check cache first
|
|
438
|
+
if (this.seqCounters.has(key)) {
|
|
439
|
+
return this.seqCounters.get(key);
|
|
440
|
+
}
|
|
441
|
+
// Load from file to find max seq
|
|
442
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
443
|
+
const events = await readEventsFromFile(filePath);
|
|
444
|
+
const maxSeq = events.reduce((max, e) => Math.max(max, e.seq ?? 0), 0);
|
|
445
|
+
// Update cache
|
|
446
|
+
if (maxSeq > 0) {
|
|
447
|
+
this.seqCounters.set(key, maxSeq);
|
|
448
|
+
}
|
|
449
|
+
return maxSeq;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get events within a specific sequence range (inclusive)
|
|
453
|
+
*/
|
|
454
|
+
async getEventRange(worldId, chatId, fromSeq, toSeq) {
|
|
455
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
456
|
+
let events = await readEventsFromFile(filePath);
|
|
457
|
+
// Filter by sequence range
|
|
458
|
+
events = events.filter(e => {
|
|
459
|
+
const seq = e.seq ?? 0;
|
|
460
|
+
return seq >= fromSeq && seq <= toSeq;
|
|
461
|
+
});
|
|
462
|
+
// Sort by sequence and time
|
|
463
|
+
events.sort((a, b) => {
|
|
464
|
+
const seqA = a.seq ?? 0;
|
|
465
|
+
const seqB = b.seq ?? 0;
|
|
466
|
+
if (seqA !== seqB) {
|
|
467
|
+
return seqA - seqB;
|
|
468
|
+
}
|
|
469
|
+
return a.createdAt.getTime() - b.createdAt.getTime();
|
|
470
|
+
});
|
|
471
|
+
return events;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Compact a specific event file (remove deleted events, rewrite file)
|
|
475
|
+
* This is useful after bulk deletions to reclaim space
|
|
476
|
+
*/
|
|
477
|
+
async compact(worldId, chatId) {
|
|
478
|
+
const filePath = getEventFilePath(this.baseDir, worldId, chatId);
|
|
479
|
+
if (!existsSync(filePath)) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
// Read all events
|
|
483
|
+
const events = await readEventsFromFile(filePath);
|
|
484
|
+
// Write them back (this removes any gaps or corruption)
|
|
485
|
+
await writeEventsToFile(filePath, events);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Create a new file-backed event storage instance
|
|
490
|
+
*/
|
|
491
|
+
export function createFileEventStorage(config) {
|
|
492
|
+
return new FileEventStorage(config);
|
|
493
|
+
}
|
|
494
|
+
//# sourceMappingURL=fileEventStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileEventStorage.js","sourceRoot":"","sources":["../../../../core/storage/eventStorage/fileEventStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Storage Factory
|
|
3
|
+
*
|
|
4
|
+
* Exports factory functions and types for creating event storage backends.
|
|
5
|
+
* Provides a simple API to create the appropriate storage backend based on configuration.
|
|
6
|
+
*
|
|
7
|
+
* Supported Backends:
|
|
8
|
+
* - SQLite: Production-ready persistent storage with transactions and foreign keys
|
|
9
|
+
* - Memory: Fast in-memory storage for tests and development
|
|
10
|
+
* - File: File-backed JSONL storage for simple persistence needs
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createMemoryEventStorage } from './storage/eventStorage';
|
|
15
|
+
* const storage = createMemoryEventStorage();
|
|
16
|
+
*
|
|
17
|
+
* import { createSQLiteEventStorage } from './storage/eventStorage';
|
|
18
|
+
* const storage = await createSQLiteEventStorage(db);
|
|
19
|
+
*
|
|
20
|
+
* import { createFileEventStorage } from './storage/eventStorage';
|
|
21
|
+
* const storage = createFileEventStorage({ baseDir: './data/events' });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export type { StoredEvent, GetEventsOptions, EventStorage } from './types.js';
|
|
25
|
+
export { createSQLiteEventStorage } from './sqliteEventStorage.js';
|
|
26
|
+
export { createMemoryEventStorage } from './memoryEventStorage.js';
|
|
27
|
+
export { createFileEventStorage } from './fileEventStorage.js';
|
|
28
|
+
export type { FileEventStorageConfig } from './fileEventStorage.js';
|
|
29
|
+
export { MemoryEventStorage } from './memoryEventStorage.js';
|
|
30
|
+
export { FileEventStorage } from './fileEventStorage.js';
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../core/storage/eventStorage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,YAAY,EACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|