@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.
- package/dist/agent/DextoAgent.cjs +27 -14
- package/dist/agent/DextoAgent.d.ts +7 -6
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +27 -14
- package/dist/approval/manager.cjs +328 -178
- package/dist/approval/manager.d.ts +39 -31
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +328 -178
- package/dist/approval/session-approval-store.cjs +91 -0
- package/dist/approval/session-approval-store.d.ts +55 -0
- package/dist/approval/session-approval-store.d.ts.map +1 -0
- package/dist/approval/session-approval-store.js +68 -0
- package/dist/llm/executor/turn-executor.cjs +7 -3
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +7 -3
- package/dist/llm/services/factory.cjs +10 -4
- package/dist/llm/services/factory.d.ts +2 -21
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +11 -7
- package/dist/llm/services/types.d.ts +33 -2
- package/dist/llm/services/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +4 -5
- package/dist/llm/services/vercel.d.ts +3 -3
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +2 -3
- package/dist/logger/default-logger-factory.d.ts +12 -12
- package/dist/logger/v2/schemas.d.ts +6 -6
- package/dist/mcp/schemas.d.ts +10 -10
- package/dist/session/chat-session.cjs +39 -41
- package/dist/session/chat-session.d.ts +22 -12
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +39 -41
- package/dist/session/message-queue-store.cjs +75 -0
- package/dist/session/message-queue-store.d.ts +16 -0
- package/dist/session/message-queue-store.d.ts.map +1 -0
- package/dist/session/message-queue-store.js +52 -0
- package/dist/session/message-queue.cjs +140 -46
- package/dist/session/message-queue.d.ts +18 -6
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +140 -46
- package/dist/session/session-manager.cjs +130 -25
- package/dist/session/session-manager.d.ts +18 -1
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +130 -25
- package/dist/session/title-generator.cjs +9 -2
- package/dist/session/title-generator.d.ts +2 -0
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +9 -2
- package/dist/telemetry/errors.cjs +2 -2
- package/dist/telemetry/errors.js +2 -2
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +3 -1
- package/dist/telemetry/telemetry.cjs +62 -21
- package/dist/telemetry/telemetry.d.ts +14 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +62 -21
- package/dist/test-utils/session-state-stores.cjs +68 -0
- package/dist/test-utils/session-state-stores.js +42 -0
- package/dist/tools/session-tool-preferences-store.cjs +86 -0
- package/dist/tools/session-tool-preferences-store.d.ts +29 -0
- package/dist/tools/session-tool-preferences-store.d.ts.map +1 -0
- package/dist/tools/session-tool-preferences-store.js +63 -0
- package/dist/tools/tool-manager.cjs +131 -32
- package/dist/tools/tool-manager.d.ts +17 -6
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +131 -32
- package/dist/utils/service-initializer.cjs +38 -5
- package/dist/utils/service-initializer.d.ts +11 -1
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +36 -4
- package/package.json +1 -1
|
@@ -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,
|
|
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
|
-
|
|
19
|
-
|
|
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,
|
|
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
|
-
|
|
247
|
-
|
|
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
|
-
|
|
140
|
-
this.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
this.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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
|
-
|
|
154
|
-
|
|
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.
|
|
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
|
-
|
|
330
|
-
|
|
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.
|
|
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
|
-
|
|
392
|
-
|
|
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(
|
|
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(
|
|
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) {
|