genbox-agent 1.0.39 → 1.0.41
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/dist/hook.d.ts +6 -5
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +200 -81
- package/dist/hook.js.map +1 -1
- package/dist/hooks/daemon-client.d.ts +39 -0
- package/dist/hooks/daemon-client.d.ts.map +1 -0
- package/dist/hooks/daemon-client.js +238 -0
- package/dist/hooks/daemon-client.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +23 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/server/auth.d.ts +51 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +154 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/index.d.ts +156 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +595 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/port-finder.d.ts +45 -0
- package/dist/server/port-finder.d.ts.map +1 -0
- package/dist/server/port-finder.js +267 -0
- package/dist/server/port-finder.js.map +1 -0
- package/dist/storage/index.d.ts +82 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +209 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/manager.d.ts +112 -0
- package/dist/storage/manager.d.ts.map +1 -0
- package/dist/storage/manager.js +200 -0
- package/dist/storage/manager.js.map +1 -0
- package/dist/storage/repositories/events.d.ts +101 -0
- package/dist/storage/repositories/events.d.ts.map +1 -0
- package/dist/storage/repositories/events.js +258 -0
- package/dist/storage/repositories/events.js.map +1 -0
- package/dist/storage/repositories/index.d.ts +9 -0
- package/dist/storage/repositories/index.d.ts.map +1 -0
- package/dist/storage/repositories/index.js +25 -0
- package/dist/storage/repositories/index.js.map +1 -0
- package/dist/storage/repositories/messages.d.ts +123 -0
- package/dist/storage/repositories/messages.d.ts.map +1 -0
- package/dist/storage/repositories/messages.js +209 -0
- package/dist/storage/repositories/messages.js.map +1 -0
- package/dist/storage/repositories/sessions.d.ts +158 -0
- package/dist/storage/repositories/sessions.d.ts.map +1 -0
- package/dist/storage/repositories/sessions.js +342 -0
- package/dist/storage/repositories/sessions.js.map +1 -0
- package/dist/storage/schema.d.ts +42 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +278 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/sync/background-sync.d.ts +83 -0
- package/dist/sync/background-sync.d.ts.map +1 -0
- package/dist/sync/background-sync.js +367 -0
- package/dist/sync/background-sync.js.map +1 -0
- package/dist/sync/index.d.ts +7 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +23 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/unified-daemon.js +219 -0
- package/dist/unified-daemon.js.map +1 -1
- package/dist/unified-hook.d.ts +4 -3
- package/dist/unified-hook.d.ts.map +1 -1
- package/dist/unified-hook.js +155 -31
- package/dist/unified-hook.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage Manager
|
|
3
|
+
*
|
|
4
|
+
* High-level interface for local storage operations.
|
|
5
|
+
* Wraps LocalStorage and all repositories.
|
|
6
|
+
*/
|
|
7
|
+
import { StorageConfig } from './index';
|
|
8
|
+
import { SessionRepository, Session, CreateSessionInput, UpdateSessionInput, TokenMetricsUpdate } from './repositories/sessions';
|
|
9
|
+
import { MessageRepository, Message, CreateMessageInput, ContentBlock } from './repositories/messages';
|
|
10
|
+
import { EventRepository, SessionEvent, CreateEventInput } from './repositories/events';
|
|
11
|
+
import { EventType, SessionStatus, SessionState, Provider } from './schema';
|
|
12
|
+
export { Session, CreateSessionInput, UpdateSessionInput, TokenMetricsUpdate, Message, CreateMessageInput, ContentBlock, SessionEvent, CreateEventInput, EventType, SessionStatus, SessionState, Provider, };
|
|
13
|
+
/**
|
|
14
|
+
* Storage Manager - unified interface for all storage operations
|
|
15
|
+
*/
|
|
16
|
+
export declare class StorageManager {
|
|
17
|
+
private storage;
|
|
18
|
+
sessions: SessionRepository;
|
|
19
|
+
messages: MessageRepository;
|
|
20
|
+
events: EventRepository;
|
|
21
|
+
constructor(config?: StorageConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Get database stats
|
|
24
|
+
*/
|
|
25
|
+
getStats(): {
|
|
26
|
+
sessions: number;
|
|
27
|
+
messages: number;
|
|
28
|
+
toolUses: number;
|
|
29
|
+
events: number;
|
|
30
|
+
sizeBytes: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Get pending sync counts
|
|
34
|
+
*/
|
|
35
|
+
getPendingSyncCounts(): {
|
|
36
|
+
sessions: number;
|
|
37
|
+
messages: number;
|
|
38
|
+
toolUses: number;
|
|
39
|
+
events: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Close storage
|
|
43
|
+
*/
|
|
44
|
+
close(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Record a hook event (from Claude/Gemini/Codex hooks)
|
|
47
|
+
* Creates session if needed, updates metrics, stores event
|
|
48
|
+
*/
|
|
49
|
+
recordHookEvent(input: {
|
|
50
|
+
sessionId: string;
|
|
51
|
+
eventType: EventType;
|
|
52
|
+
provider?: Provider;
|
|
53
|
+
projectPath?: string;
|
|
54
|
+
data?: Record<string, any>;
|
|
55
|
+
inputTokens?: number;
|
|
56
|
+
outputTokens?: number;
|
|
57
|
+
cacheReadTokens?: number;
|
|
58
|
+
cacheWriteTokens?: number;
|
|
59
|
+
contextTokens?: number;
|
|
60
|
+
costCents?: number;
|
|
61
|
+
}): {
|
|
62
|
+
session: Session;
|
|
63
|
+
event: SessionEvent;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Record a message
|
|
67
|
+
*/
|
|
68
|
+
recordMessage(input: CreateMessageInput): Message;
|
|
69
|
+
/**
|
|
70
|
+
* Get session with recent events
|
|
71
|
+
*/
|
|
72
|
+
getSessionWithEvents(sessionId: string, eventLimit?: number): {
|
|
73
|
+
session: Session | null;
|
|
74
|
+
events: SessionEvent[];
|
|
75
|
+
messages: Message[];
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Get all data for sync
|
|
79
|
+
*/
|
|
80
|
+
getUnsyncedData(limits?: {
|
|
81
|
+
sessions: number;
|
|
82
|
+
messages: number;
|
|
83
|
+
events: number;
|
|
84
|
+
}): {
|
|
85
|
+
sessions: Session[];
|
|
86
|
+
messages: Message[];
|
|
87
|
+
events: SessionEvent[];
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Mark data as synced
|
|
91
|
+
*/
|
|
92
|
+
markSynced(data: {
|
|
93
|
+
sessionIds?: string[];
|
|
94
|
+
messageIds?: string[];
|
|
95
|
+
eventIds?: string[];
|
|
96
|
+
}): void;
|
|
97
|
+
/**
|
|
98
|
+
* Cleanup old data
|
|
99
|
+
*/
|
|
100
|
+
cleanup(): {
|
|
101
|
+
eventsDeleted: number;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get or create the storage manager instance
|
|
106
|
+
*/
|
|
107
|
+
export declare function getStorageManager(config?: StorageConfig): StorageManager;
|
|
108
|
+
/**
|
|
109
|
+
* Close the storage manager
|
|
110
|
+
*/
|
|
111
|
+
export declare function closeStorageManager(): void;
|
|
112
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/storage/manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,aAAa,EAA4B,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACjI,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG5E,OAAO,EACL,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,EACP,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,QAAQ,GACT,CAAC;AAEF;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAe;IACvB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;gBAEnB,MAAM,CAAC,EAAE,aAAa;IASlC;;OAEG;IACH,QAAQ;;;;;;;IAIR;;OAEG;IACH,oBAAoB;;;;;;IAIpB;;OAEG;IACH,KAAK;IAIL;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAG3B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE;IA6E7C;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO;IAuBjD;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG;QACxD,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,YAAY,EAAE,CAAC;QACvB,QAAQ,EAAE,OAAO,EAAE,CAAC;KACrB;IAYD;;OAEG;IACH,eAAe,CAAC,MAAM;;;;KAA+C,GAAG;QACtE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,YAAY,EAAE,CAAC;KACxB;IAQD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE;QACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,GAAG,IAAI;IAcR;;OAEG;IACH,OAAO,IAAI;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE;CAIrC;AAKD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,cAAc,CAKxE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Storage Manager
|
|
4
|
+
*
|
|
5
|
+
* High-level interface for local storage operations.
|
|
6
|
+
* Wraps LocalStorage and all repositories.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.StorageManager = void 0;
|
|
10
|
+
exports.getStorageManager = getStorageManager;
|
|
11
|
+
exports.closeStorageManager = closeStorageManager;
|
|
12
|
+
const index_1 = require("./index");
|
|
13
|
+
const sessions_1 = require("./repositories/sessions");
|
|
14
|
+
const messages_1 = require("./repositories/messages");
|
|
15
|
+
const events_1 = require("./repositories/events");
|
|
16
|
+
/**
|
|
17
|
+
* Storage Manager - unified interface for all storage operations
|
|
18
|
+
*/
|
|
19
|
+
class StorageManager {
|
|
20
|
+
storage;
|
|
21
|
+
sessions;
|
|
22
|
+
messages;
|
|
23
|
+
events;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.storage = (0, index_1.getStorage)(config);
|
|
26
|
+
const db = this.storage.getDb();
|
|
27
|
+
this.sessions = new sessions_1.SessionRepository(db);
|
|
28
|
+
this.messages = new messages_1.MessageRepository(db);
|
|
29
|
+
this.events = new events_1.EventRepository(db);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get database stats
|
|
33
|
+
*/
|
|
34
|
+
getStats() {
|
|
35
|
+
return this.storage.getStats();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get pending sync counts
|
|
39
|
+
*/
|
|
40
|
+
getPendingSyncCounts() {
|
|
41
|
+
return this.storage.getPendingSyncCounts();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Close storage
|
|
45
|
+
*/
|
|
46
|
+
close() {
|
|
47
|
+
(0, index_1.closeStorage)();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Record a hook event (from Claude/Gemini/Codex hooks)
|
|
51
|
+
* Creates session if needed, updates metrics, stores event
|
|
52
|
+
*/
|
|
53
|
+
recordHookEvent(input) {
|
|
54
|
+
const { sessionId, eventType, provider = 'claude', projectPath, data, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, contextTokens, costCents, } = input;
|
|
55
|
+
// Ensure session exists
|
|
56
|
+
let session = this.sessions.getById(sessionId);
|
|
57
|
+
if (!session) {
|
|
58
|
+
session = this.sessions.create({
|
|
59
|
+
id: sessionId,
|
|
60
|
+
provider,
|
|
61
|
+
projectPath,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Update session metrics if provided
|
|
65
|
+
if (inputTokens || outputTokens || cacheReadTokens || cacheWriteTokens) {
|
|
66
|
+
this.sessions.updateMetrics(sessionId, {
|
|
67
|
+
inputTokens,
|
|
68
|
+
outputTokens,
|
|
69
|
+
cacheReadTokens,
|
|
70
|
+
cacheWriteTokens,
|
|
71
|
+
contextTokens,
|
|
72
|
+
}, costCents || 0);
|
|
73
|
+
session = this.sessions.getById(sessionId);
|
|
74
|
+
}
|
|
75
|
+
// Create event
|
|
76
|
+
const event = this.events.create({
|
|
77
|
+
sessionId,
|
|
78
|
+
type: eventType,
|
|
79
|
+
data,
|
|
80
|
+
contextTokens: session.contextTokens,
|
|
81
|
+
costCentsSoFar: Math.round(session.estimatedCostUsd * 100),
|
|
82
|
+
messageCount: session.messageCount,
|
|
83
|
+
});
|
|
84
|
+
// Handle special event types
|
|
85
|
+
switch (eventType) {
|
|
86
|
+
case 'session_start':
|
|
87
|
+
this.sessions.updateStatus(sessionId, 'active');
|
|
88
|
+
break;
|
|
89
|
+
case 'session_end':
|
|
90
|
+
this.sessions.updateStatus(sessionId, 'ended');
|
|
91
|
+
break;
|
|
92
|
+
case 'prompt_submitted':
|
|
93
|
+
this.sessions.incrementCounts(sessionId, { userPrompts: 1, messages: 1 });
|
|
94
|
+
this.sessions.updateState(sessionId, 'thinking');
|
|
95
|
+
break;
|
|
96
|
+
case 'response_completed':
|
|
97
|
+
this.sessions.incrementCounts(sessionId, { assistantResponses: 1, messages: 1 });
|
|
98
|
+
this.sessions.updateState(sessionId, 'waiting_for_input');
|
|
99
|
+
break;
|
|
100
|
+
case 'tool_started':
|
|
101
|
+
this.sessions.updateState(sessionId, 'executing_tool', data?.toolName);
|
|
102
|
+
break;
|
|
103
|
+
case 'tool_completed':
|
|
104
|
+
case 'tool_error':
|
|
105
|
+
this.sessions.incrementCounts(sessionId, { toolUses: 1 });
|
|
106
|
+
this.sessions.updateState(sessionId, 'responding');
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
return { session: this.sessions.getById(sessionId), event };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Record a message
|
|
113
|
+
*/
|
|
114
|
+
recordMessage(input) {
|
|
115
|
+
const message = this.messages.create(input);
|
|
116
|
+
// Update session counts
|
|
117
|
+
this.sessions.incrementCounts(input.sessionId, {
|
|
118
|
+
messages: 1,
|
|
119
|
+
userPrompts: input.role === 'user' ? 1 : 0,
|
|
120
|
+
assistantResponses: input.role === 'assistant' ? 1 : 0,
|
|
121
|
+
});
|
|
122
|
+
// Update session metrics
|
|
123
|
+
if (input.inputTokens || input.outputTokens) {
|
|
124
|
+
this.sessions.updateMetrics(input.sessionId, {
|
|
125
|
+
inputTokens: input.inputTokens,
|
|
126
|
+
outputTokens: input.outputTokens,
|
|
127
|
+
cacheReadTokens: input.cacheReadTokens,
|
|
128
|
+
cacheWriteTokens: input.cacheWriteTokens,
|
|
129
|
+
}, input.costCents || 0);
|
|
130
|
+
}
|
|
131
|
+
return message;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get session with recent events
|
|
135
|
+
*/
|
|
136
|
+
getSessionWithEvents(sessionId, eventLimit = 20) {
|
|
137
|
+
const session = this.sessions.getById(sessionId);
|
|
138
|
+
if (!session) {
|
|
139
|
+
return { session: null, events: [], messages: [] };
|
|
140
|
+
}
|
|
141
|
+
const events = this.events.getBySessionRecent(sessionId, eventLimit);
|
|
142
|
+
const messages = this.messages.getBySession(sessionId);
|
|
143
|
+
return { session, events, messages };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get all data for sync
|
|
147
|
+
*/
|
|
148
|
+
getUnsyncedData(limits = { sessions: 50, messages: 100, events: 200 }) {
|
|
149
|
+
return {
|
|
150
|
+
sessions: this.sessions.getUnsynced(limits.sessions),
|
|
151
|
+
messages: this.messages.getUnsynced(limits.messages),
|
|
152
|
+
events: this.events.getUnsynced(limits.events),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Mark data as synced
|
|
157
|
+
*/
|
|
158
|
+
markSynced(data) {
|
|
159
|
+
if (data.sessionIds?.length) {
|
|
160
|
+
for (const id of data.sessionIds) {
|
|
161
|
+
this.sessions.markSynced(id);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (data.messageIds?.length) {
|
|
165
|
+
this.messages.markManySynced(data.messageIds);
|
|
166
|
+
}
|
|
167
|
+
if (data.eventIds?.length) {
|
|
168
|
+
this.events.markManySynced(data.eventIds);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Cleanup old data
|
|
173
|
+
*/
|
|
174
|
+
cleanup() {
|
|
175
|
+
const eventsDeleted = this.events.deleteOld();
|
|
176
|
+
return { eventsDeleted };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.StorageManager = StorageManager;
|
|
180
|
+
// Singleton instance
|
|
181
|
+
let managerInstance = null;
|
|
182
|
+
/**
|
|
183
|
+
* Get or create the storage manager instance
|
|
184
|
+
*/
|
|
185
|
+
function getStorageManager(config) {
|
|
186
|
+
if (!managerInstance) {
|
|
187
|
+
managerInstance = new StorageManager(config);
|
|
188
|
+
}
|
|
189
|
+
return managerInstance;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Close the storage manager
|
|
193
|
+
*/
|
|
194
|
+
function closeStorageManager() {
|
|
195
|
+
if (managerInstance) {
|
|
196
|
+
managerInstance.close();
|
|
197
|
+
managerInstance = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/storage/manager.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AA+PH,8CAKC;AAKD,kDAKC;AA5QD,mCAAgF;AAChF,sDAAiI;AACjI,sDAAuG;AACvG,kDAAwF;AAoBxF;;GAEG;AACH,MAAa,cAAc;IACjB,OAAO,CAAe;IACvB,QAAQ,CAAoB;IAC5B,QAAQ,CAAoB;IAC5B,MAAM,CAAkB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAEhC,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAAiB,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG,IAAI,4BAAiB,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,wBAAe,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAA,oBAAY,GAAE,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,KAcf;QACC,MAAM,EACJ,SAAS,EACT,SAAS,EACT,QAAQ,GAAG,QAAQ,EACnB,WAAW,EACX,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,GACV,GAAG,KAAK,CAAC;QAEV,wBAAwB;QACxB,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAC7B,EAAE,EAAE,SAAS;gBACb,QAAQ;gBACR,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;QAED,qCAAqC;QACrC,IAAI,WAAW,IAAI,YAAY,IAAI,eAAe,IAAI,gBAAgB,EAAE,CAAC;YACvE,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE;gBACrC,WAAW;gBACX,YAAY;gBACZ,eAAe;gBACf,gBAAgB;gBAChB,aAAa;aACd,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC;YAEnB,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAE,CAAC;QAC9C,CAAC;QAED,eAAe;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAC/B,SAAS;YACT,IAAI,EAAE,SAAS;YACf,IAAI;YACJ,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,GAAG,GAAG,CAAC;YAC1D,YAAY,EAAE,OAAO,CAAC,YAAY;SACnC,CAAC,CAAC;QAEH,6BAA6B;QAC7B,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,eAAe;gBAClB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBAChD,MAAM;YACR,KAAK,aAAa;gBAChB,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;gBAC/C,MAAM;YACR,KAAK,kBAAkB;gBACrB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC1E,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBACjD,MAAM;YACR,KAAK,oBAAoB;gBACvB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;gBACjF,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;gBAC1D,MAAM;YACR,KAAK,cAAc;gBACjB,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACvE,MAAM;YACR,KAAK,gBAAgB,CAAC;YACtB,KAAK,YAAY;gBACf,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC1D,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;gBACnD,MAAM;QACV,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAE,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,KAAyB;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE5C,wBAAwB;QACxB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE;YAC7C,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,kBAAkB,EAAE,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACvD,CAAC,CAAC;QAEH,yBAAyB;QACzB,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC5C,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,EAAE;gBAC3C,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;aACzC,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;QAC3B,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAC,SAAiB,EAAE,UAAU,GAAG,EAAE;QAKrD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAEvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;QAKnE,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;YACpD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;YACpD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC;SAC/C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,IAIV;QACC,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YAC5B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACjC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,EAAE,aAAa,EAAE,CAAC;IAC3B,CAAC;CACF;AA3ND,wCA2NC;AAED,qBAAqB;AACrB,IAAI,eAAe,GAA0B,IAAI,CAAC;AAElD;;GAEG;AACH,SAAgB,iBAAiB,CAAC,MAAsB;IACtD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB;IACjC,IAAI,eAAe,EAAE,CAAC;QACpB,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Repository
|
|
3
|
+
*
|
|
4
|
+
* CRUD operations for session events, compatible with Session V2 API.
|
|
5
|
+
* Events are lightweight activity markers with 7-day auto-cleanup.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { EventType } from '../schema';
|
|
9
|
+
/**
|
|
10
|
+
* Event entity (matches V2 API)
|
|
11
|
+
*/
|
|
12
|
+
export interface SessionEvent {
|
|
13
|
+
id: string;
|
|
14
|
+
sessionId: string;
|
|
15
|
+
type: EventType;
|
|
16
|
+
data?: Record<string, any>;
|
|
17
|
+
contextTokens?: number;
|
|
18
|
+
costCentsSoFar?: number;
|
|
19
|
+
messageCount?: number;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
syncedAt?: number;
|
|
22
|
+
syncPending: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create event input
|
|
26
|
+
*/
|
|
27
|
+
export interface CreateEventInput {
|
|
28
|
+
id?: string;
|
|
29
|
+
sessionId: string;
|
|
30
|
+
type: EventType;
|
|
31
|
+
data?: Record<string, any>;
|
|
32
|
+
contextTokens?: number;
|
|
33
|
+
costCentsSoFar?: number;
|
|
34
|
+
messageCount?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Event repository
|
|
38
|
+
*/
|
|
39
|
+
export declare class EventRepository {
|
|
40
|
+
private db;
|
|
41
|
+
private stmts;
|
|
42
|
+
constructor(db: Database.Database);
|
|
43
|
+
private prepareStatements;
|
|
44
|
+
/**
|
|
45
|
+
* Create a new event
|
|
46
|
+
*/
|
|
47
|
+
create(input: CreateEventInput): SessionEvent;
|
|
48
|
+
/**
|
|
49
|
+
* Create multiple events in a transaction
|
|
50
|
+
*/
|
|
51
|
+
createMany(inputs: CreateEventInput[]): SessionEvent[];
|
|
52
|
+
/**
|
|
53
|
+
* Get event by ID
|
|
54
|
+
*/
|
|
55
|
+
getById(id: string): SessionEvent | null;
|
|
56
|
+
/**
|
|
57
|
+
* Get all events for a session
|
|
58
|
+
*/
|
|
59
|
+
getBySession(sessionId: string): SessionEvent[];
|
|
60
|
+
/**
|
|
61
|
+
* Get recent events for a session
|
|
62
|
+
*/
|
|
63
|
+
getBySessionRecent(sessionId: string, limit?: number): SessionEvent[];
|
|
64
|
+
/**
|
|
65
|
+
* Get events by type
|
|
66
|
+
*/
|
|
67
|
+
getByType(type: EventType, limit?: number): SessionEvent[];
|
|
68
|
+
/**
|
|
69
|
+
* Get event count for a session
|
|
70
|
+
*/
|
|
71
|
+
count(sessionId: string): number;
|
|
72
|
+
/**
|
|
73
|
+
* Mark event as synced
|
|
74
|
+
*/
|
|
75
|
+
markSynced(id: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Mark multiple events as synced
|
|
78
|
+
*/
|
|
79
|
+
markManySynced(ids: string[]): void;
|
|
80
|
+
/**
|
|
81
|
+
* Get unsynced events
|
|
82
|
+
*/
|
|
83
|
+
getUnsynced(limit?: number): SessionEvent[];
|
|
84
|
+
/**
|
|
85
|
+
* Delete event
|
|
86
|
+
*/
|
|
87
|
+
delete(id: string): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Delete all events for a session
|
|
90
|
+
*/
|
|
91
|
+
deleteBySession(sessionId: string): number;
|
|
92
|
+
/**
|
|
93
|
+
* Delete old events (manual cleanup)
|
|
94
|
+
*/
|
|
95
|
+
deleteOld(olderThanMs?: number): number;
|
|
96
|
+
/**
|
|
97
|
+
* Map database row to SessionEvent object
|
|
98
|
+
*/
|
|
99
|
+
private mapRow;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/storage/repositories/events.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAG3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,SAAS,EAAE,MAAM,CAAC;IAGlB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,eAAe;IAed,OAAO,CAAC,EAAE;IAdtB,OAAO,CAAC,KAAK,CAYX;gBAEkB,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAIzC,OAAO,CAAC,iBAAiB;IA8DzB;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY;IAkB7C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,YAAY,EAAE;IAoCtD;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAKxC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE;IAK/C;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,YAAY,EAAE;IAKjE;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,SAAM,GAAG,YAAY,EAAE;IAKvD;;OAEG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAKhC;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAUnC;;OAEG;IACH,WAAW,CAAC,KAAK,SAAM,GAAG,YAAY,EAAE;IAKxC;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAK3B;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAK1C;;OAEG;IACH,SAAS,CAAC,WAAW,GAAE,MAAgC,GAAG,MAAM;IAMhE;;OAEG;IACH,OAAO,CAAC,MAAM;CAcf"}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Event Repository
|
|
4
|
+
*
|
|
5
|
+
* CRUD operations for session events, compatible with Session V2 API.
|
|
6
|
+
* Events are lightweight activity markers with 7-day auto-cleanup.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.EventRepository = void 0;
|
|
43
|
+
const crypto = __importStar(require("crypto"));
|
|
44
|
+
/**
|
|
45
|
+
* Event repository
|
|
46
|
+
*/
|
|
47
|
+
class EventRepository {
|
|
48
|
+
db;
|
|
49
|
+
stmts;
|
|
50
|
+
constructor(db) {
|
|
51
|
+
this.db = db;
|
|
52
|
+
this.stmts = this.prepareStatements();
|
|
53
|
+
}
|
|
54
|
+
prepareStatements() {
|
|
55
|
+
return {
|
|
56
|
+
insert: this.db.prepare(`
|
|
57
|
+
INSERT INTO events (
|
|
58
|
+
id, session_id, type, data,
|
|
59
|
+
context_tokens, cost_cents_so_far, message_count,
|
|
60
|
+
created_at
|
|
61
|
+
) VALUES (
|
|
62
|
+
@id, @sessionId, @type, @data,
|
|
63
|
+
@contextTokens, @costCentsSoFar, @messageCount,
|
|
64
|
+
@createdAt
|
|
65
|
+
)
|
|
66
|
+
`),
|
|
67
|
+
getById: this.db.prepare(`
|
|
68
|
+
SELECT * FROM events WHERE id = ?
|
|
69
|
+
`),
|
|
70
|
+
getBySession: this.db.prepare(`
|
|
71
|
+
SELECT * FROM events WHERE session_id = ? ORDER BY created_at DESC
|
|
72
|
+
`),
|
|
73
|
+
getBySessionRecent: this.db.prepare(`
|
|
74
|
+
SELECT * FROM events
|
|
75
|
+
WHERE session_id = ?
|
|
76
|
+
ORDER BY created_at DESC
|
|
77
|
+
LIMIT ?
|
|
78
|
+
`),
|
|
79
|
+
getByType: this.db.prepare(`
|
|
80
|
+
SELECT * FROM events WHERE type = ? ORDER BY created_at DESC LIMIT ?
|
|
81
|
+
`),
|
|
82
|
+
markSynced: this.db.prepare(`
|
|
83
|
+
UPDATE events SET
|
|
84
|
+
synced_at = @syncedAt,
|
|
85
|
+
sync_pending = 0
|
|
86
|
+
WHERE id = @id
|
|
87
|
+
`),
|
|
88
|
+
getUnsynced: this.db.prepare(`
|
|
89
|
+
SELECT * FROM events WHERE sync_pending = 1 ORDER BY created_at ASC LIMIT ?
|
|
90
|
+
`),
|
|
91
|
+
delete: this.db.prepare(`
|
|
92
|
+
DELETE FROM events WHERE id = ?
|
|
93
|
+
`),
|
|
94
|
+
deleteBySession: this.db.prepare(`
|
|
95
|
+
DELETE FROM events WHERE session_id = ?
|
|
96
|
+
`),
|
|
97
|
+
deleteOld: this.db.prepare(`
|
|
98
|
+
DELETE FROM events WHERE created_at < ?
|
|
99
|
+
`),
|
|
100
|
+
count: this.db.prepare(`
|
|
101
|
+
SELECT COUNT(*) as count FROM events WHERE session_id = ?
|
|
102
|
+
`),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create a new event
|
|
107
|
+
*/
|
|
108
|
+
create(input) {
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
const id = input.id || crypto.randomUUID();
|
|
111
|
+
this.stmts.insert.run({
|
|
112
|
+
id,
|
|
113
|
+
sessionId: input.sessionId,
|
|
114
|
+
type: input.type,
|
|
115
|
+
data: input.data ? JSON.stringify(input.data) : null,
|
|
116
|
+
contextTokens: input.contextTokens || null,
|
|
117
|
+
costCentsSoFar: input.costCentsSoFar || null,
|
|
118
|
+
messageCount: input.messageCount || null,
|
|
119
|
+
createdAt: now,
|
|
120
|
+
});
|
|
121
|
+
return this.getById(id);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create multiple events in a transaction
|
|
125
|
+
*/
|
|
126
|
+
createMany(inputs) {
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
const events = [];
|
|
129
|
+
this.db.transaction(() => {
|
|
130
|
+
for (const input of inputs) {
|
|
131
|
+
const id = input.id || crypto.randomUUID();
|
|
132
|
+
this.stmts.insert.run({
|
|
133
|
+
id,
|
|
134
|
+
sessionId: input.sessionId,
|
|
135
|
+
type: input.type,
|
|
136
|
+
data: input.data ? JSON.stringify(input.data) : null,
|
|
137
|
+
contextTokens: input.contextTokens || null,
|
|
138
|
+
costCentsSoFar: input.costCentsSoFar || null,
|
|
139
|
+
messageCount: input.messageCount || null,
|
|
140
|
+
createdAt: now,
|
|
141
|
+
});
|
|
142
|
+
events.push({
|
|
143
|
+
id,
|
|
144
|
+
sessionId: input.sessionId,
|
|
145
|
+
type: input.type,
|
|
146
|
+
data: input.data,
|
|
147
|
+
contextTokens: input.contextTokens,
|
|
148
|
+
costCentsSoFar: input.costCentsSoFar,
|
|
149
|
+
messageCount: input.messageCount,
|
|
150
|
+
createdAt: now,
|
|
151
|
+
syncPending: true,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
})();
|
|
155
|
+
return events;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get event by ID
|
|
159
|
+
*/
|
|
160
|
+
getById(id) {
|
|
161
|
+
const row = this.stmts.getById.get(id);
|
|
162
|
+
return row ? this.mapRow(row) : null;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get all events for a session
|
|
166
|
+
*/
|
|
167
|
+
getBySession(sessionId) {
|
|
168
|
+
const rows = this.stmts.getBySession.all(sessionId);
|
|
169
|
+
return rows.map(row => this.mapRow(row));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get recent events for a session
|
|
173
|
+
*/
|
|
174
|
+
getBySessionRecent(sessionId, limit = 20) {
|
|
175
|
+
const rows = this.stmts.getBySessionRecent.all(sessionId, limit);
|
|
176
|
+
return rows.map(row => this.mapRow(row));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get events by type
|
|
180
|
+
*/
|
|
181
|
+
getByType(type, limit = 100) {
|
|
182
|
+
const rows = this.stmts.getByType.all(type, limit);
|
|
183
|
+
return rows.map(row => this.mapRow(row));
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get event count for a session
|
|
187
|
+
*/
|
|
188
|
+
count(sessionId) {
|
|
189
|
+
const row = this.stmts.count.get(sessionId);
|
|
190
|
+
return row.count;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Mark event as synced
|
|
194
|
+
*/
|
|
195
|
+
markSynced(id) {
|
|
196
|
+
this.stmts.markSynced.run({ id, syncedAt: Date.now() });
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Mark multiple events as synced
|
|
200
|
+
*/
|
|
201
|
+
markManySynced(ids) {
|
|
202
|
+
const stmt = this.stmts.markSynced;
|
|
203
|
+
const syncedAt = Date.now();
|
|
204
|
+
this.db.transaction(() => {
|
|
205
|
+
for (const id of ids) {
|
|
206
|
+
stmt.run({ id, syncedAt });
|
|
207
|
+
}
|
|
208
|
+
})();
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get unsynced events
|
|
212
|
+
*/
|
|
213
|
+
getUnsynced(limit = 100) {
|
|
214
|
+
const rows = this.stmts.getUnsynced.all(limit);
|
|
215
|
+
return rows.map(row => this.mapRow(row));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Delete event
|
|
219
|
+
*/
|
|
220
|
+
delete(id) {
|
|
221
|
+
const result = this.stmts.delete.run(id);
|
|
222
|
+
return result.changes > 0;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Delete all events for a session
|
|
226
|
+
*/
|
|
227
|
+
deleteBySession(sessionId) {
|
|
228
|
+
const result = this.stmts.deleteBySession.run(sessionId);
|
|
229
|
+
return result.changes;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Delete old events (manual cleanup)
|
|
233
|
+
*/
|
|
234
|
+
deleteOld(olderThanMs = 7 * 24 * 60 * 60 * 1000) {
|
|
235
|
+
const cutoff = Date.now() - olderThanMs;
|
|
236
|
+
const result = this.stmts.deleteOld.run(cutoff);
|
|
237
|
+
return result.changes;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Map database row to SessionEvent object
|
|
241
|
+
*/
|
|
242
|
+
mapRow(row) {
|
|
243
|
+
return {
|
|
244
|
+
id: row.id,
|
|
245
|
+
sessionId: row.session_id,
|
|
246
|
+
type: row.type,
|
|
247
|
+
data: row.data ? JSON.parse(row.data) : undefined,
|
|
248
|
+
contextTokens: row.context_tokens,
|
|
249
|
+
costCentsSoFar: row.cost_cents_so_far,
|
|
250
|
+
messageCount: row.message_count,
|
|
251
|
+
createdAt: row.created_at,
|
|
252
|
+
syncedAt: row.synced_at,
|
|
253
|
+
syncPending: row.sync_pending === 1,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
exports.EventRepository = EventRepository;
|
|
258
|
+
//# sourceMappingURL=events.js.map
|