@dexto/core 1.6.24 → 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 (80) hide show
  1. package/dist/agent/DextoAgent.cjs +52 -17
  2. package/dist/agent/DextoAgent.d.ts +11 -6
  3. package/dist/agent/DextoAgent.d.ts.map +1 -1
  4. package/dist/agent/DextoAgent.js +52 -17
  5. package/dist/agent/state-manager.cjs +6 -0
  6. package/dist/agent/state-manager.d.ts +4 -0
  7. package/dist/agent/state-manager.d.ts.map +1 -1
  8. package/dist/agent/state-manager.js +6 -0
  9. package/dist/approval/manager.cjs +328 -178
  10. package/dist/approval/manager.d.ts +39 -31
  11. package/dist/approval/manager.d.ts.map +1 -1
  12. package/dist/approval/manager.js +328 -178
  13. package/dist/approval/session-approval-store.cjs +91 -0
  14. package/dist/approval/session-approval-store.d.ts +55 -0
  15. package/dist/approval/session-approval-store.d.ts.map +1 -0
  16. package/dist/approval/session-approval-store.js +68 -0
  17. package/dist/llm/executor/stream-processor.cjs +24 -15
  18. package/dist/llm/executor/stream-processor.d.ts +5 -0
  19. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  20. package/dist/llm/executor/stream-processor.js +24 -15
  21. package/dist/llm/executor/turn-executor.cjs +7 -3
  22. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  23. package/dist/llm/executor/turn-executor.js +7 -3
  24. package/dist/llm/services/factory.cjs +10 -4
  25. package/dist/llm/services/factory.d.ts +2 -21
  26. package/dist/llm/services/factory.d.ts.map +1 -1
  27. package/dist/llm/services/factory.js +11 -7
  28. package/dist/llm/services/types.d.ts +33 -2
  29. package/dist/llm/services/types.d.ts.map +1 -1
  30. package/dist/llm/services/vercel.cjs +4 -5
  31. package/dist/llm/services/vercel.d.ts +3 -3
  32. package/dist/llm/services/vercel.d.ts.map +1 -1
  33. package/dist/llm/services/vercel.js +2 -3
  34. package/dist/logger/default-logger-factory.d.ts +12 -12
  35. package/dist/logger/v2/schemas.d.ts +6 -6
  36. package/dist/mcp/schemas.d.ts +10 -10
  37. package/dist/session/chat-session.cjs +39 -41
  38. package/dist/session/chat-session.d.ts +22 -12
  39. package/dist/session/chat-session.d.ts.map +1 -1
  40. package/dist/session/chat-session.js +39 -41
  41. package/dist/session/message-queue-store.cjs +75 -0
  42. package/dist/session/message-queue-store.d.ts +16 -0
  43. package/dist/session/message-queue-store.d.ts.map +1 -0
  44. package/dist/session/message-queue-store.js +52 -0
  45. package/dist/session/message-queue.cjs +140 -46
  46. package/dist/session/message-queue.d.ts +18 -6
  47. package/dist/session/message-queue.d.ts.map +1 -1
  48. package/dist/session/message-queue.js +140 -46
  49. package/dist/session/session-manager.cjs +130 -25
  50. package/dist/session/session-manager.d.ts +18 -1
  51. package/dist/session/session-manager.d.ts.map +1 -1
  52. package/dist/session/session-manager.js +130 -25
  53. package/dist/session/title-generator.cjs +9 -2
  54. package/dist/session/title-generator.d.ts +2 -0
  55. package/dist/session/title-generator.d.ts.map +1 -1
  56. package/dist/session/title-generator.js +9 -2
  57. package/dist/telemetry/errors.cjs +2 -2
  58. package/dist/telemetry/errors.js +2 -2
  59. package/dist/telemetry/index.d.ts +1 -1
  60. package/dist/telemetry/index.d.ts.map +1 -1
  61. package/dist/telemetry/index.js +3 -1
  62. package/dist/telemetry/telemetry.cjs +62 -21
  63. package/dist/telemetry/telemetry.d.ts +14 -0
  64. package/dist/telemetry/telemetry.d.ts.map +1 -1
  65. package/dist/telemetry/telemetry.js +62 -21
  66. package/dist/test-utils/session-state-stores.cjs +68 -0
  67. package/dist/test-utils/session-state-stores.js +42 -0
  68. package/dist/tools/session-tool-preferences-store.cjs +86 -0
  69. package/dist/tools/session-tool-preferences-store.d.ts +29 -0
  70. package/dist/tools/session-tool-preferences-store.d.ts.map +1 -0
  71. package/dist/tools/session-tool-preferences-store.js +63 -0
  72. package/dist/tools/tool-manager.cjs +131 -32
  73. package/dist/tools/tool-manager.d.ts +17 -6
  74. package/dist/tools/tool-manager.d.ts.map +1 -1
  75. package/dist/tools/tool-manager.js +131 -32
  76. package/dist/utils/service-initializer.cjs +38 -5
  77. package/dist/utils/service-initializer.d.ts +11 -1
  78. package/dist/utils/service-initializer.d.ts.map +1 -1
  79. package/dist/utils/service-initializer.js +36 -4
  80. package/package.json +1 -1
@@ -0,0 +1,91 @@
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_approval_store_exports = {};
20
+ __export(session_approval_store_exports, {
21
+ SessionApprovalStore: () => SessionApprovalStore
22
+ });
23
+ module.exports = __toCommonJS(session_approval_store_exports);
24
+ var import_zod = require("zod");
25
+ const ApprovedDirectoryTypeSchema = import_zod.z.enum(["session", "once"]);
26
+ const PersistedApprovedDirectorySchema = import_zod.z.object({
27
+ path: import_zod.z.string(),
28
+ type: ApprovedDirectoryTypeSchema
29
+ }).strict();
30
+ const SessionApprovalStateSchema = import_zod.z.object({
31
+ toolPatterns: import_zod.z.record(import_zod.z.array(import_zod.z.string())).default({}),
32
+ approvedDirectories: import_zod.z.array(PersistedApprovedDirectorySchema).default([])
33
+ }).strict();
34
+ const DEFAULT_APPROVAL_STATE = {
35
+ toolPatterns: {},
36
+ approvedDirectories: []
37
+ };
38
+ class SessionApprovalStore {
39
+ constructor(storageManager, logger, options = {}) {
40
+ this.storageManager = storageManager;
41
+ this.logger = logger;
42
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
43
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
44
+ }
45
+ cacheTtlSeconds;
46
+ buildKey(sessionId) {
47
+ return sessionId ? `session-approvals:${sessionId}` : "session-approvals:global";
48
+ }
49
+ async load(sessionId) {
50
+ const key = this.buildKey(sessionId);
51
+ const cached = await this.storageManager.getCache().get(key);
52
+ if (cached !== void 0) {
53
+ return this.parseState(cached, key);
54
+ }
55
+ const stored = await this.storageManager.getDatabase().get(key);
56
+ if (stored === void 0) {
57
+ return structuredClone(DEFAULT_APPROVAL_STATE);
58
+ }
59
+ const parsed = this.parseState(stored, key);
60
+ await this.storageManager.getCache().set(key, parsed, this.cacheTtlSeconds);
61
+ return parsed;
62
+ }
63
+ async save(sessionId, state) {
64
+ const key = this.buildKey(sessionId);
65
+ const normalized = SessionApprovalStateSchema.parse(state);
66
+ await this.storageManager.getDatabase().set(key, normalized);
67
+ await this.storageManager.getCache().set(key, normalized, this.cacheTtlSeconds);
68
+ }
69
+ async delete(sessionId) {
70
+ const key = this.buildKey(sessionId);
71
+ await Promise.all([
72
+ this.storageManager.getDatabase().delete(key),
73
+ this.storageManager.getCache().delete(key)
74
+ ]);
75
+ }
76
+ parseState(value, key) {
77
+ const result = SessionApprovalStateSchema.safeParse(value);
78
+ if (result.success) {
79
+ return result.data;
80
+ }
81
+ this.logger.warn("Invalid persisted approval state encountered; using defaults", {
82
+ key,
83
+ error: result.error.message
84
+ });
85
+ return structuredClone(DEFAULT_APPROVAL_STATE);
86
+ }
87
+ }
88
+ // Annotate the CommonJS export names for ESM import in node:
89
+ 0 && (module.exports = {
90
+ SessionApprovalStore
91
+ });
@@ -0,0 +1,55 @@
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 PersistedApprovedDirectorySchema: z.ZodObject<{
5
+ path: z.ZodString;
6
+ type: z.ZodEnum<["session", "once"]>;
7
+ }, "strict", z.ZodTypeAny, {
8
+ path: string;
9
+ type: "session" | "once";
10
+ }, {
11
+ path: string;
12
+ type: "session" | "once";
13
+ }>;
14
+ declare const SessionApprovalStateSchema: z.ZodObject<{
15
+ toolPatterns: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
16
+ approvedDirectories: z.ZodDefault<z.ZodArray<z.ZodObject<{
17
+ path: z.ZodString;
18
+ type: z.ZodEnum<["session", "once"]>;
19
+ }, "strict", z.ZodTypeAny, {
20
+ path: string;
21
+ type: "session" | "once";
22
+ }, {
23
+ path: string;
24
+ type: "session" | "once";
25
+ }>, "many">>;
26
+ }, "strict", z.ZodTypeAny, {
27
+ toolPatterns: Record<string, string[]>;
28
+ approvedDirectories: {
29
+ path: string;
30
+ type: "session" | "once";
31
+ }[];
32
+ }, {
33
+ toolPatterns?: Record<string, string[]> | undefined;
34
+ approvedDirectories?: {
35
+ path: string;
36
+ type: "session" | "once";
37
+ }[] | undefined;
38
+ }>;
39
+ export type PersistedApprovedDirectory = z.output<typeof PersistedApprovedDirectorySchema>;
40
+ export type SessionApprovalState = z.output<typeof SessionApprovalStateSchema>;
41
+ export declare class SessionApprovalStore {
42
+ private readonly storageManager;
43
+ private readonly logger;
44
+ private readonly cacheTtlSeconds;
45
+ constructor(storageManager: StorageManager, logger: Logger, options?: {
46
+ cacheTtlMs?: number;
47
+ });
48
+ private buildKey;
49
+ load(sessionId?: string): Promise<SessionApprovalState>;
50
+ save(sessionId: string | undefined, state: SessionApprovalState): Promise<void>;
51
+ delete(sessionId?: string): Promise<void>;
52
+ private parseState;
53
+ }
54
+ export {};
55
+ //# sourceMappingURL=session-approval-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-approval-store.d.ts","sourceRoot":"","sources":["../../src/approval/session-approval-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;AAIpD,QAAA,MAAM,gCAAgC;;;;;;;;;EAKzB,CAAC;AAEd,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;EAKnB,CAAC;AAEd,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAC3F,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAO/E,qBAAa,oBAAoB;IAIzB,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,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiBvD,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/E,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/C,OAAO,CAAC,UAAU;CAYrB"}
@@ -0,0 +1,68 @@
1
+ import "../chunk-PTJYTZNU.js";
2
+ import { z } from "zod";
3
+ const ApprovedDirectoryTypeSchema = z.enum(["session", "once"]);
4
+ const PersistedApprovedDirectorySchema = z.object({
5
+ path: z.string(),
6
+ type: ApprovedDirectoryTypeSchema
7
+ }).strict();
8
+ const SessionApprovalStateSchema = z.object({
9
+ toolPatterns: z.record(z.array(z.string())).default({}),
10
+ approvedDirectories: z.array(PersistedApprovedDirectorySchema).default([])
11
+ }).strict();
12
+ const DEFAULT_APPROVAL_STATE = {
13
+ toolPatterns: {},
14
+ approvedDirectories: []
15
+ };
16
+ class SessionApprovalStore {
17
+ constructor(storageManager, logger, options = {}) {
18
+ this.storageManager = storageManager;
19
+ this.logger = logger;
20
+ const cacheTtlMs = options.cacheTtlMs ?? 36e5;
21
+ this.cacheTtlSeconds = Math.max(1, Math.floor(cacheTtlMs / 1e3));
22
+ }
23
+ cacheTtlSeconds;
24
+ buildKey(sessionId) {
25
+ return sessionId ? `session-approvals:${sessionId}` : "session-approvals:global";
26
+ }
27
+ async load(sessionId) {
28
+ const key = this.buildKey(sessionId);
29
+ const cached = await this.storageManager.getCache().get(key);
30
+ if (cached !== void 0) {
31
+ return this.parseState(cached, key);
32
+ }
33
+ const stored = await this.storageManager.getDatabase().get(key);
34
+ if (stored === void 0) {
35
+ return structuredClone(DEFAULT_APPROVAL_STATE);
36
+ }
37
+ const parsed = this.parseState(stored, key);
38
+ await this.storageManager.getCache().set(key, parsed, this.cacheTtlSeconds);
39
+ return parsed;
40
+ }
41
+ async save(sessionId, state) {
42
+ const key = this.buildKey(sessionId);
43
+ const normalized = SessionApprovalStateSchema.parse(state);
44
+ await this.storageManager.getDatabase().set(key, normalized);
45
+ await this.storageManager.getCache().set(key, normalized, this.cacheTtlSeconds);
46
+ }
47
+ async delete(sessionId) {
48
+ const key = this.buildKey(sessionId);
49
+ await Promise.all([
50
+ this.storageManager.getDatabase().delete(key),
51
+ this.storageManager.getCache().delete(key)
52
+ ]);
53
+ }
54
+ parseState(value, key) {
55
+ const result = SessionApprovalStateSchema.safeParse(value);
56
+ if (result.success) {
57
+ return result.data;
58
+ }
59
+ this.logger.warn("Invalid persisted approval state encountered; using defaults", {
60
+ key,
61
+ error: result.error.message
62
+ });
63
+ return structuredClone(DEFAULT_APPROVAL_STATE);
64
+ }
65
+ }
66
+ export {
67
+ SessionApprovalStore
68
+ };
@@ -368,11 +368,8 @@ class StreamProcessor {
368
368
  }
369
369
  case "error": {
370
370
  const err = event.error instanceof Error ? event.error : new Error(String(event.error));
371
- this.logger.error("LLM error", { error: err });
372
- this.eventBus.emit("llm:error", {
373
- error: err
374
- });
375
- break;
371
+ await this.persistFailedToolResults(err.message);
372
+ throw err;
376
373
  }
377
374
  case "abort": {
378
375
  this.logger.debug("Stream aborted, emitting partial response");
@@ -427,11 +424,6 @@ class StreamProcessor {
427
424
  };
428
425
  }
429
426
  this.logger.error("Stream processing failed", { error });
430
- this.eventBus.emit("llm:error", {
431
- error: error instanceof Error ? error : new Error(String(error)),
432
- context: "StreamProcessor",
433
- recoverable: false
434
- });
435
427
  throw error;
436
428
  }
437
429
  return {
@@ -567,14 +559,31 @@ class StreamProcessor {
567
559
  * Called on abort/cancel to prevent "tool_use ids were found without tool_result" errors.
568
560
  */
569
561
  async persistCancelledToolResults() {
562
+ await this.persistPendingToolResults({
563
+ logLabel: "cancelled",
564
+ resultText: "Cancelled by user",
565
+ errorMessage: "Cancelled by user"
566
+ });
567
+ }
568
+ /**
569
+ * Persist synthetic failed results for pending tool calls before surfacing a fatal stream error.
570
+ */
571
+ async persistFailedToolResults(errorMessage) {
572
+ await this.persistPendingToolResults({
573
+ logLabel: "failed",
574
+ resultText: `Error: ${errorMessage}`,
575
+ errorMessage
576
+ });
577
+ }
578
+ async persistPendingToolResults(options) {
570
579
  if (this.pendingToolCalls.size === 0) return;
571
580
  this.logger.debug(
572
- `Persisting cancelled results for ${this.pendingToolCalls.size} pending tool call(s)`
581
+ `Persisting ${options.logLabel} results for ${this.pendingToolCalls.size} pending tool call(s)`
573
582
  );
574
583
  for (const [toolCallId, { toolName }] of this.pendingToolCalls) {
575
584
  const metadata = this.toolCallMetadata?.get(toolCallId);
576
- const cancelledResult = {
577
- content: [{ type: "text", text: "Cancelled by user" }],
585
+ const syntheticResult = {
586
+ content: [{ type: "text", text: options.resultText }],
578
587
  meta: {
579
588
  toolName,
580
589
  toolCallId,
@@ -584,7 +593,7 @@ class StreamProcessor {
584
593
  await this.contextManager.addToolResult(
585
594
  toolCallId,
586
595
  toolName,
587
- cancelledResult,
596
+ syntheticResult,
588
597
  metadata
589
598
  );
590
599
  this.eventBus.emit("llm:tool-result", {
@@ -597,7 +606,7 @@ class StreamProcessor {
597
606
  },
598
607
  callId: toolCallId,
599
608
  success: false,
600
- error: "Cancelled by user",
609
+ error: options.errorMessage,
601
610
  ...metadata?.requireApproval !== void 0 && {
602
611
  requireApproval: metadata.requireApproval
603
612
  },
@@ -73,5 +73,10 @@ export declare class StreamProcessor {
73
73
  * Called on abort/cancel to prevent "tool_use ids were found without tool_result" errors.
74
74
  */
75
75
  private persistCancelledToolResults;
76
+ /**
77
+ * Persist synthetic failed results for pending tool calls before surfacing a fatal stream error.
78
+ */
79
+ private persistFailedToolResults;
80
+ private persistPendingToolResults;
76
81
  }
77
82
  //# sourceMappingURL=stream-processor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-processor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/stream-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,OAAO,KAAK,EAAE,WAAW,EAAoB,gBAAgB,EAAc,MAAM,aAAa,CAAC;AA4C/F,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,eAAe;IA4BpB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,gBAAgB,CAAC;IAlC7B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,YAAY,CAAmE;IACvF,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAgD;IACxE,OAAO,CAAC,gBAAgB,CAAkE;IAE1F;;;;;;;;;OASG;gBAES,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,eAAe,EACzB,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,qBAAqB,EACrC,MAAM,EAAE,MAAM,EACN,SAAS,GAAE,OAAc,EACzB,gBAAgB,CAAC,EAAE,GAAG,CAC1B,MAAM,EACN;QACI,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;QAClD,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACxB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;KAC5C,CACJ,YAAA;IAMC,OAAO,CACT,QAAQ,EAAE,MAAM,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,GACzD,OAAO,CAAC,qBAAqB,CAAC;IA0gBjC,OAAO,CAAC,kCAAkC;IAoB1C,OAAO,CAAC,cAAc;IA0CtB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,eAAe;YA8BT,gCAAgC;IA0B9C,OAAO,CAAC,sBAAsB;YAwChB,sBAAsB;YAKtB,gBAAgB;IAO9B;;;;OAIG;YACW,2BAA2B;CAiD5C"}
1
+ {"version":3,"file":"stream-processor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/stream-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAG1E,OAAO,KAAK,EAAE,WAAW,EAAoB,gBAAgB,EAAc,MAAM,aAAa,CAAC;AA4C/F,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,eAAe;IA4BpB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,gBAAgB,CAAC;IAlC7B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,YAAY,CAAmE;IACvF,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAgD;IACxE,OAAO,CAAC,gBAAgB,CAAkE;IAE1F;;;;;;;;;OASG;gBAES,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,eAAe,EACzB,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,qBAAqB,EACrC,MAAM,EAAE,MAAM,EACN,SAAS,GAAE,OAAc,EACzB,gBAAgB,CAAC,EAAE,GAAG,CAC1B,MAAM,EACN;QACI,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;QAClD,IAAI,CAAC,EAAE,gBAAgB,CAAC;QACxB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;KAC5C,CACJ,YAAA;IAMC,OAAO,CACT,QAAQ,EAAE,MAAM,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,GACzD,OAAO,CAAC,qBAAqB,CAAC;IA+fjC,OAAO,CAAC,kCAAkC;IAoB1C,OAAO,CAAC,cAAc;IA0CtB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,eAAe;YA8BT,gCAAgC;IA0B9C,OAAO,CAAC,sBAAsB;YAwChB,sBAAsB;YAKtB,gBAAgB;IAO9B;;;;OAIG;YACW,2BAA2B;IAQzC;;OAEG;YACW,wBAAwB;YAQxB,yBAAyB;CAqD1C"}
@@ -346,11 +346,8 @@ class StreamProcessor {
346
346
  }
347
347
  case "error": {
348
348
  const err = event.error instanceof Error ? event.error : new Error(String(event.error));
349
- this.logger.error("LLM error", { error: err });
350
- this.eventBus.emit("llm:error", {
351
- error: err
352
- });
353
- break;
349
+ await this.persistFailedToolResults(err.message);
350
+ throw err;
354
351
  }
355
352
  case "abort": {
356
353
  this.logger.debug("Stream aborted, emitting partial response");
@@ -405,11 +402,6 @@ class StreamProcessor {
405
402
  };
406
403
  }
407
404
  this.logger.error("Stream processing failed", { error });
408
- this.eventBus.emit("llm:error", {
409
- error: error instanceof Error ? error : new Error(String(error)),
410
- context: "StreamProcessor",
411
- recoverable: false
412
- });
413
405
  throw error;
414
406
  }
415
407
  return {
@@ -545,14 +537,31 @@ class StreamProcessor {
545
537
  * Called on abort/cancel to prevent "tool_use ids were found without tool_result" errors.
546
538
  */
547
539
  async persistCancelledToolResults() {
540
+ await this.persistPendingToolResults({
541
+ logLabel: "cancelled",
542
+ resultText: "Cancelled by user",
543
+ errorMessage: "Cancelled by user"
544
+ });
545
+ }
546
+ /**
547
+ * Persist synthetic failed results for pending tool calls before surfacing a fatal stream error.
548
+ */
549
+ async persistFailedToolResults(errorMessage) {
550
+ await this.persistPendingToolResults({
551
+ logLabel: "failed",
552
+ resultText: `Error: ${errorMessage}`,
553
+ errorMessage
554
+ });
555
+ }
556
+ async persistPendingToolResults(options) {
548
557
  if (this.pendingToolCalls.size === 0) return;
549
558
  this.logger.debug(
550
- `Persisting cancelled results for ${this.pendingToolCalls.size} pending tool call(s)`
559
+ `Persisting ${options.logLabel} results for ${this.pendingToolCalls.size} pending tool call(s)`
551
560
  );
552
561
  for (const [toolCallId, { toolName }] of this.pendingToolCalls) {
553
562
  const metadata = this.toolCallMetadata?.get(toolCallId);
554
- const cancelledResult = {
555
- content: [{ type: "text", text: "Cancelled by user" }],
563
+ const syntheticResult = {
564
+ content: [{ type: "text", text: options.resultText }],
556
565
  meta: {
557
566
  toolName,
558
567
  toolCallId,
@@ -562,7 +571,7 @@ class StreamProcessor {
562
571
  await this.contextManager.addToolResult(
563
572
  toolCallId,
564
573
  toolName,
565
- cancelledResult,
574
+ syntheticResult,
566
575
  metadata
567
576
  );
568
577
  this.eventBus.emit("llm:tool-result", {
@@ -575,7 +584,7 @@ class StreamProcessor {
575
584
  },
576
585
  callId: toolCallId,
577
586
  success: false,
578
- error: "Cancelled by user",
587
+ error: options.errorMessage,
579
588
  ...metadata?.requireApproval !== void 0 && {
580
589
  requireApproval: metadata.requireApproval
581
590
  },
@@ -187,7 +187,7 @@ class TurnExecutor {
187
187
  once: true
188
188
  });
189
189
  }
190
- const coalesced = this.messageQueue.dequeueAll();
190
+ const coalesced = await this.messageQueue.dequeueAll();
191
191
  if (coalesced) {
192
192
  await this.injectQueuedMessages(coalesced);
193
193
  }
@@ -320,7 +320,7 @@ class TurnExecutor {
320
320
  );
321
321
  }
322
322
  if (result.finishReason !== "tool-calls") {
323
- const queuedOnTerminate = this.messageQueue.dequeueAll();
323
+ const queuedOnTerminate = await this.messageQueue.dequeueAll();
324
324
  if (queuedOnTerminate) {
325
325
  this.logger.debug(
326
326
  `Continuing: ${queuedOnTerminate.messages.length} queued message(s) to process`
@@ -757,7 +757,11 @@ class TurnExecutor {
757
757
  if (!this.stepAbortController.signal.aborted) {
758
758
  this.stepAbortController.abort();
759
759
  }
760
- this.messageQueue.clear();
760
+ void this.messageQueue.clear().catch((error) => {
761
+ this.logger.warn(
762
+ `Failed to clear queued follow-up messages during cleanup: ${error instanceof Error ? error.message : String(error)}`
763
+ );
764
+ });
761
765
  }
762
766
  /**
763
767
  * Check if context should be compacted based on estimated token count.
@@ -1 +1 @@
1
- {"version":3,"file":"turn-executor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/turn-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,aAAa,EAMb,KAAK,YAAY,EAEpB,MAAM,IAAI,CAAC;AAEZ,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAQ1D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAK1D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAER,kBAAkB,EAClB,UAAU,EAGb,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAQ1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAexE;;;;;;;;;;;GAWG;AACH,qBAAa,YAAY;IAuBjB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,UAAU;IAElB,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,cAAc,CAAC;IAzC3B,OAAO,CAAC,MAAM,CAAS;IACvB;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,kBAAkB,CAAmC;IAC7D;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAQpB;gBAGQ,KAAK,EAAE,aAAa,EACpB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,cAAc,CAAC,YAAY,CAAC,EAC5C,QAAQ,EAAE,eAAe,EACzB,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACrC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAElC,SAAS,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;KAC9C,EACO,UAAU,EAAE,UAAU,EAC9B,MAAM,EAAE,MAAM,EACN,YAAY,EAAE,mBAAmB,EACjC,WAAW,CAAC,EAAE,WAAW,YAAA,EACzB,cAAc,CAAC,EAAE,WAAW,YAAA,EACpC,kBAAkB,GAAE,kBAAkB,GAAG,IAAW;IAcxD;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAoBhC;;;;;;OAMG;IACG,OAAO,CACT,kBAAkB,EAAE,yBAAyB,EAC7C,SAAS,GAAE,OAAc,GAC1B,OAAO,CAAC,cAAc,CAAC;IAsV1B;;;OAGG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;YACW,oBAAoB;IAmBlC;;;;;;;;OAQG;YACW,mBAAmB;IAkFjC;;;;;;;OAOG;YACW,WAAW;IAqIzB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAuF9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAU;IAC/C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAU;IAE/C;;;;;;;;;;;OAWG;YACW,mBAAmB;IAkDjC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAgB1B;;;OAGG;IACH,OAAO,CAAC,OAAO;IAYf;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;;OAMG;IACH,OAAO,CAAC,uBAAuB;IAO/B;;;;;;;;;;;OAWG;YACW,cAAc;IAwF5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAyF3B"}
1
+ {"version":3,"file":"turn-executor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/turn-executor.ts"],"names":[],"mappings":"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"}
@@ -119,7 +119,7 @@ class TurnExecutor {
119
119
  once: true
120
120
  });
121
121
  }
122
- const coalesced = this.messageQueue.dequeueAll();
122
+ const coalesced = await this.messageQueue.dequeueAll();
123
123
  if (coalesced) {
124
124
  await this.injectQueuedMessages(coalesced);
125
125
  }
@@ -252,7 +252,7 @@ class TurnExecutor {
252
252
  );
253
253
  }
254
254
  if (result.finishReason !== "tool-calls") {
255
- const queuedOnTerminate = this.messageQueue.dequeueAll();
255
+ const queuedOnTerminate = await this.messageQueue.dequeueAll();
256
256
  if (queuedOnTerminate) {
257
257
  this.logger.debug(
258
258
  `Continuing: ${queuedOnTerminate.messages.length} queued message(s) to process`
@@ -689,7 +689,11 @@ class TurnExecutor {
689
689
  if (!this.stepAbortController.signal.aborted) {
690
690
  this.stepAbortController.abort();
691
691
  }
692
- this.messageQueue.clear();
692
+ void this.messageQueue.clear().catch((error) => {
693
+ this.logger.warn(
694
+ `Failed to clear queued follow-up messages during cleanup: ${error instanceof Error ? error.message : String(error)}`
695
+ );
696
+ });
693
697
  }
694
698
  /**
695
699
  * Check if context should be compacted based on estimated token count.
@@ -237,9 +237,9 @@ function createVercelModel(llmConfig, context) {
237
237
  throw import_errors.LLMError.unsupportedProvider(provider);
238
238
  }
239
239
  }
240
- function createLLMService(config, toolManager, systemPromptManager, historyProvider, sessionEventBus, sessionId, resourceManager, logger, options = {}) {
241
- const { usageScopeId, compactionStrategy } = options;
242
- const model = createVercelModel(config, {
240
+ function createLLMService(config, toolManager, systemPromptManager, historyProvider, sessionEventBus, sessionId, resourceManager, logger, options, languageModelFactory) {
241
+ const { usageScopeId, compactionStrategy, messageQueue } = options;
242
+ const providerContext = {
243
243
  sessionId,
244
244
  ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
245
245
  onCodexRateLimitStatus: (snapshot) => {
@@ -249,7 +249,12 @@ function createLLMService(config, toolManager, systemPromptManager, historyProvi
249
249
  snapshot
250
250
  });
251
251
  }
252
- });
252
+ };
253
+ const model = languageModelFactory?.({
254
+ config,
255
+ context: providerContext,
256
+ createDefaultLanguageModel: () => createVercelModel(config, providerContext)
257
+ }) ?? createVercelModel(config, providerContext);
253
258
  return new import_vercel.VercelLLMService(
254
259
  toolManager,
255
260
  model,
@@ -260,6 +265,7 @@ function createLLMService(config, toolManager, systemPromptManager, historyProvi
260
265
  sessionId,
261
266
  resourceManager,
262
267
  logger,
268
+ messageQueue,
263
269
  usageScopeId,
264
270
  compactionStrategy
265
271
  );
@@ -6,26 +6,7 @@ import { SessionEventBus } from '../../events/index.js';
6
6
  import type { ConversationHistoryProvider } from '../../session/history/types.js';
7
7
  import type { SystemPromptManager } from '../../systemPrompt/manager.js';
8
8
  import type { Logger } from '../../logger/v2/types.js';
9
- import { type CodexRateLimitSnapshot } from '../providers/codex-app-server.js';
10
- import type { CompactionStrategy } from '../../context/compaction/types.js';
11
- /**
12
- * Context for model creation, including session info for usage tracking.
13
- */
14
- export interface DextoProviderContext {
15
- /** Session ID for usage tracking */
16
- sessionId?: string;
17
- /** Client source for usage attribution (cli, web, sdk) */
18
- clientSource?: 'cli' | 'web' | 'sdk';
19
- /** Working directory for providers that need an explicit workspace root. */
20
- cwd?: string;
21
- /** Optional callback for ChatGPT Login rate-limit status updates from Codex. */
22
- onCodexRateLimitStatus?: (snapshot: CodexRateLimitSnapshot) => void;
23
- }
24
- export interface CreateLLMServiceOptions {
25
- usageScopeId?: string | undefined;
26
- compactionStrategy?: CompactionStrategy | null | undefined;
27
- cwd?: string | undefined;
28
- }
9
+ import type { CreateLLMServiceOptions, DextoProviderContext, LanguageModelFactory } from './types.js';
29
10
  /**
30
11
  * Create a Vercel AI SDK LanguageModel from config.
31
12
  *
@@ -52,5 +33,5 @@ export declare function createVercelModel(llmConfig: ValidatedLLMConfig, context
52
33
  * @param options Session-scoped runtime options
53
34
  * @returns VercelLLMService instance
54
35
  */
55
- export declare function createLLMService(config: ValidatedLLMConfig, toolManager: ToolManager, systemPromptManager: SystemPromptManager, historyProvider: ConversationHistoryProvider, sessionEventBus: SessionEventBus, sessionId: string, resourceManager: import('../../resources/index.js').ResourceManager, logger: Logger, options?: CreateLLMServiceOptions): VercelLLMService;
36
+ export declare function createLLMService(config: ValidatedLLMConfig, toolManager: ToolManager, systemPromptManager: SystemPromptManager, historyProvider: ConversationHistoryProvider, sessionEventBus: SessionEventBus, sessionId: string, resourceManager: import('../../resources/index.js').ResourceManager, logger: Logger, options: CreateLLMServiceOptions, languageModelFactory?: LanguageModelFactory): VercelLLMService;
56
37
  //# sourceMappingURL=factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/llm/services/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAYnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAEH,KAAK,sBAAsB,EAC9B,MAAM,kCAAkC,CAAC;AAQ1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AA2C5E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACrC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACvE;AAED,MAAM,WAAW,uBAAuB;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3D,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAUD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,kBAAkB,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC/B,aAAa,CAyOf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,2BAA2B,EAC5C,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,OAAO,0BAA0B,EAAE,eAAe,EACnE,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,uBAA4B,GACtC,gBAAgB,CA4BlB"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/llm/services/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAYnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EACR,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACvB,MAAM,YAAY,CAAC;AA6DpB;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,kBAAkB,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC/B,aAAa,CAyOf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,eAAe,EAAE,2BAA2B,EAC5C,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,OAAO,0BAA0B,EAAE,eAAe,EACnE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,uBAAuB,EAChC,oBAAoB,CAAC,EAAE,oBAAoB,GAC5C,gBAAgB,CAoClB"}
@@ -15,9 +15,7 @@ import { createCohere } from "@ai-sdk/cohere";
15
15
  import { createLocalLanguageModel } from "../providers/local/ai-sdk-adapter.js";
16
16
  import { requiresApiKey } from "../registry/index.js";
17
17
  import { getPrimaryApiKeyEnvVar, resolveApiKeyForProvider } from "../../utils/api-key-resolver.js";
18
- import {
19
- createCodexLanguageModel
20
- } from "../providers/codex-app-server.js";
18
+ import { createCodexLanguageModel } from "../providers/codex-app-server.js";
21
19
  import { isCodexBaseURL } from "../providers/codex-base-url.js";
22
20
  import { findDextoProjectRoot } from "../../utils/execution-context.js";
23
21
  import {
@@ -219,9 +217,9 @@ function createVercelModel(llmConfig, context) {
219
217
  throw LLMError.unsupportedProvider(provider);
220
218
  }
221
219
  }
222
- function createLLMService(config, toolManager, systemPromptManager, historyProvider, sessionEventBus, sessionId, resourceManager, logger, options = {}) {
223
- const { usageScopeId, compactionStrategy } = options;
224
- const model = createVercelModel(config, {
220
+ function createLLMService(config, toolManager, systemPromptManager, historyProvider, sessionEventBus, sessionId, resourceManager, logger, options, languageModelFactory) {
221
+ const { usageScopeId, compactionStrategy, messageQueue } = options;
222
+ const providerContext = {
225
223
  sessionId,
226
224
  ...options.cwd !== void 0 ? { cwd: options.cwd } : {},
227
225
  onCodexRateLimitStatus: (snapshot) => {
@@ -231,7 +229,12 @@ function createLLMService(config, toolManager, systemPromptManager, historyProvi
231
229
  snapshot
232
230
  });
233
231
  }
234
- });
232
+ };
233
+ const model = languageModelFactory?.({
234
+ config,
235
+ context: providerContext,
236
+ createDefaultLanguageModel: () => createVercelModel(config, providerContext)
237
+ }) ?? createVercelModel(config, providerContext);
235
238
  return new VercelLLMService(
236
239
  toolManager,
237
240
  model,
@@ -242,6 +245,7 @@ function createLLMService(config, toolManager, systemPromptManager, historyProvi
242
245
  sessionId,
243
246
  resourceManager,
244
247
  logger,
248
+ messageQueue,
245
249
  usageScopeId,
246
250
  compactionStrategy
247
251
  );
@@ -1,7 +1,11 @@
1
- import { LanguageModel } from 'ai';
1
+ import type { CompactionStrategy } from '../../context/compaction/types.js';
2
+ import type { LanguageModel } from 'ai';
3
+ import type { CodexRateLimitSnapshot } from '../providers/codex-app-server.js';
4
+ import type { ValidatedLLMConfig } from '../schemas.js';
2
5
  import type { LLMProvider } from '../types.js';
6
+ import type { MessageQueueService } from '../../session/message-queue.js';
3
7
  /**
4
- * Configuration object returned by LLMService.getConfig()
8
+ * Configuration object returned by the default session LLM service.
5
9
  */
6
10
  export type LLMServiceConfig = {
7
11
  provider: LLMProvider;
@@ -9,6 +13,33 @@ export type LLMServiceConfig = {
9
13
  configuredMaxInputTokens?: number | null;
10
14
  modelMaxInputTokens?: number | null;
11
15
  };
16
+ export interface CreateLLMServiceOptions {
17
+ usageScopeId?: string | undefined;
18
+ compactionStrategy?: CompactionStrategy | null | undefined;
19
+ cwd?: string | undefined;
20
+ messageQueue: MessageQueueService;
21
+ }
22
+ /**
23
+ * Context for model creation, including session info for usage tracking.
24
+ */
25
+ export interface DextoProviderContext {
26
+ /** Session ID for usage tracking */
27
+ sessionId?: string;
28
+ /** Client source for usage attribution (cli, web, sdk) */
29
+ clientSource?: 'cli' | 'web' | 'sdk';
30
+ /** Working directory for providers that need an explicit workspace root. */
31
+ cwd?: string;
32
+ /** Optional callback for ChatGPT Login rate-limit status updates from Codex. */
33
+ onCodexRateLimitStatus?: (snapshot: CodexRateLimitSnapshot) => void;
34
+ }
35
+ export interface LanguageModelFactoryInput {
36
+ config: ValidatedLLMConfig;
37
+ context: DextoProviderContext;
38
+ }
39
+ export interface LanguageModelFactoryContext extends LanguageModelFactoryInput {
40
+ createDefaultLanguageModel: () => LanguageModel;
41
+ }
42
+ export type LanguageModelFactory = (context: LanguageModelFactoryContext) => LanguageModel;
12
43
  /**
13
44
  * Token usage statistics from LLM
14
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/llm/services/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/llm/services/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,aAAa,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3D,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,YAAY,EAAE,mBAAmB,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACrC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACvE;AAED,MAAM,WAAW,yBAAyB;IACtC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,WAAW,2BAA4B,SAAQ,yBAAyB;IAC1E,0BAA0B,EAAE,MAAM,aAAa,CAAC;CACnD;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,2BAA2B,KAAK,aAAa,CAAC;AAE3F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B"}