@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.
Files changed (150) hide show
  1. package/dist/agent/DextoAgent.cjs +102 -104
  2. package/dist/agent/DextoAgent.d.ts +11 -10
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +103 -105
  5. package/dist/agent/error-codes.cjs +1 -0
  6. package/dist/agent/error-codes.d.ts +1 -0
  7. package/dist/agent/error-codes.d.ts.map +1 -1
  8. package/dist/agent/error-codes.js +1 -0
  9. package/dist/agent/errors.cjs +13 -0
  10. package/dist/agent/errors.d.ts +6 -0
  11. package/dist/agent/errors.d.ts.map +1 -1
  12. package/dist/agent/errors.js +13 -0
  13. package/dist/agent/index.d.ts +1 -0
  14. package/dist/agent/index.d.ts.map +1 -1
  15. package/dist/agent/schemas.d.ts +2 -2
  16. package/dist/agent/types.d.ts +11 -0
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/approval/factory.cjs +1 -0
  19. package/dist/approval/factory.d.ts.map +1 -1
  20. package/dist/approval/factory.js +1 -0
  21. package/dist/approval/manager.cjs +345 -182
  22. package/dist/approval/manager.d.ts +45 -31
  23. package/dist/approval/manager.d.ts.map +1 -1
  24. package/dist/approval/manager.js +345 -182
  25. package/dist/approval/schemas.cjs +10 -0
  26. package/dist/approval/schemas.d.ts +305 -0
  27. package/dist/approval/schemas.d.ts.map +1 -1
  28. package/dist/approval/schemas.js +10 -0
  29. package/dist/approval/session-approval-store.cjs +91 -0
  30. package/dist/approval/session-approval-store.d.ts +55 -0
  31. package/dist/approval/session-approval-store.d.ts.map +1 -0
  32. package/dist/approval/session-approval-store.js +68 -0
  33. package/dist/events/index.cjs +210 -75
  34. package/dist/events/index.d.ts +44 -181
  35. package/dist/events/index.d.ts.map +1 -1
  36. package/dist/events/index.js +206 -74
  37. package/dist/hooks/manager.cjs +5 -2
  38. package/dist/hooks/manager.d.ts +2 -0
  39. package/dist/hooks/manager.d.ts.map +1 -1
  40. package/dist/hooks/manager.js +5 -2
  41. package/dist/hooks/types.d.ts +3 -0
  42. package/dist/hooks/types.d.ts.map +1 -1
  43. package/dist/index.browser.d.ts +1 -0
  44. package/dist/index.browser.d.ts.map +1 -1
  45. package/dist/index.cjs +3 -1
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -0
  49. package/dist/llm/executor/turn-executor.cjs +15 -7
  50. package/dist/llm/executor/turn-executor.d.ts +3 -1
  51. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  52. package/dist/llm/executor/turn-executor.js +15 -7
  53. package/dist/llm/services/factory.cjs +10 -4
  54. package/dist/llm/services/factory.d.ts +2 -21
  55. package/dist/llm/services/factory.d.ts.map +1 -1
  56. package/dist/llm/services/factory.js +11 -7
  57. package/dist/llm/services/types.d.ts +33 -2
  58. package/dist/llm/services/types.d.ts.map +1 -1
  59. package/dist/llm/services/vercel.cjs +33 -11
  60. package/dist/llm/services/vercel.d.ts +6 -3
  61. package/dist/llm/services/vercel.d.ts.map +1 -1
  62. package/dist/llm/services/vercel.js +29 -8
  63. package/dist/logger/default-logger-factory.d.ts +12 -12
  64. package/dist/logger/v2/schemas.d.ts +6 -6
  65. package/dist/mcp/manager.cjs +7 -2
  66. package/dist/mcp/manager.d.ts +3 -1
  67. package/dist/mcp/manager.d.ts.map +1 -1
  68. package/dist/mcp/manager.js +7 -2
  69. package/dist/mcp/mcp-client.cjs +71 -62
  70. package/dist/mcp/mcp-client.d.ts +3 -2
  71. package/dist/mcp/mcp-client.d.ts.map +1 -1
  72. package/dist/mcp/mcp-client.js +71 -62
  73. package/dist/mcp/schemas.d.ts +10 -10
  74. package/dist/resources/handlers/filesystem-handler.cjs +22 -3
  75. package/dist/resources/handlers/filesystem-handler.d.ts.map +1 -1
  76. package/dist/resources/handlers/filesystem-handler.js +22 -3
  77. package/dist/runtime/host-runtime.cjs +163 -0
  78. package/dist/runtime/host-runtime.d.ts +23 -0
  79. package/dist/runtime/host-runtime.d.ts.map +1 -0
  80. package/dist/runtime/host-runtime.js +133 -0
  81. package/dist/runtime/index.cjs +42 -0
  82. package/dist/runtime/index.d.ts +2 -0
  83. package/dist/runtime/index.d.ts.map +1 -0
  84. package/dist/runtime/index.js +21 -0
  85. package/dist/runtime/run-context.cjs +53 -0
  86. package/dist/runtime/run-context.d.ts +13 -0
  87. package/dist/runtime/run-context.d.ts.map +1 -0
  88. package/dist/runtime/run-context.js +34 -0
  89. package/dist/session/chat-session.cjs +67 -71
  90. package/dist/session/chat-session.d.ts +25 -25
  91. package/dist/session/chat-session.d.ts.map +1 -1
  92. package/dist/session/chat-session.js +68 -72
  93. package/dist/session/error-codes.cjs +1 -0
  94. package/dist/session/error-codes.d.ts +2 -1
  95. package/dist/session/error-codes.d.ts.map +1 -1
  96. package/dist/session/error-codes.js +1 -0
  97. package/dist/session/errors.cjs +13 -0
  98. package/dist/session/errors.d.ts +6 -0
  99. package/dist/session/errors.d.ts.map +1 -1
  100. package/dist/session/errors.js +13 -0
  101. package/dist/session/message-queue-store.cjs +75 -0
  102. package/dist/session/message-queue-store.d.ts +16 -0
  103. package/dist/session/message-queue-store.d.ts.map +1 -0
  104. package/dist/session/message-queue-store.js +52 -0
  105. package/dist/session/message-queue.cjs +140 -46
  106. package/dist/session/message-queue.d.ts +18 -6
  107. package/dist/session/message-queue.d.ts.map +1 -1
  108. package/dist/session/message-queue.js +140 -46
  109. package/dist/session/session-manager.cjs +130 -25
  110. package/dist/session/session-manager.d.ts +18 -1
  111. package/dist/session/session-manager.d.ts.map +1 -1
  112. package/dist/session/session-manager.js +130 -25
  113. package/dist/session/title-generator.cjs +9 -2
  114. package/dist/session/title-generator.d.ts +2 -0
  115. package/dist/session/title-generator.d.ts.map +1 -1
  116. package/dist/session/title-generator.js +9 -2
  117. package/dist/telemetry/decorators.cjs +75 -57
  118. package/dist/telemetry/decorators.d.ts +2 -0
  119. package/dist/telemetry/decorators.d.ts.map +1 -1
  120. package/dist/telemetry/decorators.js +75 -57
  121. package/dist/telemetry/errors.cjs +2 -2
  122. package/dist/telemetry/errors.js +2 -2
  123. package/dist/telemetry/index.d.ts +1 -1
  124. package/dist/telemetry/index.d.ts.map +1 -1
  125. package/dist/telemetry/index.js +3 -1
  126. package/dist/telemetry/telemetry.cjs +62 -21
  127. package/dist/telemetry/telemetry.d.ts +14 -0
  128. package/dist/telemetry/telemetry.d.ts.map +1 -1
  129. package/dist/telemetry/telemetry.js +62 -21
  130. package/dist/telemetry/utils.cjs +9 -6
  131. package/dist/telemetry/utils.d.ts +3 -0
  132. package/dist/telemetry/utils.d.ts.map +1 -1
  133. package/dist/telemetry/utils.js +9 -6
  134. package/dist/test-utils/session-state-stores.cjs +68 -0
  135. package/dist/test-utils/session-state-stores.js +42 -0
  136. package/dist/tools/session-tool-preferences-store.cjs +86 -0
  137. package/dist/tools/session-tool-preferences-store.d.ts +29 -0
  138. package/dist/tools/session-tool-preferences-store.d.ts.map +1 -0
  139. package/dist/tools/session-tool-preferences-store.js +63 -0
  140. package/dist/tools/tool-manager.cjs +223 -68
  141. package/dist/tools/tool-manager.d.ts +29 -9
  142. package/dist/tools/tool-manager.d.ts.map +1 -1
  143. package/dist/tools/tool-manager.js +223 -68
  144. package/dist/tools/types.d.ts +7 -1
  145. package/dist/tools/types.d.ts.map +1 -1
  146. package/dist/utils/service-initializer.cjs +38 -5
  147. package/dist/utils/service-initializer.d.ts +11 -1
  148. package/dist/utils/service-initializer.d.ts.map +1 -1
  149. package/dist/utils/service-initializer.js +36 -4
  150. package/package.json +1 -1
@@ -4,21 +4,23 @@ import { createDatabaseHistoryProvider } from "./history/factory.js";
4
4
  import { createLLMService } from "../llm/services/factory.js";
5
5
  import {
6
6
  SessionEventBus,
7
- SessionEventNames
7
+ forwardSessionEventsToAgentBus
8
8
  } from "../events/index.js";
9
9
  import { DextoLogComponent } from "../logger/v2/types.js";
10
10
  import { DextoRuntimeError, ErrorScope, ErrorType } from "../errors/index.js";
11
11
  import { HookErrorCode } from "../hooks/error-codes.js";
12
+ import { MessageQueueService } from "./message-queue.js";
12
13
  import { getUsagePricingMetadata, hasMeaningfulTokenUsage } from "../llm/usage-metadata.js";
13
14
  import { parseCodexBaseURL } from "../llm/providers/codex-base-url.js";
15
+ import { SessionError } from "./errors.js";
14
16
  class ChatSession {
15
17
  /**
16
18
  * Creates a new ChatSession instance.
17
19
  *
18
20
  * Each session creates its own isolated services:
19
21
  * - ConversationHistoryProvider (with session-specific storage, shared across LLM switches)
20
- * - LLMService (creates its own properly-typed ContextManager internally)
21
- * - SessionEventBus (session-local event handling with forwarding)
22
+ * - LLM service (creates its own properly-typed ContextManager internally)
23
+ * - SessionEventBus (session-local event handling)
22
24
  *
23
25
  * @param services - The shared services from the agent (state manager, prompt, client managers, etc.)
24
26
  * @param id - Unique identifier for this session
@@ -29,7 +31,13 @@ class ChatSession {
29
31
  this.id = id;
30
32
  this.logger = logger.createChild(DextoLogComponent.SESSION);
31
33
  this.eventBus = new SessionEventBus();
32
- this.setupEventForwarding();
34
+ this.messageQueue = new MessageQueueService(
35
+ this.eventBus,
36
+ this.logger,
37
+ this.id,
38
+ this.services.messageQueueStore
39
+ );
40
+ this.setupTokenAccumulation();
33
41
  this.logger.debug(`ChatSession ${this.id}: Created, awaiting initialization`);
34
42
  }
35
43
  /**
@@ -52,15 +60,16 @@ class ChatSession {
52
60
  /**
53
61
  * Handles AI model interactions, tool execution, and response generation for this session.
54
62
  *
55
- * Each session has its own LLMService instance that uses the session's
63
+ * Each session has its own LLM runtime instance that uses the session's
56
64
  * ContextManager and event bus.
57
65
  */
58
66
  llmService;
59
67
  /**
60
- * Map of event forwarder functions for cleanup.
61
- * Stores the bound functions so they can be removed from the event bus.
68
+ * Durable queued follow-up messages for this session.
69
+ * Reused across LLM switches so mid-task follow-ups survive service recreation.
62
70
  */
63
- forwarders = /* @__PURE__ */ new Map();
71
+ messageQueue;
72
+ activeForwarderCleanup = null;
64
73
  /**
65
74
  * Token accumulator listener for cleanup.
66
75
  */
@@ -78,27 +87,20 @@ class ChatSession {
78
87
  async init() {
79
88
  await this.initializeServices();
80
89
  }
81
- /**
82
- * Sets up event forwarding from session bus to global agent bus.
83
- *
84
- * All session events are automatically forwarded to the global bus with the same
85
- * event names, but with session context added to the payload. This allows the app
86
- * layer to continue listening to standard events while having access to session
87
- * information when needed.
88
- */
89
- setupEventForwarding() {
90
- SessionEventNames.forEach((eventName) => {
91
- const forwarder = (payload) => {
92
- const payloadWithSession = payload && typeof payload === "object" ? { ...payload, sessionId: this.id } : { sessionId: this.id };
93
- this.services.agentEventBus.emit(eventName, payloadWithSession);
94
- };
95
- this.forwarders.set(eventName, forwarder);
96
- this.eventBus.on(eventName, forwarder);
90
+ attachRunEventForwarders(runContext) {
91
+ const cleanup = forwardSessionEventsToAgentBus({
92
+ sessionEventBus: this.eventBus,
93
+ agentEventBus: this.services.agentEventBus,
94
+ sessionId: this.id,
95
+ ...runContext?.hostRuntime !== void 0 ? { hostRuntime: runContext.hostRuntime } : {}
97
96
  });
98
- this.setupTokenAccumulation();
99
- this.logger.debug(
100
- `[setupEventForwarding] Event forwarding setup complete for session=${this.id}`
101
- );
97
+ this.activeForwarderCleanup = cleanup;
98
+ return () => {
99
+ if (this.activeForwarderCleanup === cleanup) {
100
+ this.activeForwarderCleanup = null;
101
+ }
102
+ cleanup();
103
+ };
102
104
  }
103
105
  /**
104
106
  * Sets up token usage accumulation by listening to llm:response events.
@@ -147,33 +149,35 @@ class ChatSession {
147
149
  async initializeServices() {
148
150
  const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
149
151
  const llmConfig = runtimeConfig.llm;
150
- const workspace = await this.services.workspaceManager?.getWorkspace();
152
+ await this.messageQueue.initialize();
151
153
  this.historyProvider = createDatabaseHistoryProvider(
152
154
  this.services.storageManager.getDatabase(),
153
155
  this.id,
154
156
  this.logger
155
157
  );
156
- const compactionStrategy = this.services.compactionStrategy;
157
- this.llmService = createLLMService(
158
+ this.llmService = await this.createSessionLLMService(llmConfig, runtimeConfig.usageScopeId);
159
+ this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
160
+ }
161
+ async createSessionLLMService(llmConfig, usageScopeId) {
162
+ const workspace = await this.services.workspaceManager?.getWorkspace();
163
+ const options = {
164
+ usageScopeId,
165
+ compactionStrategy: this.services.compactionStrategy,
166
+ ...workspace?.path !== void 0 && { cwd: workspace.path },
167
+ messageQueue: this.messageQueue
168
+ };
169
+ return createLLMService(
158
170
  llmConfig,
159
171
  this.services.toolManager,
160
172
  this.services.systemPromptManager,
161
173
  this.historyProvider,
162
- // Pass history provider for service to use
163
174
  this.eventBus,
164
- // Use session event bus
165
175
  this.id,
166
176
  this.services.resourceManager,
167
- // Pass ResourceManager for blob storage
168
177
  this.logger,
169
- // Pass logger for dependency injection
170
- {
171
- usageScopeId: runtimeConfig.usageScopeId,
172
- compactionStrategy,
173
- cwd: workspace?.path
174
- }
178
+ options,
179
+ this.services.languageModelFactory
175
180
  );
176
- this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
177
181
  }
178
182
  /**
179
183
  * Saves a blocked interaction to history when a plugin blocks execution.
@@ -242,8 +246,12 @@ class ChatSession {
242
246
  this.logger.debug(
243
247
  `Streaming session ${this.id} | textParts=${textParts.length} | images=${imageParts.length} | files=${fileParts.length}`
244
248
  );
249
+ if (this.isBusy()) {
250
+ throw SessionError.busy(this.id);
251
+ }
245
252
  this.currentRunController = new AbortController();
246
253
  const signal = options?.signal ? this.combineSignals(options.signal, this.currentRunController.signal) : this.currentRunController.signal;
254
+ const detachForwarders = this.attachRunEventForwarders(options?.runContext);
247
255
  try {
248
256
  const textContent = textParts.map((p) => p.text).join("\n");
249
257
  const firstImage = imageParts[0];
@@ -273,6 +281,7 @@ class ChatSession {
273
281
  mcpManager: this.services.mcpManager,
274
282
  toolManager: this.services.toolManager,
275
283
  stateManager: this.services.stateManager,
284
+ ...options?.runContext !== void 0 && { runContext: options.runContext },
276
285
  sessionId: this.id,
277
286
  abortSignal: signal
278
287
  }
@@ -282,7 +291,10 @@ class ChatSession {
282
291
  modifiedParts = modifiedParts.filter((p) => p.type !== "text");
283
292
  modifiedParts.unshift({ type: "text", text: modifiedBeforePayload.text });
284
293
  }
285
- const streamResult = await this.llmService.stream(modifiedParts, { signal });
294
+ const streamResult = await this.llmService.stream(modifiedParts, {
295
+ signal,
296
+ ...options?.runContext !== void 0 && { runContext: options.runContext }
297
+ });
286
298
  const llmConfig = this.services.stateManager.getLLMConfig(this.id);
287
299
  const beforeResponsePayload = {
288
300
  content: streamResult.text,
@@ -298,6 +310,7 @@ class ChatSession {
298
310
  mcpManager: this.services.mcpManager,
299
311
  toolManager: this.services.toolManager,
300
312
  stateManager: this.services.stateManager,
313
+ ...options?.runContext !== void 0 && { runContext: options.runContext },
301
314
  sessionId: this.id,
302
315
  abortSignal: signal
303
316
  }
@@ -353,6 +366,7 @@ class ChatSession {
353
366
  );
354
367
  throw error;
355
368
  } finally {
369
+ detachForwarders();
356
370
  this.currentRunController = null;
357
371
  }
358
372
  }
@@ -429,9 +443,9 @@ class ChatSession {
429
443
  return this.llmService.getContextManager();
430
444
  }
431
445
  /**
432
- * Gets the session's LLMService instance.
446
+ * Gets the session's LLM service instance.
433
447
  *
434
- * @returns The LLMService for this session
448
+ * @returns The session LLM service for this session
435
449
  */
436
450
  getLLMService() {
437
451
  return this.llmService;
@@ -458,26 +472,10 @@ class ChatSession {
458
472
  async switchLLM(newLLMConfig) {
459
473
  try {
460
474
  const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
461
- const workspace = await this.services.workspaceManager?.getWorkspace();
462
- const compactionStrategy = this.services.compactionStrategy;
463
- const newLLMService = createLLMService(
475
+ this.llmService = await this.createSessionLLMService(
464
476
  newLLMConfig,
465
- this.services.toolManager,
466
- this.services.systemPromptManager,
467
- this.historyProvider,
468
- // Pass the SAME history provider - preserves conversation!
469
- this.eventBus,
470
- // Use session event bus
471
- this.id,
472
- this.services.resourceManager,
473
- this.logger,
474
- {
475
- usageScopeId: runtimeConfig.usageScopeId,
476
- compactionStrategy,
477
- cwd: workspace?.path
478
- }
477
+ runtimeConfig.usageScopeId
479
478
  );
480
- this.llmService = newLLMService;
481
479
  this.logger.info(
482
480
  `ChatSession ${this.id}: LLM switched to ${newLLMConfig.provider}/${newLLMConfig.model}`
483
481
  );
@@ -519,10 +517,8 @@ class ChatSession {
519
517
  */
520
518
  dispose() {
521
519
  this.logger.debug(`Disposing session ${this.id} - cleaning up event listeners`);
522
- this.forwarders.forEach((forwarder, eventName) => {
523
- this.eventBus.off(eventName, forwarder);
524
- });
525
- this.forwarders.clear();
520
+ this.activeForwarderCleanup?.();
521
+ this.activeForwarderCleanup = null;
526
522
  if (this.tokenAccumulatorListener) {
527
523
  this.eventBus.off("llm:response", this.tokenAccumulatorListener);
528
524
  this.tokenAccumulatorListener = null;
@@ -543,8 +539,8 @@ class ChatSession {
543
539
  * @param message The user message to queue
544
540
  * @returns Queue position and message ID
545
541
  */
546
- queueMessage(message) {
547
- return this.llmService.getMessageQueue().enqueue(message);
542
+ async queueMessage(message) {
543
+ return await this.llmService.getMessageQueue().enqueue(message);
548
544
  }
549
545
  /**
550
546
  * Get all messages currently in the queue.
@@ -558,17 +554,17 @@ class ChatSession {
558
554
  * @param id Message ID to remove
559
555
  * @returns true if message was found and removed; false otherwise
560
556
  */
561
- removeQueuedMessage(id) {
562
- return this.llmService.getMessageQueue().remove(id);
557
+ async removeQueuedMessage(id) {
558
+ return await this.llmService.getMessageQueue().remove(id);
563
559
  }
564
560
  /**
565
561
  * Clear all queued messages.
566
562
  * @returns Number of messages that were cleared
567
563
  */
568
- clearMessageQueue() {
564
+ async clearMessageQueue() {
569
565
  const queue = this.llmService.getMessageQueue();
570
566
  const count = queue.pendingCount();
571
- queue.clear();
567
+ await queue.clear();
572
568
  return count;
573
569
  }
574
570
  /**
@@ -27,6 +27,7 @@ var SessionErrorCode = /* @__PURE__ */ ((SessionErrorCode2) => {
27
27
  SessionErrorCode2["SESSION_MAX_SESSIONS_EXCEEDED"] = "session_max_sessions_exceeded";
28
28
  SessionErrorCode2["SESSION_STORAGE_FAILED"] = "session_storage_failed";
29
29
  SessionErrorCode2["SESSION_RESET_FAILED"] = "session_reset_failed";
30
+ SessionErrorCode2["SESSION_BUSY"] = "session_busy";
30
31
  return SessionErrorCode2;
31
32
  })(SessionErrorCode || {});
32
33
  // Annotate the CommonJS export names for ESM import in node:
@@ -7,6 +7,7 @@ export declare enum SessionErrorCode {
7
7
  SESSION_INITIALIZATION_FAILED = "session_initialization_failed",
8
8
  SESSION_MAX_SESSIONS_EXCEEDED = "session_max_sessions_exceeded",
9
9
  SESSION_STORAGE_FAILED = "session_storage_failed",
10
- SESSION_RESET_FAILED = "session_reset_failed"
10
+ SESSION_RESET_FAILED = "session_reset_failed",
11
+ SESSION_BUSY = "session_busy"
11
12
  }
12
13
  //# sourceMappingURL=error-codes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/session/error-codes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,oBAAY,gBAAgB;IAExB,iBAAiB,sBAAsB;IACvC,6BAA6B,kCAAkC;IAC/D,6BAA6B,kCAAkC;IAG/D,sBAAsB,2BAA2B;IAGjD,oBAAoB,yBAAyB;CAChD"}
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/session/error-codes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,oBAAY,gBAAgB;IAExB,iBAAiB,sBAAsB;IACvC,6BAA6B,kCAAkC;IAC/D,6BAA6B,kCAAkC;IAG/D,sBAAsB,2BAA2B;IAGjD,oBAAoB,yBAAyB;IAC7C,YAAY,iBAAiB;CAChC"}
@@ -5,6 +5,7 @@ var SessionErrorCode = /* @__PURE__ */ ((SessionErrorCode2) => {
5
5
  SessionErrorCode2["SESSION_MAX_SESSIONS_EXCEEDED"] = "session_max_sessions_exceeded";
6
6
  SessionErrorCode2["SESSION_STORAGE_FAILED"] = "session_storage_failed";
7
7
  SessionErrorCode2["SESSION_RESET_FAILED"] = "session_reset_failed";
8
+ SessionErrorCode2["SESSION_BUSY"] = "session_busy";
8
9
  return SessionErrorCode2;
9
10
  })(SessionErrorCode || {});
10
11
  export {
@@ -86,6 +86,19 @@ class SessionError {
86
86
  { sessionId, reason }
87
87
  );
88
88
  }
89
+ /**
90
+ * Session already processing a run
91
+ */
92
+ static busy(sessionId) {
93
+ return new import_DextoRuntimeError.DextoRuntimeError(
94
+ import_error_codes.SessionErrorCode.SESSION_BUSY,
95
+ import_types.ErrorScope.SESSION,
96
+ import_types.ErrorType.CONFLICT,
97
+ `Session '${sessionId}' is already processing a message`,
98
+ { sessionId },
99
+ "Wait for the current run to finish before starting another one"
100
+ );
101
+ }
89
102
  }
90
103
  // Annotate the CommonJS export names for ESM import in node:
91
104
  0 && (module.exports = {
@@ -39,5 +39,11 @@ export declare class SessionError {
39
39
  sessionId: string;
40
40
  reason: string;
41
41
  }>;
42
+ /**
43
+ * Session already processing a run
44
+ */
45
+ static busy(sessionId: string): DextoRuntimeError<{
46
+ sessionId: string;
47
+ }>;
42
48
  }
43
49
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/session/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAInE;;;GAGG;AACH,qBAAa,YAAY;IACrB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM;;;IAUjC;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;IAU7D;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;;;;IAWpE;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;IAUzE;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;CASvD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/session/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAInE;;;GAGG;AACH,qBAAa,YAAY;IACrB;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM;;;IAUjC;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;IAU7D;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;;;;IAWpE;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;IAUzE;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;IAUpD;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM;;;CAUhC"}
@@ -64,6 +64,19 @@ class SessionError {
64
64
  { sessionId, reason }
65
65
  );
66
66
  }
67
+ /**
68
+ * Session already processing a run
69
+ */
70
+ static busy(sessionId) {
71
+ return new DextoRuntimeError(
72
+ SessionErrorCode.SESSION_BUSY,
73
+ ErrorScope.SESSION,
74
+ ErrorType.CONFLICT,
75
+ `Session '${sessionId}' is already processing a message`,
76
+ { sessionId },
77
+ "Wait for the current run to finish before starting another one"
78
+ );
79
+ }
67
80
  }
68
81
  export {
69
82
  SessionError
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var message_queue_store_exports = {};
20
+ __export(message_queue_store_exports, {
21
+ MessageQueueStore: () => MessageQueueStore
22
+ });
23
+ module.exports = __toCommonJS(message_queue_store_exports);
24
+ class MessageQueueStore {
25
+ constructor(storageManager, logger, options = {}) {
26
+ this.storageManager = storageManager;
27
+ this.logger = logger;
28
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
29
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
30
+ }
31
+ cacheTtlSeconds;
32
+ buildKey(sessionId) {
33
+ return `session-message-queue:${sessionId}`;
34
+ }
35
+ async load(sessionId) {
36
+ const key = this.buildKey(sessionId);
37
+ const cached = await this.storageManager.getCache().get(key);
38
+ if (Array.isArray(cached)) {
39
+ return structuredClone(cached);
40
+ }
41
+ const stored = await this.storageManager.getDatabase().get(key);
42
+ if (!Array.isArray(stored)) {
43
+ if (stored !== void 0) {
44
+ this.logger.warn("Invalid persisted message queue encountered; ignoring state", {
45
+ key
46
+ });
47
+ }
48
+ return [];
49
+ }
50
+ const cloned = structuredClone(stored);
51
+ await this.storageManager.getCache().set(key, cloned, this.cacheTtlSeconds);
52
+ return cloned;
53
+ }
54
+ async save(sessionId, queue) {
55
+ const key = this.buildKey(sessionId);
56
+ if (queue.length === 0) {
57
+ await this.delete(sessionId);
58
+ return;
59
+ }
60
+ const cloned = structuredClone(queue);
61
+ await this.storageManager.getDatabase().set(key, cloned);
62
+ await this.storageManager.getCache().set(key, cloned, this.cacheTtlSeconds);
63
+ }
64
+ async delete(sessionId) {
65
+ const key = this.buildKey(sessionId);
66
+ await Promise.all([
67
+ this.storageManager.getDatabase().delete(key),
68
+ this.storageManager.getCache().delete(key)
69
+ ]);
70
+ }
71
+ }
72
+ // Annotate the CommonJS export names for ESM import in node:
73
+ 0 && (module.exports = {
74
+ MessageQueueStore
75
+ });
@@ -0,0 +1,16 @@
1
+ import type { Logger } from '../logger/v2/types.js';
2
+ import type { StorageManager } from '../storage/index.js';
3
+ import type { QueuedMessage } from './types.js';
4
+ export declare class MessageQueueStore {
5
+ private readonly storageManager;
6
+ private readonly logger;
7
+ private readonly cacheTtlSeconds;
8
+ constructor(storageManager: StorageManager, logger: Logger, options?: {
9
+ cacheTtlMs?: number;
10
+ });
11
+ private buildKey;
12
+ load(sessionId: string): Promise<QueuedMessage[]>;
13
+ save(sessionId: string, queue: QueuedMessage[]): Promise<void>;
14
+ delete(sessionId: string): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=message-queue-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-queue-store.d.ts","sourceRoot":"","sources":["../../src/session/message-queue-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,iBAAiB;IAItB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJ3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAGpB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EAC/B,OAAO,GAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO;IAMzC,OAAO,CAAC,QAAQ;IAIV,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAsBjD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9D,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOjD"}
@@ -0,0 +1,52 @@
1
+ import "../chunk-PTJYTZNU.js";
2
+ class MessageQueueStore {
3
+ constructor(storageManager, logger, options = {}) {
4
+ this.storageManager = storageManager;
5
+ this.logger = logger;
6
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
7
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
8
+ }
9
+ cacheTtlSeconds;
10
+ buildKey(sessionId) {
11
+ return `session-message-queue:${sessionId}`;
12
+ }
13
+ async load(sessionId) {
14
+ const key = this.buildKey(sessionId);
15
+ const cached = await this.storageManager.getCache().get(key);
16
+ if (Array.isArray(cached)) {
17
+ return structuredClone(cached);
18
+ }
19
+ const stored = await this.storageManager.getDatabase().get(key);
20
+ if (!Array.isArray(stored)) {
21
+ if (stored !== void 0) {
22
+ this.logger.warn("Invalid persisted message queue encountered; ignoring state", {
23
+ key
24
+ });
25
+ }
26
+ return [];
27
+ }
28
+ const cloned = structuredClone(stored);
29
+ await this.storageManager.getCache().set(key, cloned, this.cacheTtlSeconds);
30
+ return cloned;
31
+ }
32
+ async save(sessionId, queue) {
33
+ const key = this.buildKey(sessionId);
34
+ if (queue.length === 0) {
35
+ await this.delete(sessionId);
36
+ return;
37
+ }
38
+ const cloned = structuredClone(queue);
39
+ await this.storageManager.getDatabase().set(key, cloned);
40
+ await this.storageManager.getCache().set(key, cloned, this.cacheTtlSeconds);
41
+ }
42
+ async delete(sessionId) {
43
+ const key = this.buildKey(sessionId);
44
+ await Promise.all([
45
+ this.storageManager.getDatabase().delete(key),
46
+ this.storageManager.getCache().delete(key)
47
+ ]);
48
+ }
49
+ }
50
+ export {
51
+ MessageQueueStore
52
+ };