@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
@@ -8,17 +8,17 @@ class Telemetry {
8
8
  name = "dexto-service";
9
9
  _isInitialized = false;
10
10
  _sdk;
11
+ _shutdownHandler;
11
12
  static _initPromise;
12
13
  static _signalHandlers;
13
- constructor(config, enabled, sdk) {
14
+ constructor(config, options) {
14
15
  const serviceName = config.serviceName ?? "dexto-service";
15
16
  const tracerName = config.tracerName ?? serviceName;
16
17
  this.name = serviceName;
17
18
  this.tracer = trace.getTracer(tracerName);
18
- if (sdk) {
19
- this._sdk = sdk;
20
- }
21
- this._isInitialized = enabled && !!sdk;
19
+ this._sdk = options.sdk;
20
+ this._shutdownHandler = options.shutdown;
21
+ this._isInitialized = options.initialized;
22
22
  }
23
23
  static async buildTraceExporter(config) {
24
24
  const e = config?.export;
@@ -146,7 +146,10 @@ class Telemetry {
146
146
  process.once("SIGINT", sigint);
147
147
  Telemetry._signalHandlers = { sigterm, sigint };
148
148
  }
149
- globalThis.__TELEMETRY__ = new Telemetry(config, enabled, sdk);
149
+ globalThis.__TELEMETRY__ = new Telemetry(config, {
150
+ initialized: enabled && !!sdk,
151
+ ...sdk !== void 0 && { sdk }
152
+ });
150
153
  }
151
154
  return globalThis.__TELEMETRY__;
152
155
  })();
@@ -162,6 +165,38 @@ class Telemetry {
162
165
  );
163
166
  }
164
167
  }
168
+ /**
169
+ * Register a global telemetry instance after a host installs its own provider/exporter lifecycle.
170
+ *
171
+ * This keeps core instrumentation active without forcing the default Node SDK bootstrap path.
172
+ */
173
+ static async registerGlobal(options = {}) {
174
+ try {
175
+ if (globalThis.__TELEMETRY__) return globalThis.__TELEMETRY__;
176
+ if (Telemetry._initPromise) return Telemetry._initPromise;
177
+ const config = options.config ?? {};
178
+ const initialized = options.initialized ?? true;
179
+ Telemetry._initPromise = Promise.resolve().then(() => {
180
+ if (!globalThis.__TELEMETRY__) {
181
+ globalThis.__TELEMETRY__ = new Telemetry(config, {
182
+ initialized,
183
+ ...options.shutdown !== void 0 && { shutdown: options.shutdown }
184
+ });
185
+ }
186
+ return globalThis.__TELEMETRY__;
187
+ });
188
+ return await Telemetry._initPromise;
189
+ } catch (error) {
190
+ Telemetry._initPromise = void 0;
191
+ if (error instanceof DextoRuntimeError) {
192
+ throw error;
193
+ }
194
+ throw TelemetryError.initializationFailed(
195
+ error instanceof Error ? error.message : String(error),
196
+ error
197
+ );
198
+ }
199
+ }
165
200
  static getActiveSpan() {
166
201
  const span = trace.getActiveSpan();
167
202
  return span;
@@ -243,25 +278,31 @@ class Telemetry {
243
278
  * This ensures agent switching works even when telemetry export fails.
244
279
  */
245
280
  async shutdown() {
246
- if (this._sdk) {
247
- try {
281
+ try {
282
+ if (this._shutdownHandler) {
283
+ await this._shutdownHandler();
284
+ } else if (this._sdk) {
248
285
  await this._sdk.shutdown();
249
- } catch (error) {
250
- const errorMsg = error instanceof Error ? error.message : String(error);
251
- logger.warn(`Telemetry shutdown failed to flush spans (non-blocking): ${errorMsg}`);
252
- } finally {
253
- this._isInitialized = false;
254
- globalThis.__TELEMETRY__ = void 0;
255
- if (Telemetry._signalHandlers) {
256
- process.off("SIGTERM", Telemetry._signalHandlers.sigterm);
257
- process.off("SIGINT", Telemetry._signalHandlers.sigint);
258
- Telemetry._signalHandlers = void 0;
259
- }
260
- this._sdk = void 0;
261
- Telemetry._initPromise = void 0;
262
286
  }
287
+ } catch (error) {
288
+ const errorMsg = error instanceof Error ? error.message : String(error);
289
+ logger.warn(`Telemetry shutdown failed to flush spans (non-blocking): ${errorMsg}`);
290
+ } finally {
291
+ this.cleanupAfterShutdown();
263
292
  }
264
293
  }
294
+ cleanupAfterShutdown() {
295
+ this._isInitialized = false;
296
+ globalThis.__TELEMETRY__ = void 0;
297
+ if (Telemetry._signalHandlers) {
298
+ process.off("SIGTERM", Telemetry._signalHandlers.sigterm);
299
+ process.off("SIGINT", Telemetry._signalHandlers.sigint);
300
+ Telemetry._signalHandlers = void 0;
301
+ }
302
+ this._sdk = void 0;
303
+ this._shutdownHandler = void 0;
304
+ Telemetry._initPromise = void 0;
305
+ }
265
306
  }
266
307
  export {
267
308
  Telemetry
@@ -0,0 +1,68 @@
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 session_state_stores_exports = {};
20
+ __export(session_state_stores_exports, {
21
+ createInMemoryMessageQueueStore: () => createInMemoryMessageQueueStore,
22
+ createInMemorySessionApprovalStore: () => createInMemorySessionApprovalStore,
23
+ createInMemorySessionStateStorage: () => createInMemorySessionStateStorage,
24
+ createInMemorySessionToolPreferencesStore: () => createInMemorySessionToolPreferencesStore
25
+ });
26
+ module.exports = __toCommonJS(session_state_stores_exports);
27
+ var import_session_approval_store = require("../approval/session-approval-store.js");
28
+ var import_session_tool_preferences_store = require("../tools/session-tool-preferences-store.js");
29
+ var import_in_memory_storage = require("./in-memory-storage.js");
30
+ function createInMemorySessionStateStorage() {
31
+ const cache = (0, import_in_memory_storage.createInMemoryCache)();
32
+ const database = (0, import_in_memory_storage.createInMemoryDatabase)();
33
+ return {
34
+ getCache: () => cache,
35
+ getDatabase: () => database
36
+ };
37
+ }
38
+ function createInMemorySessionApprovalStore(logger, storageManager = createInMemorySessionStateStorage()) {
39
+ return new import_session_approval_store.SessionApprovalStore(storageManager, logger);
40
+ }
41
+ function createInMemorySessionToolPreferencesStore(logger, storageManager = createInMemorySessionStateStorage()) {
42
+ return new import_session_tool_preferences_store.SessionToolPreferencesStore(storageManager, logger);
43
+ }
44
+ function createInMemoryMessageQueueStore() {
45
+ const queues = /* @__PURE__ */ new Map();
46
+ return {
47
+ async load(sessionId) {
48
+ return structuredClone(queues.get(sessionId) ?? []);
49
+ },
50
+ async save(sessionId, queue) {
51
+ if (queue.length === 0) {
52
+ queues.delete(sessionId);
53
+ return;
54
+ }
55
+ queues.set(sessionId, structuredClone(queue));
56
+ },
57
+ async delete(sessionId) {
58
+ queues.delete(sessionId);
59
+ }
60
+ };
61
+ }
62
+ // Annotate the CommonJS export names for ESM import in node:
63
+ 0 && (module.exports = {
64
+ createInMemoryMessageQueueStore,
65
+ createInMemorySessionApprovalStore,
66
+ createInMemorySessionStateStorage,
67
+ createInMemorySessionToolPreferencesStore
68
+ });
@@ -0,0 +1,42 @@
1
+ import "../chunk-PTJYTZNU.js";
2
+ import { SessionApprovalStore } from "../approval/session-approval-store.js";
3
+ import { SessionToolPreferencesStore } from "../tools/session-tool-preferences-store.js";
4
+ import { createInMemoryCache, createInMemoryDatabase } from "./in-memory-storage.js";
5
+ function createInMemorySessionStateStorage() {
6
+ const cache = createInMemoryCache();
7
+ const database = createInMemoryDatabase();
8
+ return {
9
+ getCache: () => cache,
10
+ getDatabase: () => database
11
+ };
12
+ }
13
+ function createInMemorySessionApprovalStore(logger, storageManager = createInMemorySessionStateStorage()) {
14
+ return new SessionApprovalStore(storageManager, logger);
15
+ }
16
+ function createInMemorySessionToolPreferencesStore(logger, storageManager = createInMemorySessionStateStorage()) {
17
+ return new SessionToolPreferencesStore(storageManager, logger);
18
+ }
19
+ function createInMemoryMessageQueueStore() {
20
+ const queues = /* @__PURE__ */ new Map();
21
+ return {
22
+ async load(sessionId) {
23
+ return structuredClone(queues.get(sessionId) ?? []);
24
+ },
25
+ async save(sessionId, queue) {
26
+ if (queue.length === 0) {
27
+ queues.delete(sessionId);
28
+ return;
29
+ }
30
+ queues.set(sessionId, structuredClone(queue));
31
+ },
32
+ async delete(sessionId) {
33
+ queues.delete(sessionId);
34
+ }
35
+ };
36
+ }
37
+ export {
38
+ createInMemoryMessageQueueStore,
39
+ createInMemorySessionApprovalStore,
40
+ createInMemorySessionStateStorage,
41
+ createInMemorySessionToolPreferencesStore
42
+ };
@@ -0,0 +1,86 @@
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 session_tool_preferences_store_exports = {};
20
+ __export(session_tool_preferences_store_exports, {
21
+ SessionToolPreferencesStore: () => SessionToolPreferencesStore
22
+ });
23
+ module.exports = __toCommonJS(session_tool_preferences_store_exports);
24
+ var import_zod = require("zod");
25
+ const SessionToolPreferencesSchema = import_zod.z.object({
26
+ userAutoApproveTools: import_zod.z.array(import_zod.z.string()).default([]),
27
+ disabledTools: import_zod.z.array(import_zod.z.string()).default([])
28
+ }).strict();
29
+ const DEFAULT_SESSION_TOOL_PREFERENCES = {
30
+ userAutoApproveTools: [],
31
+ disabledTools: []
32
+ };
33
+ class SessionToolPreferencesStore {
34
+ constructor(storageManager, logger, options = {}) {
35
+ this.storageManager = storageManager;
36
+ this.logger = logger;
37
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
38
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
39
+ }
40
+ cacheTtlSeconds;
41
+ buildKey(sessionId) {
42
+ return `session-tool-preferences:${sessionId}`;
43
+ }
44
+ async load(sessionId) {
45
+ const key = this.buildKey(sessionId);
46
+ const cached = await this.storageManager.getCache().get(key);
47
+ if (cached !== void 0) {
48
+ return this.parsePreferences(cached, key);
49
+ }
50
+ const stored = await this.storageManager.getDatabase().get(key);
51
+ if (stored === void 0) {
52
+ return structuredClone(DEFAULT_SESSION_TOOL_PREFERENCES);
53
+ }
54
+ const parsed = this.parsePreferences(stored, key);
55
+ await this.storageManager.getCache().set(key, parsed, this.cacheTtlSeconds);
56
+ return parsed;
57
+ }
58
+ async save(sessionId, preferences) {
59
+ const key = this.buildKey(sessionId);
60
+ const normalized = SessionToolPreferencesSchema.parse(preferences);
61
+ await this.storageManager.getDatabase().set(key, normalized);
62
+ await this.storageManager.getCache().set(key, normalized, 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
+ parsePreferences(value, key) {
72
+ const result = SessionToolPreferencesSchema.safeParse(value);
73
+ if (result.success) {
74
+ return result.data;
75
+ }
76
+ this.logger.warn("Invalid persisted session tool preferences encountered; using defaults", {
77
+ key,
78
+ error: result.error.message
79
+ });
80
+ return structuredClone(DEFAULT_SESSION_TOOL_PREFERENCES);
81
+ }
82
+ }
83
+ // Annotate the CommonJS export names for ESM import in node:
84
+ 0 && (module.exports = {
85
+ SessionToolPreferencesStore
86
+ });
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import type { StorageManager } from '../storage/index.js';
3
+ import type { Logger } from '../logger/v2/types.js';
4
+ declare const SessionToolPreferencesSchema: z.ZodObject<{
5
+ userAutoApproveTools: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
6
+ disabledTools: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
7
+ }, "strict", z.ZodTypeAny, {
8
+ userAutoApproveTools: string[];
9
+ disabledTools: string[];
10
+ }, {
11
+ userAutoApproveTools?: string[] | undefined;
12
+ disabledTools?: string[] | undefined;
13
+ }>;
14
+ export type SessionToolPreferences = z.output<typeof SessionToolPreferencesSchema>;
15
+ export declare class SessionToolPreferencesStore {
16
+ private readonly storageManager;
17
+ private readonly logger;
18
+ private readonly cacheTtlSeconds;
19
+ constructor(storageManager: StorageManager, logger: Logger, options?: {
20
+ cacheTtlMs?: number;
21
+ });
22
+ private buildKey;
23
+ load(sessionId: string): Promise<SessionToolPreferences>;
24
+ save(sessionId: string, preferences: SessionToolPreferences): Promise<void>;
25
+ delete(sessionId: string): Promise<void>;
26
+ private parsePreferences;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=session-tool-preferences-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-tool-preferences-store.d.ts","sourceRoot":"","sources":["../../src/tools/session-tool-preferences-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,QAAA,MAAM,4BAA4B;;;;;;;;;EAKrB,CAAC;AAEd,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAOnF,qBAAa,2BAA2B;IAIhC,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,sBAAsB,CAAC;IAiBxD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO3E,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,OAAO,CAAC,gBAAgB;CAY3B"}
@@ -0,0 +1,63 @@
1
+ import "../chunk-PTJYTZNU.js";
2
+ import { z } from "zod";
3
+ const SessionToolPreferencesSchema = z.object({
4
+ userAutoApproveTools: z.array(z.string()).default([]),
5
+ disabledTools: z.array(z.string()).default([])
6
+ }).strict();
7
+ const DEFAULT_SESSION_TOOL_PREFERENCES = {
8
+ userAutoApproveTools: [],
9
+ disabledTools: []
10
+ };
11
+ class SessionToolPreferencesStore {
12
+ constructor(storageManager, logger, options = {}) {
13
+ this.storageManager = storageManager;
14
+ this.logger = logger;
15
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
16
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
17
+ }
18
+ cacheTtlSeconds;
19
+ buildKey(sessionId) {
20
+ return `session-tool-preferences:${sessionId}`;
21
+ }
22
+ async load(sessionId) {
23
+ const key = this.buildKey(sessionId);
24
+ const cached = await this.storageManager.getCache().get(key);
25
+ if (cached !== void 0) {
26
+ return this.parsePreferences(cached, key);
27
+ }
28
+ const stored = await this.storageManager.getDatabase().get(key);
29
+ if (stored === void 0) {
30
+ return structuredClone(DEFAULT_SESSION_TOOL_PREFERENCES);
31
+ }
32
+ const parsed = this.parsePreferences(stored, key);
33
+ await this.storageManager.getCache().set(key, parsed, this.cacheTtlSeconds);
34
+ return parsed;
35
+ }
36
+ async save(sessionId, preferences) {
37
+ const key = this.buildKey(sessionId);
38
+ const normalized = SessionToolPreferencesSchema.parse(preferences);
39
+ await this.storageManager.getDatabase().set(key, normalized);
40
+ await this.storageManager.getCache().set(key, normalized, 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
+ parsePreferences(value, key) {
50
+ const result = SessionToolPreferencesSchema.safeParse(value);
51
+ if (result.success) {
52
+ return result.data;
53
+ }
54
+ this.logger.warn("Invalid persisted session tool preferences encountered; using defaults", {
55
+ key,
56
+ error: result.error.message
57
+ });
58
+ return structuredClone(DEFAULT_SESSION_TOOL_PREFERENCES);
59
+ }
60
+ }
61
+ export {
62
+ SessionToolPreferencesStore
63
+ };
@@ -81,6 +81,24 @@ _ToolManager_decorators = [(0, import_decorators.InstrumentClass)({
81
81
  excludeMethods: ["setHookSupport", "getApprovalManager", "getAllowedToolsProvider"]
82
82
  })];
83
83
  let _ToolManager = class _ToolManager {
84
+ constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, tools, logger, sessionToolPreferencesStore) {
85
+ this.sessionToolPreferencesStore = sessionToolPreferencesStore;
86
+ this.mcpManager = mcpManager;
87
+ this.approvalManager = approvalManager;
88
+ this.allowedToolsProvider = allowedToolsProvider;
89
+ this.approvalMode = approvalMode;
90
+ this.agentEventBus = agentEventBus;
91
+ this.toolPolicies = toolPolicies;
92
+ this.logger = logger.createChild(import_types2.DextoLogComponent.TOOLS);
93
+ this.setTools(tools);
94
+ this.toolExecutionContextFactory = () => {
95
+ throw import_errors.ToolError.configInvalid(
96
+ "ToolExecutionContextFactory not configured. DextoAgent.start() must configure tool execution context before tools can run."
97
+ );
98
+ };
99
+ this.setupNotificationListeners();
100
+ this.logger.debug("ToolManager initialized");
101
+ }
84
102
  mcpManager;
85
103
  agentTools = /* @__PURE__ */ new Map();
86
104
  approvalManager;
@@ -113,6 +131,8 @@ let _ToolManager = class _ToolManager {
113
131
  // Session-level auto-approve tools set by users (UI)
114
132
  sessionUserAutoApproveTools = /* @__PURE__ */ new Map();
115
133
  sessionDisabledTools = /* @__PURE__ */ new Map();
134
+ restoredSessionPreferences = /* @__PURE__ */ new Set();
135
+ sessionPreferenceLocks = /* @__PURE__ */ new Map();
116
136
  globalDisabledTools = [];
117
137
  cleanupHandlers = /* @__PURE__ */ new Set();
118
138
  cleanupStarted = false;
@@ -136,22 +156,76 @@ let _ToolManager = class _ToolManager {
136
156
  }
137
157
  return this.resolveLocalToolIdOrAlias(pattern) ?? pattern;
138
158
  }
139
- constructor(mcpManager, approvalManager, allowedToolsProvider, approvalMode, agentEventBus, toolPolicies, tools, logger) {
140
- this.mcpManager = mcpManager;
141
- this.approvalManager = approvalManager;
142
- this.allowedToolsProvider = allowedToolsProvider;
143
- this.approvalMode = approvalMode;
144
- this.agentEventBus = agentEventBus;
145
- this.toolPolicies = toolPolicies;
146
- this.logger = logger.createChild(import_types2.DextoLogComponent.TOOLS);
147
- this.setTools(tools);
148
- this.toolExecutionContextFactory = () => {
149
- throw import_errors.ToolError.configInvalid(
150
- "ToolExecutionContextFactory not configured. DextoAgent.start() must configure tool execution context before tools can run."
151
- );
159
+ async runWithSessionPreferenceLock(sessionId, fn) {
160
+ const previousLock = this.sessionPreferenceLocks.get(sessionId) ?? Promise.resolve();
161
+ const currentResult = previousLock.catch(() => {
162
+ }).then(() => fn());
163
+ const currentLock = currentResult.then(
164
+ () => void 0,
165
+ () => void 0
166
+ );
167
+ this.sessionPreferenceLocks.set(sessionId, currentLock);
168
+ try {
169
+ return await currentResult;
170
+ } finally {
171
+ if (this.sessionPreferenceLocks.get(sessionId) === currentLock) {
172
+ this.sessionPreferenceLocks.delete(sessionId);
173
+ }
174
+ }
175
+ }
176
+ applySessionToolPreferences(sessionId, preferences) {
177
+ if (preferences.userAutoApproveTools.length > 0) {
178
+ this.sessionUserAutoApproveTools.set(sessionId, [...preferences.userAutoApproveTools]);
179
+ } else {
180
+ this.sessionUserAutoApproveTools.delete(sessionId);
181
+ }
182
+ if (preferences.disabledTools.length > 0) {
183
+ this.sessionDisabledTools.set(sessionId, [...preferences.disabledTools]);
184
+ } else {
185
+ this.sessionDisabledTools.delete(sessionId);
186
+ }
187
+ }
188
+ getSessionToolPreferencesSnapshot(sessionId) {
189
+ return {
190
+ userAutoApproveTools: [...this.sessionUserAutoApproveTools.get(sessionId) ?? []],
191
+ disabledTools: [...this.sessionDisabledTools.get(sessionId) ?? []]
152
192
  };
153
- this.setupNotificationListeners();
154
- this.logger.debug("ToolManager initialized");
193
+ }
194
+ async restoreSessionState(sessionId) {
195
+ if (this.restoredSessionPreferences.has(sessionId)) {
196
+ return;
197
+ }
198
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
199
+ if (this.restoredSessionPreferences.has(sessionId)) {
200
+ return;
201
+ }
202
+ const preferences = await this.sessionToolPreferencesStore.load(sessionId);
203
+ this.applySessionToolPreferences(sessionId, preferences);
204
+ this.restoredSessionPreferences.add(sessionId);
205
+ this.logger.debug("Restored persisted session tool preferences", {
206
+ sessionId,
207
+ autoApproveCount: preferences.userAutoApproveTools.length,
208
+ disabledCount: preferences.disabledTools.length
209
+ });
210
+ });
211
+ }
212
+ evictSessionState(sessionId) {
213
+ this.sessionAutoApproveTools.delete(sessionId);
214
+ this.sessionUserAutoApproveTools.delete(sessionId);
215
+ this.sessionDisabledTools.delete(sessionId);
216
+ this.restoredSessionPreferences.delete(sessionId);
217
+ }
218
+ async deleteSessionState(sessionId) {
219
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
220
+ this.evictSessionState(sessionId);
221
+ await this.sessionToolPreferencesStore.delete(sessionId);
222
+ });
223
+ }
224
+ async persistSessionToolPreferences(sessionId) {
225
+ await this.sessionToolPreferencesStore.save(
226
+ sessionId,
227
+ this.getSessionToolPreferencesSnapshot(sessionId)
228
+ );
155
229
  }
156
230
  /**
157
231
  * Initialize the ToolManager and its components
@@ -308,15 +382,19 @@ let _ToolManager = class _ToolManager {
308
382
  /**
309
383
  * Set session-level auto-approve tools chosen by the user.
310
384
  */
311
- setSessionUserAutoApproveTools(sessionId, autoApproveTools) {
385
+ async setSessionUserAutoApproveTools(sessionId, autoApproveTools) {
386
+ await this.restoreSessionState(sessionId);
312
387
  if (autoApproveTools.length === 0) {
313
- this.clearSessionUserAutoApproveTools(sessionId);
388
+ await this.clearSessionUserAutoApproveTools(sessionId);
314
389
  return;
315
390
  }
316
391
  const normalized = autoApproveTools.map(
317
392
  (pattern) => this.normalizeToolPolicyPattern(pattern)
318
393
  );
319
- this.sessionUserAutoApproveTools.set(sessionId, normalized);
394
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
395
+ this.sessionUserAutoApproveTools.set(sessionId, normalized);
396
+ await this.persistSessionToolPreferences(sessionId);
397
+ });
320
398
  this.logger.info(
321
399
  `Session user auto-approve tools set for '${sessionId}': ${autoApproveTools.length} tools`
322
400
  );
@@ -325,9 +403,14 @@ let _ToolManager = class _ToolManager {
325
403
  /**
326
404
  * Clear session-level auto-approve tools chosen by the user.
327
405
  */
328
- clearSessionUserAutoApproveTools(sessionId) {
329
- const hadAutoApprove = this.sessionUserAutoApproveTools.has(sessionId);
330
- this.sessionUserAutoApproveTools.delete(sessionId);
406
+ async clearSessionUserAutoApproveTools(sessionId) {
407
+ await this.restoreSessionState(sessionId);
408
+ let hadAutoApprove = false;
409
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
410
+ hadAutoApprove = this.sessionUserAutoApproveTools.has(sessionId);
411
+ this.sessionUserAutoApproveTools.delete(sessionId);
412
+ await this.persistSessionToolPreferences(sessionId);
413
+ });
331
414
  if (hadAutoApprove) {
332
415
  this.logger.info(`Session user auto-approve tools cleared for '${sessionId}'`);
333
416
  }
@@ -368,12 +451,16 @@ let _ToolManager = class _ToolManager {
368
451
  /**
369
452
  * Set session-level disabled tools (overrides global list).
370
453
  */
371
- setSessionDisabledTools(sessionId, toolNames) {
454
+ async setSessionDisabledTools(sessionId, toolNames) {
455
+ await this.restoreSessionState(sessionId);
372
456
  if (toolNames.length === 0) {
373
- this.clearSessionDisabledTools(sessionId);
457
+ await this.clearSessionDisabledTools(sessionId);
374
458
  return;
375
459
  }
376
- this.sessionDisabledTools.set(sessionId, [...toolNames]);
460
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
461
+ this.sessionDisabledTools.set(sessionId, [...toolNames]);
462
+ await this.persistSessionToolPreferences(sessionId);
463
+ });
377
464
  this.logger.info("Session disabled tools updated", {
378
465
  sessionId,
379
466
  count: toolNames.length
@@ -387,9 +474,14 @@ let _ToolManager = class _ToolManager {
387
474
  /**
388
475
  * Clear session-level disabled tools.
389
476
  */
390
- clearSessionDisabledTools(sessionId) {
391
- const hadOverrides = this.sessionDisabledTools.has(sessionId);
392
- this.sessionDisabledTools.delete(sessionId);
477
+ async clearSessionDisabledTools(sessionId) {
478
+ await this.restoreSessionState(sessionId);
479
+ let hadOverrides = false;
480
+ await this.runWithSessionPreferenceLock(sessionId, async () => {
481
+ hadOverrides = this.sessionDisabledTools.has(sessionId);
482
+ this.sessionDisabledTools.delete(sessionId);
483
+ await this.persistSessionToolPreferences(sessionId);
484
+ });
393
485
  if (hadOverrides) {
394
486
  this.logger.info("Session disabled tools cleared", { sessionId });
395
487
  }
@@ -789,7 +881,7 @@ let _ToolManager = class _ToolManager {
789
881
  return false;
790
882
  }
791
883
  if (!patternKey) return false;
792
- return this.approvalManager.matchesPattern(toolName, patternKey);
884
+ return this.approvalManager.matchesPattern(toolName, patternKey, sessionId);
793
885
  },
794
886
  { rememberPattern: void 0 }
795
887
  // Don't propagate pattern choice to auto-approved requests
@@ -820,7 +912,10 @@ let _ToolManager = class _ToolManager {
820
912
  if (!directoryAccess) {
821
913
  return false;
822
914
  }
823
- return this.approvalManager.isDirectorySessionApproved(directoryAccess.parentDir);
915
+ return this.approvalManager.isDirectorySessionApproved(
916
+ directoryAccess.parentDir,
917
+ sessionId
918
+ );
824
919
  },
825
920
  { rememberDirectory: false }
826
921
  );
@@ -1470,7 +1565,11 @@ let _ToolManager = class _ToolManager {
1470
1565
  async tryQuickApprovalResolution(toolName, args, sessionId, directoryAccess) {
1471
1566
  if (directoryAccess) {
1472
1567
  if (this.approvalMode === "auto-approve") {
1473
- this.approvalManager.addApprovedDirectory(directoryAccess.parentDir, "once");
1568
+ await this.approvalManager.addApprovedDirectory(
1569
+ directoryAccess.parentDir,
1570
+ "once",
1571
+ sessionId
1572
+ );
1474
1573
  return { requireApproval: false };
1475
1574
  }
1476
1575
  return null;
@@ -1494,7 +1593,7 @@ let _ToolManager = class _ToolManager {
1494
1593
  return { requireApproval: false };
1495
1594
  }
1496
1595
  const patternKey = this.getToolPatternKey(toolName, args);
1497
- if (patternKey && this.approvalManager.matchesPattern(toolName, patternKey)) {
1596
+ if (patternKey && this.approvalManager.matchesPattern(toolName, patternKey, sessionId)) {
1498
1597
  this.logger.info(
1499
1598
  `Tool '${toolName}' matched approved pattern key '${patternKey}' \u2013 skipping confirmation.`
1500
1599
  );
@@ -1604,7 +1703,7 @@ let _ToolManager = class _ToolManager {
1604
1703
  );
1605
1704
  this.autoApprovePendingToolRequests(toolName, allowSessionId);
1606
1705
  } else if (rememberPattern && this.getToolApprovalPatternKeyFn(toolName)) {
1607
- this.approvalManager.addPattern(toolName, rememberPattern);
1706
+ await this.approvalManager.addPattern(toolName, rememberPattern, sessionId);
1608
1707
  this.logger.info(`Pattern '${rememberPattern}' added for tool '${toolName}' approval`);
1609
1708
  this.autoApprovePendingPatternRequests(toolName, sessionId);
1610
1709
  } else if (rememberDirectory) {