@dexto/core 1.5.0 → 1.5.2

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 (73) hide show
  1. package/dist/agent/schemas.d.ts +60 -12
  2. package/dist/agent/schemas.d.ts.map +1 -1
  3. package/dist/context/manager.cjs +4 -0
  4. package/dist/context/manager.d.ts.map +1 -1
  5. package/dist/context/manager.js +4 -0
  6. package/dist/context/types.d.ts +5 -0
  7. package/dist/context/types.d.ts.map +1 -1
  8. package/dist/events/index.cjs +4 -1
  9. package/dist/events/index.d.ts +20 -4
  10. package/dist/events/index.d.ts.map +1 -1
  11. package/dist/events/index.js +3 -1
  12. package/dist/llm/executor/provider-options.cjs +87 -0
  13. package/dist/llm/executor/provider-options.d.ts +49 -0
  14. package/dist/llm/executor/provider-options.d.ts.map +1 -0
  15. package/dist/llm/executor/provider-options.js +63 -0
  16. package/dist/llm/executor/stream-processor.cjs +11 -8
  17. package/dist/llm/executor/stream-processor.d.ts.map +1 -1
  18. package/dist/llm/executor/stream-processor.js +11 -8
  19. package/dist/llm/executor/turn-executor.cjs +12 -1
  20. package/dist/llm/executor/turn-executor.d.ts +2 -1
  21. package/dist/llm/executor/turn-executor.d.ts.map +1 -1
  22. package/dist/llm/executor/turn-executor.js +12 -1
  23. package/dist/llm/formatters/vercel.cjs +9 -1
  24. package/dist/llm/formatters/vercel.d.ts.map +1 -1
  25. package/dist/llm/formatters/vercel.js +9 -1
  26. package/dist/llm/registry.cjs +69 -0
  27. package/dist/llm/registry.d.ts +9 -0
  28. package/dist/llm/registry.d.ts.map +1 -1
  29. package/dist/llm/registry.js +68 -0
  30. package/dist/llm/schemas.cjs +18 -2
  31. package/dist/llm/schemas.d.ts +34 -11
  32. package/dist/llm/schemas.d.ts.map +1 -1
  33. package/dist/llm/schemas.js +18 -2
  34. package/dist/llm/services/vercel.cjs +3 -1
  35. package/dist/llm/services/vercel.d.ts.map +1 -1
  36. package/dist/llm/services/vercel.js +3 -1
  37. package/dist/logger/logger.cjs +7 -3
  38. package/dist/logger/logger.d.ts.map +1 -1
  39. package/dist/logger/logger.js +7 -3
  40. package/dist/memory/schemas.d.ts +2 -2
  41. package/dist/providers/discovery.cjs +14 -0
  42. package/dist/providers/discovery.d.ts +4 -2
  43. package/dist/providers/discovery.d.ts.map +1 -1
  44. package/dist/providers/discovery.js +14 -0
  45. package/dist/session/history/database.cjs +49 -15
  46. package/dist/session/history/database.d.ts.map +1 -1
  47. package/dist/session/history/database.js +49 -15
  48. package/dist/session/session-manager.cjs +2 -1
  49. package/dist/session/session-manager.d.ts.map +1 -1
  50. package/dist/session/session-manager.js +2 -1
  51. package/dist/storage/database/postgres-store.cjs +174 -78
  52. package/dist/storage/database/postgres-store.d.ts +19 -0
  53. package/dist/storage/database/postgres-store.d.ts.map +1 -1
  54. package/dist/storage/database/postgres-store.js +174 -78
  55. package/dist/storage/database/schemas.cjs +4 -1
  56. package/dist/storage/database/schemas.d.ts +8 -0
  57. package/dist/storage/database/schemas.d.ts.map +1 -1
  58. package/dist/storage/database/schemas.js +4 -1
  59. package/dist/storage/schemas.d.ts +7 -0
  60. package/dist/storage/schemas.d.ts.map +1 -1
  61. package/dist/tools/custom-tool-registry.d.ts +9 -3
  62. package/dist/tools/custom-tool-registry.d.ts.map +1 -1
  63. package/dist/tools/internal-tools/provider.cjs +5 -2
  64. package/dist/tools/internal-tools/provider.d.ts.map +1 -1
  65. package/dist/tools/internal-tools/provider.js +5 -2
  66. package/dist/tools/tool-manager.cjs +1 -1
  67. package/dist/tools/tool-manager.d.ts.map +1 -1
  68. package/dist/tools/tool-manager.js +1 -1
  69. package/dist/utils/safe-stringify.cjs +10 -6
  70. package/dist/utils/safe-stringify.d.ts +5 -2
  71. package/dist/utils/safe-stringify.d.ts.map +1 -1
  72. package/dist/utils/safe-stringify.js +10 -6
  73. package/package.json +1 -1
@@ -28,8 +28,8 @@ export declare const MemorySchema: z.ZodObject<{
28
28
  }, z.ZodTypeAny, "passthrough">>>;
29
29
  }, "strict", z.ZodTypeAny, {
30
30
  content: string;
31
- id: string;
32
31
  createdAt: number;
32
+ id: string;
33
33
  updatedAt: number;
34
34
  metadata?: z.objectOutputType<{
35
35
  source: z.ZodOptional<z.ZodEnum<["user", "system"]>>;
@@ -38,8 +38,8 @@ export declare const MemorySchema: z.ZodObject<{
38
38
  tags?: string[] | undefined;
39
39
  }, {
40
40
  content: string;
41
- id: string;
42
41
  createdAt: number;
42
+ id: string;
43
43
  updatedAt: number;
44
44
  metadata?: z.objectInputType<{
45
45
  source: z.ZodOptional<z.ZodEnum<["user", "system"]>>;
@@ -24,6 +24,7 @@ __export(discovery_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(discovery_exports);
26
26
  var import_blob = require("../storage/blob/index.js");
27
+ var import_database = require("../storage/database/index.js");
27
28
  var import_compaction = require("../context/compaction/index.js");
28
29
  var import_custom_tool_registry = require("../tools/custom-tool-registry.js");
29
30
  var import_constants = require("../tools/internal-tools/constants.js");
@@ -60,12 +61,23 @@ function listAllProviders() {
60
61
  }
61
62
  return info;
62
63
  });
64
+ const databaseProviders = import_database.databaseRegistry.getProviders().map((provider) => {
65
+ const info = {
66
+ type: provider.type,
67
+ category: "database"
68
+ };
69
+ if (provider.metadata) {
70
+ info.metadata = provider.metadata;
71
+ }
72
+ return info;
73
+ });
63
74
  const internalTools = import_constants.INTERNAL_TOOL_NAMES.map((name) => ({
64
75
  name,
65
76
  description: import_registry.INTERNAL_TOOL_REGISTRY[name].description
66
77
  }));
67
78
  return {
68
79
  blob: blobProviders,
80
+ database: databaseProviders,
69
81
  compaction: compactionProviders,
70
82
  customTools: customToolProviders,
71
83
  internalTools
@@ -79,6 +91,8 @@ function hasProvider(category, type) {
79
91
  switch (category) {
80
92
  case "blob":
81
93
  return import_blob.blobStoreRegistry.has(type);
94
+ case "database":
95
+ return import_database.databaseRegistry.has(type);
82
96
  case "compaction":
83
97
  return import_compaction.compactionRegistry.has(type);
84
98
  case "customTools":
@@ -5,7 +5,7 @@ export interface DiscoveredProvider {
5
5
  /** Provider type identifier (e.g., 'local', 's3', 'reactive-overflow') */
6
6
  type: string;
7
7
  /** Provider category */
8
- category: 'blob' | 'compaction' | 'customTools';
8
+ category: 'blob' | 'database' | 'compaction' | 'customTools';
9
9
  /** Optional metadata about the provider */
10
10
  metadata?: {
11
11
  displayName?: string;
@@ -28,6 +28,8 @@ export interface InternalToolDiscovery {
28
28
  export interface ProviderDiscovery {
29
29
  /** Blob storage providers */
30
30
  blob: DiscoveredProvider[];
31
+ /** Database providers */
32
+ database: DiscoveredProvider[];
31
33
  /** Compaction strategy providers */
32
34
  compaction: DiscoveredProvider[];
33
35
  /** Custom tool providers */
@@ -38,7 +40,7 @@ export interface ProviderDiscovery {
38
40
  /**
39
41
  * Provider category type.
40
42
  */
41
- export type ProviderCategory = 'blob' | 'compaction' | 'customTools';
43
+ export type ProviderCategory = 'blob' | 'database' | 'compaction' | 'customTools';
42
44
  /**
43
45
  * List all registered providers across all registries.
44
46
  *
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/providers/discovery.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IAEb,wBAAwB;IACxB,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;IAEhD,2CAA2C;IAC3C,QAAQ,CAAC,EACH;QACI,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,GACD,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IAEb,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAE3B,oCAAoC;IACpC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IAEjC,4BAA4B;IAC5B,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAElC,iDAAiD;IACjD,aAAa,EAAE,qBAAqB,EAAE,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,aAAa,CAAC;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CAkDpD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,kBAAkB,EAAE,CAGvF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAW7E"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/providers/discovery.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IAEb,wBAAwB;IACxB,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,aAAa,CAAC;IAE7D,2CAA2C;IAC3C,QAAQ,CAAC,EACH;QACI,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,GACD,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IAEb,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,6BAA6B;IAC7B,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAE3B,yBAAyB;IACzB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAE/B,oCAAoC;IACpC,UAAU,EAAE,kBAAkB,EAAE,CAAC;IAEjC,4BAA4B;IAC5B,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAElC,iDAAiD;IACjD,aAAa,EAAE,qBAAqB,EAAE,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,aAAa,CAAC;AAElF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CA+DpD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,kBAAkB,EAAE,CAGvF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAa7E"}
@@ -1,5 +1,6 @@
1
1
  import "../chunk-PTJYTZNU.js";
2
2
  import { blobStoreRegistry } from "../storage/blob/index.js";
3
+ import { databaseRegistry } from "../storage/database/index.js";
3
4
  import { compactionRegistry } from "../context/compaction/index.js";
4
5
  import { customToolRegistry } from "../tools/custom-tool-registry.js";
5
6
  import { INTERNAL_TOOL_NAMES } from "../tools/internal-tools/constants.js";
@@ -36,12 +37,23 @@ function listAllProviders() {
36
37
  }
37
38
  return info;
38
39
  });
40
+ const databaseProviders = databaseRegistry.getProviders().map((provider) => {
41
+ const info = {
42
+ type: provider.type,
43
+ category: "database"
44
+ };
45
+ if (provider.metadata) {
46
+ info.metadata = provider.metadata;
47
+ }
48
+ return info;
49
+ });
39
50
  const internalTools = INTERNAL_TOOL_NAMES.map((name) => ({
40
51
  name,
41
52
  description: INTERNAL_TOOL_REGISTRY[name].description
42
53
  }));
43
54
  return {
44
55
  blob: blobProviders,
56
+ database: databaseProviders,
45
57
  compaction: compactionProviders,
46
58
  customTools: customToolProviders,
47
59
  internalTools
@@ -55,6 +67,8 @@ function hasProvider(category, type) {
55
67
  switch (category) {
56
68
  case "blob":
57
69
  return blobStoreRegistry.has(type);
70
+ case "database":
71
+ return databaseRegistry.has(type);
58
72
  case "compaction":
59
73
  return compactionRegistry.has(type);
60
74
  case "customTools":
@@ -42,10 +42,37 @@ class DatabaseHistoryProvider {
42
42
  if (this.cache === null) {
43
43
  const key = this.getMessagesKey();
44
44
  try {
45
- this.cache = await this.database.getRange(key, 0, 1e4);
46
- this.logger.debug(
47
- `DatabaseHistoryProvider: Loaded ${this.cache.length} messages from DB for session ${this.sessionId}`
48
- );
45
+ const limit = 1e4;
46
+ const rawMessages = await this.database.getRange(key, 0, limit);
47
+ if (rawMessages.length === limit) {
48
+ this.logger.warn(
49
+ `DatabaseHistoryProvider: Session ${this.sessionId} hit message limit (${limit}), history may be truncated`
50
+ );
51
+ }
52
+ const seen = /* @__PURE__ */ new Set();
53
+ this.cache = [];
54
+ let duplicateCount = 0;
55
+ for (const msg of rawMessages) {
56
+ if (msg.id && seen.has(msg.id)) {
57
+ duplicateCount++;
58
+ continue;
59
+ }
60
+ if (msg.id) {
61
+ seen.add(msg.id);
62
+ }
63
+ this.cache.push(msg);
64
+ }
65
+ if (duplicateCount > 0) {
66
+ this.logger.warn(
67
+ `DatabaseHistoryProvider: Found ${duplicateCount} duplicate messages for session ${this.sessionId}, deduped to ${this.cache.length}`
68
+ );
69
+ this.dirty = true;
70
+ this.scheduleFlush();
71
+ } else {
72
+ this.logger.debug(
73
+ `DatabaseHistoryProvider: Loaded ${this.cache.length} messages for session ${this.sessionId}`
74
+ );
75
+ }
49
76
  } catch (error) {
50
77
  this.logger.error(
51
78
  `DatabaseHistoryProvider: Error loading messages for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
@@ -64,15 +91,17 @@ class DatabaseHistoryProvider {
64
91
  if (this.cache === null) {
65
92
  await this.getHistory();
66
93
  }
94
+ if (message.id && this.cache.some((m) => m.id === message.id)) {
95
+ this.logger.debug(
96
+ `DatabaseHistoryProvider: Message ${message.id} already exists, skipping`
97
+ );
98
+ return;
99
+ }
67
100
  this.cache.push(message);
68
101
  try {
69
102
  await this.database.append(key, message);
70
103
  this.logger.debug(
71
- `DatabaseHistoryProvider: Saved message for session ${this.sessionId}`,
72
- {
73
- role: message.role,
74
- id: message.id
75
- }
104
+ `DatabaseHistoryProvider: Saved message ${message.id} (${message.role}) for session ${this.sessionId}`
76
105
  );
77
106
  } catch (error) {
78
107
  this.cache.pop();
@@ -159,18 +188,23 @@ class DatabaseHistoryProvider {
159
188
  return;
160
189
  }
161
190
  const key = this.getMessagesKey();
162
- const messageCount = this.cache.length;
191
+ const snapshot = [...this.cache];
192
+ const messageCount = snapshot.length;
193
+ this.logger.debug(
194
+ `DatabaseHistoryProvider: FLUSH START key=${key} snapshotSize=${messageCount} ids=[${snapshot.map((m) => m.id).join(",")}]`
195
+ );
163
196
  try {
164
197
  await this.database.delete(key);
165
- for (const msg of this.cache) {
198
+ this.logger.debug(`DatabaseHistoryProvider: FLUSH DELETED key=${key}`);
199
+ for (const msg of snapshot) {
166
200
  await this.database.append(key, msg);
167
201
  }
202
+ this.logger.debug(
203
+ `DatabaseHistoryProvider: FLUSH REAPPENDED key=${key} count=${messageCount}`
204
+ );
168
205
  if (!this.flushTimer) {
169
206
  this.dirty = false;
170
207
  }
171
- this.logger.debug(
172
- `DatabaseHistoryProvider: Flushed ${messageCount} messages to DB for session ${this.sessionId}`
173
- );
174
208
  } catch (error) {
175
209
  this.logger.error(
176
210
  `DatabaseHistoryProvider: Error flushing messages for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
@@ -192,7 +226,7 @@ class DatabaseHistoryProvider {
192
226
  }
193
227
  this.flushTimer = setTimeout(() => {
194
228
  this.flushTimer = null;
195
- this.doFlush().catch(() => {
229
+ this.flush().catch(() => {
196
230
  });
197
231
  }, DatabaseHistoryProvider.FLUSH_DELAY_MS);
198
232
  }
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/session/history/database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,uBAAwB,YAAW,4BAA4B;IAapE,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ;IAbpB,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,YAAY,CAA8B;IAGlD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;gBAGjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAC1B,MAAM,EAAE,YAAY;IAKlB,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAyBxC,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCpD,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCtD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BnC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;;OAGG;YACW,OAAO;IAoCrB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;CAGzB"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/session/history/database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,uBAAwB,YAAW,4BAA4B;IAapE,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ;IAbpB,OAAO,CAAC,MAAM,CAAe;IAG7B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,YAAY,CAA8B;IAGlD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAO;gBAGjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAC1B,MAAM,EAAE,YAAY;IAKlB,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IA2DxC,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCpD,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCtD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BnC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;;OAGG;YACW,OAAO;IA+CrB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;CAGzB"}
@@ -20,10 +20,37 @@ class DatabaseHistoryProvider {
20
20
  if (this.cache === null) {
21
21
  const key = this.getMessagesKey();
22
22
  try {
23
- this.cache = await this.database.getRange(key, 0, 1e4);
24
- this.logger.debug(
25
- `DatabaseHistoryProvider: Loaded ${this.cache.length} messages from DB for session ${this.sessionId}`
26
- );
23
+ const limit = 1e4;
24
+ const rawMessages = await this.database.getRange(key, 0, limit);
25
+ if (rawMessages.length === limit) {
26
+ this.logger.warn(
27
+ `DatabaseHistoryProvider: Session ${this.sessionId} hit message limit (${limit}), history may be truncated`
28
+ );
29
+ }
30
+ const seen = /* @__PURE__ */ new Set();
31
+ this.cache = [];
32
+ let duplicateCount = 0;
33
+ for (const msg of rawMessages) {
34
+ if (msg.id && seen.has(msg.id)) {
35
+ duplicateCount++;
36
+ continue;
37
+ }
38
+ if (msg.id) {
39
+ seen.add(msg.id);
40
+ }
41
+ this.cache.push(msg);
42
+ }
43
+ if (duplicateCount > 0) {
44
+ this.logger.warn(
45
+ `DatabaseHistoryProvider: Found ${duplicateCount} duplicate messages for session ${this.sessionId}, deduped to ${this.cache.length}`
46
+ );
47
+ this.dirty = true;
48
+ this.scheduleFlush();
49
+ } else {
50
+ this.logger.debug(
51
+ `DatabaseHistoryProvider: Loaded ${this.cache.length} messages for session ${this.sessionId}`
52
+ );
53
+ }
27
54
  } catch (error) {
28
55
  this.logger.error(
29
56
  `DatabaseHistoryProvider: Error loading messages for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
@@ -42,15 +69,17 @@ class DatabaseHistoryProvider {
42
69
  if (this.cache === null) {
43
70
  await this.getHistory();
44
71
  }
72
+ if (message.id && this.cache.some((m) => m.id === message.id)) {
73
+ this.logger.debug(
74
+ `DatabaseHistoryProvider: Message ${message.id} already exists, skipping`
75
+ );
76
+ return;
77
+ }
45
78
  this.cache.push(message);
46
79
  try {
47
80
  await this.database.append(key, message);
48
81
  this.logger.debug(
49
- `DatabaseHistoryProvider: Saved message for session ${this.sessionId}`,
50
- {
51
- role: message.role,
52
- id: message.id
53
- }
82
+ `DatabaseHistoryProvider: Saved message ${message.id} (${message.role}) for session ${this.sessionId}`
54
83
  );
55
84
  } catch (error) {
56
85
  this.cache.pop();
@@ -137,18 +166,23 @@ class DatabaseHistoryProvider {
137
166
  return;
138
167
  }
139
168
  const key = this.getMessagesKey();
140
- const messageCount = this.cache.length;
169
+ const snapshot = [...this.cache];
170
+ const messageCount = snapshot.length;
171
+ this.logger.debug(
172
+ `DatabaseHistoryProvider: FLUSH START key=${key} snapshotSize=${messageCount} ids=[${snapshot.map((m) => m.id).join(",")}]`
173
+ );
141
174
  try {
142
175
  await this.database.delete(key);
143
- for (const msg of this.cache) {
176
+ this.logger.debug(`DatabaseHistoryProvider: FLUSH DELETED key=${key}`);
177
+ for (const msg of snapshot) {
144
178
  await this.database.append(key, msg);
145
179
  }
180
+ this.logger.debug(
181
+ `DatabaseHistoryProvider: FLUSH REAPPENDED key=${key} count=${messageCount}`
182
+ );
146
183
  if (!this.flushTimer) {
147
184
  this.dirty = false;
148
185
  }
149
- this.logger.debug(
150
- `DatabaseHistoryProvider: Flushed ${messageCount} messages to DB for session ${this.sessionId}`
151
- );
152
186
  } catch (error) {
153
187
  this.logger.error(
154
188
  `DatabaseHistoryProvider: Error flushing messages for session ${this.sessionId}: ${error instanceof Error ? error.message : String(error)}`
@@ -170,7 +204,7 @@ class DatabaseHistoryProvider {
170
204
  }
171
205
  this.flushTimer = setTimeout(() => {
172
206
  this.flushTimer = null;
173
- this.doFlush().catch(() => {
207
+ this.flush().catch(() => {
174
208
  });
175
209
  }, DatabaseHistoryProvider.FLUSH_DELAY_MS);
176
210
  }
@@ -245,13 +245,14 @@ class SessionManager {
245
245
  await this.ensureInitialized();
246
246
  const session = await this.getSession(sessionId);
247
247
  if (session) {
248
- await session.reset();
249
248
  await session.cleanup();
250
249
  this.sessions.delete(sessionId);
251
250
  }
252
251
  const sessionKey = `session:${sessionId}`;
253
252
  await this.services.storageManager.getDatabase().delete(sessionKey);
254
253
  await this.services.storageManager.getCache().delete(sessionKey);
254
+ const messagesKey = `messages:${sessionId}`;
255
+ await this.services.storageManager.getDatabase().delete(messagesKey);
255
256
  this.logger.debug(`Deleted session and conversation history: ${sessionId}`);
256
257
  }
257
258
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"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"}
@@ -223,13 +223,14 @@ class SessionManager {
223
223
  await this.ensureInitialized();
224
224
  const session = await this.getSession(sessionId);
225
225
  if (session) {
226
- await session.reset();
227
226
  await session.cleanup();
228
227
  this.sessions.delete(sessionId);
229
228
  }
230
229
  const sessionKey = `session:${sessionId}`;
231
230
  await this.services.storageManager.getDatabase().delete(sessionKey);
232
231
  await this.services.storageManager.getCache().delete(sessionKey);
232
+ const messagesKey = `messages:${sessionId}`;
233
+ await this.services.storageManager.getDatabase().delete(messagesKey);
233
234
  this.logger.debug(`Deleted session and conversation history: ${sessionId}`);
234
235
  }
235
236
  /**