@dexto/core 1.6.25 → 1.6.26

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 (72) hide show
  1. package/dist/agent/DextoAgent.cjs +27 -14
  2. package/dist/agent/DextoAgent.d.ts +7 -6
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +27 -14
  5. package/dist/approval/manager.cjs +328 -178
  6. package/dist/approval/manager.d.ts +39 -31
  7. package/dist/approval/manager.d.ts.map +1 -1
  8. package/dist/approval/manager.js +328 -178
  9. package/dist/approval/session-approval-store.cjs +91 -0
  10. package/dist/approval/session-approval-store.d.ts +55 -0
  11. package/dist/approval/session-approval-store.d.ts.map +1 -0
  12. package/dist/approval/session-approval-store.js +68 -0
  13. package/dist/llm/executor/turn-executor.cjs +7 -3
  14. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  15. package/dist/llm/executor/turn-executor.js +7 -3
  16. package/dist/llm/services/factory.cjs +10 -4
  17. package/dist/llm/services/factory.d.ts +2 -21
  18. package/dist/llm/services/factory.d.ts.map +1 -1
  19. package/dist/llm/services/factory.js +11 -7
  20. package/dist/llm/services/types.d.ts +33 -2
  21. package/dist/llm/services/types.d.ts.map +1 -1
  22. package/dist/llm/services/vercel.cjs +4 -5
  23. package/dist/llm/services/vercel.d.ts +3 -3
  24. package/dist/llm/services/vercel.d.ts.map +1 -1
  25. package/dist/llm/services/vercel.js +2 -3
  26. package/dist/logger/default-logger-factory.d.ts +12 -12
  27. package/dist/logger/v2/schemas.d.ts +6 -6
  28. package/dist/mcp/schemas.d.ts +10 -10
  29. package/dist/session/chat-session.cjs +39 -41
  30. package/dist/session/chat-session.d.ts +22 -12
  31. package/dist/session/chat-session.d.ts.map +1 -1
  32. package/dist/session/chat-session.js +39 -41
  33. package/dist/session/message-queue-store.cjs +75 -0
  34. package/dist/session/message-queue-store.d.ts +16 -0
  35. package/dist/session/message-queue-store.d.ts.map +1 -0
  36. package/dist/session/message-queue-store.js +52 -0
  37. package/dist/session/message-queue.cjs +140 -46
  38. package/dist/session/message-queue.d.ts +18 -6
  39. package/dist/session/message-queue.d.ts.map +1 -1
  40. package/dist/session/message-queue.js +140 -46
  41. package/dist/session/session-manager.cjs +130 -25
  42. package/dist/session/session-manager.d.ts +18 -1
  43. package/dist/session/session-manager.d.ts.map +1 -1
  44. package/dist/session/session-manager.js +130 -25
  45. package/dist/session/title-generator.cjs +9 -2
  46. package/dist/session/title-generator.d.ts +2 -0
  47. package/dist/session/title-generator.d.ts.map +1 -1
  48. package/dist/session/title-generator.js +9 -2
  49. package/dist/telemetry/errors.cjs +2 -2
  50. package/dist/telemetry/errors.js +2 -2
  51. package/dist/telemetry/index.d.ts +1 -1
  52. package/dist/telemetry/index.d.ts.map +1 -1
  53. package/dist/telemetry/index.js +3 -1
  54. package/dist/telemetry/telemetry.cjs +62 -21
  55. package/dist/telemetry/telemetry.d.ts +14 -0
  56. package/dist/telemetry/telemetry.d.ts.map +1 -1
  57. package/dist/telemetry/telemetry.js +62 -21
  58. package/dist/test-utils/session-state-stores.cjs +68 -0
  59. package/dist/test-utils/session-state-stores.js +42 -0
  60. package/dist/tools/session-tool-preferences-store.cjs +86 -0
  61. package/dist/tools/session-tool-preferences-store.d.ts +29 -0
  62. package/dist/tools/session-tool-preferences-store.d.ts.map +1 -0
  63. package/dist/tools/session-tool-preferences-store.js +63 -0
  64. package/dist/tools/tool-manager.cjs +131 -32
  65. package/dist/tools/tool-manager.d.ts +17 -6
  66. package/dist/tools/tool-manager.d.ts.map +1 -1
  67. package/dist/tools/tool-manager.js +131 -32
  68. package/dist/utils/service-initializer.cjs +38 -5
  69. package/dist/utils/service-initializer.d.ts +11 -1
  70. package/dist/utils/service-initializer.d.ts.map +1 -1
  71. package/dist/utils/service-initializer.js +36 -4
  72. package/package.json +1 -1
@@ -16,11 +16,13 @@ class SessionManager {
16
16
  this.maxSessions = config.maxSessions ?? 100;
17
17
  this.sessionTTL = config.sessionTTL ?? 36e5;
18
18
  this.sessionLoggerFactory = config.sessionLoggerFactory ?? defaultSessionLoggerFactory;
19
+ this.languageModelFactory = config.languageModelFactory;
19
20
  this.logger = logger.createChild(DextoLogComponent.SESSION);
20
21
  }
21
22
  sessions = /* @__PURE__ */ new Map();
22
23
  maxSessions;
23
24
  sessionTTL;
25
+ static MESSAGE_QUEUE_KEY_PREFIX = "session-message-queue:";
24
26
  initialized = false;
25
27
  cleanupInterval;
26
28
  initializationPromise;
@@ -34,6 +36,16 @@ class SessionManager {
34
36
  static FORK_TITLE_PREFIX = "Fork: ";
35
37
  static FORK_PARENT_ID_PREVIEW_LENGTH = 8;
36
38
  sessionLoggerFactory;
39
+ languageModelFactory;
40
+ getChatSessionServices() {
41
+ return {
42
+ ...this.services,
43
+ sessionManager: this,
44
+ ...this.languageModelFactory !== void 0 && {
45
+ languageModelFactory: this.languageModelFactory
46
+ }
47
+ };
48
+ }
37
49
  /**
38
50
  * Initialize the SessionManager with persistent storage.
39
51
  * This must be called before using any session operations.
@@ -42,6 +54,7 @@ class SessionManager {
42
54
  if (this.initialized) {
43
55
  return;
44
56
  }
57
+ await this.clearPersistedQueuedMessages("startup");
45
58
  await this.restoreSessionsFromStorage();
46
59
  const cleanupIntervalMs = Math.min(this.sessionTTL / 4, 15 * 60 * 1e3);
47
60
  this.cleanupInterval = setInterval(
@@ -72,7 +85,11 @@ class SessionManager {
72
85
  if (now - lastActivity <= this.sessionTTL) {
73
86
  this.logger.debug(`Session ${sessionId} restored from storage`);
74
87
  } else {
75
- await this.services.storageManager.getDatabase().delete(sessionKey);
88
+ await Promise.all([
89
+ this.services.storageManager.getDatabase().delete(sessionKey),
90
+ this.services.storageManager.getCache().delete(sessionKey),
91
+ this.deleteSessionInteractionState(sessionId)
92
+ ]);
76
93
  this.logger.debug(`Expired session ${sessionId} cleaned up during restore`);
77
94
  }
78
95
  }
@@ -83,6 +100,31 @@ class SessionManager {
83
100
  );
84
101
  }
85
102
  }
103
+ async clearPersistedQueuedMessages(reason) {
104
+ try {
105
+ const queueKeys = await this.services.storageManager.getDatabase().list(SessionManager.MESSAGE_QUEUE_KEY_PREFIX);
106
+ if (queueKeys.length === 0) {
107
+ return;
108
+ }
109
+ await Promise.all(
110
+ queueKeys.map(
111
+ (key) => this.services.messageQueueStore.delete(
112
+ key.slice(SessionManager.MESSAGE_QUEUE_KEY_PREFIX.length)
113
+ )
114
+ )
115
+ );
116
+ const message = `${reason === "startup" ? "Cleared stale queued follow-up state from previous agent run" : "Cleared queued follow-up state during agent shutdown"} (${queueKeys.length} session bucket(s))`;
117
+ if (reason === "startup") {
118
+ this.logger.info(message);
119
+ } else {
120
+ this.logger.debug(message);
121
+ }
122
+ } catch (error) {
123
+ this.logger.warn(
124
+ `Failed to clear persisted queued follow-up state during ${reason}: ${error instanceof Error ? error.message : String(error)}`
125
+ );
126
+ }
127
+ }
86
128
  /**
87
129
  * Ensures the SessionManager is initialized before operations.
88
130
  */
@@ -274,12 +316,10 @@ class SessionManager {
274
316
  this.services.stateManager.updateLLM(restoredConfig, id);
275
317
  }
276
318
  }
277
- const session2 = new ChatSession(
278
- { ...this.services, sessionManager: this },
279
- id,
280
- sessionLogger
281
- );
319
+ const session2 = new ChatSession(this.getChatSessionServices(), id, sessionLogger);
282
320
  await session2.init();
321
+ await this.services.toolManager.restoreSessionState(id);
322
+ await this.services.approvalManager.restoreSessionState(id);
283
323
  this.sessions.set(id, session2);
284
324
  this.logger.info(`Restored session from storage: ${id}`);
285
325
  return session2;
@@ -288,6 +328,7 @@ class SessionManager {
288
328
  if (activeSessionKeys.length >= this.maxSessions) {
289
329
  throw SessionError.maxSessionsExceeded(activeSessionKeys.length, this.maxSessions);
290
330
  }
331
+ await this.deleteSessionInteractionState(id);
291
332
  const workspace = await this.services.workspaceManager?.getWorkspace();
292
333
  const sessionData = {
293
334
  id,
@@ -313,11 +354,7 @@ class SessionManager {
313
354
  agentId,
314
355
  sessionId: id
315
356
  });
316
- session = new ChatSession(
317
- { ...this.services, sessionManager: this },
318
- id,
319
- sessionLogger
320
- );
357
+ session = new ChatSession(this.getChatSessionServices(), id, sessionLogger);
321
358
  await session.init();
322
359
  this.sessions.set(id, session);
323
360
  await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
@@ -376,11 +413,13 @@ class SessionManager {
376
413
  }
377
414
  }
378
415
  const session = new ChatSession(
379
- { ...this.services, sessionManager: this },
416
+ this.getChatSessionServices(),
380
417
  sessionId,
381
418
  sessionLogger
382
419
  );
383
420
  await session.init();
421
+ await this.services.toolManager.restoreSessionState(sessionId);
422
+ await this.services.approvalManager.restoreSessionState(sessionId);
384
423
  this.sessions.set(sessionId, session);
385
424
  return session;
386
425
  }
@@ -402,6 +441,7 @@ class SessionManager {
402
441
  }
403
442
  const sessionKey = `session:${sessionId}`;
404
443
  await this.services.storageManager.getCache().delete(sessionKey);
444
+ this.evictSessionInteractionState(sessionId);
405
445
  this.logger.debug(
406
446
  `Ended session (removed from memory, chat history preserved): ${sessionId}`
407
447
  );
@@ -422,12 +462,13 @@ class SessionManager {
422
462
  const sessionKey = `session:${sessionId}`;
423
463
  await this.services.storageManager.getDatabase().delete(sessionKey);
424
464
  await this.services.storageManager.getCache().delete(sessionKey);
465
+ await this.deleteSessionInteractionState(sessionId);
425
466
  const messagesKey = `messages:${sessionId}`;
426
467
  await this.services.storageManager.getDatabase().delete(messagesKey);
427
468
  this.logger.debug(`Deleted session and conversation history: ${sessionId}`);
428
469
  }
429
470
  /**
430
- * Resets the conversation history for a session while keeping the session alive.
471
+ * Resets conversation and session-scoped interaction state while keeping the session alive.
431
472
  *
432
473
  * @param sessionId The session ID to reset
433
474
  * @throws Error if session doesn't exist
@@ -439,6 +480,15 @@ class SessionManager {
439
480
  throw SessionError.notFound(sessionId);
440
481
  }
441
482
  await session.reset();
483
+ await session.clearMessageQueue();
484
+ await Promise.all([
485
+ this.services.toolManager.deleteSessionState(sessionId),
486
+ this.services.approvalManager.deleteSessionState(sessionId)
487
+ ]);
488
+ if (this.services.stateManager.hasSessionLLMOverride(sessionId)) {
489
+ this.services.stateManager.clearSessionOverride(sessionId);
490
+ await session.switchLLM(this.services.stateManager.getRuntimeConfig().llm);
491
+ }
442
492
  await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
443
493
  const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
444
494
  if (!sessionData) {
@@ -446,6 +496,7 @@ class SessionManager {
446
496
  }
447
497
  sessionData.messageCount = 0;
448
498
  sessionData.lastActivity = Date.now();
499
+ delete sessionData.llmOverride;
449
500
  await this.persistSessionData(sessionKey, sessionData);
450
501
  });
451
502
  this.logger.debug(`Reset session conversation: ${sessionId}`);
@@ -736,6 +787,7 @@ class SessionManager {
736
787
  if (session) {
737
788
  session.dispose();
738
789
  this.sessions.delete(sessionId);
790
+ this.evictSessionInteractionState(sessionId);
739
791
  this.logger.debug(
740
792
  `Removed expired session from memory: ${sessionId} (chat history preserved)`
741
793
  );
@@ -760,8 +812,7 @@ class SessionManager {
760
812
  const session = await this.getSession(sId);
761
813
  if (session) {
762
814
  try {
763
- this.services.stateManager.updateLLM(newLLMConfig, sId);
764
- await session.switchLLM(newLLMConfig);
815
+ await this.applySessionLLMSwitch(sId, session, newLLMConfig);
765
816
  } catch (error) {
766
817
  failedSessions.push(sId);
767
818
  this.logger.warn(
@@ -790,16 +841,7 @@ class SessionManager {
790
841
  if (!session) {
791
842
  throw SessionError.notFound(sessionId);
792
843
  }
793
- await session.switchLLM(newLLMConfig);
794
- await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
795
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
796
- if (!sessionData) {
797
- return;
798
- }
799
- const { apiKey: _apiKey, ...configWithoutApiKey } = newLLMConfig;
800
- sessionData.llmOverride = configWithoutApiKey;
801
- await this.persistSessionData(sessionKey, sessionData);
802
- });
844
+ await this.applySessionLLMSwitch(sessionId, session, newLLMConfig);
803
845
  this.services.agentEventBus.emit("llm:switched", {
804
846
  newConfig: newLLMConfig,
805
847
  historyRetained: true,
@@ -808,6 +850,68 @@ class SessionManager {
808
850
  const message = `Successfully switched to ${newLLMConfig.provider}/${newLLMConfig.model} for session ${sessionId}`;
809
851
  return { message, warnings: [] };
810
852
  }
853
+ async applySessionLLMSwitch(sessionId, session, newLLMConfig) {
854
+ const previousLLMConfig = this.services.stateManager.getRuntimeConfig(sessionId).llm;
855
+ const previousHadOverride = this.services.stateManager.hasSessionLLMOverride(sessionId);
856
+ const previousPersistedOverride = await this.getPersistedSessionLLMOverride(sessionId);
857
+ await this.setPersistedSessionLLMOverride(
858
+ sessionId,
859
+ this.toPersistedLLMConfig(newLLMConfig)
860
+ );
861
+ try {
862
+ this.services.stateManager.updateLLM(newLLMConfig, sessionId);
863
+ await session.switchLLM(newLLMConfig);
864
+ } catch (error) {
865
+ await this.setPersistedSessionLLMOverride(sessionId, previousPersistedOverride);
866
+ if (previousHadOverride) {
867
+ this.services.stateManager.updateLLM(previousLLMConfig, sessionId);
868
+ } else {
869
+ this.services.stateManager.clearSessionOverride(sessionId);
870
+ }
871
+ try {
872
+ await session.switchLLM(previousLLMConfig);
873
+ } catch (rollbackError) {
874
+ this.logger.error(
875
+ `Failed to roll back LLM switch for session ${sessionId}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`
876
+ );
877
+ }
878
+ throw error;
879
+ }
880
+ }
881
+ async getPersistedSessionLLMOverride(sessionId) {
882
+ const sessionData = await this.getSessionData(sessionId);
883
+ return sessionData?.llmOverride;
884
+ }
885
+ toPersistedLLMConfig(newLLMConfig) {
886
+ const { apiKey: _apiKey, ...configWithoutApiKey } = newLLMConfig;
887
+ return configWithoutApiKey;
888
+ }
889
+ async setPersistedSessionLLMOverride(sessionId, llmOverride) {
890
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
891
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
892
+ if (!sessionData) {
893
+ return;
894
+ }
895
+ if (llmOverride !== void 0) {
896
+ sessionData.llmOverride = llmOverride;
897
+ } else {
898
+ delete sessionData.llmOverride;
899
+ }
900
+ await this.persistSessionData(sessionKey, sessionData);
901
+ });
902
+ }
903
+ async deleteSessionInteractionState(sessionId) {
904
+ this.services.stateManager.clearSessionOverride(sessionId);
905
+ await Promise.all([
906
+ this.services.toolManager.deleteSessionState(sessionId),
907
+ this.services.approvalManager.deleteSessionState(sessionId),
908
+ this.services.messageQueueStore.delete(sessionId)
909
+ ]);
910
+ }
911
+ evictSessionInteractionState(sessionId) {
912
+ this.services.toolManager.evictSessionState(sessionId);
913
+ this.services.approvalManager.evictSessionState(sessionId);
914
+ }
811
915
  async runWithSessionDataLock(sessionId, fn) {
812
916
  const sessionKey = `session:${sessionId}`;
813
917
  const previousLock = this.sessionDataLocks.get(sessionKey) ?? Promise.resolve();
@@ -868,6 +972,7 @@ class SessionManager {
868
972
  delete this.cleanupInterval;
869
973
  this.logger.debug("Periodic session cleanup stopped");
870
974
  }
975
+ await this.clearPersistedQueuedMessages("shutdown");
871
976
  const sessionIds = Array.from(this.sessions.keys());
872
977
  for (const sessionId of sessionIds) {
873
978
  try {
@@ -25,6 +25,7 @@ module.exports = __toCommonJS(title_generator_exports);
25
25
  var import_factory = require("../llm/services/factory.js");
26
26
  var import_events = require("../events/index.js");
27
27
  var import_memory = require("./history/memory.js");
28
+ var import_message_queue = require("./message-queue.js");
28
29
  async function generateSessionTitle(config, toolManager, systemPromptManager, resourceManager, userText, logger, opts = {}) {
29
30
  const timeoutMs = opts.timeoutMs;
30
31
  const controller = timeoutMs !== void 0 ? new AbortController() : void 0;
@@ -35,15 +36,21 @@ async function generateSessionTitle(config, toolManager, systemPromptManager, re
35
36
  try {
36
37
  const history = new import_memory.MemoryHistoryProvider(logger);
37
38
  const bus = new import_events.SessionEventBus();
39
+ const sessionId = `titlegen-${Math.random().toString(36).slice(2)}`;
40
+ const options = {
41
+ messageQueue: import_message_queue.MessageQueueService.createEphemeral(bus, logger, sessionId)
42
+ };
38
43
  const tempService = (0, import_factory.createLLMService)(
39
44
  config,
40
45
  toolManager,
41
46
  systemPromptManager,
42
47
  history,
43
48
  bus,
44
- `titlegen-${Math.random().toString(36).slice(2)}`,
49
+ sessionId,
45
50
  resourceManager,
46
- logger
51
+ logger,
52
+ options,
53
+ opts.languageModelFactory
47
54
  );
48
55
  const instruction = [
49
56
  "Generate a short conversation title from the following user message.",
@@ -3,6 +3,7 @@ import type { ToolManager } from '../tools/tool-manager.js';
3
3
  import type { SystemPromptManager } from '../systemPrompt/manager.js';
4
4
  import type { ResourceManager } from '../resources/index.js';
5
5
  import type { Logger } from '../logger/v2/types.js';
6
+ import type { LanguageModelFactory } from '../llm/services/types.js';
6
7
  export interface GenerateSessionTitleResult {
7
8
  title?: string;
8
9
  error?: string;
@@ -14,6 +15,7 @@ export interface GenerateSessionTitleResult {
14
15
  */
15
16
  export declare function generateSessionTitle(config: ValidatedLLMConfig, toolManager: ToolManager, systemPromptManager: SystemPromptManager, resourceManager: ResourceManager, userText: string, logger: Logger, opts?: {
16
17
  timeoutMs?: number;
18
+ languageModelFactory?: LanguageModelFactory;
17
19
  }): Promise<GenerateSessionTitleResult>;
18
20
  /**
19
21
  * Heuristic fallback when the LLM-based title fails.
@@ -1 +1 @@
1
- {"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../src/session/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAKpD,MAAM,WAAW,0BAA0B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,0BAA0B,CAAC,CAmDrC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8BzE"}
1
+ {"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../src/session/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAA2B,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAM9F,MAAM,WAAW,0BAA0B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;CAAO,GAC/E,OAAO,CAAC,0BAA0B,CAAC,CAyDrC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8BzE"}
@@ -2,6 +2,7 @@ import "../chunk-PTJYTZNU.js";
2
2
  import { createLLMService } from "../llm/services/factory.js";
3
3
  import { SessionEventBus } from "../events/index.js";
4
4
  import { MemoryHistoryProvider } from "./history/memory.js";
5
+ import { MessageQueueService } from "./message-queue.js";
5
6
  async function generateSessionTitle(config, toolManager, systemPromptManager, resourceManager, userText, logger, opts = {}) {
6
7
  const timeoutMs = opts.timeoutMs;
7
8
  const controller = timeoutMs !== void 0 ? new AbortController() : void 0;
@@ -12,15 +13,21 @@ async function generateSessionTitle(config, toolManager, systemPromptManager, re
12
13
  try {
13
14
  const history = new MemoryHistoryProvider(logger);
14
15
  const bus = new SessionEventBus();
16
+ const sessionId = `titlegen-${Math.random().toString(36).slice(2)}`;
17
+ const options = {
18
+ messageQueue: MessageQueueService.createEphemeral(bus, logger, sessionId)
19
+ };
15
20
  const tempService = createLLMService(
16
21
  config,
17
22
  toolManager,
18
23
  systemPromptManager,
19
24
  history,
20
25
  bus,
21
- `titlegen-${Math.random().toString(36).slice(2)}`,
26
+ sessionId,
22
27
  resourceManager,
23
- logger
28
+ logger,
29
+ options,
30
+ opts.languageModelFactory
24
31
  );
25
32
  const instruction = [
26
33
  "Generate a short conversation title from the following user message.",
@@ -80,9 +80,9 @@ class TelemetryError {
80
80
  import_error_codes.TelemetryErrorCode.NOT_INITIALIZED,
81
81
  import_types.ErrorScope.TELEMETRY,
82
82
  import_types.ErrorType.USER,
83
- "Telemetry not initialized. Call Telemetry.init() first.",
83
+ "Telemetry not initialized. Call Telemetry.init() or Telemetry.registerGlobal() first.",
84
84
  {
85
- hint: "Ensure telemetry is initialized before accessing the global instance."
85
+ hint: "Ensure telemetry is initialized via Telemetry.init() or Telemetry.registerGlobal() before accessing the global instance."
86
86
  }
87
87
  );
88
88
  }
@@ -58,9 +58,9 @@ class TelemetryError {
58
58
  TelemetryErrorCode.NOT_INITIALIZED,
59
59
  ErrorScope.TELEMETRY,
60
60
  ErrorType.USER,
61
- "Telemetry not initialized. Call Telemetry.init() first.",
61
+ "Telemetry not initialized. Call Telemetry.init() or Telemetry.registerGlobal() first.",
62
62
  {
63
- hint: "Ensure telemetry is initialized before accessing the global instance."
63
+ hint: "Ensure telemetry is initialized via Telemetry.init() or Telemetry.registerGlobal() before accessing the global instance."
64
64
  }
65
65
  );
66
66
  }
@@ -1,4 +1,4 @@
1
- export { Telemetry } from './telemetry.js';
1
+ export { Telemetry, type TelemetryRegistrationOptions, type TelemetryShutdownHandler, } from './telemetry.js';
2
2
  export { OtelConfigurationSchema } from './schemas.js';
3
3
  export type { OtelConfiguration } from './schemas.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,SAAS,EACT,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,GAChC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import "../chunk-PTJYTZNU.js";
2
- import { Telemetry } from "./telemetry.js";
2
+ import {
3
+ Telemetry
4
+ } from "./telemetry.js";
3
5
  import { OtelConfigurationSchema } from "./schemas.js";
4
6
  export {
5
7
  OtelConfigurationSchema,
@@ -40,17 +40,17 @@ class Telemetry {
40
40
  name = "dexto-service";
41
41
  _isInitialized = false;
42
42
  _sdk;
43
+ _shutdownHandler;
43
44
  static _initPromise;
44
45
  static _signalHandlers;
45
- constructor(config, enabled, sdk) {
46
+ constructor(config, options) {
46
47
  const serviceName = config.serviceName ?? "dexto-service";
47
48
  const tracerName = config.tracerName ?? serviceName;
48
49
  this.name = serviceName;
49
50
  this.tracer = import_api.trace.getTracer(tracerName);
50
- if (sdk) {
51
- this._sdk = sdk;
52
- }
53
- this._isInitialized = enabled && !!sdk;
51
+ this._sdk = options.sdk;
52
+ this._shutdownHandler = options.shutdown;
53
+ this._isInitialized = options.initialized;
54
54
  }
55
55
  static async buildTraceExporter(config) {
56
56
  const e = config?.export;
@@ -178,7 +178,10 @@ class Telemetry {
178
178
  process.once("SIGINT", sigint);
179
179
  Telemetry._signalHandlers = { sigterm, sigint };
180
180
  }
181
- globalThis.__TELEMETRY__ = new Telemetry(config, enabled, sdk);
181
+ globalThis.__TELEMETRY__ = new Telemetry(config, {
182
+ initialized: enabled && !!sdk,
183
+ ...sdk !== void 0 && { sdk }
184
+ });
182
185
  }
183
186
  return globalThis.__TELEMETRY__;
184
187
  })();
@@ -194,6 +197,38 @@ class Telemetry {
194
197
  );
195
198
  }
196
199
  }
200
+ /**
201
+ * Register a global telemetry instance after a host installs its own provider/exporter lifecycle.
202
+ *
203
+ * This keeps core instrumentation active without forcing the default Node SDK bootstrap path.
204
+ */
205
+ static async registerGlobal(options = {}) {
206
+ try {
207
+ if (globalThis.__TELEMETRY__) return globalThis.__TELEMETRY__;
208
+ if (Telemetry._initPromise) return Telemetry._initPromise;
209
+ const config = options.config ?? {};
210
+ const initialized = options.initialized ?? true;
211
+ Telemetry._initPromise = Promise.resolve().then(() => {
212
+ if (!globalThis.__TELEMETRY__) {
213
+ globalThis.__TELEMETRY__ = new Telemetry(config, {
214
+ initialized,
215
+ ...options.shutdown !== void 0 && { shutdown: options.shutdown }
216
+ });
217
+ }
218
+ return globalThis.__TELEMETRY__;
219
+ });
220
+ return await Telemetry._initPromise;
221
+ } catch (error) {
222
+ Telemetry._initPromise = void 0;
223
+ if (error instanceof import_DextoRuntimeError.DextoRuntimeError) {
224
+ throw error;
225
+ }
226
+ throw import_errors.TelemetryError.initializationFailed(
227
+ error instanceof Error ? error.message : String(error),
228
+ error
229
+ );
230
+ }
231
+ }
197
232
  static getActiveSpan() {
198
233
  const span = import_api.trace.getActiveSpan();
199
234
  return span;
@@ -275,25 +310,31 @@ class Telemetry {
275
310
  * This ensures agent switching works even when telemetry export fails.
276
311
  */
277
312
  async shutdown() {
278
- if (this._sdk) {
279
- try {
313
+ try {
314
+ if (this._shutdownHandler) {
315
+ await this._shutdownHandler();
316
+ } else if (this._sdk) {
280
317
  await this._sdk.shutdown();
281
- } catch (error) {
282
- const errorMsg = error instanceof Error ? error.message : String(error);
283
- import_logger.logger.warn(`Telemetry shutdown failed to flush spans (non-blocking): ${errorMsg}`);
284
- } finally {
285
- this._isInitialized = false;
286
- globalThis.__TELEMETRY__ = void 0;
287
- if (Telemetry._signalHandlers) {
288
- process.off("SIGTERM", Telemetry._signalHandlers.sigterm);
289
- process.off("SIGINT", Telemetry._signalHandlers.sigint);
290
- Telemetry._signalHandlers = void 0;
291
- }
292
- this._sdk = void 0;
293
- Telemetry._initPromise = void 0;
294
318
  }
319
+ } catch (error) {
320
+ const errorMsg = error instanceof Error ? error.message : String(error);
321
+ import_logger.logger.warn(`Telemetry shutdown failed to flush spans (non-blocking): ${errorMsg}`);
322
+ } finally {
323
+ this.cleanupAfterShutdown();
295
324
  }
296
325
  }
326
+ cleanupAfterShutdown() {
327
+ this._isInitialized = false;
328
+ globalThis.__TELEMETRY__ = void 0;
329
+ if (Telemetry._signalHandlers) {
330
+ process.off("SIGTERM", Telemetry._signalHandlers.sigterm);
331
+ process.off("SIGINT", Telemetry._signalHandlers.sigint);
332
+ Telemetry._signalHandlers = void 0;
333
+ }
334
+ this._sdk = void 0;
335
+ this._shutdownHandler = void 0;
336
+ Telemetry._initPromise = void 0;
337
+ }
297
338
  }
298
339
  // Annotate the CommonJS export names for ESM import in node:
299
340
  0 && (module.exports = {
@@ -1,5 +1,11 @@
1
1
  import type { Tracer, Context, BaggageEntry } from '@opentelemetry/api';
2
2
  import type { OtelConfiguration } from './schemas.js';
3
+ export type TelemetryShutdownHandler = () => Promise<void>;
4
+ export type TelemetryRegistrationOptions = {
5
+ config?: OtelConfiguration | undefined;
6
+ initialized?: boolean | undefined;
7
+ shutdown?: TelemetryShutdownHandler | undefined;
8
+ };
3
9
  declare global {
4
10
  var __TELEMETRY__: Telemetry | undefined;
5
11
  }
@@ -17,6 +23,7 @@ export declare class Telemetry {
17
23
  name: string;
18
24
  private _isInitialized;
19
25
  private _sdk?;
26
+ private _shutdownHandler?;
20
27
  private static _initPromise?;
21
28
  private static _signalHandlers?;
22
29
  private constructor();
@@ -28,6 +35,12 @@ export declare class Telemetry {
28
35
  * @returns Telemetry instance that can be used for tracing
29
36
  */
30
37
  static init(config?: OtelConfiguration, exporter?: import('@opentelemetry/sdk-trace-base').SpanExporter): Promise<Telemetry>;
38
+ /**
39
+ * Register a global telemetry instance after a host installs its own provider/exporter lifecycle.
40
+ *
41
+ * This keeps core instrumentation active without forcing the default Node SDK bootstrap path.
42
+ */
43
+ static registerGlobal(options?: TelemetryRegistrationOptions): Promise<Telemetry>;
31
44
  static getActiveSpan(): import("@opentelemetry/api").Span | undefined;
32
45
  /**
33
46
  * Get the global telemetry instance
@@ -70,5 +83,6 @@ export declare class Telemetry {
70
83
  * This ensures agent switching works even when telemetry export fails.
71
84
  */
72
85
  shutdown(): Promise<void>;
86
+ private cleanupAfterShutdown;
73
87
  }
74
88
  //# sourceMappingURL=telemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/telemetry/telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAYtD,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAS;IACX,MAAM,EAAE,MAAM,CAA4B;IACjD,IAAI,EAAE,MAAM,CAAmB;IAC/B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,IAAI,CAAC,CAA0B;IACvC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAiC;IAC7D,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAA0D;IAEzF,OAAO;mBAYc,kBAAkB;IA0DvC;;;;;OAKG;WACU,IAAI,CACb,MAAM,GAAE,iBAAsB,EAC9B,QAAQ,CAAC,EAAE,OAAO,+BAA+B,EAAE,YAAY,GAChE,OAAO,CAAC,SAAS,CAAC;IA8HrB,MAAM,CAAC,aAAa;IAKpB;;;;OAIG;IACH,MAAM,CAAC,GAAG,IAAI,SAAS;IAOvB;;;OAGG;IACH,MAAM,CAAC,iBAAiB,IAAI,OAAO;IAInC;;;;;OAKG;WACU,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5C;;;OAGG;IACI,aAAa,IAAI,OAAO;IAI/B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,GAAE,OAA8B;IAc5F,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI;IAI/C;;;OAGG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxC;;;;;;;;;OASG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA8BzC"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/telemetry/telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAUtD,MAAM,MAAM,wBAAwB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAE3D,MAAM,MAAM,4BAA4B,GAAG;IACvC,MAAM,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;CACnD,CAAC;AASF,OAAO,CAAC,MAAM,CAAC;IACX,IAAI,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;;;;GAQG;AACH,qBAAa,SAAS;IACX,MAAM,EAAE,MAAM,CAA4B;IACjD,IAAI,EAAE,MAAM,CAAmB;IAC/B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,IAAI,CAAC,CAA0B;IACvC,OAAO,CAAC,gBAAgB,CAAC,CAAuC;IAChE,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAiC;IAC7D,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAA0D;IAEzF,OAAO;mBAWc,kBAAkB;IA0DvC;;;;;OAKG;WACU,IAAI,CACb,MAAM,GAAE,iBAAsB,EAC9B,QAAQ,CAAC,EAAE,OAAO,+BAA+B,EAAE,YAAY,GAChE,OAAO,CAAC,SAAS,CAAC;IAiIrB;;;;OAIG;WACU,cAAc,CAAC,OAAO,GAAE,4BAAiC,GAAG,OAAO,CAAC,SAAS,CAAC;IAiC3F,MAAM,CAAC,aAAa;IAKpB;;;;OAIG;IACH,MAAM,CAAC,GAAG,IAAI,SAAS;IAOvB;;;OAGG;IACH,MAAM,CAAC,iBAAiB,IAAI,OAAO;IAInC;;;;;OAKG;WACU,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5C;;;OAGG;IACI,aAAa,IAAI,OAAO;IAI/B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,GAAG,GAAE,OAA8B;IAc5F,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI;IAI/C;;;OAGG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxC;;;;;;;;;OASG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtC,OAAO,CAAC,oBAAoB;CAiB/B"}