@agent-relay/storage 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.
@@ -0,0 +1,156 @@
1
+ import type { PayloadKind, SendMeta } from '@agent-relay/protocol/types';
2
+ export type MessageStatus = 'unread' | 'read' | 'acked' | 'failed';
3
+ export interface StoredMessage {
4
+ id: string;
5
+ ts: number;
6
+ from: string;
7
+ to: string;
8
+ topic?: string;
9
+ kind: PayloadKind;
10
+ body: string;
11
+ data?: Record<string, unknown>;
12
+ /** Optional metadata (importance, replyTo, etc.) */
13
+ payloadMeta?: SendMeta;
14
+ /** Optional thread ID for grouping related messages */
15
+ thread?: string;
16
+ deliverySeq?: number;
17
+ deliverySessionId?: string;
18
+ sessionId?: string;
19
+ /** Per-recipient message status */
20
+ status: MessageStatus;
21
+ /** Whether the message is marked as urgent */
22
+ is_urgent: boolean;
23
+ /** Whether the message was sent as a broadcast (to: '*') */
24
+ is_broadcast?: boolean;
25
+ /** Number of replies in this thread (when message.id is used as thread) */
26
+ replyCount?: number;
27
+ }
28
+ export interface MessageQuery {
29
+ limit?: number;
30
+ sinceTs?: number;
31
+ from?: string;
32
+ to?: string;
33
+ topic?: string;
34
+ /** Filter by thread ID */
35
+ thread?: string;
36
+ order?: 'asc' | 'desc';
37
+ /** Only include unread messages */
38
+ unreadOnly?: boolean;
39
+ /** Only include urgent messages */
40
+ urgentOnly?: boolean;
41
+ }
42
+ export interface StoredSession {
43
+ id: string;
44
+ agentName: string;
45
+ cli?: string;
46
+ projectId?: string;
47
+ projectRoot?: string;
48
+ startedAt: number;
49
+ endedAt?: number;
50
+ messageCount: number;
51
+ summary?: string;
52
+ resumeToken?: string;
53
+ /** How the session was closed: 'agent' (explicit), 'disconnect', 'error', or undefined (still active) */
54
+ closedBy?: 'agent' | 'disconnect' | 'error';
55
+ }
56
+ export interface SessionQuery {
57
+ agentName?: string;
58
+ projectId?: string;
59
+ since?: number;
60
+ limit?: number;
61
+ }
62
+ export interface AgentSummary {
63
+ agentName: string;
64
+ projectId?: string;
65
+ lastUpdated: number;
66
+ currentTask?: string;
67
+ completedTasks?: string[];
68
+ decisions?: string[];
69
+ context?: string;
70
+ files?: string[];
71
+ }
72
+ export interface StorageAdapter {
73
+ init(): Promise<void>;
74
+ saveMessage(message: StoredMessage): Promise<void>;
75
+ getMessages(query?: MessageQuery): Promise<StoredMessage[]>;
76
+ getMessageById?(id: string): Promise<StoredMessage | null>;
77
+ updateMessageStatus?(id: string, status: MessageStatus): Promise<void>;
78
+ close?(): Promise<void>;
79
+ startSession?(session: Omit<StoredSession, 'messageCount'>): Promise<void>;
80
+ endSession?(sessionId: string, options?: {
81
+ summary?: string;
82
+ closedBy?: 'agent' | 'disconnect' | 'error';
83
+ }): Promise<void>;
84
+ getSessions?(query?: SessionQuery): Promise<StoredSession[]>;
85
+ getRecentSessions?(limit?: number): Promise<StoredSession[]>;
86
+ incrementSessionMessageCount?(sessionId: string): Promise<void>;
87
+ getSessionByResumeToken?(resumeToken: string): Promise<StoredSession | null>;
88
+ saveAgentSummary?(summary: Omit<AgentSummary, 'lastUpdated'>): Promise<void>;
89
+ getAgentSummary?(agentName: string): Promise<AgentSummary | null>;
90
+ getAllAgentSummaries?(): Promise<AgentSummary[]>;
91
+ getPendingMessagesForSession?(agentName: string, sessionId: string): Promise<StoredMessage[]>;
92
+ getMaxSeqByStream?(agentName: string, sessionId: string): Promise<Array<{
93
+ peer: string;
94
+ topic?: string;
95
+ maxSeq: number;
96
+ }>>;
97
+ /** Get channels that an agent is a member of (based on stored membership events) */
98
+ getChannelMembershipsForAgent?(memberName: string): Promise<string[]>;
99
+ }
100
+ /**
101
+ * Storage configuration options.
102
+ * Can be set via CLI options or environment variables.
103
+ */
104
+ export interface StorageConfig {
105
+ /** Storage type: 'sqlite', 'sqlite-batched', 'none', or 'postgres' (future) */
106
+ type?: string;
107
+ /** Path for SQLite database */
108
+ path?: string;
109
+ /** Connection URL for database (postgres://..., mysql://...) */
110
+ url?: string;
111
+ /** Batch configuration for batched adapters */
112
+ batch?: {
113
+ maxBatchSize?: number;
114
+ maxBatchDelayMs?: number;
115
+ maxBatchBytes?: number;
116
+ logBatches?: boolean;
117
+ };
118
+ }
119
+ /**
120
+ * In-memory storage adapter (no persistence).
121
+ * Useful for testing or when persistence is not needed.
122
+ */
123
+ export declare class MemoryStorageAdapter implements StorageAdapter {
124
+ private messages;
125
+ init(): Promise<void>;
126
+ saveMessage(message: StoredMessage): Promise<void>;
127
+ getMessages(query?: MessageQuery): Promise<StoredMessage[]>;
128
+ getMessageById(id: string): Promise<StoredMessage | null>;
129
+ updateMessageStatus(id: string, status: MessageStatus): Promise<void>;
130
+ getPendingMessagesForSession(agentName: string, sessionId: string): Promise<StoredMessage[]>;
131
+ getMaxSeqByStream(agentName: string, sessionId: string): Promise<Array<{
132
+ peer: string;
133
+ topic?: string;
134
+ maxSeq: number;
135
+ }>>;
136
+ close(): Promise<void>;
137
+ }
138
+ /**
139
+ * Get storage configuration from environment variables.
140
+ */
141
+ export declare function getStorageConfigFromEnv(): StorageConfig;
142
+ /**
143
+ * Create a storage adapter based on configuration.
144
+ *
145
+ * Configuration priority:
146
+ * 1. Explicit config passed to function
147
+ * 2. Environment variables (AGENT_RELAY_STORAGE_TYPE, AGENT_RELAY_STORAGE_PATH, AGENT_RELAY_STORAGE_URL)
148
+ * 3. Default: SQLite at provided dbPath
149
+ *
150
+ * Supported storage types:
151
+ * - 'sqlite' (default): SQLite file-based storage
152
+ * - 'none' or 'memory': In-memory storage (no persistence)
153
+ * - 'postgres': PostgreSQL (requires AGENT_RELAY_STORAGE_URL) - future
154
+ */
155
+ export declare function createStorageAdapter(dbPath: string, config?: StorageConfig): Promise<StorageAdapter>;
156
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * In-memory storage adapter (no persistence).
3
+ * Useful for testing or when persistence is not needed.
4
+ */
5
+ export class MemoryStorageAdapter {
6
+ messages = [];
7
+ async init() {
8
+ // No initialization needed
9
+ }
10
+ async saveMessage(message) {
11
+ this.messages.push(message);
12
+ // Keep only last 1000 messages to prevent memory issues
13
+ if (this.messages.length > 1000) {
14
+ this.messages = this.messages.slice(-1000);
15
+ }
16
+ }
17
+ async getMessages(query) {
18
+ let result = [...this.messages];
19
+ if (query?.from) {
20
+ result = result.filter(m => m.from === query.from);
21
+ }
22
+ if (query?.to) {
23
+ result = result.filter(m => m.to === query.to);
24
+ }
25
+ if (query?.topic) {
26
+ result = result.filter(m => m.topic === query.topic);
27
+ }
28
+ if (query?.thread) {
29
+ result = result.filter(m => m.thread === query.thread);
30
+ }
31
+ if (query?.sinceTs) {
32
+ result = result.filter(m => m.ts >= query.sinceTs);
33
+ }
34
+ if (query?.order === 'asc') {
35
+ result.sort((a, b) => a.ts - b.ts);
36
+ }
37
+ else {
38
+ result.sort((a, b) => b.ts - a.ts);
39
+ }
40
+ if (query?.limit) {
41
+ result = result.slice(0, query.limit);
42
+ }
43
+ // Calculate replyCount for each message (count of messages where thread === message.id)
44
+ return result.map(m => ({
45
+ ...m,
46
+ replyCount: this.messages.filter(msg => msg.thread === m.id).length,
47
+ }));
48
+ }
49
+ async getMessageById(id) {
50
+ // Support both exact match and prefix match (for short IDs)
51
+ const msg = this.messages.find(m => m.id === id || m.id.startsWith(id));
52
+ if (!msg)
53
+ return null;
54
+ return {
55
+ ...msg,
56
+ replyCount: this.messages.filter(m => m.thread === msg.id).length,
57
+ };
58
+ }
59
+ async updateMessageStatus(id, status) {
60
+ const msg = this.messages.find(m => m.id === id || m.id.startsWith(id));
61
+ if (msg) {
62
+ msg.status = status;
63
+ }
64
+ }
65
+ async getPendingMessagesForSession(agentName, sessionId) {
66
+ return this.messages
67
+ .filter(m => m.to === agentName && m.deliverySessionId === sessionId && m.status !== 'acked')
68
+ .sort((a, b) => {
69
+ const seqA = mSeq(a);
70
+ const seqB = mSeq(b);
71
+ return seqA === seqB ? a.ts - b.ts : seqA - seqB;
72
+ });
73
+ function mSeq(msg) {
74
+ return msg.deliverySeq ?? 0;
75
+ }
76
+ }
77
+ async getMaxSeqByStream(agentName, sessionId) {
78
+ const aggregates = new Map();
79
+ for (const msg of this.messages) {
80
+ if (msg.to !== agentName)
81
+ continue;
82
+ if (msg.deliverySessionId !== sessionId)
83
+ continue;
84
+ if (msg.deliverySeq === undefined || msg.deliverySeq === null)
85
+ continue;
86
+ const topic = msg.topic ?? 'default';
87
+ const key = `${topic}:${msg.from}`;
88
+ const current = aggregates.get(key);
89
+ if (!current || msg.deliverySeq > current.maxSeq) {
90
+ aggregates.set(key, { peer: msg.from, topic: msg.topic, maxSeq: msg.deliverySeq });
91
+ }
92
+ }
93
+ return Array.from(aggregates.values());
94
+ }
95
+ async close() {
96
+ this.messages = [];
97
+ }
98
+ }
99
+ /**
100
+ * Get storage configuration from environment variables.
101
+ */
102
+ export function getStorageConfigFromEnv() {
103
+ return {
104
+ type: process.env.AGENT_RELAY_STORAGE_TYPE,
105
+ path: process.env.AGENT_RELAY_STORAGE_PATH,
106
+ url: process.env.AGENT_RELAY_STORAGE_URL,
107
+ };
108
+ }
109
+ /**
110
+ * Create a storage adapter based on configuration.
111
+ *
112
+ * Configuration priority:
113
+ * 1. Explicit config passed to function
114
+ * 2. Environment variables (AGENT_RELAY_STORAGE_TYPE, AGENT_RELAY_STORAGE_PATH, AGENT_RELAY_STORAGE_URL)
115
+ * 3. Default: SQLite at provided dbPath
116
+ *
117
+ * Supported storage types:
118
+ * - 'sqlite' (default): SQLite file-based storage
119
+ * - 'none' or 'memory': In-memory storage (no persistence)
120
+ * - 'postgres': PostgreSQL (requires AGENT_RELAY_STORAGE_URL) - future
121
+ */
122
+ export async function createStorageAdapter(dbPath, config) {
123
+ // Merge with env config, explicit config takes priority
124
+ const envConfig = getStorageConfigFromEnv();
125
+ const finalConfig = {
126
+ type: config?.type ?? envConfig.type ?? 'sqlite',
127
+ path: config?.path ?? envConfig.path ?? dbPath,
128
+ url: config?.url ?? envConfig.url,
129
+ };
130
+ const storageType = finalConfig.type?.toLowerCase();
131
+ switch (storageType) {
132
+ case 'none':
133
+ case 'memory': {
134
+ console.log('[storage] Using in-memory storage (no persistence)');
135
+ const adapter = new MemoryStorageAdapter();
136
+ await adapter.init();
137
+ return adapter;
138
+ }
139
+ case 'postgres':
140
+ case 'postgresql': {
141
+ if (!finalConfig.url) {
142
+ throw new Error('PostgreSQL storage requires AGENT_RELAY_STORAGE_URL environment variable or --storage-url option');
143
+ }
144
+ // Future: implement PostgreSQL adapter
145
+ throw new Error('PostgreSQL storage is not yet implemented. Use sqlite or none.');
146
+ }
147
+ case 'sqlite-batched':
148
+ case 'batched': {
149
+ console.log('[storage] Using batched SQLite storage');
150
+ const { BatchedSqliteAdapter } = await import('./batched-sqlite-adapter.js');
151
+ const adapter = new BatchedSqliteAdapter({
152
+ dbPath: finalConfig.path,
153
+ batch: finalConfig.batch,
154
+ });
155
+ await adapter.init();
156
+ return adapter;
157
+ }
158
+ case 'sqlite':
159
+ default: {
160
+ const { SqliteStorageAdapter } = await import('./sqlite-adapter.js');
161
+ const adapter = new SqliteStorageAdapter({ dbPath: finalConfig.path });
162
+ await adapter.init();
163
+ return adapter;
164
+ }
165
+ }
166
+ }
167
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Batched SQLite Storage Adapter
3
+ *
4
+ * Wraps SqliteStorageAdapter to provide batched writes for improved throughput.
5
+ * Messages are buffered and flushed either when:
6
+ * - Batch size is reached
7
+ * - Time threshold is exceeded
8
+ * - Memory threshold is exceeded
9
+ * - close() is called
10
+ *
11
+ * All reads still go directly to SQLite for consistency.
12
+ */
13
+ import { SqliteStorageAdapter, type SqliteAdapterOptions } from './sqlite-adapter.js';
14
+ import type { StoredMessage, MessageStatus } from './adapter.js';
15
+ export interface BatchConfig {
16
+ /** Maximum messages in a batch before flush (default: 50) */
17
+ maxBatchSize: number;
18
+ /** Maximum time to wait before flush in ms (default: 100) */
19
+ maxBatchDelayMs: number;
20
+ /** Maximum bytes in memory before flush (default: 1MB) */
21
+ maxBatchBytes: number;
22
+ /** Whether to log batch operations (default: false) */
23
+ logBatches: boolean;
24
+ }
25
+ export declare const DEFAULT_BATCH_CONFIG: BatchConfig;
26
+ export interface BatchedSqliteAdapterOptions extends SqliteAdapterOptions {
27
+ batch?: Partial<BatchConfig>;
28
+ }
29
+ export declare class BatchedSqliteAdapter extends SqliteStorageAdapter {
30
+ private batchConfig;
31
+ private pending;
32
+ private pendingBytes;
33
+ private flushTimer?;
34
+ private flushing;
35
+ private flushPromise?;
36
+ private metrics;
37
+ constructor(options: BatchedSqliteAdapterOptions);
38
+ /**
39
+ * Queue a message for batched writing.
40
+ * May trigger an immediate flush if thresholds are exceeded.
41
+ */
42
+ saveMessage(message: StoredMessage): Promise<void>;
43
+ /**
44
+ * Flush all pending messages to SQLite.
45
+ */
46
+ flush(): Promise<void>;
47
+ /**
48
+ * Write a batch of messages within a transaction.
49
+ */
50
+ private writeBatch;
51
+ /**
52
+ * Get batch metrics for monitoring.
53
+ */
54
+ getBatchMetrics(): typeof this.metrics & {
55
+ pendingCount: number;
56
+ pendingBytes: number;
57
+ };
58
+ /**
59
+ * Reset metrics (useful for testing or periodic reporting).
60
+ */
61
+ resetMetrics(): void;
62
+ /**
63
+ * Close the adapter, flushing any pending messages first.
64
+ */
65
+ close(): Promise<void>;
66
+ /**
67
+ * Update message status - goes directly to SQLite (not batched).
68
+ */
69
+ updateMessageStatus(id: string, status: MessageStatus): Promise<void>;
70
+ /**
71
+ * Get channel memberships for an agent - read-only, delegates to parent.
72
+ */
73
+ getChannelMembershipsForAgent(memberName: string): Promise<string[]>;
74
+ }
75
+ //# sourceMappingURL=batched-sqlite-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batched-sqlite-adapter.d.ts","sourceRoot":"","sources":["../src/batched-sqlite-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,oBAAoB,EACpB,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,oBAAoB,EAAE,WAKlC,CAAC;AAEF,MAAM,WAAW,2BAA4B,SAAQ,oBAAoB;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC9B;AAOD,qBAAa,oBAAqB,SAAQ,oBAAoB;IAC5D,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAC,CAAgB;IAGrC,OAAO,CAAC,OAAO,CAOb;gBAEU,OAAO,EAAE,2BAA2B;IAKhD;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCxD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B;;OAEG;YACW,UAAU;IA+BxB;;OAEG;IACH,eAAe,IAAI,OAAO,IAAI,CAAC,OAAO,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAQvF;;OAEG;IACH,YAAY,IAAI,IAAI;IAWpB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACG,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3E;;OAEG;IACG,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAG3E"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Batched SQLite Storage Adapter
3
+ *
4
+ * Wraps SqliteStorageAdapter to provide batched writes for improved throughput.
5
+ * Messages are buffered and flushed either when:
6
+ * - Batch size is reached
7
+ * - Time threshold is exceeded
8
+ * - Memory threshold is exceeded
9
+ * - close() is called
10
+ *
11
+ * All reads still go directly to SQLite for consistency.
12
+ */
13
+ import { SqliteStorageAdapter, } from './sqlite-adapter.js';
14
+ export const DEFAULT_BATCH_CONFIG = {
15
+ maxBatchSize: 50,
16
+ maxBatchDelayMs: 100,
17
+ maxBatchBytes: 1024 * 1024, // 1MB
18
+ logBatches: false,
19
+ };
20
+ export class BatchedSqliteAdapter extends SqliteStorageAdapter {
21
+ batchConfig;
22
+ pending = [];
23
+ pendingBytes = 0;
24
+ flushTimer;
25
+ flushing = false;
26
+ flushPromise;
27
+ // Metrics
28
+ metrics = {
29
+ batchesWritten: 0,
30
+ messagesWritten: 0,
31
+ bytesWritten: 0,
32
+ flushDueToSize: 0,
33
+ flushDueToTime: 0,
34
+ flushDueToBytes: 0,
35
+ };
36
+ constructor(options) {
37
+ super(options);
38
+ this.batchConfig = { ...DEFAULT_BATCH_CONFIG, ...options.batch };
39
+ }
40
+ /**
41
+ * Queue a message for batched writing.
42
+ * May trigger an immediate flush if thresholds are exceeded.
43
+ */
44
+ async saveMessage(message) {
45
+ // Ensure any pending flush completes first
46
+ if (this.flushPromise) {
47
+ await this.flushPromise;
48
+ }
49
+ const msgJson = JSON.stringify(message);
50
+ const sizeBytes = Buffer.byteLength(msgJson, 'utf-8');
51
+ this.pending.push({ message, sizeBytes });
52
+ this.pendingBytes += sizeBytes;
53
+ // Check flush conditions
54
+ let flushReason = null;
55
+ if (this.pending.length >= this.batchConfig.maxBatchSize) {
56
+ flushReason = 'size';
57
+ this.metrics.flushDueToSize++;
58
+ }
59
+ else if (this.pendingBytes >= this.batchConfig.maxBatchBytes) {
60
+ flushReason = 'bytes';
61
+ this.metrics.flushDueToBytes++;
62
+ }
63
+ if (flushReason) {
64
+ await this.flush();
65
+ }
66
+ else if (!this.flushTimer) {
67
+ // Schedule time-based flush
68
+ this.flushTimer = setTimeout(() => {
69
+ this.metrics.flushDueToTime++;
70
+ this.flush().catch((err) => {
71
+ console.error('[batched-sqlite] Timer flush failed:', err);
72
+ });
73
+ }, this.batchConfig.maxBatchDelayMs);
74
+ }
75
+ }
76
+ /**
77
+ * Flush all pending messages to SQLite.
78
+ */
79
+ async flush() {
80
+ // Clear timer if set
81
+ if (this.flushTimer) {
82
+ clearTimeout(this.flushTimer);
83
+ this.flushTimer = undefined;
84
+ }
85
+ // Skip if nothing to flush or already flushing
86
+ if (this.pending.length === 0 || this.flushing) {
87
+ return;
88
+ }
89
+ this.flushing = true;
90
+ // Take current batch
91
+ const batch = this.pending;
92
+ const batchBytes = this.pendingBytes;
93
+ this.pending = [];
94
+ this.pendingBytes = 0;
95
+ this.flushPromise = this.writeBatch(batch, batchBytes);
96
+ try {
97
+ await this.flushPromise;
98
+ }
99
+ finally {
100
+ this.flushing = false;
101
+ this.flushPromise = undefined;
102
+ }
103
+ }
104
+ /**
105
+ * Write a batch of messages within a transaction.
106
+ */
107
+ async writeBatch(batch, batchBytes) {
108
+ const startTime = Date.now();
109
+ try {
110
+ // Use transaction for atomicity and performance
111
+ // The parent class's db is private, so we call saveMessage in a loop
112
+ // but the SQLite driver will batch them efficiently due to WAL mode
113
+ for (const { message } of batch) {
114
+ await super.saveMessage(message);
115
+ }
116
+ // Update metrics
117
+ this.metrics.batchesWritten++;
118
+ this.metrics.messagesWritten += batch.length;
119
+ this.metrics.bytesWritten += batchBytes;
120
+ if (this.batchConfig.logBatches) {
121
+ const elapsed = Date.now() - startTime;
122
+ console.log(`[batched-sqlite] Wrote ${batch.length} messages (${(batchBytes / 1024).toFixed(1)}KB) in ${elapsed}ms`);
123
+ }
124
+ }
125
+ catch (err) {
126
+ // On failure, re-queue messages for retry
127
+ console.error('[batched-sqlite] Batch write failed, re-queuing:', err);
128
+ this.pending = [...batch, ...this.pending];
129
+ this.pendingBytes += batchBytes;
130
+ throw err;
131
+ }
132
+ }
133
+ /**
134
+ * Get batch metrics for monitoring.
135
+ */
136
+ getBatchMetrics() {
137
+ return {
138
+ ...this.metrics,
139
+ pendingCount: this.pending.length,
140
+ pendingBytes: this.pendingBytes,
141
+ };
142
+ }
143
+ /**
144
+ * Reset metrics (useful for testing or periodic reporting).
145
+ */
146
+ resetMetrics() {
147
+ this.metrics = {
148
+ batchesWritten: 0,
149
+ messagesWritten: 0,
150
+ bytesWritten: 0,
151
+ flushDueToSize: 0,
152
+ flushDueToTime: 0,
153
+ flushDueToBytes: 0,
154
+ };
155
+ }
156
+ /**
157
+ * Close the adapter, flushing any pending messages first.
158
+ */
159
+ async close() {
160
+ // Ensure all pending messages are written
161
+ if (this.flushTimer) {
162
+ clearTimeout(this.flushTimer);
163
+ this.flushTimer = undefined;
164
+ }
165
+ // Wait for any in-progress flush
166
+ if (this.flushPromise) {
167
+ await this.flushPromise;
168
+ }
169
+ // Flush remaining
170
+ if (this.pending.length > 0) {
171
+ await this.flush();
172
+ }
173
+ await super.close();
174
+ }
175
+ /**
176
+ * Update message status - goes directly to SQLite (not batched).
177
+ */
178
+ async updateMessageStatus(id, status) {
179
+ // Status updates should be immediate, not batched
180
+ return super.updateMessageStatus(id, status);
181
+ }
182
+ /**
183
+ * Get channel memberships for an agent - read-only, delegates to parent.
184
+ */
185
+ async getChannelMembershipsForAgent(memberName) {
186
+ return super.getChannelMembershipsForAgent(memberName);
187
+ }
188
+ }
189
+ //# sourceMappingURL=batched-sqlite-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batched-sqlite-adapter.js","sourceRoot":"","sources":["../src/batched-sqlite-adapter.ts"],"names":[],"mappings":"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"}