@nocobase/plugin-ai 2.0.17 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +14 -14
- package/dist/node_modules/fast-glob/package.json +1 -1
- package/dist/node_modules/flexsearch/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/checkpoints/cleaner.d.ts +28 -0
- package/dist/server/ai-employees/checkpoints/cleaner.js +140 -0
- package/dist/server/ai-employees/checkpoints/index.d.ts +2 -36
- package/dist/server/ai-employees/checkpoints/index.js +5 -561
- package/dist/server/ai-employees/checkpoints/saver.d.ts +44 -0
- package/dist/server/ai-employees/checkpoints/saver.js +595 -0
- package/dist/server/manager/built-in-manager.js +1 -1
- package/dist/server/plugin.js +14 -0
- package/package.json +2 -2
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var saver_exports = {};
|
|
28
|
+
__export(saver_exports, {
|
|
29
|
+
SequelizeCollectionSaver: () => SequelizeCollectionSaver
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(saver_exports);
|
|
32
|
+
var import_langgraph_checkpoint = require("@langchain/langgraph-checkpoint");
|
|
33
|
+
var import_database = require("@nocobase/database");
|
|
34
|
+
class SequelizeCollectionSaver extends import_langgraph_checkpoint.BaseCheckpointSaver {
|
|
35
|
+
constructor(provideCollectionManager, serde) {
|
|
36
|
+
super(serde);
|
|
37
|
+
this.provideCollectionManager = provideCollectionManager;
|
|
38
|
+
}
|
|
39
|
+
async getTuple(config) {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
const { thread_id, checkpoint_ns = "", checkpoint_id } = config.configurable ?? {};
|
|
42
|
+
let findOptions;
|
|
43
|
+
if (checkpoint_id) {
|
|
44
|
+
findOptions = {
|
|
45
|
+
where: {
|
|
46
|
+
threadId: thread_id,
|
|
47
|
+
checkpointNs: checkpoint_ns,
|
|
48
|
+
checkpointId: checkpoint_id
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
} else {
|
|
52
|
+
findOptions = {
|
|
53
|
+
where: {
|
|
54
|
+
threadId: thread_id,
|
|
55
|
+
checkpointNs: checkpoint_ns
|
|
56
|
+
},
|
|
57
|
+
order: [["checkpointId", "DESC"]],
|
|
58
|
+
limit: 1
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const checkpointRow = (_a = await this.checkpointsModel.findOne(findOptions)) == null ? void 0 : _a.toJSON();
|
|
62
|
+
if (!checkpointRow) {
|
|
63
|
+
return void 0;
|
|
64
|
+
}
|
|
65
|
+
const { threadId, checkpointNs, checkpointId, parentCheckpointId } = checkpointRow;
|
|
66
|
+
checkpointRow.channelValues = [];
|
|
67
|
+
for (const [channel, version] of Object.entries(checkpointRow.checkpoint.channel_versions ?? {})) {
|
|
68
|
+
const blob = (_b = await this.checkpointBlobsModel.findOne({
|
|
69
|
+
where: {
|
|
70
|
+
threadId,
|
|
71
|
+
checkpointNs,
|
|
72
|
+
channel,
|
|
73
|
+
version: String(version)
|
|
74
|
+
}
|
|
75
|
+
})) == null ? void 0 : _b.toJSON();
|
|
76
|
+
if (!blob) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
checkpointRow.channelValues.push([
|
|
80
|
+
new TextEncoder().encode(blob.channel),
|
|
81
|
+
new TextEncoder().encode(blob.type),
|
|
82
|
+
blob.blob ? Uint8Array.from(blob.blob) : null
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
const checkpointWrites = await this.getCheckpointWrites([threadId], checkpointNs, checkpointId);
|
|
86
|
+
checkpointRow.pendingWrites = checkpointWrites[`${threadId}:${checkpointNs}:${checkpointId}`];
|
|
87
|
+
if (checkpointRow.checkpoint.v < 4 && checkpointRow.parentCheckpointId != null) {
|
|
88
|
+
const sendsResult = await this.getPendingSends([threadId]);
|
|
89
|
+
const pendingSends = sendsResult[`${threadId}:${parentCheckpointId}`];
|
|
90
|
+
if (pendingSends == null ? void 0 : pendingSends.length) {
|
|
91
|
+
await this._migratePendingSends(pendingSends, checkpointRow);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const checkpoint = await this._loadCheckpoint(checkpointRow.checkpoint, checkpointRow.channelValues);
|
|
95
|
+
const finalConfig = {
|
|
96
|
+
configurable: {
|
|
97
|
+
thread_id,
|
|
98
|
+
checkpoint_ns,
|
|
99
|
+
checkpoint_id: checkpointId
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const metadata = await this._loadMetadata(checkpointRow.metadata);
|
|
103
|
+
const parentConfig = parentCheckpointId ? {
|
|
104
|
+
configurable: {
|
|
105
|
+
thread_id,
|
|
106
|
+
checkpoint_ns,
|
|
107
|
+
checkpoint_id: parentCheckpointId
|
|
108
|
+
}
|
|
109
|
+
} : void 0;
|
|
110
|
+
const pendingWrites = await this._loadWrites(checkpointRow.pendingWrites);
|
|
111
|
+
return {
|
|
112
|
+
config: finalConfig,
|
|
113
|
+
checkpoint,
|
|
114
|
+
metadata,
|
|
115
|
+
parentConfig,
|
|
116
|
+
pendingWrites
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
async *list(config, options) {
|
|
120
|
+
const { filter, before, limit } = options ?? {};
|
|
121
|
+
const findOptions = this._searchWhere(config, filter, before);
|
|
122
|
+
findOptions.order = [["checkpointId", "DESC"]];
|
|
123
|
+
if (limit !== void 0) {
|
|
124
|
+
findOptions.limit = Number.parseInt(limit.toString(), 10);
|
|
125
|
+
}
|
|
126
|
+
const result = (await this.checkpointsModel.findAll(findOptions)).map((x) => x.toJSON());
|
|
127
|
+
const [checkpointWrites, checkpointBlobs] = await Promise.all([
|
|
128
|
+
this.getCheckpointWrites(result.map((x) => x.threadId)),
|
|
129
|
+
this.getCheckpointBlobs(result.map((x) => x.threadId))
|
|
130
|
+
]);
|
|
131
|
+
for (const checkpointRow of result) {
|
|
132
|
+
const { threadId, checkpointNs, checkpointId } = checkpointRow;
|
|
133
|
+
checkpointRow.channelValues = Object.entries(checkpointRow.checkpoint.channel_versions ?? {}).map(([channel, version]) => checkpointBlobs[`${threadId}:${checkpointNs}:${channel}:${version}`]).filter((x) => x == null ? void 0 : x.length).flatMap((x) => [...x]);
|
|
134
|
+
checkpointRow.pendingWrites = checkpointWrites[`${threadId}:${checkpointNs}:${checkpointId}`];
|
|
135
|
+
}
|
|
136
|
+
const toMigrate = result.filter((row) => row.checkpoint.v < 4 && row.parentCheckpointId != null);
|
|
137
|
+
if (toMigrate.length > 0) {
|
|
138
|
+
const sendsResult = await this.getPendingSends(result.map((x) => x.threadId));
|
|
139
|
+
for (const row of toMigrate) {
|
|
140
|
+
const pendingSends = sendsResult[`${row.threadId}:${row.parentCheckpointId}`];
|
|
141
|
+
if (pendingSends == null ? void 0 : pendingSends.length) {
|
|
142
|
+
await this._migratePendingSends(pendingSends, row);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const value of result) {
|
|
147
|
+
yield {
|
|
148
|
+
config: {
|
|
149
|
+
configurable: {
|
|
150
|
+
thread_id: value.threadId,
|
|
151
|
+
checkpoint_ns: value.checkpointNs,
|
|
152
|
+
checkpoint_id: value.checkpointId
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
checkpoint: await this._loadCheckpoint(value.checkpoint, value.channelValues),
|
|
156
|
+
metadata: await this._loadMetadata(value.metadata),
|
|
157
|
+
parentConfig: value.parentCheckpointId ? {
|
|
158
|
+
configurable: {
|
|
159
|
+
thread_id: value.threadId,
|
|
160
|
+
checkpoint_ns: value.checkpointNs,
|
|
161
|
+
checkpoint_id: value.parentCheckpointId
|
|
162
|
+
}
|
|
163
|
+
} : void 0,
|
|
164
|
+
pendingWrites: await this._loadWrites(value.pendingWrites)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async _migratePendingSends(pendingSends, mutableRow) {
|
|
169
|
+
const textEncoder = new TextEncoder();
|
|
170
|
+
const textDecoder = new TextDecoder();
|
|
171
|
+
const row = mutableRow;
|
|
172
|
+
const [enc, blob] = await this.serde.dumpsTyped(
|
|
173
|
+
await Promise.all(pendingSends.map(([enc2, blob2]) => this.serde.loadsTyped(textDecoder.decode(enc2), blob2)))
|
|
174
|
+
);
|
|
175
|
+
row.channelValues ??= [];
|
|
176
|
+
row.channelValues.push([textEncoder.encode(import_langgraph_checkpoint.TASKS), textEncoder.encode(enc), blob]);
|
|
177
|
+
row.checkpoint.channel_versions[import_langgraph_checkpoint.TASKS] = Object.keys(mutableRow.checkpoint.channel_versions).length > 0 ? (0, import_langgraph_checkpoint.maxChannelVersion)(...Object.values(mutableRow.checkpoint.channel_versions)) : this.getNextVersion(void 0);
|
|
178
|
+
}
|
|
179
|
+
async put(config, checkpoint, metadata, newVersions) {
|
|
180
|
+
if (config.configurable === void 0) {
|
|
181
|
+
throw new Error(`Missing "configurable" field in "config" param`);
|
|
182
|
+
}
|
|
183
|
+
const { thread_id, checkpoint_ns = "", checkpoint_id } = config.configurable;
|
|
184
|
+
const nextConfig = {
|
|
185
|
+
configurable: {
|
|
186
|
+
thread_id,
|
|
187
|
+
checkpoint_ns,
|
|
188
|
+
checkpoint_id: checkpoint.id
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const serializedCheckpoint = this._dumpCheckpoint(checkpoint);
|
|
192
|
+
const serializedBlobs = await this._dumpBlobs(thread_id, checkpoint_ns, checkpoint.channel_values, newVersions);
|
|
193
|
+
const serializedMetadata = await this._dumpMetadata(metadata);
|
|
194
|
+
return await this.sequelize.transaction(async (transaction) => {
|
|
195
|
+
const checkpointBlobs = await this.checkpointBlobsModel.findAll({
|
|
196
|
+
where: {
|
|
197
|
+
threadId: thread_id,
|
|
198
|
+
checkpointNs: checkpoint_ns
|
|
199
|
+
},
|
|
200
|
+
attributes: {
|
|
201
|
+
exclude: ["blob"]
|
|
202
|
+
},
|
|
203
|
+
transaction
|
|
204
|
+
});
|
|
205
|
+
const duplicateBlobsFilter = checkpointBlobs.map(({ channel, version }) => `${channel}:${version}`);
|
|
206
|
+
await this.checkpointBlobsModel.bulkCreate(
|
|
207
|
+
serializedBlobs.filter(
|
|
208
|
+
([_threadId, _checkpointNs, channel, version]) => !duplicateBlobsFilter.includes(`${channel}:${version}`)
|
|
209
|
+
).map(([threadId, checkpointNs, channel, version, type, blob]) => ({
|
|
210
|
+
threadId,
|
|
211
|
+
checkpointNs,
|
|
212
|
+
channel,
|
|
213
|
+
version,
|
|
214
|
+
type,
|
|
215
|
+
blob: blob ? Buffer.from(blob) : null
|
|
216
|
+
})),
|
|
217
|
+
{
|
|
218
|
+
transaction
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
const checkPointFindOptions = {
|
|
222
|
+
where: { threadId: thread_id, checkpointNs: checkpoint_ns, checkpointId: checkpoint.id },
|
|
223
|
+
transaction
|
|
224
|
+
};
|
|
225
|
+
const existed = await this.checkpointsModel.count(checkPointFindOptions);
|
|
226
|
+
if (existed === 0) {
|
|
227
|
+
await this.checkpointsModel.create(
|
|
228
|
+
{
|
|
229
|
+
threadId: thread_id,
|
|
230
|
+
checkpointNs: checkpoint_ns,
|
|
231
|
+
checkpointId: checkpoint.id,
|
|
232
|
+
parentCheckpointId: checkpoint_id,
|
|
233
|
+
checkpoint: serializedCheckpoint,
|
|
234
|
+
metadata: serializedMetadata
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
transaction
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
} else {
|
|
241
|
+
await this.checkpointsModel.update(
|
|
242
|
+
{
|
|
243
|
+
checkpoint: serializedCheckpoint,
|
|
244
|
+
metadata: serializedMetadata
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
transaction,
|
|
248
|
+
where: checkPointFindOptions.where
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
return nextConfig;
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
async putWrites(config, writes, taskId) {
|
|
256
|
+
var _a, _b, _c, _d;
|
|
257
|
+
if (!((_a = config.configurable) == null ? void 0 : _a.thread_id)) {
|
|
258
|
+
throw new Error("config.configurable.thread_id is required");
|
|
259
|
+
}
|
|
260
|
+
const dumpedWrites = await this._dumpWrites(
|
|
261
|
+
(_b = config.configurable) == null ? void 0 : _b.thread_id,
|
|
262
|
+
(_c = config.configurable) == null ? void 0 : _c.checkpoint_ns,
|
|
263
|
+
(_d = config.configurable) == null ? void 0 : _d.checkpoint_id,
|
|
264
|
+
taskId,
|
|
265
|
+
writes
|
|
266
|
+
);
|
|
267
|
+
return await this.sequelize.transaction(async (transaction) => {
|
|
268
|
+
var _a2, _b2, _c2;
|
|
269
|
+
const checkpointWrites = await this.checkpointWritesModel.findAll({
|
|
270
|
+
where: {
|
|
271
|
+
threadId: (_a2 = config.configurable) == null ? void 0 : _a2.thread_id,
|
|
272
|
+
checkpointNs: (_b2 = config.configurable) == null ? void 0 : _b2.checkpoint_ns,
|
|
273
|
+
checkpointId: (_c2 = config.configurable) == null ? void 0 : _c2.checkpoint_id,
|
|
274
|
+
taskId
|
|
275
|
+
},
|
|
276
|
+
attributes: {
|
|
277
|
+
exclude: ["blob"]
|
|
278
|
+
},
|
|
279
|
+
transaction
|
|
280
|
+
});
|
|
281
|
+
const duplicateWritesFilter = checkpointWrites.map(
|
|
282
|
+
({ threadId, checkpointNs, checkpointId, taskId: taskId2, idx }) => `${threadId}:${checkpointNs}:${checkpointId}:${taskId2}:${idx}`
|
|
283
|
+
);
|
|
284
|
+
const dumpedWritesInclude = ([threadId, checkpointNs, checkpointId, taskId2, idx]) => duplicateWritesFilter.includes(`${threadId}:${checkpointNs}:${checkpointId}:${taskId2}:${idx}`);
|
|
285
|
+
const dumpedWritesExclude = (item) => !dumpedWritesInclude(item);
|
|
286
|
+
await this.checkpointWritesModel.bulkCreate(
|
|
287
|
+
dumpedWrites.filter(dumpedWritesExclude).map(([threadId, checkpointNs, checkpointId, taskId2, idx, channel, type, blob]) => ({
|
|
288
|
+
threadId,
|
|
289
|
+
checkpointNs,
|
|
290
|
+
checkpointId,
|
|
291
|
+
taskId: taskId2,
|
|
292
|
+
idx,
|
|
293
|
+
channel,
|
|
294
|
+
type,
|
|
295
|
+
blob: blob ? Buffer.from(blob) : null
|
|
296
|
+
})),
|
|
297
|
+
{
|
|
298
|
+
transaction
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
for (const [threadId, checkpointNs, checkpointId, taskId2, idx, channel, type, blob] of dumpedWrites.filter(
|
|
302
|
+
dumpedWritesInclude
|
|
303
|
+
)) {
|
|
304
|
+
await this.checkpointWritesModel.update(
|
|
305
|
+
{
|
|
306
|
+
channel,
|
|
307
|
+
type,
|
|
308
|
+
blob: blob ? Buffer.from(blob) : null
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
where: {
|
|
312
|
+
threadId,
|
|
313
|
+
checkpointNs,
|
|
314
|
+
checkpointId,
|
|
315
|
+
taskId: taskId2,
|
|
316
|
+
idx
|
|
317
|
+
},
|
|
318
|
+
transaction
|
|
319
|
+
}
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
deleteThread(threadId) {
|
|
325
|
+
return this.sequelize.transaction(async (transaction) => {
|
|
326
|
+
await this.checkpointsModel.destroy({
|
|
327
|
+
where: {
|
|
328
|
+
threadId
|
|
329
|
+
},
|
|
330
|
+
transaction
|
|
331
|
+
});
|
|
332
|
+
await this.checkpointBlobsModel.destroy({
|
|
333
|
+
where: {
|
|
334
|
+
threadId
|
|
335
|
+
},
|
|
336
|
+
transaction
|
|
337
|
+
});
|
|
338
|
+
await this.checkpointWritesModel.destroy({
|
|
339
|
+
where: {
|
|
340
|
+
threadId
|
|
341
|
+
},
|
|
342
|
+
transaction
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
async _loadCheckpoint(checkpoint, channelValues) {
|
|
347
|
+
return {
|
|
348
|
+
...checkpoint,
|
|
349
|
+
channel_values: await this._loadBlobs(channelValues)
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
async _loadBlobs(blobValues) {
|
|
353
|
+
if (!blobValues || blobValues.length === 0) {
|
|
354
|
+
return {};
|
|
355
|
+
}
|
|
356
|
+
const textDecoder = new TextDecoder();
|
|
357
|
+
const entries = await Promise.all(
|
|
358
|
+
blobValues.filter(([, t]) => textDecoder.decode(t) !== "empty").map(async ([k, t, v]) => [textDecoder.decode(k), await this.serde.loadsTyped(textDecoder.decode(t), v)])
|
|
359
|
+
);
|
|
360
|
+
return Object.fromEntries(entries);
|
|
361
|
+
}
|
|
362
|
+
async _loadMetadata(metadata) {
|
|
363
|
+
const [type, dumpedValue] = await this.serde.dumpsTyped(metadata);
|
|
364
|
+
return this.serde.loadsTyped(type, dumpedValue);
|
|
365
|
+
}
|
|
366
|
+
async _loadWrites(writes) {
|
|
367
|
+
const decoder = new TextDecoder();
|
|
368
|
+
return writes ? await Promise.all(
|
|
369
|
+
writes.map(async ([tid, channel, t, v]) => [
|
|
370
|
+
decoder.decode(tid),
|
|
371
|
+
decoder.decode(channel),
|
|
372
|
+
await this.serde.loadsTyped(decoder.decode(t), v)
|
|
373
|
+
])
|
|
374
|
+
) : [];
|
|
375
|
+
}
|
|
376
|
+
async _dumpBlobs(threadId, checkpointNs, values, versions) {
|
|
377
|
+
if (Object.keys(versions).length === 0) {
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
return Promise.all(
|
|
381
|
+
Object.entries(versions).map(async ([k, ver]) => {
|
|
382
|
+
const [type, value] = k in values ? await this.serde.dumpsTyped(values[k]) : ["empty", null];
|
|
383
|
+
return [threadId, checkpointNs, k, ver.toString(), type, value ? new Uint8Array(value) : void 0];
|
|
384
|
+
})
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
_dumpCheckpoint(checkpoint) {
|
|
388
|
+
const serialized = { ...checkpoint };
|
|
389
|
+
if ("channel_values" in serialized) delete serialized.channel_values;
|
|
390
|
+
return serialized;
|
|
391
|
+
}
|
|
392
|
+
async _dumpMetadata(metadata) {
|
|
393
|
+
const [, serializedMetadata] = await this.serde.dumpsTyped(metadata);
|
|
394
|
+
return JSON.parse(new TextDecoder().decode(serializedMetadata).replace(/\0/g, ""));
|
|
395
|
+
}
|
|
396
|
+
async _dumpWrites(threadId, checkpointNs, checkpointId, taskId, writes) {
|
|
397
|
+
return Promise.all(
|
|
398
|
+
writes.map(async ([channel, value], idx) => {
|
|
399
|
+
const [type, serializedValue] = await this.serde.dumpsTyped(value);
|
|
400
|
+
return [
|
|
401
|
+
threadId,
|
|
402
|
+
checkpointNs,
|
|
403
|
+
checkpointId,
|
|
404
|
+
taskId,
|
|
405
|
+
import_langgraph_checkpoint.WRITES_IDX_MAP[channel] ?? idx,
|
|
406
|
+
channel,
|
|
407
|
+
type,
|
|
408
|
+
new Uint8Array(serializedValue)
|
|
409
|
+
];
|
|
410
|
+
})
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
_searchWhere(config, filter, before) {
|
|
414
|
+
var _a, _b, _c, _d, _e;
|
|
415
|
+
const findOptions = {};
|
|
416
|
+
if ((_a = config == null ? void 0 : config.configurable) == null ? void 0 : _a.thread_id) {
|
|
417
|
+
if (!findOptions.where) {
|
|
418
|
+
findOptions.where = {};
|
|
419
|
+
}
|
|
420
|
+
findOptions.where["threadId"] = config.configurable.thread_id;
|
|
421
|
+
}
|
|
422
|
+
if (((_b = config == null ? void 0 : config.configurable) == null ? void 0 : _b.checkpoint_ns) !== void 0 && ((_c = config == null ? void 0 : config.configurable) == null ? void 0 : _c.checkpoint_ns) !== null) {
|
|
423
|
+
if (!findOptions.where) {
|
|
424
|
+
findOptions.where = {};
|
|
425
|
+
}
|
|
426
|
+
findOptions.where["checkpointNs"] = config.configurable.checkpoint_ns;
|
|
427
|
+
}
|
|
428
|
+
if ((_d = config == null ? void 0 : config.configurable) == null ? void 0 : _d.checkpoint_id) {
|
|
429
|
+
if (!findOptions.where) {
|
|
430
|
+
findOptions.where = {};
|
|
431
|
+
}
|
|
432
|
+
findOptions.where["checkpointId"] = config.configurable.checkpoint_id;
|
|
433
|
+
}
|
|
434
|
+
if (filter && Object.keys(filter).length > 0) {
|
|
435
|
+
if (!findOptions.where) {
|
|
436
|
+
findOptions.where = {};
|
|
437
|
+
}
|
|
438
|
+
if (this.sequelize.getDialect() === "postgres") {
|
|
439
|
+
findOptions.where["metadata"] = {
|
|
440
|
+
[import_database.Op.contains]: filter
|
|
441
|
+
};
|
|
442
|
+
} else {
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (((_e = before == null ? void 0 : before.configurable) == null ? void 0 : _e.checkpoint_id) !== void 0) {
|
|
446
|
+
if (!findOptions.where) {
|
|
447
|
+
findOptions.where = {};
|
|
448
|
+
}
|
|
449
|
+
findOptions.where["checkpointId"] = {
|
|
450
|
+
$lt: before.configurable.checkpoint_id
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
return findOptions;
|
|
454
|
+
}
|
|
455
|
+
async getCheckpointWrites(threadIds, checkpointNs, checkpointId) {
|
|
456
|
+
if (!(threadIds == null ? void 0 : threadIds.length)) {
|
|
457
|
+
return {};
|
|
458
|
+
}
|
|
459
|
+
const where = {
|
|
460
|
+
threadId: threadIds.length === 1 ? threadIds[0] : {
|
|
461
|
+
[import_database.Op.in]: threadIds
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
if (checkpointNs) {
|
|
465
|
+
where["checkpointNs"] = checkpointNs;
|
|
466
|
+
}
|
|
467
|
+
if (checkpointId) {
|
|
468
|
+
where["checkpointId"] = checkpointId;
|
|
469
|
+
}
|
|
470
|
+
const writes = await this.checkpointWritesModel.findAll({
|
|
471
|
+
where
|
|
472
|
+
});
|
|
473
|
+
const result = {};
|
|
474
|
+
for (const write of writes) {
|
|
475
|
+
const key = `${write.threadId}:${write.checkpointNs}:${write.checkpointId}`;
|
|
476
|
+
if (!result[key]) {
|
|
477
|
+
result[key] = [];
|
|
478
|
+
}
|
|
479
|
+
result[key].push({
|
|
480
|
+
taskId: write.taskId,
|
|
481
|
+
channel: write.channel,
|
|
482
|
+
type: write.type,
|
|
483
|
+
blob: write.blob ? Uint8Array.from(write.blob) : null,
|
|
484
|
+
idx: write.idx
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
return Object.fromEntries(
|
|
488
|
+
Object.entries(result).map(([key, list]) => [
|
|
489
|
+
key,
|
|
490
|
+
[...list].sort((a, b) => {
|
|
491
|
+
if (a.taskId !== b.taskId) {
|
|
492
|
+
return a.taskId.localeCompare(b.taskId);
|
|
493
|
+
}
|
|
494
|
+
return a.idx - b.idx;
|
|
495
|
+
}).map(({ taskId, channel, type, blob }) => [
|
|
496
|
+
new TextEncoder().encode(taskId),
|
|
497
|
+
new TextEncoder().encode(channel),
|
|
498
|
+
new TextEncoder().encode(type),
|
|
499
|
+
blob
|
|
500
|
+
])
|
|
501
|
+
])
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
async getPendingSends(threadIds) {
|
|
505
|
+
if (!(threadIds == null ? void 0 : threadIds.length)) {
|
|
506
|
+
return {};
|
|
507
|
+
}
|
|
508
|
+
const writes = await this.checkpointWritesModel.findAll({
|
|
509
|
+
where: {
|
|
510
|
+
threadId: {
|
|
511
|
+
[import_database.Op.in]: threadIds
|
|
512
|
+
},
|
|
513
|
+
channel: import_langgraph_checkpoint.TASKS
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
const result = {};
|
|
517
|
+
for (const write of writes) {
|
|
518
|
+
const key = `${write.threadId}:${write.checkpointId}`;
|
|
519
|
+
if (!result[key]) {
|
|
520
|
+
result[key] = [];
|
|
521
|
+
}
|
|
522
|
+
result[key].push({
|
|
523
|
+
taskId: write.taskId,
|
|
524
|
+
channel: write.channel,
|
|
525
|
+
type: write.type,
|
|
526
|
+
blob: write.blob ? Uint8Array.from(write.blob) : null,
|
|
527
|
+
idx: write.idx
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
return Object.fromEntries(
|
|
531
|
+
Object.entries(result).map(([key, list]) => [
|
|
532
|
+
key,
|
|
533
|
+
[...list].sort((a, b) => {
|
|
534
|
+
if (a.taskId !== b.taskId) {
|
|
535
|
+
return a.taskId.localeCompare(b.taskId);
|
|
536
|
+
}
|
|
537
|
+
return a.idx - b.idx;
|
|
538
|
+
}).map(({ type, blob }) => [new TextEncoder().encode(type), blob])
|
|
539
|
+
])
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
async getCheckpointBlobs(threadIds) {
|
|
543
|
+
const blobs = await this.checkpointBlobsModel.findAll({
|
|
544
|
+
where: {
|
|
545
|
+
threadId: threadIds.length === 1 ? threadIds[0] : {
|
|
546
|
+
[import_database.Op.in]: threadIds
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
const result = {};
|
|
551
|
+
for (const blob of blobs) {
|
|
552
|
+
const key = `${blob.threadId}:${blob.checkpointNs}:${blob.channel}:${blob.version}`;
|
|
553
|
+
if (!result[key]) {
|
|
554
|
+
result[key] = [];
|
|
555
|
+
}
|
|
556
|
+
result[key].push({
|
|
557
|
+
taskId: blob.taskId,
|
|
558
|
+
checkpointNs: blob.checkpointNs,
|
|
559
|
+
channel: blob.channel,
|
|
560
|
+
version: blob.version,
|
|
561
|
+
type: blob.type,
|
|
562
|
+
blob: blob.blob ? Uint8Array.from(blob.blob) : null
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
return Object.fromEntries(
|
|
566
|
+
Object.entries(result).map(([key, list]) => [
|
|
567
|
+
key,
|
|
568
|
+
list.map(({ channel, type, blob }) => [
|
|
569
|
+
new TextEncoder().encode(channel),
|
|
570
|
+
new TextEncoder().encode(type),
|
|
571
|
+
blob
|
|
572
|
+
])
|
|
573
|
+
])
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
get checkpointsModel() {
|
|
577
|
+
return this.collectionManager.getCollection("lcCheckpoints").model;
|
|
578
|
+
}
|
|
579
|
+
get checkpointBlobsModel() {
|
|
580
|
+
return this.collectionManager.getCollection("lcCheckpointBlobs").model;
|
|
581
|
+
}
|
|
582
|
+
get checkpointWritesModel() {
|
|
583
|
+
return this.collectionManager.getCollection("lcCheckpointWrites").model;
|
|
584
|
+
}
|
|
585
|
+
get sequelize() {
|
|
586
|
+
return this.collectionManager.db.sequelize;
|
|
587
|
+
}
|
|
588
|
+
get collectionManager() {
|
|
589
|
+
return this.provideCollectionManager().collectionManager;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
593
|
+
0 && (module.exports = {
|
|
594
|
+
SequelizeCollectionSaver
|
|
595
|
+
});
|
|
@@ -147,7 +147,7 @@ class BuiltInManager {
|
|
|
147
147
|
const existedMap = new Map(existed.map((it) => [it.username, it.toJSON()]));
|
|
148
148
|
for (const { username, description, skillSettings } of updates) {
|
|
149
149
|
let { skills } = ((_a = existedMap.get(username)) == null ? void 0 : _a.skillSettings) ?? { skills: [] };
|
|
150
|
-
skills = skills.filter((s) => {
|
|
150
|
+
skills = (skills ?? []).filter((s) => {
|
|
151
151
|
var _a2;
|
|
152
152
|
return (_a2 = s.name) == null ? void 0 : _a2.startsWith("workflowCaller-");
|
|
153
153
|
});
|
package/dist/server/plugin.js
CHANGED
|
@@ -67,6 +67,7 @@ var import_work_context_handler = require("./manager/work-context-handler");
|
|
|
67
67
|
var import_ai_coding_manager = require("./manager/ai-coding-manager");
|
|
68
68
|
var import_kimi = require("./llm-providers/kimi");
|
|
69
69
|
var import_document_loader = require("./document-loader");
|
|
70
|
+
var import_checkpoints = require("./ai-employees/checkpoints");
|
|
70
71
|
class PluginAIServer extends import_server.Plugin {
|
|
71
72
|
features = new import_ai_feature_manager.AIPluginFeatureManagerImpl();
|
|
72
73
|
aiManager = new import_ai_manager.AIManager(this);
|
|
@@ -94,6 +95,19 @@ class PluginAIServer extends import_server.Plugin {
|
|
|
94
95
|
}
|
|
95
96
|
});
|
|
96
97
|
this.snowflake = new import_snowflake.default(pluginRecord == null ? void 0 : pluginRecord.createdAt.getTime());
|
|
98
|
+
this.app.cronJobManager.addJob({
|
|
99
|
+
cronTime: "0 0 2 * * *",
|
|
100
|
+
onTick: async () => {
|
|
101
|
+
try {
|
|
102
|
+
const checkpointSaver = new import_checkpoints.SequelizeCollectionSaver(() => this.app.mainDataSource);
|
|
103
|
+
const checkpointCleaner = new import_checkpoints.CheckpointCleaner(() => this.app.mainDataSource, checkpointSaver);
|
|
104
|
+
const expiredAt = new Date(Date.now() - 48 * 60 * 60 * 1e3);
|
|
105
|
+
await checkpointCleaner.cleanOutdated(expiredAt);
|
|
106
|
+
} catch (e) {
|
|
107
|
+
this.app.log.error("langChain checkpoint clean job fail", e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
97
111
|
}
|
|
98
112
|
async load() {
|
|
99
113
|
await (0, import_tools.loadDocsIndexes)();
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "Create AI employees with diverse skills to collaborate with humans, build systems, and handle business operations.",
|
|
7
7
|
"description.ru-RU": "Поддержка интеграции с AI-сервисами: предоставляются AI-узлы для рабочих процессов, расширяя возможности бизнес-обработки.",
|
|
8
8
|
"description.zh-CN": "创建各种技能的 AI 员工,与人类协同,搭建系统,处理业务。",
|
|
9
|
-
"version": "2.0.
|
|
9
|
+
"version": "2.0.18",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"main": "dist/server/index.js",
|
|
12
12
|
"homepage": "https://docs.nocobase.com/handbook/action-ai",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"keywords": [
|
|
61
61
|
"AI"
|
|
62
62
|
],
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "f93082fd2c15618fe85e697a9cdd90614371732e"
|
|
64
64
|
}
|