@dexto/core 1.6.25 → 1.6.27
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/agent/DextoAgent.cjs +102 -104
- package/dist/agent/DextoAgent.d.ts +11 -10
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +103 -105
- package/dist/agent/error-codes.cjs +1 -0
- package/dist/agent/error-codes.d.ts +1 -0
- package/dist/agent/error-codes.d.ts.map +1 -1
- package/dist/agent/error-codes.js +1 -0
- package/dist/agent/errors.cjs +13 -0
- package/dist/agent/errors.d.ts +6 -0
- package/dist/agent/errors.d.ts.map +1 -1
- package/dist/agent/errors.js +13 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/schemas.d.ts +2 -2
- package/dist/agent/types.d.ts +11 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/approval/factory.cjs +1 -0
- package/dist/approval/factory.d.ts.map +1 -1
- package/dist/approval/factory.js +1 -0
- package/dist/approval/manager.cjs +345 -182
- package/dist/approval/manager.d.ts +45 -31
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +345 -182
- package/dist/approval/schemas.cjs +10 -0
- package/dist/approval/schemas.d.ts +305 -0
- package/dist/approval/schemas.d.ts.map +1 -1
- package/dist/approval/schemas.js +10 -0
- package/dist/approval/session-approval-store.cjs +91 -0
- package/dist/approval/session-approval-store.d.ts +55 -0
- package/dist/approval/session-approval-store.d.ts.map +1 -0
- package/dist/approval/session-approval-store.js +68 -0
- package/dist/events/index.cjs +210 -75
- package/dist/events/index.d.ts +44 -181
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +206 -74
- package/dist/hooks/manager.cjs +5 -2
- package/dist/hooks/manager.d.ts +2 -0
- package/dist/hooks/manager.d.ts.map +1 -1
- package/dist/hooks/manager.js +5 -2
- package/dist/hooks/types.d.ts +3 -0
- package/dist/hooks/types.d.ts.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/llm/executor/turn-executor.cjs +15 -7
- package/dist/llm/executor/turn-executor.d.ts +3 -1
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +15 -7
- package/dist/llm/services/factory.cjs +10 -4
- package/dist/llm/services/factory.d.ts +2 -21
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +11 -7
- package/dist/llm/services/types.d.ts +33 -2
- package/dist/llm/services/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +33 -11
- package/dist/llm/services/vercel.d.ts +6 -3
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +29 -8
- package/dist/logger/default-logger-factory.d.ts +12 -12
- package/dist/logger/v2/schemas.d.ts +6 -6
- package/dist/mcp/manager.cjs +7 -2
- package/dist/mcp/manager.d.ts +3 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +7 -2
- package/dist/mcp/mcp-client.cjs +71 -62
- package/dist/mcp/mcp-client.d.ts +3 -2
- package/dist/mcp/mcp-client.d.ts.map +1 -1
- package/dist/mcp/mcp-client.js +71 -62
- package/dist/mcp/schemas.d.ts +10 -10
- package/dist/resources/handlers/filesystem-handler.cjs +22 -3
- package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
- package/dist/resources/handlers/filesystem-handler.js +22 -3
- package/dist/runtime/host-runtime.cjs +163 -0
- package/dist/runtime/host-runtime.d.ts +23 -0
- package/dist/runtime/host-runtime.d.ts.map +1 -0
- package/dist/runtime/host-runtime.js +133 -0
- package/dist/runtime/index.cjs +42 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +21 -0
- package/dist/runtime/run-context.cjs +53 -0
- package/dist/runtime/run-context.d.ts +13 -0
- package/dist/runtime/run-context.d.ts.map +1 -0
- package/dist/runtime/run-context.js +34 -0
- package/dist/session/chat-session.cjs +67 -71
- package/dist/session/chat-session.d.ts +25 -25
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +68 -72
- package/dist/session/error-codes.cjs +1 -0
- package/dist/session/error-codes.d.ts +2 -1
- package/dist/session/error-codes.d.ts.map +1 -1
- package/dist/session/error-codes.js +1 -0
- package/dist/session/errors.cjs +13 -0
- package/dist/session/errors.d.ts +6 -0
- package/dist/session/errors.d.ts.map +1 -1
- package/dist/session/errors.js +13 -0
- package/dist/session/message-queue-store.cjs +75 -0
- package/dist/session/message-queue-store.d.ts +16 -0
- package/dist/session/message-queue-store.d.ts.map +1 -0
- package/dist/session/message-queue-store.js +52 -0
- package/dist/session/message-queue.cjs +140 -46
- package/dist/session/message-queue.d.ts +18 -6
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +140 -46
- package/dist/session/session-manager.cjs +130 -25
- package/dist/session/session-manager.d.ts +18 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +130 -25
- package/dist/session/title-generator.cjs +9 -2
- package/dist/session/title-generator.d.ts +2 -0
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +9 -2
- package/dist/telemetry/decorators.cjs +75 -57
- package/dist/telemetry/decorators.d.ts +2 -0
- package/dist/telemetry/decorators.d.ts.map +1 -1
- package/dist/telemetry/decorators.js +75 -57
- package/dist/telemetry/errors.cjs +2 -2
- package/dist/telemetry/errors.js +2 -2
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +3 -1
- package/dist/telemetry/telemetry.cjs +62 -21
- package/dist/telemetry/telemetry.d.ts +14 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +62 -21
- package/dist/telemetry/utils.cjs +9 -6
- package/dist/telemetry/utils.d.ts +3 -0
- package/dist/telemetry/utils.d.ts.map +1 -1
- package/dist/telemetry/utils.js +9 -6
- package/dist/test-utils/session-state-stores.cjs +68 -0
- package/dist/test-utils/session-state-stores.js +42 -0
- package/dist/tools/session-tool-preferences-store.cjs +86 -0
- package/dist/tools/session-tool-preferences-store.d.ts +29 -0
- package/dist/tools/session-tool-preferences-store.d.ts.map +1 -0
- package/dist/tools/session-tool-preferences-store.js +63 -0
- package/dist/tools/tool-manager.cjs +223 -68
- package/dist/tools/tool-manager.d.ts +29 -9
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +223 -68
- package/dist/tools/types.d.ts +7 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/service-initializer.cjs +38 -5
- package/dist/utils/service-initializer.d.ts +11 -1
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +36 -4
- package/package.json +1 -1
|
@@ -21,15 +21,71 @@ __export(message_queue_exports, {
|
|
|
21
21
|
MessageQueueService: () => MessageQueueService
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(message_queue_exports);
|
|
24
|
+
class EphemeralMessageQueueStore {
|
|
25
|
+
async load(sessionId) {
|
|
26
|
+
void sessionId;
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
async save(sessionId, queue) {
|
|
30
|
+
void sessionId;
|
|
31
|
+
void queue;
|
|
32
|
+
}
|
|
33
|
+
async delete(sessionId) {
|
|
34
|
+
void sessionId;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
24
37
|
function generateId() {
|
|
25
38
|
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
26
39
|
}
|
|
27
40
|
class MessageQueueService {
|
|
28
|
-
constructor(eventBus, logger) {
|
|
41
|
+
constructor(eventBus, logger, sessionId, store) {
|
|
29
42
|
this.eventBus = eventBus;
|
|
30
43
|
this.logger = logger;
|
|
44
|
+
this.sessionId = sessionId;
|
|
45
|
+
this.store = store;
|
|
31
46
|
}
|
|
32
47
|
queue = [];
|
|
48
|
+
mutationLock = Promise.resolve();
|
|
49
|
+
initialized = false;
|
|
50
|
+
initializationPromise = null;
|
|
51
|
+
static createEphemeral(eventBus, logger, sessionId) {
|
|
52
|
+
return new MessageQueueService(
|
|
53
|
+
eventBus,
|
|
54
|
+
logger,
|
|
55
|
+
sessionId,
|
|
56
|
+
new EphemeralMessageQueueStore()
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
async initialize() {
|
|
60
|
+
this.initializationPromise ??= this.runWithMutationLock(async () => {
|
|
61
|
+
if (this.initialized) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.queue = await this.store.load(this.sessionId);
|
|
65
|
+
if (this.queue.length > 0) {
|
|
66
|
+
this.logger.debug(
|
|
67
|
+
`Restored ${this.queue.length} queued message(s) for session ${this.sessionId}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
this.initialized = true;
|
|
71
|
+
}).catch((error) => {
|
|
72
|
+
this.initializationPromise = null;
|
|
73
|
+
throw error;
|
|
74
|
+
});
|
|
75
|
+
await this.initializationPromise;
|
|
76
|
+
}
|
|
77
|
+
async persistQueue() {
|
|
78
|
+
await this.store.save(this.sessionId, this.queue);
|
|
79
|
+
}
|
|
80
|
+
runWithMutationLock(fn) {
|
|
81
|
+
const currentResult = this.mutationLock.catch(() => {
|
|
82
|
+
}).then(() => fn());
|
|
83
|
+
this.mutationLock = currentResult.then(
|
|
84
|
+
() => void 0,
|
|
85
|
+
() => void 0
|
|
86
|
+
);
|
|
87
|
+
return currentResult;
|
|
88
|
+
}
|
|
33
89
|
/**
|
|
34
90
|
* Add a message to the queue.
|
|
35
91
|
* Called by API endpoint - returns immediately with queue position.
|
|
@@ -37,25 +93,33 @@ class MessageQueueService {
|
|
|
37
93
|
* @param message The user message to queue
|
|
38
94
|
* @returns Queue position and message ID
|
|
39
95
|
*/
|
|
40
|
-
enqueue(message) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
96
|
+
async enqueue(message) {
|
|
97
|
+
return await this.runWithMutationLock(async () => {
|
|
98
|
+
const queuedMsg = {
|
|
99
|
+
id: generateId(),
|
|
100
|
+
content: message.content,
|
|
101
|
+
queuedAt: Date.now(),
|
|
102
|
+
...message.metadata !== void 0 && { metadata: message.metadata },
|
|
103
|
+
...message.kind !== void 0 && { kind: message.kind }
|
|
104
|
+
};
|
|
105
|
+
this.queue.push(queuedMsg);
|
|
106
|
+
try {
|
|
107
|
+
await this.persistQueue();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
this.queue.pop();
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
this.logger.debug(`Message queued: ${queuedMsg.id}, position: ${this.queue.length}`);
|
|
113
|
+
this.eventBus.emit("message:queued", {
|
|
114
|
+
position: this.queue.length,
|
|
115
|
+
id: queuedMsg.id
|
|
116
|
+
});
|
|
117
|
+
return {
|
|
118
|
+
queued: true,
|
|
119
|
+
position: this.queue.length,
|
|
120
|
+
id: queuedMsg.id
|
|
121
|
+
};
|
|
53
122
|
});
|
|
54
|
-
return {
|
|
55
|
-
queued: true,
|
|
56
|
-
position: this.queue.length,
|
|
57
|
-
id: queuedMsg.id
|
|
58
|
-
};
|
|
59
123
|
}
|
|
60
124
|
/**
|
|
61
125
|
* Dequeue ALL pending messages and coalesce into single injection.
|
|
@@ -76,22 +140,30 @@ class MessageQueueService {
|
|
|
76
140
|
*
|
|
77
141
|
* @returns Coalesced message or null if queue is empty
|
|
78
142
|
*/
|
|
79
|
-
dequeueAll() {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
143
|
+
async dequeueAll() {
|
|
144
|
+
return await this.runWithMutationLock(async () => {
|
|
145
|
+
if (this.queue.length === 0) return null;
|
|
146
|
+
const messages = [...this.queue];
|
|
147
|
+
this.queue = [];
|
|
148
|
+
try {
|
|
149
|
+
await this.persistQueue();
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this.queue = messages;
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
const combined = this.coalesce(messages);
|
|
155
|
+
this.logger.debug(
|
|
156
|
+
`Dequeued ${messages.length} message(s): ${messages.map((m) => m.id).join(", ")}`
|
|
157
|
+
);
|
|
158
|
+
this.eventBus.emit("message:dequeued", {
|
|
159
|
+
count: messages.length,
|
|
160
|
+
ids: messages.map((m) => m.id),
|
|
161
|
+
coalesced: messages.length > 1,
|
|
162
|
+
content: combined.combinedContent,
|
|
163
|
+
messages
|
|
164
|
+
});
|
|
165
|
+
return combined;
|
|
93
166
|
});
|
|
94
|
-
return combined;
|
|
95
167
|
}
|
|
96
168
|
/**
|
|
97
169
|
* Coalesce multiple messages into one (multimodal-aware).
|
|
@@ -187,8 +259,20 @@ class MessageQueueService {
|
|
|
187
259
|
* Clear all pending messages without processing.
|
|
188
260
|
* Used during cleanup/abort.
|
|
189
261
|
*/
|
|
190
|
-
clear() {
|
|
191
|
-
this.
|
|
262
|
+
async clear() {
|
|
263
|
+
await this.runWithMutationLock(async () => {
|
|
264
|
+
if (this.queue.length === 0) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const previousQueue = [...this.queue];
|
|
268
|
+
this.queue = [];
|
|
269
|
+
try {
|
|
270
|
+
await this.persistQueue();
|
|
271
|
+
} catch (error) {
|
|
272
|
+
this.queue = previousQueue;
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
192
276
|
}
|
|
193
277
|
/**
|
|
194
278
|
* Get all queued messages (for UI display).
|
|
@@ -207,16 +291,26 @@ class MessageQueueService {
|
|
|
207
291
|
* Remove a single queued message by ID.
|
|
208
292
|
* @returns true if message was found and removed; false otherwise
|
|
209
293
|
*/
|
|
210
|
-
remove(id) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
294
|
+
async remove(id) {
|
|
295
|
+
return await this.runWithMutationLock(async () => {
|
|
296
|
+
const index = this.queue.findIndex((m) => m.id === id);
|
|
297
|
+
if (index === -1) {
|
|
298
|
+
this.logger.debug(`Remove failed: message ${id} not found in queue`);
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
const [removed] = this.queue.splice(index, 1);
|
|
302
|
+
try {
|
|
303
|
+
await this.persistQueue();
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if (removed) {
|
|
306
|
+
this.queue.splice(index, 0, removed);
|
|
307
|
+
}
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
this.logger.debug(`Message removed: ${id}, remaining: ${this.queue.length}`);
|
|
311
|
+
this.eventBus.emit("message:removed", { id });
|
|
312
|
+
return true;
|
|
313
|
+
});
|
|
220
314
|
}
|
|
221
315
|
}
|
|
222
316
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -2,6 +2,8 @@ import type { SessionEventBus } from '../events/index.js';
|
|
|
2
2
|
import type { QueuedMessage, CoalescedMessage } from './types.js';
|
|
3
3
|
import type { ContentPart } from '../context/types.js';
|
|
4
4
|
import type { Logger } from '../logger/v2/types.js';
|
|
5
|
+
import type { MessageQueueStore } from './message-queue-store.js';
|
|
6
|
+
type MessageQueueBackingStore = Pick<MessageQueueStore, 'load' | 'save' | 'delete'>;
|
|
5
7
|
/**
|
|
6
8
|
* Input for enqueuing a user message to the queue.
|
|
7
9
|
* (Not to be confused with UserMessage from context/types.ts which represents
|
|
@@ -46,8 +48,17 @@ export interface UserMessageInput {
|
|
|
46
48
|
export declare class MessageQueueService {
|
|
47
49
|
private eventBus;
|
|
48
50
|
private logger;
|
|
51
|
+
private sessionId;
|
|
52
|
+
private store;
|
|
49
53
|
private queue;
|
|
50
|
-
|
|
54
|
+
private mutationLock;
|
|
55
|
+
private initialized;
|
|
56
|
+
private initializationPromise;
|
|
57
|
+
static createEphemeral(eventBus: SessionEventBus, logger: Logger, sessionId: string): MessageQueueService;
|
|
58
|
+
constructor(eventBus: SessionEventBus, logger: Logger, sessionId: string, store: MessageQueueBackingStore);
|
|
59
|
+
initialize(): Promise<void>;
|
|
60
|
+
private persistQueue;
|
|
61
|
+
private runWithMutationLock;
|
|
51
62
|
/**
|
|
52
63
|
* Add a message to the queue.
|
|
53
64
|
* Called by API endpoint - returns immediately with queue position.
|
|
@@ -55,11 +66,11 @@ export declare class MessageQueueService {
|
|
|
55
66
|
* @param message The user message to queue
|
|
56
67
|
* @returns Queue position and message ID
|
|
57
68
|
*/
|
|
58
|
-
enqueue(message: UserMessageInput): {
|
|
69
|
+
enqueue(message: UserMessageInput): Promise<{
|
|
59
70
|
queued: true;
|
|
60
71
|
position: number;
|
|
61
72
|
id: string;
|
|
62
|
-
}
|
|
73
|
+
}>;
|
|
63
74
|
/**
|
|
64
75
|
* Dequeue ALL pending messages and coalesce into single injection.
|
|
65
76
|
* Called by executor between steps.
|
|
@@ -79,7 +90,7 @@ export declare class MessageQueueService {
|
|
|
79
90
|
*
|
|
80
91
|
* @returns Coalesced message or null if queue is empty
|
|
81
92
|
*/
|
|
82
|
-
dequeueAll(): CoalescedMessage | null
|
|
93
|
+
dequeueAll(): Promise<CoalescedMessage | null>;
|
|
83
94
|
/**
|
|
84
95
|
* Coalesce multiple messages into one (multimodal-aware).
|
|
85
96
|
* Strategy: Combine with per-kind formatting, preserve all media.
|
|
@@ -97,7 +108,7 @@ export declare class MessageQueueService {
|
|
|
97
108
|
* Clear all pending messages without processing.
|
|
98
109
|
* Used during cleanup/abort.
|
|
99
110
|
*/
|
|
100
|
-
clear(): void
|
|
111
|
+
clear(): Promise<void>;
|
|
101
112
|
/**
|
|
102
113
|
* Get all queued messages (for UI display).
|
|
103
114
|
* Returns a shallow copy to prevent external mutation.
|
|
@@ -111,6 +122,7 @@ export declare class MessageQueueService {
|
|
|
111
122
|
* Remove a single queued message by ID.
|
|
112
123
|
* @returns true if message was found and removed; false otherwise
|
|
113
124
|
*/
|
|
114
|
-
remove(id: string): boolean
|
|
125
|
+
remove(id: string): Promise<boolean>;
|
|
115
126
|
}
|
|
127
|
+
export {};
|
|
116
128
|
//# sourceMappingURL=message-queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../src/session/message-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../../src/session/message-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,KAAK,wBAAwB,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC;AAyBpF;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2DAA2D;IAC3D,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,sCAAsC;IACtC,IAAI,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,mBAAmB;IAoBxB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;IAtBjB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,qBAAqB,CAA8B;IAE3D,MAAM,CAAC,eAAe,CAClB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAClB,mBAAmB;gBAUV,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,wBAAwB;IAGrC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAsBnB,YAAY;IAI1B,OAAO,CAAC,mBAAmB;IAS3B;;;;;;OAMG;IACG,OAAO,CACT,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC;QAAE,MAAM,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAkC1D;;;;;;;;;;;;;;;;;;OAkBG;IACG,UAAU,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAgCpD;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAuGhB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB5B;;;OAGG;IACH,MAAM,IAAI,aAAa,EAAE;IAIzB;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C;;;OAGG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAwB7C"}
|
|
@@ -1,13 +1,69 @@
|
|
|
1
1
|
import "../chunk-PTJYTZNU.js";
|
|
2
|
+
class EphemeralMessageQueueStore {
|
|
3
|
+
async load(sessionId) {
|
|
4
|
+
void sessionId;
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
async save(sessionId, queue) {
|
|
8
|
+
void sessionId;
|
|
9
|
+
void queue;
|
|
10
|
+
}
|
|
11
|
+
async delete(sessionId) {
|
|
12
|
+
void sessionId;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
2
15
|
function generateId() {
|
|
3
16
|
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
4
17
|
}
|
|
5
18
|
class MessageQueueService {
|
|
6
|
-
constructor(eventBus, logger) {
|
|
19
|
+
constructor(eventBus, logger, sessionId, store) {
|
|
7
20
|
this.eventBus = eventBus;
|
|
8
21
|
this.logger = logger;
|
|
22
|
+
this.sessionId = sessionId;
|
|
23
|
+
this.store = store;
|
|
9
24
|
}
|
|
10
25
|
queue = [];
|
|
26
|
+
mutationLock = Promise.resolve();
|
|
27
|
+
initialized = false;
|
|
28
|
+
initializationPromise = null;
|
|
29
|
+
static createEphemeral(eventBus, logger, sessionId) {
|
|
30
|
+
return new MessageQueueService(
|
|
31
|
+
eventBus,
|
|
32
|
+
logger,
|
|
33
|
+
sessionId,
|
|
34
|
+
new EphemeralMessageQueueStore()
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
async initialize() {
|
|
38
|
+
this.initializationPromise ??= this.runWithMutationLock(async () => {
|
|
39
|
+
if (this.initialized) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
this.queue = await this.store.load(this.sessionId);
|
|
43
|
+
if (this.queue.length > 0) {
|
|
44
|
+
this.logger.debug(
|
|
45
|
+
`Restored ${this.queue.length} queued message(s) for session ${this.sessionId}`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
this.initialized = true;
|
|
49
|
+
}).catch((error) => {
|
|
50
|
+
this.initializationPromise = null;
|
|
51
|
+
throw error;
|
|
52
|
+
});
|
|
53
|
+
await this.initializationPromise;
|
|
54
|
+
}
|
|
55
|
+
async persistQueue() {
|
|
56
|
+
await this.store.save(this.sessionId, this.queue);
|
|
57
|
+
}
|
|
58
|
+
runWithMutationLock(fn) {
|
|
59
|
+
const currentResult = this.mutationLock.catch(() => {
|
|
60
|
+
}).then(() => fn());
|
|
61
|
+
this.mutationLock = currentResult.then(
|
|
62
|
+
() => void 0,
|
|
63
|
+
() => void 0
|
|
64
|
+
);
|
|
65
|
+
return currentResult;
|
|
66
|
+
}
|
|
11
67
|
/**
|
|
12
68
|
* Add a message to the queue.
|
|
13
69
|
* Called by API endpoint - returns immediately with queue position.
|
|
@@ -15,25 +71,33 @@ class MessageQueueService {
|
|
|
15
71
|
* @param message The user message to queue
|
|
16
72
|
* @returns Queue position and message ID
|
|
17
73
|
*/
|
|
18
|
-
enqueue(message) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
74
|
+
async enqueue(message) {
|
|
75
|
+
return await this.runWithMutationLock(async () => {
|
|
76
|
+
const queuedMsg = {
|
|
77
|
+
id: generateId(),
|
|
78
|
+
content: message.content,
|
|
79
|
+
queuedAt: Date.now(),
|
|
80
|
+
...message.metadata !== void 0 && { metadata: message.metadata },
|
|
81
|
+
...message.kind !== void 0 && { kind: message.kind }
|
|
82
|
+
};
|
|
83
|
+
this.queue.push(queuedMsg);
|
|
84
|
+
try {
|
|
85
|
+
await this.persistQueue();
|
|
86
|
+
} catch (error) {
|
|
87
|
+
this.queue.pop();
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
this.logger.debug(`Message queued: ${queuedMsg.id}, position: ${this.queue.length}`);
|
|
91
|
+
this.eventBus.emit("message:queued", {
|
|
92
|
+
position: this.queue.length,
|
|
93
|
+
id: queuedMsg.id
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
queued: true,
|
|
97
|
+
position: this.queue.length,
|
|
98
|
+
id: queuedMsg.id
|
|
99
|
+
};
|
|
31
100
|
});
|
|
32
|
-
return {
|
|
33
|
-
queued: true,
|
|
34
|
-
position: this.queue.length,
|
|
35
|
-
id: queuedMsg.id
|
|
36
|
-
};
|
|
37
101
|
}
|
|
38
102
|
/**
|
|
39
103
|
* Dequeue ALL pending messages and coalesce into single injection.
|
|
@@ -54,22 +118,30 @@ class MessageQueueService {
|
|
|
54
118
|
*
|
|
55
119
|
* @returns Coalesced message or null if queue is empty
|
|
56
120
|
*/
|
|
57
|
-
dequeueAll() {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
121
|
+
async dequeueAll() {
|
|
122
|
+
return await this.runWithMutationLock(async () => {
|
|
123
|
+
if (this.queue.length === 0) return null;
|
|
124
|
+
const messages = [...this.queue];
|
|
125
|
+
this.queue = [];
|
|
126
|
+
try {
|
|
127
|
+
await this.persistQueue();
|
|
128
|
+
} catch (error) {
|
|
129
|
+
this.queue = messages;
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
const combined = this.coalesce(messages);
|
|
133
|
+
this.logger.debug(
|
|
134
|
+
`Dequeued ${messages.length} message(s): ${messages.map((m) => m.id).join(", ")}`
|
|
135
|
+
);
|
|
136
|
+
this.eventBus.emit("message:dequeued", {
|
|
137
|
+
count: messages.length,
|
|
138
|
+
ids: messages.map((m) => m.id),
|
|
139
|
+
coalesced: messages.length > 1,
|
|
140
|
+
content: combined.combinedContent,
|
|
141
|
+
messages
|
|
142
|
+
});
|
|
143
|
+
return combined;
|
|
71
144
|
});
|
|
72
|
-
return combined;
|
|
73
145
|
}
|
|
74
146
|
/**
|
|
75
147
|
* Coalesce multiple messages into one (multimodal-aware).
|
|
@@ -165,8 +237,20 @@ class MessageQueueService {
|
|
|
165
237
|
* Clear all pending messages without processing.
|
|
166
238
|
* Used during cleanup/abort.
|
|
167
239
|
*/
|
|
168
|
-
clear() {
|
|
169
|
-
this.
|
|
240
|
+
async clear() {
|
|
241
|
+
await this.runWithMutationLock(async () => {
|
|
242
|
+
if (this.queue.length === 0) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const previousQueue = [...this.queue];
|
|
246
|
+
this.queue = [];
|
|
247
|
+
try {
|
|
248
|
+
await this.persistQueue();
|
|
249
|
+
} catch (error) {
|
|
250
|
+
this.queue = previousQueue;
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
170
254
|
}
|
|
171
255
|
/**
|
|
172
256
|
* Get all queued messages (for UI display).
|
|
@@ -185,16 +269,26 @@ class MessageQueueService {
|
|
|
185
269
|
* Remove a single queued message by ID.
|
|
186
270
|
* @returns true if message was found and removed; false otherwise
|
|
187
271
|
*/
|
|
188
|
-
remove(id) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
272
|
+
async remove(id) {
|
|
273
|
+
return await this.runWithMutationLock(async () => {
|
|
274
|
+
const index = this.queue.findIndex((m) => m.id === id);
|
|
275
|
+
if (index === -1) {
|
|
276
|
+
this.logger.debug(`Remove failed: message ${id} not found in queue`);
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const [removed] = this.queue.splice(index, 1);
|
|
280
|
+
try {
|
|
281
|
+
await this.persistQueue();
|
|
282
|
+
} catch (error) {
|
|
283
|
+
if (removed) {
|
|
284
|
+
this.queue.splice(index, 0, removed);
|
|
285
|
+
}
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
this.logger.debug(`Message removed: ${id}, remaining: ${this.queue.length}`);
|
|
289
|
+
this.eventBus.emit("message:removed", { id });
|
|
290
|
+
return true;
|
|
291
|
+
});
|
|
198
292
|
}
|
|
199
293
|
}
|
|
200
294
|
export {
|