kode-sdk 2.7.0
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/LICENSE +201 -0
- package/README.md +74 -0
- package/dist/core/agent/breakpoint-manager.d.ts +16 -0
- package/dist/core/agent/breakpoint-manager.js +36 -0
- package/dist/core/agent/message-queue.d.ts +26 -0
- package/dist/core/agent/message-queue.js +47 -0
- package/dist/core/agent/permission-manager.d.ts +9 -0
- package/dist/core/agent/permission-manager.js +32 -0
- package/dist/core/agent/todo-manager.d.ts +26 -0
- package/dist/core/agent/todo-manager.js +91 -0
- package/dist/core/agent/tool-runner.d.ts +9 -0
- package/dist/core/agent/tool-runner.js +45 -0
- package/dist/core/agent.d.ts +271 -0
- package/dist/core/agent.js +2334 -0
- package/dist/core/checkpointer.d.ts +96 -0
- package/dist/core/checkpointer.js +57 -0
- package/dist/core/checkpointers/file.d.ts +20 -0
- package/dist/core/checkpointers/file.js +153 -0
- package/dist/core/checkpointers/index.d.ts +3 -0
- package/dist/core/checkpointers/index.js +9 -0
- package/dist/core/checkpointers/redis.d.ts +35 -0
- package/dist/core/checkpointers/redis.js +113 -0
- package/dist/core/compression/ai-strategy.d.ts +53 -0
- package/dist/core/compression/ai-strategy.js +298 -0
- package/dist/core/compression/index.d.ts +12 -0
- package/dist/core/compression/index.js +27 -0
- package/dist/core/compression/prompts.d.ts +35 -0
- package/dist/core/compression/prompts.js +114 -0
- package/dist/core/compression/simple-strategy.d.ts +44 -0
- package/dist/core/compression/simple-strategy.js +240 -0
- package/dist/core/compression/token-estimator.d.ts +42 -0
- package/dist/core/compression/token-estimator.js +121 -0
- package/dist/core/compression/types.d.ts +140 -0
- package/dist/core/compression/types.js +9 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +2 -0
- package/dist/core/context-manager.d.ts +115 -0
- package/dist/core/context-manager.js +107 -0
- package/dist/core/errors.d.ts +6 -0
- package/dist/core/errors.js +17 -0
- package/dist/core/events.d.ts +49 -0
- package/dist/core/events.js +312 -0
- package/dist/core/file-pool.d.ts +43 -0
- package/dist/core/file-pool.js +120 -0
- package/dist/core/hooks.d.ts +23 -0
- package/dist/core/hooks.js +71 -0
- package/dist/core/permission-modes.d.ts +31 -0
- package/dist/core/permission-modes.js +61 -0
- package/dist/core/pool.d.ts +31 -0
- package/dist/core/pool.js +87 -0
- package/dist/core/room.d.ts +15 -0
- package/dist/core/room.js +57 -0
- package/dist/core/scheduler.d.ts +33 -0
- package/dist/core/scheduler.js +58 -0
- package/dist/core/template.d.ts +69 -0
- package/dist/core/template.js +35 -0
- package/dist/core/time-bridge.d.ts +18 -0
- package/dist/core/time-bridge.js +100 -0
- package/dist/core/todo.d.ts +34 -0
- package/dist/core/todo.js +89 -0
- package/dist/core/types.d.ts +380 -0
- package/dist/core/types.js +3 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +147 -0
- package/dist/infra/provider.d.ts +144 -0
- package/dist/infra/provider.js +294 -0
- package/dist/infra/sandbox-factory.d.ts +10 -0
- package/dist/infra/sandbox-factory.js +21 -0
- package/dist/infra/sandbox.d.ts +87 -0
- package/dist/infra/sandbox.js +255 -0
- package/dist/infra/store.d.ts +154 -0
- package/dist/infra/store.js +584 -0
- package/dist/skills/index.d.ts +12 -0
- package/dist/skills/index.js +36 -0
- package/dist/skills/injector.d.ts +29 -0
- package/dist/skills/injector.js +96 -0
- package/dist/skills/loader.d.ts +59 -0
- package/dist/skills/loader.js +215 -0
- package/dist/skills/manager.d.ts +85 -0
- package/dist/skills/manager.js +221 -0
- package/dist/skills/parser.d.ts +40 -0
- package/dist/skills/parser.js +107 -0
- package/dist/skills/types.d.ts +107 -0
- package/dist/skills/types.js +7 -0
- package/dist/skills/validator.d.ts +30 -0
- package/dist/skills/validator.js +121 -0
- package/dist/store.d.ts +1 -0
- package/dist/store.js +5 -0
- package/dist/tools/bash_kill/index.d.ts +1 -0
- package/dist/tools/bash_kill/index.js +35 -0
- package/dist/tools/bash_kill/prompt.d.ts +2 -0
- package/dist/tools/bash_kill/prompt.js +14 -0
- package/dist/tools/bash_logs/index.d.ts +1 -0
- package/dist/tools/bash_logs/index.js +40 -0
- package/dist/tools/bash_logs/prompt.d.ts +2 -0
- package/dist/tools/bash_logs/prompt.js +14 -0
- package/dist/tools/bash_run/index.d.ts +16 -0
- package/dist/tools/bash_run/index.js +61 -0
- package/dist/tools/bash_run/prompt.d.ts +2 -0
- package/dist/tools/bash_run/prompt.js +18 -0
- package/dist/tools/builtin.d.ts +9 -0
- package/dist/tools/builtin.js +27 -0
- package/dist/tools/define.d.ts +101 -0
- package/dist/tools/define.js +214 -0
- package/dist/tools/fs_edit/index.d.ts +1 -0
- package/dist/tools/fs_edit/index.js +62 -0
- package/dist/tools/fs_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_edit/prompt.js +15 -0
- package/dist/tools/fs_glob/index.d.ts +1 -0
- package/dist/tools/fs_glob/index.js +60 -0
- package/dist/tools/fs_glob/prompt.d.ts +2 -0
- package/dist/tools/fs_glob/prompt.js +18 -0
- package/dist/tools/fs_grep/index.d.ts +1 -0
- package/dist/tools/fs_grep/index.js +66 -0
- package/dist/tools/fs_grep/prompt.d.ts +2 -0
- package/dist/tools/fs_grep/prompt.js +16 -0
- package/dist/tools/fs_multi_edit/index.d.ts +1 -0
- package/dist/tools/fs_multi_edit/index.js +106 -0
- package/dist/tools/fs_multi_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_multi_edit/prompt.js +16 -0
- package/dist/tools/fs_read/index.d.ts +1 -0
- package/dist/tools/fs_read/index.js +40 -0
- package/dist/tools/fs_read/prompt.d.ts +2 -0
- package/dist/tools/fs_read/prompt.js +16 -0
- package/dist/tools/fs_rm/index.d.ts +1 -0
- package/dist/tools/fs_rm/index.js +41 -0
- package/dist/tools/fs_rm/prompt.d.ts +2 -0
- package/dist/tools/fs_rm/prompt.js +14 -0
- package/dist/tools/fs_write/index.d.ts +1 -0
- package/dist/tools/fs_write/index.js +40 -0
- package/dist/tools/fs_write/prompt.d.ts +2 -0
- package/dist/tools/fs_write/prompt.js +15 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +56 -0
- package/dist/tools/mcp.d.ts +73 -0
- package/dist/tools/mcp.js +198 -0
- package/dist/tools/registry.d.ts +29 -0
- package/dist/tools/registry.js +26 -0
- package/dist/tools/skill_activate/index.d.ts +5 -0
- package/dist/tools/skill_activate/index.js +63 -0
- package/dist/tools/skill_list/index.d.ts +5 -0
- package/dist/tools/skill_list/index.js +48 -0
- package/dist/tools/skill_resource/index.d.ts +5 -0
- package/dist/tools/skill_resource/index.js +82 -0
- package/dist/tools/task_run/index.d.ts +7 -0
- package/dist/tools/task_run/index.js +60 -0
- package/dist/tools/task_run/prompt.d.ts +5 -0
- package/dist/tools/task_run/prompt.js +29 -0
- package/dist/tools/todo_read/index.d.ts +1 -0
- package/dist/tools/todo_read/index.js +29 -0
- package/dist/tools/todo_read/prompt.d.ts +2 -0
- package/dist/tools/todo_read/prompt.js +18 -0
- package/dist/tools/todo_write/index.d.ts +1 -0
- package/dist/tools/todo_write/index.js +42 -0
- package/dist/tools/todo_write/prompt.d.ts +2 -0
- package/dist/tools/todo_write/prompt.js +23 -0
- package/dist/tools/tool.d.ts +43 -0
- package/dist/tools/tool.js +104 -0
- package/dist/tools/toolkit.d.ts +69 -0
- package/dist/tools/toolkit.js +98 -0
- package/dist/tools/type-inference.d.ts +127 -0
- package/dist/tools/type-inference.js +207 -0
- package/dist/utils/agent-id.d.ts +1 -0
- package/dist/utils/agent-id.js +28 -0
- package/dist/utils/session-id.d.ts +21 -0
- package/dist/utils/session-id.js +64 -0
- package/dist/utils/unicode.d.ts +17 -0
- package/dist/utils/unicode.js +62 -0
- package/package.json +117 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Message, ToolCallRecord } from './types';
|
|
2
|
+
import type { ToolDescriptor } from '../tools/registry';
|
|
3
|
+
/**
|
|
4
|
+
* Agent 状态快照
|
|
5
|
+
*/
|
|
6
|
+
export interface AgentState {
|
|
7
|
+
status: 'ready' | 'working' | 'paused' | 'completed' | 'failed';
|
|
8
|
+
stepCount: number;
|
|
9
|
+
lastSfpIndex: number;
|
|
10
|
+
lastBookmark?: {
|
|
11
|
+
seq: number;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Checkpoint 数据结构
|
|
17
|
+
*/
|
|
18
|
+
export interface Checkpoint {
|
|
19
|
+
id: string;
|
|
20
|
+
agentId: string;
|
|
21
|
+
sessionId?: string;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
version: string;
|
|
24
|
+
state: AgentState;
|
|
25
|
+
messages: Message[];
|
|
26
|
+
toolRecords: ToolCallRecord[];
|
|
27
|
+
tools: ToolDescriptor[];
|
|
28
|
+
config: {
|
|
29
|
+
model: string;
|
|
30
|
+
systemPrompt?: string;
|
|
31
|
+
templateId?: string;
|
|
32
|
+
};
|
|
33
|
+
metadata: {
|
|
34
|
+
isForkPoint?: boolean;
|
|
35
|
+
parentCheckpointId?: string;
|
|
36
|
+
tags?: string[];
|
|
37
|
+
[key: string]: any;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Checkpoint 元数据(列表时使用)
|
|
42
|
+
*/
|
|
43
|
+
export interface CheckpointMetadata {
|
|
44
|
+
id: string;
|
|
45
|
+
agentId: string;
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
timestamp: number;
|
|
48
|
+
isForkPoint?: boolean;
|
|
49
|
+
tags?: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checkpointer 接口
|
|
53
|
+
*
|
|
54
|
+
* 提供可选的持久化机制,解耦 Store 强依赖
|
|
55
|
+
*/
|
|
56
|
+
export interface Checkpointer {
|
|
57
|
+
/**
|
|
58
|
+
* 保存 checkpoint
|
|
59
|
+
*/
|
|
60
|
+
save(checkpoint: Checkpoint): Promise<string>;
|
|
61
|
+
/**
|
|
62
|
+
* 加载 checkpoint
|
|
63
|
+
*/
|
|
64
|
+
load(checkpointId: string): Promise<Checkpoint | null>;
|
|
65
|
+
/**
|
|
66
|
+
* 列出 Agent 的所有 checkpoints
|
|
67
|
+
*/
|
|
68
|
+
list(agentId: string, options?: {
|
|
69
|
+
sessionId?: string;
|
|
70
|
+
limit?: number;
|
|
71
|
+
offset?: number;
|
|
72
|
+
}): Promise<CheckpointMetadata[]>;
|
|
73
|
+
/**
|
|
74
|
+
* 删除 checkpoint
|
|
75
|
+
*/
|
|
76
|
+
delete(checkpointId: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Fork checkpoint(可选)
|
|
79
|
+
*/
|
|
80
|
+
fork?(checkpointId: string, newAgentId: string): Promise<string>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 内存 Checkpointer(默认实现)
|
|
84
|
+
*/
|
|
85
|
+
export declare class MemoryCheckpointer implements Checkpointer {
|
|
86
|
+
private checkpoints;
|
|
87
|
+
save(checkpoint: Checkpoint): Promise<string>;
|
|
88
|
+
load(checkpointId: string): Promise<Checkpoint | null>;
|
|
89
|
+
list(agentId: string, options?: {
|
|
90
|
+
sessionId?: string;
|
|
91
|
+
limit?: number;
|
|
92
|
+
offset?: number;
|
|
93
|
+
}): Promise<CheckpointMetadata[]>;
|
|
94
|
+
delete(checkpointId: string): Promise<void>;
|
|
95
|
+
fork(checkpointId: string, newAgentId: string): Promise<string>;
|
|
96
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryCheckpointer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 内存 Checkpointer(默认实现)
|
|
6
|
+
*/
|
|
7
|
+
class MemoryCheckpointer {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.checkpoints = new Map();
|
|
10
|
+
}
|
|
11
|
+
async save(checkpoint) {
|
|
12
|
+
this.checkpoints.set(checkpoint.id, JSON.parse(JSON.stringify(checkpoint)));
|
|
13
|
+
return checkpoint.id;
|
|
14
|
+
}
|
|
15
|
+
async load(checkpointId) {
|
|
16
|
+
const checkpoint = this.checkpoints.get(checkpointId);
|
|
17
|
+
return checkpoint ? JSON.parse(JSON.stringify(checkpoint)) : null;
|
|
18
|
+
}
|
|
19
|
+
async list(agentId, options) {
|
|
20
|
+
const allCheckpoints = Array.from(this.checkpoints.values())
|
|
21
|
+
.filter((cp) => cp.agentId === agentId)
|
|
22
|
+
.filter((cp) => !options?.sessionId || cp.sessionId === options.sessionId)
|
|
23
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
24
|
+
const start = options?.offset || 0;
|
|
25
|
+
const end = options?.limit ? start + options.limit : undefined;
|
|
26
|
+
const slice = allCheckpoints.slice(start, end);
|
|
27
|
+
return slice.map((cp) => ({
|
|
28
|
+
id: cp.id,
|
|
29
|
+
agentId: cp.agentId,
|
|
30
|
+
sessionId: cp.sessionId,
|
|
31
|
+
timestamp: cp.timestamp,
|
|
32
|
+
isForkPoint: cp.metadata.isForkPoint,
|
|
33
|
+
tags: cp.metadata.tags,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
async delete(checkpointId) {
|
|
37
|
+
this.checkpoints.delete(checkpointId);
|
|
38
|
+
}
|
|
39
|
+
async fork(checkpointId, newAgentId) {
|
|
40
|
+
const original = await this.load(checkpointId);
|
|
41
|
+
if (!original) {
|
|
42
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
43
|
+
}
|
|
44
|
+
const forked = {
|
|
45
|
+
...original,
|
|
46
|
+
id: `${newAgentId}:${Date.now()}`,
|
|
47
|
+
agentId: newAgentId,
|
|
48
|
+
timestamp: Date.now(),
|
|
49
|
+
metadata: {
|
|
50
|
+
...original.metadata,
|
|
51
|
+
parentCheckpointId: checkpointId,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
return await this.save(forked);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.MemoryCheckpointer = MemoryCheckpointer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Checkpointer, Checkpoint, CheckpointMetadata } from '../checkpointer';
|
|
2
|
+
/**
|
|
3
|
+
* File-based Checkpointer
|
|
4
|
+
*
|
|
5
|
+
* 将 checkpoints 保存到本地文件系统
|
|
6
|
+
*/
|
|
7
|
+
export declare class FileCheckpointer implements Checkpointer {
|
|
8
|
+
private readonly baseDir;
|
|
9
|
+
constructor(baseDir: string);
|
|
10
|
+
save(checkpoint: Checkpoint): Promise<string>;
|
|
11
|
+
load(checkpointId: string): Promise<Checkpoint | null>;
|
|
12
|
+
list(agentId: string, options?: {
|
|
13
|
+
sessionId?: string;
|
|
14
|
+
limit?: number;
|
|
15
|
+
offset?: number;
|
|
16
|
+
}): Promise<CheckpointMetadata[]>;
|
|
17
|
+
delete(checkpointId: string): Promise<void>;
|
|
18
|
+
fork(checkpointId: string, newAgentId: string): Promise<string>;
|
|
19
|
+
private ensureDir;
|
|
20
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FileCheckpointer = void 0;
|
|
37
|
+
const fs_1 = require("fs");
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
/**
|
|
40
|
+
* File-based Checkpointer
|
|
41
|
+
*
|
|
42
|
+
* 将 checkpoints 保存到本地文件系统
|
|
43
|
+
*/
|
|
44
|
+
class FileCheckpointer {
|
|
45
|
+
constructor(baseDir) {
|
|
46
|
+
this.baseDir = baseDir;
|
|
47
|
+
}
|
|
48
|
+
async save(checkpoint) {
|
|
49
|
+
await this.ensureDir();
|
|
50
|
+
const agentDir = path.join(this.baseDir, checkpoint.agentId);
|
|
51
|
+
await fs_1.promises.mkdir(agentDir, { recursive: true });
|
|
52
|
+
const filePath = path.join(agentDir, `${checkpoint.id}.json`);
|
|
53
|
+
await fs_1.promises.writeFile(filePath, JSON.stringify(checkpoint, null, 2), 'utf-8');
|
|
54
|
+
return checkpoint.id;
|
|
55
|
+
}
|
|
56
|
+
async load(checkpointId) {
|
|
57
|
+
try {
|
|
58
|
+
// 扫描所有 agent 目录查找 checkpoint
|
|
59
|
+
const agentDirs = await fs_1.promises.readdir(this.baseDir);
|
|
60
|
+
for (const agentId of agentDirs) {
|
|
61
|
+
const agentDir = path.join(this.baseDir, agentId);
|
|
62
|
+
const stat = await fs_1.promises.stat(agentDir);
|
|
63
|
+
if (!stat.isDirectory())
|
|
64
|
+
continue;
|
|
65
|
+
const filePath = path.join(agentDir, `${checkpointId}.json`);
|
|
66
|
+
try {
|
|
67
|
+
const content = await fs_1.promises.readFile(filePath, 'utf-8');
|
|
68
|
+
return JSON.parse(content);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async list(agentId, options) {
|
|
81
|
+
const agentDir = path.join(this.baseDir, agentId);
|
|
82
|
+
try {
|
|
83
|
+
const files = await fs_1.promises.readdir(agentDir);
|
|
84
|
+
const checkpoints = [];
|
|
85
|
+
for (const file of files) {
|
|
86
|
+
if (!file.endsWith('.json'))
|
|
87
|
+
continue;
|
|
88
|
+
const filePath = path.join(agentDir, file);
|
|
89
|
+
const content = await fs_1.promises.readFile(filePath, 'utf-8');
|
|
90
|
+
const checkpoint = JSON.parse(content);
|
|
91
|
+
if (options?.sessionId && checkpoint.sessionId !== options.sessionId) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
checkpoints.push({
|
|
95
|
+
id: checkpoint.id,
|
|
96
|
+
agentId: checkpoint.agentId,
|
|
97
|
+
sessionId: checkpoint.sessionId,
|
|
98
|
+
timestamp: checkpoint.timestamp,
|
|
99
|
+
isForkPoint: checkpoint.metadata.isForkPoint,
|
|
100
|
+
tags: checkpoint.metadata.tags,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// 按时间排序
|
|
104
|
+
checkpoints.sort((a, b) => b.timestamp - a.timestamp);
|
|
105
|
+
// 分页
|
|
106
|
+
const start = options?.offset || 0;
|
|
107
|
+
const end = options?.limit ? start + options.limit : undefined;
|
|
108
|
+
return checkpoints.slice(start, end);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async delete(checkpointId) {
|
|
115
|
+
try {
|
|
116
|
+
const agentDirs = await fs_1.promises.readdir(this.baseDir);
|
|
117
|
+
for (const agentId of agentDirs) {
|
|
118
|
+
const filePath = path.join(this.baseDir, agentId, `${checkpointId}.json`);
|
|
119
|
+
try {
|
|
120
|
+
await fs_1.promises.unlink(filePath);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Ignore errors
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async fork(checkpointId, newAgentId) {
|
|
133
|
+
const original = await this.load(checkpointId);
|
|
134
|
+
if (!original) {
|
|
135
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
136
|
+
}
|
|
137
|
+
const forked = {
|
|
138
|
+
...original,
|
|
139
|
+
id: `${newAgentId}:${Date.now()}`,
|
|
140
|
+
agentId: newAgentId,
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
metadata: {
|
|
143
|
+
...original.metadata,
|
|
144
|
+
parentCheckpointId: checkpointId,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
return await this.save(forked);
|
|
148
|
+
}
|
|
149
|
+
async ensureDir() {
|
|
150
|
+
await fs_1.promises.mkdir(this.baseDir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.FileCheckpointer = FileCheckpointer;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisCheckpointer = exports.FileCheckpointer = exports.MemoryCheckpointer = void 0;
|
|
4
|
+
var checkpointer_1 = require("../checkpointer");
|
|
5
|
+
Object.defineProperty(exports, "MemoryCheckpointer", { enumerable: true, get: function () { return checkpointer_1.MemoryCheckpointer; } });
|
|
6
|
+
var file_1 = require("./file");
|
|
7
|
+
Object.defineProperty(exports, "FileCheckpointer", { enumerable: true, get: function () { return file_1.FileCheckpointer; } });
|
|
8
|
+
var redis_1 = require("./redis");
|
|
9
|
+
Object.defineProperty(exports, "RedisCheckpointer", { enumerable: true, get: function () { return redis_1.RedisCheckpointer; } });
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Checkpointer, Checkpoint, CheckpointMetadata } from '../checkpointer';
|
|
2
|
+
/**
|
|
3
|
+
* Redis 配置
|
|
4
|
+
*/
|
|
5
|
+
export interface RedisCheckpointerConfig {
|
|
6
|
+
host?: string;
|
|
7
|
+
port?: number;
|
|
8
|
+
password?: string;
|
|
9
|
+
db?: number;
|
|
10
|
+
keyPrefix?: string;
|
|
11
|
+
ttl?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Redis-based Checkpointer
|
|
15
|
+
*
|
|
16
|
+
* 使用 Redis 存储 checkpoints(需要 ioredis)
|
|
17
|
+
*/
|
|
18
|
+
export declare class RedisCheckpointer implements Checkpointer {
|
|
19
|
+
private redis;
|
|
20
|
+
private keyPrefix;
|
|
21
|
+
private ttl?;
|
|
22
|
+
constructor(config?: RedisCheckpointerConfig);
|
|
23
|
+
save(checkpoint: Checkpoint): Promise<string>;
|
|
24
|
+
load(checkpointId: string): Promise<Checkpoint | null>;
|
|
25
|
+
list(agentId: string, options?: {
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
limit?: number;
|
|
28
|
+
offset?: number;
|
|
29
|
+
}): Promise<CheckpointMetadata[]>;
|
|
30
|
+
delete(checkpointId: string): Promise<void>;
|
|
31
|
+
fork(checkpointId: string, newAgentId: string): Promise<string>;
|
|
32
|
+
disconnect(): Promise<void>;
|
|
33
|
+
private getKey;
|
|
34
|
+
private getIndexKey;
|
|
35
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RedisCheckpointer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Redis-based Checkpointer
|
|
6
|
+
*
|
|
7
|
+
* 使用 Redis 存储 checkpoints(需要 ioredis)
|
|
8
|
+
*/
|
|
9
|
+
class RedisCheckpointer {
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.keyPrefix = config.keyPrefix || 'kode:checkpoint:';
|
|
12
|
+
this.ttl = config.ttl;
|
|
13
|
+
// 延迟加载 ioredis(可选依赖)
|
|
14
|
+
try {
|
|
15
|
+
const Redis = require('ioredis');
|
|
16
|
+
this.redis = new Redis({
|
|
17
|
+
host: config.host || 'localhost',
|
|
18
|
+
port: config.port || 6379,
|
|
19
|
+
password: config.password,
|
|
20
|
+
db: config.db || 0,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new Error('ioredis is required for RedisCheckpointer. Install it with: npm install ioredis');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async save(checkpoint) {
|
|
28
|
+
const key = this.getKey(checkpoint.id);
|
|
29
|
+
const value = JSON.stringify(checkpoint);
|
|
30
|
+
if (this.ttl) {
|
|
31
|
+
await this.redis.setex(key, this.ttl, value);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
await this.redis.set(key, value);
|
|
35
|
+
}
|
|
36
|
+
// 添加到 agent 的索引
|
|
37
|
+
const indexKey = this.getIndexKey(checkpoint.agentId);
|
|
38
|
+
await this.redis.zadd(indexKey, checkpoint.timestamp, checkpoint.id);
|
|
39
|
+
return checkpoint.id;
|
|
40
|
+
}
|
|
41
|
+
async load(checkpointId) {
|
|
42
|
+
const key = this.getKey(checkpointId);
|
|
43
|
+
const value = await this.redis.get(key);
|
|
44
|
+
if (!value)
|
|
45
|
+
return null;
|
|
46
|
+
return JSON.parse(value);
|
|
47
|
+
}
|
|
48
|
+
async list(agentId, options) {
|
|
49
|
+
const indexKey = this.getIndexKey(agentId);
|
|
50
|
+
// 按时间倒序获取 checkpoint IDs
|
|
51
|
+
const start = options?.offset || 0;
|
|
52
|
+
const end = options?.limit ? start + options.limit - 1 : -1;
|
|
53
|
+
const ids = await this.redis.zrevrange(indexKey, start, end);
|
|
54
|
+
const checkpoints = [];
|
|
55
|
+
for (const id of ids) {
|
|
56
|
+
const checkpoint = await this.load(id);
|
|
57
|
+
if (!checkpoint)
|
|
58
|
+
continue;
|
|
59
|
+
if (options?.sessionId && checkpoint.sessionId !== options.sessionId) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
checkpoints.push({
|
|
63
|
+
id: checkpoint.id,
|
|
64
|
+
agentId: checkpoint.agentId,
|
|
65
|
+
sessionId: checkpoint.sessionId,
|
|
66
|
+
timestamp: checkpoint.timestamp,
|
|
67
|
+
isForkPoint: checkpoint.metadata.isForkPoint,
|
|
68
|
+
tags: checkpoint.metadata.tags,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return checkpoints;
|
|
72
|
+
}
|
|
73
|
+
async delete(checkpointId) {
|
|
74
|
+
const checkpoint = await this.load(checkpointId);
|
|
75
|
+
if (!checkpoint)
|
|
76
|
+
return;
|
|
77
|
+
// 删除 checkpoint
|
|
78
|
+
const key = this.getKey(checkpointId);
|
|
79
|
+
await this.redis.del(key);
|
|
80
|
+
// 从索引中移除
|
|
81
|
+
const indexKey = this.getIndexKey(checkpoint.agentId);
|
|
82
|
+
await this.redis.zrem(indexKey, checkpointId);
|
|
83
|
+
}
|
|
84
|
+
async fork(checkpointId, newAgentId) {
|
|
85
|
+
const original = await this.load(checkpointId);
|
|
86
|
+
if (!original) {
|
|
87
|
+
throw new Error(`Checkpoint not found: ${checkpointId}`);
|
|
88
|
+
}
|
|
89
|
+
const forked = {
|
|
90
|
+
...original,
|
|
91
|
+
id: `${newAgentId}:${Date.now()}`,
|
|
92
|
+
agentId: newAgentId,
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
metadata: {
|
|
95
|
+
...original.metadata,
|
|
96
|
+
parentCheckpointId: checkpointId,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
return await this.save(forked);
|
|
100
|
+
}
|
|
101
|
+
async disconnect() {
|
|
102
|
+
if (this.redis) {
|
|
103
|
+
await this.redis.quit();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
getKey(checkpointId) {
|
|
107
|
+
return `${this.keyPrefix}${checkpointId}`;
|
|
108
|
+
}
|
|
109
|
+
getIndexKey(agentId) {
|
|
110
|
+
return `${this.keyPrefix}index:${agentId}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.RedisCheckpointer = RedisCheckpointer;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI 智能压缩策略
|
|
3
|
+
*
|
|
4
|
+
* 使用 LLM 生成结构化摘要:
|
|
5
|
+
* - 按 token 数保留消息(而非消息数)
|
|
6
|
+
* - 使用 AI 生成高质量摘要
|
|
7
|
+
* - 保留关键上下文信息
|
|
8
|
+
* - 内置降级机制
|
|
9
|
+
*/
|
|
10
|
+
import { Message, Timeline } from '../types';
|
|
11
|
+
import { Sandbox } from '../../infra/sandbox';
|
|
12
|
+
import { ICompressionStrategy, ContextUsage, CompressionResult, FilePoolState, AICompressionStrategyOptions } from './types';
|
|
13
|
+
export declare class AICompressionStrategy implements ICompressionStrategy {
|
|
14
|
+
private readonly store;
|
|
15
|
+
private readonly agentId;
|
|
16
|
+
private readonly maxTokens;
|
|
17
|
+
private readonly compressToTokens;
|
|
18
|
+
private readonly preserveRecentTurns;
|
|
19
|
+
private readonly summaryPrompt?;
|
|
20
|
+
private readonly eventEmitter?;
|
|
21
|
+
private readonly summaryModel;
|
|
22
|
+
constructor(opts: AICompressionStrategyOptions);
|
|
23
|
+
/**
|
|
24
|
+
* 创建摘要模型
|
|
25
|
+
*
|
|
26
|
+
* 优先使用单独配置的摘要模型,否则复用主模型配置
|
|
27
|
+
*/
|
|
28
|
+
private createSummaryModel;
|
|
29
|
+
/**
|
|
30
|
+
* 分析上下文使用情况
|
|
31
|
+
*/
|
|
32
|
+
analyze(messages: Message[]): ContextUsage;
|
|
33
|
+
/**
|
|
34
|
+
* 执行压缩
|
|
35
|
+
*/
|
|
36
|
+
compress(messages: Message[], events: Timeline[], filePool?: FilePoolState, sandbox?: Sandbox): Promise<CompressionResult | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* 使用 AI 生成摘要
|
|
39
|
+
*/
|
|
40
|
+
private generateAISummary;
|
|
41
|
+
/**
|
|
42
|
+
* 生成简单摘要(降级方案)
|
|
43
|
+
*/
|
|
44
|
+
private generateSimpleSummary;
|
|
45
|
+
/**
|
|
46
|
+
* 预览文本(截断长文本)
|
|
47
|
+
*/
|
|
48
|
+
private preview;
|
|
49
|
+
/**
|
|
50
|
+
* 处理孤立的 tool_result
|
|
51
|
+
*/
|
|
52
|
+
private sanitizeOrphanToolResults;
|
|
53
|
+
}
|