@gt-fe/eap-runtime 0.0.17 → 0.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/README.md +13 -11
- package/dist/checkpoint/checkpoint-serializer.d.ts +8 -4
- package/dist/checkpoint/checkpoint-serializer.js +58 -19
- package/dist/checkpoint/file-checkpoint-saver.js +2 -1
- package/dist/checkpoint/index.d.ts +1 -1
- package/dist/checkpoint/index.js +1 -1
- package/dist/checkpoint/pg-checkpoint-saver.js +4 -3
- package/dist/checkpoint/redis-checkpoint-saver.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -277,26 +277,28 @@ EAP_TOOL_EXECUTION_MODE=mcp # 仅 createDevRuntime / eap chat
|
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
|
280
|
-
## 11.
|
|
280
|
+
## 11. 发布 npm 包
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
升版、CHANGELOG、`git commit` / `git push` 不在脚本里,先做完再跑脚本。脚本只做构建、发布、核对 registry 上的版本号。
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
| 脚本 | 包 | registry |
|
|
285
|
+
|------|----|----------|
|
|
286
|
+
| [`scripts/publish-intranet.sh`](./scripts/publish-intranet.sh) | `@eap/runtime` | Nexus `https://maven.gtcloud.cn/repository/npm-local/` |
|
|
287
|
+
| [`scripts/publish-public.sh`](./scripts/publish-public.sh) | `@gt-fe/eap-runtime` | npmjs。临时目录改名;dist 里 `@eap/contracts` 改为 `@gt-fe/eap-contracts`。不改源码 `package.json` |
|
|
285
288
|
|
|
286
289
|
```bash
|
|
290
|
+
# 登录(一次性)
|
|
287
291
|
cp .npmrc.example .npmrc
|
|
288
292
|
npm login --registry https://maven.gtcloud.cn/repository/npm-local/
|
|
293
|
+
npm login --registry https://registry.npmjs.org/
|
|
289
294
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
pnpm run build && npm publish --registry https://maven.gtcloud.cn/repository/npm-local/
|
|
293
|
-
|
|
294
|
-
# 2) runtime:package.json 中 @eap/contracts 改为版本号(勿再用 file:)
|
|
295
|
-
cd ../runtime && pnpm run build
|
|
296
|
-
npm publish --registry https://maven.gtcloud.cn/repository/npm-local/
|
|
295
|
+
./scripts/publish-intranet.sh
|
|
296
|
+
./scripts/publish-public.sh
|
|
297
297
|
```
|
|
298
298
|
|
|
299
|
-
|
|
299
|
+
不要在源码目录对 npmjs 执行 `npm publish`(`publishConfig` 指向 Nexus;公网 dist 必须改写 contracts)。含 `_authToken` 的 `.npmrc` 已 gitignore,勿提交凭证。`@eap:registry=...` 须写入 `.npmrc` 文件,不可在 shell 中当命令执行。
|
|
300
|
+
|
|
301
|
+
UAT Hosting 吃公网包:把 `@eap/runtime` 指到 `npm:@gt-fe/eap-runtime@<本版>` 后重建镜像。
|
|
300
302
|
|
|
301
303
|
---
|
|
302
304
|
|
|
@@ -40,13 +40,17 @@ export interface CreateCheckpointParams {
|
|
|
40
40
|
* 确保所有必要字段的一致性。
|
|
41
41
|
*/
|
|
42
42
|
export declare function createCheckpointData(params: CreateCheckpointParams): CheckpointData;
|
|
43
|
+
/**
|
|
44
|
+
* 落盘用快照:可 JSON 往返的数据留下;定时器 / 函数 / 环丢掉。
|
|
45
|
+
* 环用栈判定,同一对象出现两次但不成环(菱形)仍保留。
|
|
46
|
+
*/
|
|
47
|
+
export declare function toJsonSafe(value: unknown, stack?: Set<object>): unknown;
|
|
48
|
+
/** 所有 Checkpoint Saver 落盘共用,禁止裸 JSON.stringify(state)。 */
|
|
49
|
+
export declare function stringifyJsonSafe(value: unknown): string;
|
|
43
50
|
/**
|
|
44
51
|
* 序列化 CheckpointData 为 JSON 字符串
|
|
45
52
|
*
|
|
46
|
-
*
|
|
47
|
-
* - Date 对象 → ISO 字符串
|
|
48
|
-
* - undefined 值自动剔除(JSON.stringify 默认行为)
|
|
49
|
-
* - 循环引用检测(抛出明确错误而非默认 TypeError)
|
|
53
|
+
* Date → ISO;定时器 / 循环引用省略,不抛 TypeError。
|
|
50
54
|
*/
|
|
51
55
|
export declare function serializeCheckpoint(data: CheckpointData): string;
|
|
52
56
|
/**
|
|
@@ -37,30 +37,69 @@ export function createCheckpointData(params) {
|
|
|
37
37
|
// ─────────────────────────────────────────────
|
|
38
38
|
// 序列化 / 反序列化
|
|
39
39
|
// ─────────────────────────────────────────────
|
|
40
|
+
function isTimerHandle(value) {
|
|
41
|
+
const name = value.constructor?.name;
|
|
42
|
+
if (name === 'Timeout' || name === 'TimersList' || name === 'Immediate')
|
|
43
|
+
return true;
|
|
44
|
+
return Object.prototype.hasOwnProperty.call(value, '_idlePrev')
|
|
45
|
+
&& Object.prototype.hasOwnProperty.call(value, '_idleNext');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 落盘用快照:可 JSON 往返的数据留下;定时器 / 函数 / 环丢掉。
|
|
49
|
+
* 环用栈判定,同一对象出现两次但不成环(菱形)仍保留。
|
|
50
|
+
*/
|
|
51
|
+
export function toJsonSafe(value, stack = new Set()) {
|
|
52
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
53
|
+
return value;
|
|
54
|
+
if (typeof value === 'number')
|
|
55
|
+
return Number.isFinite(value) ? value : null;
|
|
56
|
+
if (typeof value === 'bigint')
|
|
57
|
+
return value.toString();
|
|
58
|
+
if (typeof value === 'undefined' || typeof value === 'function' || typeof value === 'symbol') {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
if (value instanceof Date)
|
|
62
|
+
return value.toISOString();
|
|
63
|
+
if (typeof value !== 'object')
|
|
64
|
+
return undefined;
|
|
65
|
+
if (isTimerHandle(value))
|
|
66
|
+
return undefined;
|
|
67
|
+
if (stack.has(value))
|
|
68
|
+
return undefined;
|
|
69
|
+
const maybeToJSON = value.toJSON;
|
|
70
|
+
if (typeof maybeToJSON === 'function') {
|
|
71
|
+
return toJsonSafe(maybeToJSON.call(value), stack);
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
stack.add(value);
|
|
75
|
+
const out = value.map((item) => {
|
|
76
|
+
const next = toJsonSafe(item, stack);
|
|
77
|
+
return next === undefined ? null : next;
|
|
78
|
+
});
|
|
79
|
+
stack.delete(value);
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
stack.add(value);
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const [key, child] of Object.entries(value)) {
|
|
85
|
+
const next = toJsonSafe(child, stack);
|
|
86
|
+
if (next !== undefined)
|
|
87
|
+
out[key] = next;
|
|
88
|
+
}
|
|
89
|
+
stack.delete(value);
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
/** 所有 Checkpoint Saver 落盘共用,禁止裸 JSON.stringify(state)。 */
|
|
93
|
+
export function stringifyJsonSafe(value) {
|
|
94
|
+
return JSON.stringify(toJsonSafe(value));
|
|
95
|
+
}
|
|
40
96
|
/**
|
|
41
97
|
* 序列化 CheckpointData 为 JSON 字符串
|
|
42
98
|
*
|
|
43
|
-
*
|
|
44
|
-
* - Date 对象 → ISO 字符串
|
|
45
|
-
* - undefined 值自动剔除(JSON.stringify 默认行为)
|
|
46
|
-
* - 循环引用检测(抛出明确错误而非默认 TypeError)
|
|
99
|
+
* Date → ISO;定时器 / 循环引用省略,不抛 TypeError。
|
|
47
100
|
*/
|
|
48
101
|
export function serializeCheckpoint(data) {
|
|
49
|
-
|
|
50
|
-
return JSON.stringify(data, (_key, value) => {
|
|
51
|
-
// Date → ISO 字符串
|
|
52
|
-
if (value instanceof Date) {
|
|
53
|
-
return value.toISOString();
|
|
54
|
-
}
|
|
55
|
-
// 循环引用检测
|
|
56
|
-
if (typeof value === 'object' && value !== null) {
|
|
57
|
-
if (seen.has(value)) {
|
|
58
|
-
throw new Error(`[CheckpointSerializer] Circular reference detected during serialization`);
|
|
59
|
-
}
|
|
60
|
-
seen.add(value);
|
|
61
|
-
}
|
|
62
|
-
return value;
|
|
63
|
-
});
|
|
102
|
+
return stringifyJsonSafe(data);
|
|
64
103
|
}
|
|
65
104
|
/**
|
|
66
105
|
* 反序列化 JSON 字符串为 CheckpointData
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { readdir, readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
+
import { stringifyJsonSafe } from './checkpoint-serializer.js';
|
|
7
8
|
export class FileCheckpointSaver {
|
|
8
9
|
baseDir;
|
|
9
10
|
constructor(baseDir) {
|
|
@@ -12,7 +13,7 @@ export class FileCheckpointSaver {
|
|
|
12
13
|
async save(threadId, data) {
|
|
13
14
|
const dir = join(this.baseDir, threadId);
|
|
14
15
|
await mkdir(dir, { recursive: true });
|
|
15
|
-
await writeFile(join(dir, `${data.checkpointId}.json`),
|
|
16
|
+
await writeFile(join(dir, `${data.checkpointId}.json`), stringifyJsonSafe(data));
|
|
16
17
|
// 更新 latest 指针
|
|
17
18
|
await writeFile(join(dir, 'latest.json'), JSON.stringify({ checkpointId: data.checkpointId }));
|
|
18
19
|
}
|
|
@@ -4,7 +4,7 @@ export type { RedisCheckpointSaverOptions } from './redis-checkpoint-saver.js';
|
|
|
4
4
|
export { CompositeCheckpointSaver } from './composite-checkpoint-saver.js';
|
|
5
5
|
export { restoreCheckpoint } from './restore-checkpoint.js';
|
|
6
6
|
export { notifyCheckpointRef, stripCheckpointCollectors } from './checkpoint-ref-notify.js';
|
|
7
|
-
export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, } from './checkpoint-serializer.js';
|
|
7
|
+
export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, stringifyJsonSafe, toJsonSafe, } from './checkpoint-serializer.js';
|
|
8
8
|
export type { CreateCheckpointParams } from './checkpoint-serializer.js';
|
|
9
9
|
export { FileCheckpointSaver } from './file-checkpoint-saver.js';
|
|
10
10
|
export { InMemoryCheckpointSaver } from './in-memory-checkpoint-saver.js';
|
package/dist/checkpoint/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { RedisCheckpointSaver } from './redis-checkpoint-saver.js';
|
|
|
4
4
|
export { CompositeCheckpointSaver } from './composite-checkpoint-saver.js';
|
|
5
5
|
export { restoreCheckpoint } from './restore-checkpoint.js';
|
|
6
6
|
export { notifyCheckpointRef, stripCheckpointCollectors } from './checkpoint-ref-notify.js';
|
|
7
|
-
export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, } from './checkpoint-serializer.js';
|
|
7
|
+
export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, stringifyJsonSafe, toJsonSafe, } from './checkpoint-serializer.js';
|
|
8
8
|
export { FileCheckpointSaver } from './file-checkpoint-saver.js';
|
|
9
9
|
export { InMemoryCheckpointSaver } from './in-memory-checkpoint-saver.js';
|
|
10
10
|
export { MongoCheckpointSaver } from './mongo-checkpoint-saver.js';
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @see design.md §1.3 checkpoints 数据模型
|
|
8
8
|
* @see checkpoint-saver.contract.ts ICheckpointSaver 接口定义
|
|
9
9
|
*/
|
|
10
|
+
import { stringifyJsonSafe } from './checkpoint-serializer.js';
|
|
10
11
|
// ─────────────────────────────────────────────
|
|
11
12
|
// PostgresCheckpointSaver
|
|
12
13
|
// ─────────────────────────────────────────────
|
|
@@ -38,9 +39,9 @@ export class PostgresCheckpointSaver {
|
|
|
38
39
|
threadId,
|
|
39
40
|
data.checkpointId,
|
|
40
41
|
data.currentNodeId,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
data.engineSnapshot == null ? null :
|
|
42
|
+
stringifyJsonSafe(data.historyPath),
|
|
43
|
+
stringifyJsonSafe(data.state),
|
|
44
|
+
data.engineSnapshot == null ? null : stringifyJsonSafe(data.engineSnapshot),
|
|
44
45
|
data.createdBy || 'system',
|
|
45
46
|
data.createdAt,
|
|
46
47
|
data.updatedBy || 'system',
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @see design.md §1.3 checkpoints 数据模型
|
|
11
11
|
*/
|
|
12
|
+
import { stringifyJsonSafe } from './checkpoint-serializer.js';
|
|
12
13
|
/**
|
|
13
14
|
* RedisCheckpointSaver — ICheckpointSaver 的 Redis 实现
|
|
14
15
|
*
|
|
@@ -52,7 +53,7 @@ export class RedisCheckpointSaver {
|
|
|
52
53
|
const idxKey = this.threadIndexKey(threadId);
|
|
53
54
|
const ltKey = this.latestKey(threadId);
|
|
54
55
|
const revKey = this.reverseIndexKey(data.checkpointId);
|
|
55
|
-
const json =
|
|
56
|
+
const json = stringifyJsonSafe(data);
|
|
56
57
|
const score = new Date(data.createdAt).getTime();
|
|
57
58
|
const pipeline = this.redis.pipeline();
|
|
58
59
|
// 存储 Checkpoint JSON
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gt-fe/eap-runtime",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Enterprise Agent Platform
|
|
3
|
+
"version": "0.0.18",
|
|
4
|
+
"description": "Enterprise Agent Platform — Runtime核心:Graph执行引擎、Task生命周期、Session管理、Checkpoint持久化",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|