@ixo/sqlite-saver 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +9 -0
- package/.prettierignore +3 -0
- package/.prettierrc.js +4 -0
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +25 -0
- package/README.md +0 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +567 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/001_add_created_at_to_messages.d.ts +8 -0
- package/dist/migrations/001_add_created_at_to_messages.d.ts.map +1 -0
- package/dist/migrations/001_add_created_at_to_messages.js +32 -0
- package/dist/migrations/001_add_created_at_to_messages.js.map +1 -0
- package/dist/tests/agent-with-checkpoiner.test.d.ts +2 -0
- package/dist/tests/agent-with-checkpoiner.test.d.ts.map +1 -0
- package/dist/tests/agent-with-checkpoiner.test.js +206 -0
- package/dist/tests/agent-with-checkpoiner.test.js.map +1 -0
- package/dist/tests/checkpointer.test.d.ts +2 -0
- package/dist/tests/checkpointer.test.d.ts.map +1 -0
- package/dist/tests/checkpointer.test.js +426 -0
- package/dist/tests/checkpointer.test.js.map +1 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +284 -0
- package/dist/utils.js.map +1 -0
- package/jest.config.js +6 -0
- package/package.json +41 -0
- package/src/index.ts +929 -0
- package/src/migrations/001_add_created_at_to_messages.ts +48 -0
- package/src/tests/agent-with-checkpoiner.test.ts +264 -0
- package/src/tests/checkpointer.test.ts +628 -0
- package/src/utils.ts +358 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/utils.ts
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
4
|
+
// Stringify that can handle circular references.
|
|
5
|
+
// Inlined due to ESM import issues
|
|
6
|
+
// Source: https://www.npmjs.com/package/fast-safe-stringify
|
|
7
|
+
|
|
8
|
+
var LIMIT_REPLACE_NODE = '[...]';
|
|
9
|
+
var CIRCULAR_REPLACE_NODE = '[Circular]';
|
|
10
|
+
|
|
11
|
+
var arr = [];
|
|
12
|
+
var replacerStack = [];
|
|
13
|
+
|
|
14
|
+
function defaultOptions() {
|
|
15
|
+
return {
|
|
16
|
+
depthLimit: Number.MAX_SAFE_INTEGER,
|
|
17
|
+
edgesLimit: Number.MAX_SAFE_INTEGER,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Regular stringify
|
|
22
|
+
export function stringify(obj, replacer?, spacer?, options?) {
|
|
23
|
+
if (typeof options === 'undefined') {
|
|
24
|
+
options = defaultOptions();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
decirc(obj, '', 0, [], undefined, 0, options);
|
|
28
|
+
var res;
|
|
29
|
+
try {
|
|
30
|
+
if (replacerStack.length === 0) {
|
|
31
|
+
res = JSON.stringify(obj, replacer, spacer);
|
|
32
|
+
} else {
|
|
33
|
+
res = JSON.stringify(obj, replaceGetterValues(replacer), spacer);
|
|
34
|
+
}
|
|
35
|
+
} catch (_) {
|
|
36
|
+
return JSON.stringify(
|
|
37
|
+
'[unable to serialize, circular reference is too complex to analyze]',
|
|
38
|
+
);
|
|
39
|
+
} finally {
|
|
40
|
+
while (arr.length !== 0) {
|
|
41
|
+
var part = arr.pop();
|
|
42
|
+
if (part.length === 4) {
|
|
43
|
+
Object.defineProperty(part[0], part[1], part[3]);
|
|
44
|
+
} else {
|
|
45
|
+
part[0][part[1]] = part[2];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return res;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setReplace(replace, val, k, parent) {
|
|
53
|
+
var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k);
|
|
54
|
+
if (propertyDescriptor.get !== undefined) {
|
|
55
|
+
if (propertyDescriptor.configurable) {
|
|
56
|
+
Object.defineProperty(parent, k, { value: replace });
|
|
57
|
+
arr.push([parent, k, val, propertyDescriptor]);
|
|
58
|
+
} else {
|
|
59
|
+
replacerStack.push([val, k, replace]);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
parent[k] = replace;
|
|
63
|
+
arr.push([parent, k, val]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function decirc(val, k, edgeIndex, stack, parent, depth, options) {
|
|
68
|
+
depth += 1;
|
|
69
|
+
var i;
|
|
70
|
+
if (typeof val === 'object' && val !== null) {
|
|
71
|
+
for (i = 0; i < stack.length; i++) {
|
|
72
|
+
if (stack[i] === val) {
|
|
73
|
+
setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
typeof options.depthLimit !== 'undefined' &&
|
|
80
|
+
depth > options.depthLimit
|
|
81
|
+
) {
|
|
82
|
+
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
typeof options.edgesLimit !== 'undefined' &&
|
|
88
|
+
edgeIndex + 1 > options.edgesLimit
|
|
89
|
+
) {
|
|
90
|
+
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
stack.push(val);
|
|
95
|
+
// Optimize for Arrays. Big arrays could kill the performance otherwise!
|
|
96
|
+
if (Array.isArray(val)) {
|
|
97
|
+
for (i = 0; i < val.length; i++) {
|
|
98
|
+
decirc(val[i], i, i, stack, val, depth, options);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
var keys = Object.keys(val);
|
|
102
|
+
for (i = 0; i < keys.length; i++) {
|
|
103
|
+
var key = keys[i];
|
|
104
|
+
decirc(val[key], key, i, stack, val, depth, options);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
stack.pop();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Stable-stringify
|
|
112
|
+
function compareFunction(a, b) {
|
|
113
|
+
if (a < b) {
|
|
114
|
+
return -1;
|
|
115
|
+
}
|
|
116
|
+
if (a > b) {
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function deterministicStringify(obj, replacer, spacer, options) {
|
|
123
|
+
if (typeof options === 'undefined') {
|
|
124
|
+
options = defaultOptions();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
var tmp = deterministicDecirc(obj, '', 0, [], undefined, 0, options) || obj;
|
|
128
|
+
var res;
|
|
129
|
+
try {
|
|
130
|
+
if (replacerStack.length === 0) {
|
|
131
|
+
res = JSON.stringify(tmp, replacer, spacer);
|
|
132
|
+
} else {
|
|
133
|
+
res = JSON.stringify(tmp, replaceGetterValues(replacer), spacer);
|
|
134
|
+
}
|
|
135
|
+
} catch (_) {
|
|
136
|
+
return JSON.stringify(
|
|
137
|
+
'[unable to serialize, circular reference is too complex to analyze]',
|
|
138
|
+
);
|
|
139
|
+
} finally {
|
|
140
|
+
// Ensure that we restore the object as it was.
|
|
141
|
+
while (arr.length !== 0) {
|
|
142
|
+
var part = arr.pop();
|
|
143
|
+
if (part.length === 4) {
|
|
144
|
+
Object.defineProperty(part[0], part[1], part[3]);
|
|
145
|
+
} else {
|
|
146
|
+
part[0][part[1]] = part[2];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return res;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function deterministicDecirc(val, k, edgeIndex, stack, parent, depth, options) {
|
|
154
|
+
depth += 1;
|
|
155
|
+
var i;
|
|
156
|
+
if (typeof val === 'object' && val !== null) {
|
|
157
|
+
for (i = 0; i < stack.length; i++) {
|
|
158
|
+
if (stack[i] === val) {
|
|
159
|
+
setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
if (typeof val.toJSON === 'function') {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
} catch (_) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (
|
|
172
|
+
typeof options.depthLimit !== 'undefined' &&
|
|
173
|
+
depth > options.depthLimit
|
|
174
|
+
) {
|
|
175
|
+
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (
|
|
180
|
+
typeof options.edgesLimit !== 'undefined' &&
|
|
181
|
+
edgeIndex + 1 > options.edgesLimit
|
|
182
|
+
) {
|
|
183
|
+
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
stack.push(val);
|
|
188
|
+
// Optimize for Arrays. Big arrays could kill the performance otherwise!
|
|
189
|
+
if (Array.isArray(val)) {
|
|
190
|
+
for (i = 0; i < val.length; i++) {
|
|
191
|
+
deterministicDecirc(val[i], i, i, stack, val, depth, options);
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
// Create a temporary object in the required way
|
|
195
|
+
var tmp = {};
|
|
196
|
+
var keys = Object.keys(val).sort(compareFunction);
|
|
197
|
+
for (i = 0; i < keys.length; i++) {
|
|
198
|
+
var key = keys[i];
|
|
199
|
+
deterministicDecirc(val[key], key, i, stack, val, depth, options);
|
|
200
|
+
tmp[key] = val[key];
|
|
201
|
+
}
|
|
202
|
+
if (typeof parent !== 'undefined') {
|
|
203
|
+
arr.push([parent, k, val]);
|
|
204
|
+
parent[k] = tmp;
|
|
205
|
+
} else {
|
|
206
|
+
return tmp;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
stack.pop();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// wraps replacer function to handle values we couldn't replace
|
|
214
|
+
// and mark them as replaced value
|
|
215
|
+
function replaceGetterValues(replacer) {
|
|
216
|
+
replacer =
|
|
217
|
+
typeof replacer !== 'undefined'
|
|
218
|
+
? replacer
|
|
219
|
+
: function (k, v) {
|
|
220
|
+
return v;
|
|
221
|
+
};
|
|
222
|
+
return function (key, val) {
|
|
223
|
+
if (replacerStack.length > 0) {
|
|
224
|
+
for (var i = 0; i < replacerStack.length; i++) {
|
|
225
|
+
var part = replacerStack[i];
|
|
226
|
+
if (part[1] === key && part[0] === val) {
|
|
227
|
+
val = part[2];
|
|
228
|
+
replacerStack.splice(i, 1);
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return replacer.call(this, key, val);
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function _encodeConstructorArgs(
|
|
238
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
239
|
+
constructor: Function,
|
|
240
|
+
method?: string,
|
|
241
|
+
args?: any[],
|
|
242
|
+
kwargs?: Record<string, any>
|
|
243
|
+
): object {
|
|
244
|
+
return {
|
|
245
|
+
lc: 2,
|
|
246
|
+
type: "constructor",
|
|
247
|
+
id: [constructor.name],
|
|
248
|
+
method: method ?? null,
|
|
249
|
+
args: args ?? [],
|
|
250
|
+
kwargs: kwargs ?? {},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function _default(obj: any): any {
|
|
255
|
+
if (obj === undefined) {
|
|
256
|
+
return {
|
|
257
|
+
lc: 2,
|
|
258
|
+
type: 'undefined',
|
|
259
|
+
};
|
|
260
|
+
} else if (obj instanceof Set || obj instanceof Map) {
|
|
261
|
+
return _encodeConstructorArgs(obj.constructor, undefined, [
|
|
262
|
+
Array.from(obj),
|
|
263
|
+
]);
|
|
264
|
+
} else if (obj instanceof RegExp) {
|
|
265
|
+
return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);
|
|
266
|
+
} else if (obj instanceof Error) {
|
|
267
|
+
return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);
|
|
268
|
+
// TODO: Remove special case
|
|
269
|
+
} else if (obj?.lg_name === 'Send') {
|
|
270
|
+
return {
|
|
271
|
+
node: obj.node,
|
|
272
|
+
args: obj.args,
|
|
273
|
+
};
|
|
274
|
+
} else {
|
|
275
|
+
return obj;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export interface CleanAdditionalKwargs {
|
|
280
|
+
msgFromMatrixRoom: boolean;
|
|
281
|
+
timestamp: string;
|
|
282
|
+
oracleName: string;
|
|
283
|
+
reasoning?: string;
|
|
284
|
+
reasoningDetails?: Array<{
|
|
285
|
+
type: string;
|
|
286
|
+
text: string;
|
|
287
|
+
}>;
|
|
288
|
+
[key: string]: unknown; // Allow additional properties for LangChain compatibility
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Cleans up additional_kwargs by extracting reasoning information and keeping only essential fields
|
|
293
|
+
* @param additionalKwargs - The original additional_kwargs object
|
|
294
|
+
* @param msgFromMatrixRoom - Whether the message came from Matrix room
|
|
295
|
+
* @returns Cleaned additional_kwargs with only essential fields
|
|
296
|
+
*/
|
|
297
|
+
export function cleanAdditionalKwargs(
|
|
298
|
+
additionalKwargs: any,
|
|
299
|
+
msgFromMatrixRoom: boolean,
|
|
300
|
+
): CleanAdditionalKwargs {
|
|
301
|
+
// Extract reasoning information from raw response
|
|
302
|
+
// Note: Reasoning is only available when the AI model supports it (e.g., GPT-OSS-120B with include_reasoning: true)
|
|
303
|
+
const rawResponse = additionalKwargs.__raw_response as any;
|
|
304
|
+
|
|
305
|
+
// Check if reasoning exists in the response
|
|
306
|
+
// Reasoning will not be present in all AI responses, only when the model supports it
|
|
307
|
+
const hasReasoning = rawResponse?.choices?.[0]?.delta?.reasoning;
|
|
308
|
+
const reasoning = hasReasoning
|
|
309
|
+
? rawResponse.choices[0].delta.reasoning
|
|
310
|
+
: undefined;
|
|
311
|
+
const reasoningDetails =
|
|
312
|
+
hasReasoning && rawResponse.choices[0].delta.reasoning_details
|
|
313
|
+
? rawResponse.choices[0].delta.reasoning_details
|
|
314
|
+
: undefined;
|
|
315
|
+
|
|
316
|
+
// Return cleaned additional_kwargs with only essential fields
|
|
317
|
+
const cleanedKwargs: CleanAdditionalKwargs = {
|
|
318
|
+
msgFromMatrixRoom,
|
|
319
|
+
timestamp: new Date().toISOString(),
|
|
320
|
+
oracleName: process.env.ORACLE_NAME || 'IXO Oracle',
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// Add reasoning fields only if they exist
|
|
324
|
+
if (reasoning) {
|
|
325
|
+
cleanedKwargs.reasoning = reasoning;
|
|
326
|
+
}
|
|
327
|
+
if (
|
|
328
|
+
reasoningDetails &&
|
|
329
|
+
Array.isArray(reasoningDetails) &&
|
|
330
|
+
reasoningDetails.length > 0
|
|
331
|
+
) {
|
|
332
|
+
// Clean up reasoning details - remove useless format field and keep only useful data
|
|
333
|
+
cleanedKwargs.reasoningDetails = reasoningDetails
|
|
334
|
+
.filter(
|
|
335
|
+
(
|
|
336
|
+
detail,
|
|
337
|
+
): detail is NonNullable<
|
|
338
|
+
CleanAdditionalKwargs['reasoningDetails']
|
|
339
|
+
>[number] => {
|
|
340
|
+
// Type guard to ensure detail has required properties
|
|
341
|
+
return (
|
|
342
|
+
detail &&
|
|
343
|
+
typeof detail === 'object' &&
|
|
344
|
+
typeof detail.type === 'string' &&
|
|
345
|
+
typeof detail.text === 'string' &&
|
|
346
|
+
detail.text.trim().length > 0 // Only keep details with actual text content
|
|
347
|
+
);
|
|
348
|
+
},
|
|
349
|
+
)
|
|
350
|
+
.map((detail) => ({
|
|
351
|
+
type: detail.type,
|
|
352
|
+
text: detail.text,
|
|
353
|
+
// Skip index and format fields - not useful
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return cleanedKwargs;
|
|
358
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@ixo/typescript-config/nestjs.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": "./",
|
|
5
|
+
"outDir": "./dist",
|
|
6
|
+
"rootDir": "./src",
|
|
7
|
+
"allowSyntheticDefaultImports": true
|
|
8
|
+
},
|
|
9
|
+
"include": ["src/**/*"],
|
|
10
|
+
"exclude": ["node_modules", "dist", "coverage", "migrations"]
|
|
11
|
+
}
|