@dexto/core 1.6.17 → 1.6.19

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 (77) hide show
  1. package/dist/agent/DextoAgent.cjs +63 -9
  2. package/dist/agent/DextoAgent.d.ts +11 -1
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +56 -2
  5. package/dist/agent/runtime-config.d.ts +2 -0
  6. package/dist/agent/runtime-config.d.ts.map +1 -1
  7. package/dist/approval/index.cjs +6 -0
  8. package/dist/approval/index.d.ts +1 -1
  9. package/dist/approval/index.d.ts.map +1 -1
  10. package/dist/approval/index.js +11 -1
  11. package/dist/approval/schemas.cjs +3 -3
  12. package/dist/approval/schemas.d.ts +107 -108
  13. package/dist/approval/schemas.d.ts.map +1 -1
  14. package/dist/approval/schemas.js +4 -4
  15. package/dist/approval/types.cjs +75 -27
  16. package/dist/approval/types.d.ts +30 -21
  17. package/dist/approval/types.d.ts.map +1 -1
  18. package/dist/approval/types.js +72 -27
  19. package/dist/index.browser.cjs +6 -0
  20. package/dist/index.browser.d.ts +1 -1
  21. package/dist/index.browser.d.ts.map +1 -1
  22. package/dist/index.browser.js +11 -1
  23. package/dist/llm/executor/stream-processor.cjs +2 -2
  24. package/dist/llm/executor/stream-processor.d.ts +1 -0
  25. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  26. package/dist/llm/executor/stream-processor.js +2 -2
  27. package/dist/llm/executor/turn-executor.cjs +3 -0
  28. package/dist/llm/executor/turn-executor.d.ts +1 -0
  29. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  30. package/dist/llm/executor/turn-executor.js +3 -0
  31. package/dist/llm/services/factory.cjs +12 -1
  32. package/dist/llm/services/factory.d.ts +10 -3
  33. package/dist/llm/services/factory.d.ts.map +1 -1
  34. package/dist/llm/services/factory.js +12 -1
  35. package/dist/llm/services/vercel.cjs +4 -1
  36. package/dist/llm/services/vercel.d.ts +2 -1
  37. package/dist/llm/services/vercel.d.ts.map +1 -1
  38. package/dist/llm/services/vercel.js +4 -1
  39. package/dist/llm/usage-scope.cjs +4 -13
  40. package/dist/llm/usage-scope.d.ts +3 -2
  41. package/dist/llm/usage-scope.d.ts.map +1 -1
  42. package/dist/llm/usage-scope.js +3 -11
  43. package/dist/mcp/bundled-config.cjs +206 -0
  44. package/dist/mcp/bundled-config.d.ts +10 -0
  45. package/dist/mcp/bundled-config.d.ts.map +1 -0
  46. package/dist/mcp/bundled-config.js +173 -0
  47. package/dist/mcp/index.cjs +43 -15
  48. package/dist/mcp/index.d.ts +11 -7
  49. package/dist/mcp/index.d.ts.map +1 -1
  50. package/dist/mcp/index.js +35 -7
  51. package/dist/prompts/providers/config-prompt-provider.cjs +15 -1
  52. package/dist/prompts/providers/config-prompt-provider.d.ts.map +1 -1
  53. package/dist/prompts/providers/config-prompt-provider.js +15 -1
  54. package/dist/session/chat-session.cjs +13 -4
  55. package/dist/session/chat-session.d.ts +1 -0
  56. package/dist/session/chat-session.d.ts.map +1 -1
  57. package/dist/session/chat-session.js +13 -4
  58. package/dist/session/session-manager.cjs +140 -67
  59. package/dist/session/session-manager.d.ts +8 -1
  60. package/dist/session/session-manager.d.ts.map +1 -1
  61. package/dist/session/session-manager.js +142 -67
  62. package/dist/systemPrompt/manager.cjs +7 -1
  63. package/dist/systemPrompt/manager.d.ts.map +1 -1
  64. package/dist/systemPrompt/manager.js +7 -1
  65. package/dist/systemPrompt/schemas.cjs +7 -0
  66. package/dist/systemPrompt/schemas.d.ts +14 -0
  67. package/dist/systemPrompt/schemas.d.ts.map +1 -1
  68. package/dist/systemPrompt/schemas.js +6 -0
  69. package/dist/systemPrompt/types.d.ts +2 -0
  70. package/dist/systemPrompt/types.d.ts.map +1 -1
  71. package/dist/tools/tool-manager.cjs +20 -1
  72. package/dist/tools/tool-manager.d.ts.map +1 -1
  73. package/dist/tools/tool-manager.js +21 -2
  74. package/dist/utils/execution-context.cjs +26 -0
  75. package/dist/utils/execution-context.d.ts.map +1 -1
  76. package/dist/utils/execution-context.js +27 -1
  77. package/package.json +4 -3
@@ -3,6 +3,10 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
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
+ };
6
10
  var __copyProps = (to, from, except, desc) => {
7
11
  if (from && typeof from === "object" || typeof from === "function") {
8
12
  for (let key of __getOwnPropNames(from))
@@ -11,24 +15,48 @@ var __copyProps = (to, from, except, desc) => {
11
15
  }
12
16
  return to;
13
17
  };
14
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
19
  var mcp_exports = {};
20
+ __export(mcp_exports, {
21
+ DEFAULT_MCP_CONNECTION_MODE: () => import_schemas.DEFAULT_MCP_CONNECTION_MODE,
22
+ DextoMcpClient: () => import_mcp_client.DextoMcpClient,
23
+ HttpServerConfigSchema: () => import_schemas.HttpServerConfigSchema,
24
+ MCPError: () => import_errors.MCPError,
25
+ MCPErrorCode: () => import_error_codes.MCPErrorCode,
26
+ MCPManager: () => import_manager.MCPManager,
27
+ MCP_CONNECTION_MODES: () => import_schemas.MCP_CONNECTION_MODES,
28
+ MCP_CONNECTION_STATUSES: () => import_schemas.MCP_CONNECTION_STATUSES,
29
+ MCP_SERVER_TYPES: () => import_schemas.MCP_SERVER_TYPES,
30
+ McpServerConfigSchema: () => import_schemas.McpServerConfigSchema,
31
+ ServersConfigSchema: () => import_schemas.ServersConfigSchema,
32
+ SseServerConfigSchema: () => import_schemas.SseServerConfigSchema,
33
+ StdioServerConfigSchema: () => import_schemas.StdioServerConfigSchema,
34
+ loadBundledMcpConfigFromDirectory: () => import_bundled_config.loadBundledMcpConfigFromDirectory,
35
+ resolveAndValidateMcpServerConfig: () => import_resolver.resolveAndValidateMcpServerConfig
36
+ });
17
37
  module.exports = __toCommonJS(mcp_exports);
18
- __reExport(mcp_exports, require("./manager.js"), module.exports);
19
- __reExport(mcp_exports, require("./mcp-client.js"), module.exports);
20
- __reExport(mcp_exports, require("./types.js"), module.exports);
21
- __reExport(mcp_exports, require("./schemas.js"), module.exports);
22
- __reExport(mcp_exports, require("./errors.js"), module.exports);
23
- __reExport(mcp_exports, require("./error-codes.js"), module.exports);
24
- __reExport(mcp_exports, require("./resolver.js"), module.exports);
38
+ var import_manager = require("./manager.js");
39
+ var import_mcp_client = require("./mcp-client.js");
40
+ var import_schemas = require("./schemas.js");
41
+ var import_errors = require("./errors.js");
42
+ var import_error_codes = require("./error-codes.js");
43
+ var import_resolver = require("./resolver.js");
44
+ var import_bundled_config = require("./bundled-config.js");
25
45
  // Annotate the CommonJS export names for ESM import in node:
26
46
  0 && (module.exports = {
27
- ...require("./manager.js"),
28
- ...require("./mcp-client.js"),
29
- ...require("./types.js"),
30
- ...require("./schemas.js"),
31
- ...require("./errors.js"),
32
- ...require("./error-codes.js"),
33
- ...require("./resolver.js")
47
+ DEFAULT_MCP_CONNECTION_MODE,
48
+ DextoMcpClient,
49
+ HttpServerConfigSchema,
50
+ MCPError,
51
+ MCPErrorCode,
52
+ MCPManager,
53
+ MCP_CONNECTION_MODES,
54
+ MCP_CONNECTION_STATUSES,
55
+ MCP_SERVER_TYPES,
56
+ McpServerConfigSchema,
57
+ ServersConfigSchema,
58
+ SseServerConfigSchema,
59
+ StdioServerConfigSchema,
60
+ loadBundledMcpConfigFromDirectory,
61
+ resolveAndValidateMcpServerConfig
34
62
  });
@@ -1,8 +1,12 @@
1
- export * from './manager.js';
2
- export * from './mcp-client.js';
3
- export * from './types.js';
4
- export * from './schemas.js';
5
- export * from './errors.js';
6
- export * from './error-codes.js';
7
- export * from './resolver.js';
1
+ export { MCPManager } from './manager.js';
2
+ export { DextoMcpClient } from './mcp-client.js';
3
+ export type { McpAuthProvider, McpAuthProviderFactory, MCPResourceSummary, MCPResolvedResource, McpClient, } from './types.js';
4
+ export { MCP_SERVER_TYPES, MCP_CONNECTION_MODES, MCP_CONNECTION_STATUSES, DEFAULT_MCP_CONNECTION_MODE, StdioServerConfigSchema, SseServerConfigSchema, HttpServerConfigSchema, McpServerConfigSchema, ServersConfigSchema, } from './schemas.js';
5
+ export type { McpServerType, McpConnectionMode, McpConnectionStatus, McpServerStatus, StdioServerConfig, ValidatedStdioServerConfig, SseServerConfig, ValidatedSseServerConfig, HttpServerConfig, ValidatedHttpServerConfig, McpServerConfig, ValidatedMcpServerConfig, ServersConfig, ValidatedServersConfig, } from './schemas.js';
6
+ export { MCPError } from './errors.js';
7
+ export { MCPErrorCode } from './error-codes.js';
8
+ export { resolveAndValidateMcpServerConfig } from './resolver.js';
9
+ export type { McpServerContext } from './resolver.js';
10
+ export { loadBundledMcpConfigFromDirectory } from './bundled-config.js';
11
+ export type { LoadBundledMcpConfigOptions, LoadBundledMcpConfigResult } from './bundled-config.js';
8
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EACR,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,SAAS,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,2BAA2B,EAC3B,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,GACtB,MAAM,cAAc,CAAC;AACtB,YAAY,EACR,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,0BAA0B,EAC1B,eAAe,EACf,wBAAwB,EACxB,gBAAgB,EAChB,yBAAyB,EACzB,eAAe,EACf,wBAAwB,EACxB,aAAa,EACb,sBAAsB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,iCAAiC,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/mcp/index.js CHANGED
@@ -1,7 +1,35 @@
1
- export * from "./manager.js";
2
- export * from "./mcp-client.js";
3
- export * from "./types.js";
4
- export * from "./schemas.js";
5
- export * from "./errors.js";
6
- export * from "./error-codes.js";
7
- export * from "./resolver.js";
1
+ import "../chunk-PTJYTZNU.js";
2
+ import { MCPManager } from "./manager.js";
3
+ import { DextoMcpClient } from "./mcp-client.js";
4
+ import {
5
+ MCP_SERVER_TYPES,
6
+ MCP_CONNECTION_MODES,
7
+ MCP_CONNECTION_STATUSES,
8
+ DEFAULT_MCP_CONNECTION_MODE,
9
+ StdioServerConfigSchema,
10
+ SseServerConfigSchema,
11
+ HttpServerConfigSchema,
12
+ McpServerConfigSchema,
13
+ ServersConfigSchema
14
+ } from "./schemas.js";
15
+ import { MCPError } from "./errors.js";
16
+ import { MCPErrorCode } from "./error-codes.js";
17
+ import { resolveAndValidateMcpServerConfig } from "./resolver.js";
18
+ import { loadBundledMcpConfigFromDirectory } from "./bundled-config.js";
19
+ export {
20
+ DEFAULT_MCP_CONNECTION_MODE,
21
+ DextoMcpClient,
22
+ HttpServerConfigSchema,
23
+ MCPError,
24
+ MCPErrorCode,
25
+ MCPManager,
26
+ MCP_CONNECTION_MODES,
27
+ MCP_CONNECTION_STATUSES,
28
+ MCP_SERVER_TYPES,
29
+ McpServerConfigSchema,
30
+ ServersConfigSchema,
31
+ SseServerConfigSchema,
32
+ StdioServerConfigSchema,
33
+ loadBundledMcpConfigFromDirectory,
34
+ resolveAndValidateMcpServerConfig
35
+ };
@@ -26,6 +26,7 @@ var import_types = require("../../logger/v2/types.js");
26
26
  var import_errors = require("../errors.js");
27
27
  var import_utils = require("../utils.js");
28
28
  var import_name_validation = require("../name-validation.js");
29
+ var import_bundled_config = require("../../mcp/bundled-config.js");
29
30
  var import_promises = require("fs/promises");
30
31
  var import_fs = require("fs");
31
32
  var import_path = require("path");
@@ -223,6 +224,16 @@ class ConfigPromptProvider {
223
224
  const model = prompt.model ?? parsed.model;
224
225
  const context = prompt.context ?? parsed.context;
225
226
  const agent = prompt.agent ?? parsed.agent;
227
+ const bundledMcpResult = (0, import_bundled_config.loadBundledMcpConfigFromDirectory)(
228
+ (0, import_path.dirname)(filePath),
229
+ parsed.id,
230
+ {
231
+ scanNestedMcps: true
232
+ }
233
+ );
234
+ for (const warning of bundledMcpResult.warnings) {
235
+ this.logger.warn(warning);
236
+ }
226
237
  const displayName = parsed.id;
227
238
  const promptName = prompt.namespace ? `config:${prompt.namespace}:${parsed.id}` : `config:${parsed.id}`;
228
239
  const promptInfo = {
@@ -248,7 +259,10 @@ class ConfigPromptProvider {
248
259
  showInStarters: prompt.showInStarters,
249
260
  originalId: parsed.id,
250
261
  ...prompt.namespace && { namespace: prompt.namespace },
251
- ...parsed.toolkits !== void 0 && { toolkits: parsed.toolkits }
262
+ ...parsed.toolkits !== void 0 && { toolkits: parsed.toolkits },
263
+ ...bundledMcpResult.mcpServers !== void 0 && {
264
+ mcpServers: bundledMcpResult.mcpServers
265
+ }
252
266
  }
253
267
  };
254
268
  return { info: promptInfo, content: parsed.content };
@@ -1 +1 @@
1
- {"version":3,"file":"config-prompt-provider.d.ts","sourceRoot":"","sources":["../../../src/prompts/providers/config-prompt-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAc,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AASvD;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACvD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAS;gBAEX,WAAW,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;IAM7D,SAAS,IAAI,MAAM;IAInB,eAAe,IAAI,IAAI;IAOvB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAYrC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAUxD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAgCjF,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAgC3D,iBAAiB;IAsC/B,OAAO,CAAC,mBAAmB;YA8Bb,iBAAiB;IAkG/B,OAAO,CAAC,mBAAmB;IAuL3B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,cAAc;CA+BzB"}
1
+ {"version":3,"file":"config-prompt-provider.d.ts","sourceRoot":"","sources":["../../../src/prompts/providers/config-prompt-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAc,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAUvD;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,YAAW,cAAc;IACvD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAS;gBAEX,WAAW,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;IAM7D,SAAS,IAAI,MAAM;IAInB,eAAe,IAAI,IAAI;IAOvB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAYrC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAUxD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAgCjF,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAgC3D,iBAAiB;IAsC/B,OAAO,CAAC,mBAAmB;YA8Bb,iBAAiB;IAgH/B,OAAO,CAAC,mBAAmB;IAuL3B,OAAO,CAAC,iBAAiB;IAyBzB,OAAO,CAAC,cAAc;CA+BzB"}
@@ -4,6 +4,7 @@ import { DextoLogComponent } from "../../logger/v2/types.js";
4
4
  import { PromptError } from "../errors.js";
5
5
  import { expandPlaceholders } from "../utils.js";
6
6
  import { assertValidPromptName } from "../name-validation.js";
7
+ import { loadBundledMcpConfigFromDirectory } from "../../mcp/bundled-config.js";
7
8
  import { readFile, realpath } from "fs/promises";
8
9
  import { existsSync } from "fs";
9
10
  import { basename, dirname, relative, sep } from "path";
@@ -201,6 +202,16 @@ class ConfigPromptProvider {
201
202
  const model = prompt.model ?? parsed.model;
202
203
  const context = prompt.context ?? parsed.context;
203
204
  const agent = prompt.agent ?? parsed.agent;
205
+ const bundledMcpResult = loadBundledMcpConfigFromDirectory(
206
+ dirname(filePath),
207
+ parsed.id,
208
+ {
209
+ scanNestedMcps: true
210
+ }
211
+ );
212
+ for (const warning of bundledMcpResult.warnings) {
213
+ this.logger.warn(warning);
214
+ }
204
215
  const displayName = parsed.id;
205
216
  const promptName = prompt.namespace ? `config:${prompt.namespace}:${parsed.id}` : `config:${parsed.id}`;
206
217
  const promptInfo = {
@@ -226,7 +237,10 @@ class ConfigPromptProvider {
226
237
  showInStarters: prompt.showInStarters,
227
238
  originalId: parsed.id,
228
239
  ...prompt.namespace && { namespace: prompt.namespace },
229
- ...parsed.toolkits !== void 0 && { toolkits: parsed.toolkits }
240
+ ...parsed.toolkits !== void 0 && { toolkits: parsed.toolkits },
241
+ ...bundledMcpResult.mcpServers !== void 0 && {
242
+ mcpServers: bundledMcpResult.mcpServers
243
+ }
230
244
  }
231
245
  };
232
246
  return { info: promptInfo, content: parsed.content };
@@ -166,6 +166,7 @@ class ChatSession {
166
166
  async initializeServices() {
167
167
  const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
168
168
  const llmConfig = runtimeConfig.llm;
169
+ const workspace = await this.services.workspaceManager?.getWorkspace();
169
170
  this.historyProvider = (0, import_factory.createDatabaseHistoryProvider)(
170
171
  this.services.storageManager.getDatabase(),
171
172
  this.id,
@@ -185,8 +186,11 @@ class ChatSession {
185
186
  // Pass ResourceManager for blob storage
186
187
  this.logger,
187
188
  // Pass logger for dependency injection
188
- compactionStrategy
189
- // Pass compaction strategy
189
+ {
190
+ usageScopeId: runtimeConfig.usageScopeId,
191
+ compactionStrategy,
192
+ cwd: workspace?.path
193
+ }
190
194
  );
191
195
  this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
192
196
  }
@@ -472,6 +476,8 @@ class ChatSession {
472
476
  */
473
477
  async switchLLM(newLLMConfig) {
474
478
  try {
479
+ const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
480
+ const workspace = await this.services.workspaceManager?.getWorkspace();
475
481
  const compactionStrategy = this.services.compactionStrategy;
476
482
  const newLLMService = (0, import_factory2.createLLMService)(
477
483
  newLLMConfig,
@@ -484,8 +490,11 @@ class ChatSession {
484
490
  this.id,
485
491
  this.services.resourceManager,
486
492
  this.logger,
487
- compactionStrategy
488
- // Pass compaction strategy
493
+ {
494
+ usageScopeId: runtimeConfig.usageScopeId,
495
+ compactionStrategy,
496
+ cwd: workspace?.path
497
+ }
489
498
  );
490
499
  this.llmService = newLLMService;
491
500
  this.logger.info(
@@ -121,6 +121,7 @@ export declare class ChatSession {
121
121
  hookManager: HookManager;
122
122
  mcpManager: MCPManager;
123
123
  sessionManager: import('./session-manager.js').SessionManager;
124
+ workspaceManager?: import('../workspace/manager.js').WorkspaceManager;
124
125
  compactionStrategy: CompactionStrategy | null;
125
126
  }, id: string, logger: Logger);
126
127
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/session/chat-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/session/chat-session.ts"],"names":[],"mappings":"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"}
@@ -147,6 +147,7 @@ class ChatSession {
147
147
  async initializeServices() {
148
148
  const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
149
149
  const llmConfig = runtimeConfig.llm;
150
+ const workspace = await this.services.workspaceManager?.getWorkspace();
150
151
  this.historyProvider = createDatabaseHistoryProvider(
151
152
  this.services.storageManager.getDatabase(),
152
153
  this.id,
@@ -166,8 +167,11 @@ class ChatSession {
166
167
  // Pass ResourceManager for blob storage
167
168
  this.logger,
168
169
  // Pass logger for dependency injection
169
- compactionStrategy
170
- // Pass compaction strategy
170
+ {
171
+ usageScopeId: runtimeConfig.usageScopeId,
172
+ compactionStrategy,
173
+ cwd: workspace?.path
174
+ }
171
175
  );
172
176
  this.logger.debug(`ChatSession ${this.id}: Services initialized with storage`);
173
177
  }
@@ -453,6 +457,8 @@ class ChatSession {
453
457
  */
454
458
  async switchLLM(newLLMConfig) {
455
459
  try {
460
+ const runtimeConfig = this.services.stateManager.getRuntimeConfig(this.id);
461
+ const workspace = await this.services.workspaceManager?.getWorkspace();
456
462
  const compactionStrategy = this.services.compactionStrategy;
457
463
  const newLLMService = createLLMService(
458
464
  newLLMConfig,
@@ -465,8 +471,11 @@ class ChatSession {
465
471
  this.id,
466
472
  this.services.resourceManager,
467
473
  this.logger,
468
- compactionStrategy
469
- // Pass compaction strategy
474
+ {
475
+ usageScopeId: runtimeConfig.usageScopeId,
476
+ compactionStrategy,
477
+ cwd: workspace?.path
478
+ }
470
479
  );
471
480
  this.llmService = newLLMService;
472
481
  this.logger.info(
@@ -35,6 +35,8 @@ var import_crypto = require("crypto");
35
35
  var import_chat_session = require("./chat-session.js");
36
36
  var import_types = require("../logger/v2/types.js");
37
37
  var import_errors = require("./errors.js");
38
+ var import_zod = require("zod");
39
+ var import_schemas = require("../systemPrompt/schemas.js");
38
40
  function defaultSessionLoggerFactory(options) {
39
41
  return options.baseLogger.createChild(import_types.DextoLogComponent.SESSION);
40
42
  }
@@ -54,8 +56,8 @@ class SessionManager {
54
56
  initializationPromise;
55
57
  // Add a Map to track ongoing session creation operations to prevent race conditions
56
58
  pendingCreations = /* @__PURE__ */ new Map();
57
- // Per-session mutex for token usage updates to prevent lost updates from concurrent calls
58
- tokenUsageLocks = /* @__PURE__ */ new Map();
59
+ // Per-session mutex for any SessionData read-modify-write path.
60
+ sessionDataLocks = /* @__PURE__ */ new Map();
59
61
  logger;
60
62
  static FORK_HISTORY_BATCH_SIZE = 500;
61
63
  static FORK_ID_GENERATION_MAX_ATTEMPTS = 5;
@@ -183,8 +185,15 @@ class SessionManager {
183
185
  lastActivity: now,
184
186
  messageCount: parentSessionData.messageCount,
185
187
  parentSessionId,
186
- metadata: {
187
- title: childTitle
188
+ ...parentSessionData.metadata !== void 0 ? {
189
+ metadata: {
190
+ ...parentSessionData.metadata,
191
+ title: childTitle
192
+ }
193
+ } : {
194
+ metadata: {
195
+ title: childTitle
196
+ }
188
197
  },
189
198
  ...parentSessionData.workspaceId !== void 0 && {
190
199
  workspaceId: parentSessionData.workspaceId
@@ -460,14 +469,15 @@ class SessionManager {
460
469
  throw import_errors.SessionError.notFound(sessionId);
461
470
  }
462
471
  await session.reset();
463
- const sessionKey = `session:${sessionId}`;
464
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
465
- if (sessionData) {
472
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
473
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
474
+ if (!sessionData) {
475
+ return;
476
+ }
466
477
  sessionData.messageCount = 0;
467
478
  sessionData.lastActivity = Date.now();
468
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
469
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
470
- }
479
+ await this.persistSessionData(sessionKey, sessionData);
480
+ });
471
481
  this.logger.debug(`Reset session conversation: ${sessionId}`);
472
482
  }
473
483
  /**
@@ -508,11 +518,69 @@ class SessionManager {
508
518
  ...sessionData.usageTracking && { usageTracking: sessionData.usageTracking }
509
519
  };
510
520
  }
511
- async markUntrackedChatGPTLoginUsage(sessionId) {
521
+ async getSessionSystemPromptContributors(sessionId) {
512
522
  await this.ensureInitialized();
513
523
  const sessionKey = `session:${sessionId}`;
514
- const previousLock = this.tokenUsageLocks.get(sessionKey) ?? Promise.resolve();
515
- const currentLock = previousLock.then(async () => {
524
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
525
+ if (!sessionData) {
526
+ throw import_errors.SessionError.notFound(sessionId);
527
+ }
528
+ return this.parseSessionPromptContributors(sessionId, sessionData);
529
+ }
530
+ async upsertSessionSystemPromptContributor(sessionId, contributor) {
531
+ await this.ensureInitialized();
532
+ return await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
533
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
534
+ if (!sessionData) {
535
+ throw import_errors.SessionError.notFound(sessionId);
536
+ }
537
+ const existing = this.parseSessionPromptContributors(sessionId, sessionData);
538
+ const next = existing.filter((entry) => entry.id !== contributor.id);
539
+ const replaced = next.length !== existing.length;
540
+ next.push(contributor);
541
+ next.sort((left, right) => left.priority - right.priority);
542
+ sessionData.metadata = sessionData.metadata || {};
543
+ sessionData.metadata.systemPromptContributors = next;
544
+ sessionData.lastActivity = Date.now();
545
+ await this.persistSessionData(sessionKey, sessionData);
546
+ return replaced;
547
+ });
548
+ }
549
+ async removeSessionSystemPromptContributor(sessionId, contributorId) {
550
+ await this.ensureInitialized();
551
+ return await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
552
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
553
+ if (!sessionData) {
554
+ throw import_errors.SessionError.notFound(sessionId);
555
+ }
556
+ const existing = this.parseSessionPromptContributors(sessionId, sessionData);
557
+ const next = existing.filter((entry) => entry.id !== contributorId);
558
+ const removed = next.length !== existing.length;
559
+ if (!removed) {
560
+ return false;
561
+ }
562
+ sessionData.metadata = sessionData.metadata || {};
563
+ sessionData.metadata.systemPromptContributors = next;
564
+ sessionData.lastActivity = Date.now();
565
+ await this.persistSessionData(sessionKey, sessionData);
566
+ return true;
567
+ });
568
+ }
569
+ parseSessionPromptContributors(sessionId, sessionData) {
570
+ try {
571
+ return import_schemas.SessionPromptContributorSchema.array().parse(
572
+ sessionData.metadata?.systemPromptContributors ?? []
573
+ );
574
+ } catch (error) {
575
+ if (error instanceof import_zod.ZodError) {
576
+ throw import_errors.SessionError.storageFailed(sessionId, "read", error.message);
577
+ }
578
+ throw error;
579
+ }
580
+ }
581
+ async markUntrackedChatGPTLoginUsage(sessionId) {
582
+ await this.ensureInitialized();
583
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
516
584
  const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
517
585
  if (!sessionData || sessionData.usageTracking?.hasUntrackedChatGPTLoginUsage) {
518
586
  return;
@@ -521,17 +589,8 @@ class SessionManager {
521
589
  ...sessionData.usageTracking ?? {},
522
590
  hasUntrackedChatGPTLoginUsage: true
523
591
  };
524
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
525
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
592
+ await this.persistSessionData(sessionKey, sessionData);
526
593
  });
527
- this.tokenUsageLocks.set(sessionKey, currentLock);
528
- try {
529
- await currentLock;
530
- } finally {
531
- if (this.tokenUsageLocks.get(sessionKey) === currentLock) {
532
- this.tokenUsageLocks.delete(sessionKey);
533
- }
534
- }
535
594
  }
536
595
  /**
537
596
  * Get the global session manager configuration.
@@ -546,27 +605,29 @@ class SessionManager {
546
605
  * Updates the last activity timestamp for a session.
547
606
  */
548
607
  async updateSessionActivity(sessionId) {
549
- const sessionKey = `session:${sessionId}`;
550
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
551
- if (sessionData) {
608
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
609
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
610
+ if (!sessionData) {
611
+ return;
612
+ }
552
613
  sessionData.lastActivity = Date.now();
553
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
554
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
555
- }
614
+ await this.persistSessionData(sessionKey, sessionData);
615
+ });
556
616
  }
557
617
  /**
558
618
  * Increments the message count for a session.
559
619
  */
560
620
  async incrementMessageCount(sessionId) {
561
621
  await this.ensureInitialized();
562
- const sessionKey = `session:${sessionId}`;
563
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
564
- if (sessionData) {
622
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
623
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
624
+ if (!sessionData) {
625
+ return;
626
+ }
565
627
  sessionData.messageCount++;
566
628
  sessionData.lastActivity = Date.now();
567
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
568
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
569
- }
629
+ await this.persistSessionData(sessionKey, sessionData);
630
+ });
570
631
  }
571
632
  /**
572
633
  * Accumulates token usage for a session.
@@ -581,9 +642,7 @@ class SessionManager {
581
642
  */
582
643
  async accumulateTokenUsage(sessionId, usage, cost, modelInfo) {
583
644
  await this.ensureInitialized();
584
- const sessionKey = `session:${sessionId}`;
585
- const previousLock = this.tokenUsageLocks.get(sessionKey) ?? Promise.resolve();
586
- const currentLock = previousLock.then(async () => {
645
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
587
646
  const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
588
647
  if (!sessionData) return;
589
648
  if (modelInfo) {
@@ -604,17 +663,8 @@ class SessionManager {
604
663
  sessionData.estimatedCost = (sessionData.estimatedCost ?? 0) + cost;
605
664
  }
606
665
  sessionData.lastActivity = Date.now();
607
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
608
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
666
+ await this.persistSessionData(sessionKey, sessionData);
609
667
  });
610
- this.tokenUsageLocks.set(sessionKey, currentLock);
611
- try {
612
- await currentLock;
613
- } finally {
614
- if (this.tokenUsageLocks.get(sessionKey) === currentLock) {
615
- this.tokenUsageLocks.delete(sessionKey);
616
- }
617
- }
618
668
  }
619
669
  /**
620
670
  * Helper to accumulate token usage into a target SessionTokenUsage object.
@@ -673,20 +723,20 @@ class SessionManager {
673
723
  */
674
724
  async setSessionTitle(sessionId, title, opts = {}) {
675
725
  await this.ensureInitialized();
676
- const sessionKey = `session:${sessionId}`;
677
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
678
- if (!sessionData) {
679
- throw import_errors.SessionError.notFound(sessionId);
680
- }
681
726
  const normalized = title.trim().slice(0, 80);
682
- if (opts.ifUnsetOnly && sessionData.metadata?.title) {
683
- return;
684
- }
685
- sessionData.metadata = sessionData.metadata || {};
686
- sessionData.metadata.title = normalized;
687
- sessionData.lastActivity = Date.now();
688
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
689
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
727
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
728
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
729
+ if (!sessionData) {
730
+ throw import_errors.SessionError.notFound(sessionId);
731
+ }
732
+ if (opts.ifUnsetOnly && sessionData.metadata?.title) {
733
+ return;
734
+ }
735
+ sessionData.metadata = sessionData.metadata || {};
736
+ sessionData.metadata.title = normalized;
737
+ sessionData.lastActivity = Date.now();
738
+ await this.persistSessionData(sessionKey, sessionData);
739
+ });
690
740
  }
691
741
  /**
692
742
  * Gets the stored title for a session, if any.
@@ -771,14 +821,15 @@ class SessionManager {
771
821
  throw import_errors.SessionError.notFound(sessionId);
772
822
  }
773
823
  await session.switchLLM(newLLMConfig);
774
- const sessionKey = `session:${sessionId}`;
775
- const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
776
- if (sessionData) {
824
+ await this.runWithSessionDataLock(sessionId, async (sessionKey) => {
825
+ const sessionData = await this.services.storageManager.getDatabase().get(sessionKey);
826
+ if (!sessionData) {
827
+ return;
828
+ }
777
829
  const { apiKey: _apiKey, ...configWithoutApiKey } = newLLMConfig;
778
830
  sessionData.llmOverride = configWithoutApiKey;
779
- await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
780
- await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
781
- }
831
+ await this.persistSessionData(sessionKey, sessionData);
832
+ });
782
833
  this.services.agentEventBus.emit("llm:switched", {
783
834
  newConfig: newLLMConfig,
784
835
  historyRetained: true,
@@ -787,6 +838,28 @@ class SessionManager {
787
838
  const message = `Successfully switched to ${newLLMConfig.provider}/${newLLMConfig.model} for session ${sessionId}`;
788
839
  return { message, warnings: [] };
789
840
  }
841
+ async runWithSessionDataLock(sessionId, fn) {
842
+ const sessionKey = `session:${sessionId}`;
843
+ const previousLock = this.sessionDataLocks.get(sessionKey) ?? Promise.resolve();
844
+ const currentResult = previousLock.catch(() => {
845
+ }).then(() => fn(sessionKey));
846
+ const currentLock = currentResult.then(
847
+ () => void 0,
848
+ () => void 0
849
+ );
850
+ this.sessionDataLocks.set(sessionKey, currentLock);
851
+ try {
852
+ return await currentResult;
853
+ } finally {
854
+ if (this.sessionDataLocks.get(sessionKey) === currentLock) {
855
+ this.sessionDataLocks.delete(sessionKey);
856
+ }
857
+ }
858
+ }
859
+ async persistSessionData(sessionKey, sessionData) {
860
+ await this.services.storageManager.getDatabase().set(sessionKey, sessionData);
861
+ await this.services.storageManager.getCache().set(sessionKey, sessionData, this.sessionTTL / 1e3);
862
+ }
790
863
  /**
791
864
  * Get session statistics for monitoring and debugging.
792
865
  */