@shareai-lab/kode-sdk 1.0.0-beta.8 → 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 +21 -0
- package/README.md +115 -273
- package/README.zh-CN.md +114 -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 +57 -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 +228 -62
- package/dist/core/agent.js +1890 -615
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +2 -0
- package/dist/core/context-manager.d.ts +82 -0
- package/dist/core/context-manager.js +241 -0
- package/dist/core/errors.d.ts +22 -0
- package/dist/core/errors.js +49 -0
- package/dist/core/events.d.ts +41 -10
- package/dist/core/events.js +270 -68
- package/dist/core/file-pool.d.ts +41 -0
- package/dist/core/file-pool.js +102 -0
- package/dist/core/hooks.d.ts +3 -3
- package/dist/core/hooks.js +1 -1
- package/dist/core/permission-modes.d.ts +31 -0
- package/dist/core/permission-modes.js +61 -0
- package/dist/core/pool.d.ts +56 -13
- package/dist/core/pool.js +244 -34
- package/dist/core/room.d.ts +2 -2
- package/dist/core/room.js +10 -10
- package/dist/core/scheduler.d.ts +30 -23
- package/dist/core/scheduler.js +42 -168
- package/dist/core/skills/index.d.ts +10 -0
- package/dist/core/skills/index.js +20 -0
- package/dist/core/skills/management-manager.d.ts +130 -0
- package/dist/core/skills/management-manager.js +557 -0
- package/dist/core/skills/manager.d.ts +47 -0
- package/dist/core/skills/manager.js +243 -0
- package/dist/core/skills/operation-queue.d.ts +87 -0
- package/dist/core/skills/operation-queue.js +113 -0
- package/dist/core/skills/sandbox-file-manager.d.ts +82 -0
- package/dist/core/skills/sandbox-file-manager.js +183 -0
- package/dist/core/skills/types.d.ts +120 -0
- package/dist/core/skills/types.js +9 -0
- package/dist/core/skills/xml-generator.d.ts +13 -0
- package/dist/core/skills/xml-generator.js +70 -0
- package/dist/core/template.d.ts +57 -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 +311 -114
- package/dist/core/types.js +1 -12
- package/dist/index.d.ts +47 -9
- package/dist/index.js +108 -15
- package/dist/infra/db/postgres/postgres-store.d.ts +97 -0
- package/dist/infra/db/postgres/postgres-store.js +1073 -0
- package/dist/infra/db/sqlite/sqlite-store.d.ts +84 -0
- package/dist/infra/db/sqlite/sqlite-store.js +800 -0
- package/dist/infra/e2b/e2b-fs.d.ts +29 -0
- package/dist/infra/e2b/e2b-fs.js +128 -0
- package/dist/infra/e2b/e2b-sandbox.d.ts +37 -0
- package/dist/infra/e2b/e2b-sandbox.js +156 -0
- package/dist/infra/e2b/e2b-template.d.ts +24 -0
- package/dist/infra/e2b/e2b-template.js +105 -0
- package/dist/infra/e2b/index.d.ts +4 -0
- package/dist/infra/e2b/index.js +9 -0
- package/dist/infra/e2b/types.d.ts +46 -0
- package/dist/infra/e2b/types.js +2 -0
- package/dist/infra/provider.d.ts +17 -58
- package/dist/infra/provider.js +65 -116
- package/dist/infra/providers/anthropic.d.ts +42 -0
- package/dist/infra/providers/anthropic.js +308 -0
- package/dist/infra/providers/core/errors.d.ts +230 -0
- package/dist/infra/providers/core/errors.js +353 -0
- package/dist/infra/providers/core/fork.d.ts +106 -0
- package/dist/infra/providers/core/fork.js +418 -0
- package/dist/infra/providers/core/index.d.ts +10 -0
- package/dist/infra/providers/core/index.js +76 -0
- package/dist/infra/providers/core/logger.d.ts +186 -0
- package/dist/infra/providers/core/logger.js +191 -0
- package/dist/infra/providers/core/retry.d.ts +62 -0
- package/dist/infra/providers/core/retry.js +189 -0
- package/dist/infra/providers/core/usage.d.ts +151 -0
- package/dist/infra/providers/core/usage.js +376 -0
- package/dist/infra/providers/gemini.d.ts +49 -0
- package/dist/infra/providers/gemini.js +493 -0
- package/dist/infra/providers/index.d.ts +25 -0
- package/dist/infra/providers/index.js +83 -0
- package/dist/infra/providers/openai.d.ts +123 -0
- package/dist/infra/providers/openai.js +662 -0
- package/dist/infra/providers/types.d.ts +334 -0
- package/dist/infra/providers/types.js +20 -0
- package/dist/infra/providers/utils.d.ts +53 -0
- package/dist/infra/providers/utils.js +400 -0
- package/dist/infra/sandbox-factory.d.ts +13 -0
- package/dist/infra/sandbox-factory.js +30 -0
- package/dist/infra/sandbox.d.ts +35 -6
- package/dist/infra/sandbox.js +174 -8
- package/dist/infra/store/factory.d.ts +45 -0
- package/dist/infra/store/factory.js +80 -0
- package/dist/infra/store/index.d.ts +3 -0
- package/dist/infra/store/index.js +26 -0
- package/dist/infra/store/json-store.d.ts +67 -0
- package/dist/infra/store/json-store.js +606 -0
- package/dist/infra/store/types.d.ts +342 -0
- package/dist/infra/store/types.js +2 -0
- package/dist/infra/store.d.ts +12 -32
- package/dist/infra/store.js +27 -130
- 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 +7 -13
- package/dist/tools/builtin.js +19 -90
- 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 +40 -0
- package/dist/tools/fs_glob/prompt.d.ts +2 -0
- package/dist/tools/fs_glob/prompt.js +15 -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_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 +11 -0
- package/dist/tools/index.js +61 -0
- package/dist/tools/mcp.d.ts +69 -0
- package/dist/tools/mcp.js +185 -0
- package/dist/tools/registry.d.ts +29 -0
- package/dist/tools/registry.js +26 -0
- package/dist/tools/scripts.d.ts +22 -0
- package/dist/tools/scripts.js +205 -0
- package/dist/tools/skills.d.ts +20 -0
- package/dist/tools/skills.js +115 -0
- package/dist/tools/task_run/index.d.ts +7 -0
- package/dist/tools/task_run/index.js +58 -0
- package/dist/tools/task_run/prompt.d.ts +5 -0
- package/dist/tools/task_run/prompt.js +25 -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 +211 -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/logger.d.ts +15 -0
- package/dist/utils/logger.js +44 -0
- package/dist/utils/session-id.js +16 -16
- package/package.json +35 -11
- package/dist/tools/bash.d.ts +0 -63
- package/dist/tools/bash.js +0 -92
- package/dist/tools/fs.d.ts +0 -96
- package/dist/tools/fs.js +0 -100
- package/dist/tools/task.d.ts +0 -38
- package/dist/tools/task.js +0 -45
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sandbox文件管理器模块
|
|
4
|
+
*
|
|
5
|
+
* 设计原则 (UNIX哲学):
|
|
6
|
+
* - 简洁: 只负责sandbox中的文件操作
|
|
7
|
+
* - 模块化: 独立的文件操作逻辑
|
|
8
|
+
* - 安全: 强制边界控制,确保只能访问技能目录内文件
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.SandboxFileManager = void 0;
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
/**
|
|
48
|
+
* Sandbox文件管理器类
|
|
49
|
+
*
|
|
50
|
+
* 职责:
|
|
51
|
+
* - 在sandbox隔离环境中执行文件操作
|
|
52
|
+
* - 确保文件访问边界在技能目录内
|
|
53
|
+
* - 提供read、write、delete、list等基础文件操作
|
|
54
|
+
*/
|
|
55
|
+
class SandboxFileManager {
|
|
56
|
+
constructor(sandboxFactory) {
|
|
57
|
+
this.sandboxFactory = sandboxFactory;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 在sandbox中读取文件
|
|
61
|
+
* @param skillBaseDir 技能根目录
|
|
62
|
+
* @param relativePath 相对路径
|
|
63
|
+
*/
|
|
64
|
+
async readFile(skillBaseDir, relativePath) {
|
|
65
|
+
const sandbox = this.createSkillSandbox(skillBaseDir);
|
|
66
|
+
// 使用sandbox的fs接口读取文件(自动边界检查)
|
|
67
|
+
const content = await sandbox.fs.read(relativePath);
|
|
68
|
+
return content;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 在sandbox中写入文件
|
|
72
|
+
* @param skillBaseDir 技能根目录
|
|
73
|
+
* @param relativePath 相对路径
|
|
74
|
+
* @param content 文件内容
|
|
75
|
+
*/
|
|
76
|
+
async writeFile(skillBaseDir, relativePath, content) {
|
|
77
|
+
const sandbox = this.createSkillSandbox(skillBaseDir);
|
|
78
|
+
// 使用sandbox的fs接口写入文件(自动边界检查)
|
|
79
|
+
await sandbox.fs.write(relativePath, content);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 在sandbox中删除文件
|
|
83
|
+
* @param skillBaseDir 技能根目录
|
|
84
|
+
* @param relativePath 相对路径
|
|
85
|
+
*/
|
|
86
|
+
async deleteFile(skillBaseDir, relativePath) {
|
|
87
|
+
const sandbox = this.createSkillSandbox(skillBaseDir);
|
|
88
|
+
// 注意:sandbox.fs没有直接删除接口,需要通过exec执行
|
|
89
|
+
const cmd = this.getDeleteCommand(relativePath);
|
|
90
|
+
await sandbox.exec(cmd, { timeoutMs: 5000 });
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 在sandbox中列出目录
|
|
94
|
+
* @param skillBaseDir 技能根目录
|
|
95
|
+
* @param relativePath 相对路径
|
|
96
|
+
*/
|
|
97
|
+
async listFiles(skillBaseDir, relativePath = '.') {
|
|
98
|
+
const sandbox = this.createSkillSandbox(skillBaseDir);
|
|
99
|
+
// 使用glob获取文件列表
|
|
100
|
+
const pattern = path.join(relativePath, '**/*').replace(/\\/g, '/');
|
|
101
|
+
const files = await sandbox.fs.glob(pattern, {
|
|
102
|
+
absolute: true,
|
|
103
|
+
});
|
|
104
|
+
// 构建文件树
|
|
105
|
+
return this.buildFileTree(files, skillBaseDir, relativePath);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 在sandbox中创建目录
|
|
109
|
+
* @param skillBaseDir 技能根目录
|
|
110
|
+
* @param relativePath 相对路径
|
|
111
|
+
*/
|
|
112
|
+
async createDir(skillBaseDir, relativePath) {
|
|
113
|
+
const sandbox = this.createSkillSandbox(skillBaseDir);
|
|
114
|
+
// 使用write创建一个临时文件来创建目录(sandbox.fs.write会自动创建目录)
|
|
115
|
+
const tempFile = path.join(relativePath, '.gitkeep');
|
|
116
|
+
await sandbox.fs.write(tempFile, '');
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 创建技能的sandbox实例
|
|
120
|
+
* 关键:设置enforceBoundary=true,确保只能在技能目录内操作
|
|
121
|
+
*/
|
|
122
|
+
createSkillSandbox(skillBaseDir) {
|
|
123
|
+
const config = {
|
|
124
|
+
kind: 'local',
|
|
125
|
+
workDir: skillBaseDir, // 工作目录为技能根目录
|
|
126
|
+
baseDir: skillBaseDir, // 基础目录为技能根目录
|
|
127
|
+
enforceBoundary: true, // 强制边界检查
|
|
128
|
+
allowPaths: [], // 不允许访问额外路径
|
|
129
|
+
};
|
|
130
|
+
return this.sandboxFactory.create(config);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 获取删除命令(跨平台)
|
|
134
|
+
*/
|
|
135
|
+
getDeleteCommand(filePath) {
|
|
136
|
+
const platform = os.platform();
|
|
137
|
+
if (platform === 'win32') {
|
|
138
|
+
return `del /F /Q "${filePath}"`;
|
|
139
|
+
}
|
|
140
|
+
return `rm -f "${filePath}"`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* 构建文件树
|
|
144
|
+
*/
|
|
145
|
+
buildFileTree(files, basePath, relativePath) {
|
|
146
|
+
const fs = require('fs');
|
|
147
|
+
const path = require('path');
|
|
148
|
+
// 递归构建树结构
|
|
149
|
+
const buildNode = (dirPath, name) => {
|
|
150
|
+
const fullPath = path.join(dirPath, name);
|
|
151
|
+
const relative = path.relative(basePath, fullPath);
|
|
152
|
+
const stat = fs.statSync(fullPath);
|
|
153
|
+
const node = {
|
|
154
|
+
name,
|
|
155
|
+
type: stat.isDirectory() ? 'dir' : 'file',
|
|
156
|
+
path: relative.replace(/\\/g, '/'),
|
|
157
|
+
size: stat.size,
|
|
158
|
+
modifiedTime: stat.mtime.toISOString(),
|
|
159
|
+
};
|
|
160
|
+
if (stat.isDirectory()) {
|
|
161
|
+
try {
|
|
162
|
+
const entries = fs.readdirSync(fullPath);
|
|
163
|
+
node.children = entries
|
|
164
|
+
.filter((entry) => !entry.startsWith('.'))
|
|
165
|
+
.map((entry) => buildNode(fullPath, entry))
|
|
166
|
+
.sort((a, b) => {
|
|
167
|
+
// 目录优先,然后按名称排序
|
|
168
|
+
if (a.type !== b.type) {
|
|
169
|
+
return a.type === 'dir' ? -1 : 1;
|
|
170
|
+
}
|
|
171
|
+
return a.name.localeCompare(b.name);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
node.children = [];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return node;
|
|
179
|
+
};
|
|
180
|
+
return buildNode(basePath, relativePath);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.SandboxFileManager = SandboxFileManager;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills 核心类型定义
|
|
3
|
+
*
|
|
4
|
+
* 设计原则 (UNIX哲学):
|
|
5
|
+
* - 简洁: 类型定义清晰,职责单一
|
|
6
|
+
* - 模块化: 类型独立,易于维护和扩展
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Skill 元数据
|
|
10
|
+
*/
|
|
11
|
+
export interface SkillMetadata {
|
|
12
|
+
/** skill名称 */
|
|
13
|
+
name: string;
|
|
14
|
+
/** skill描述 */
|
|
15
|
+
description: string;
|
|
16
|
+
/** SKILL.md文件路径 */
|
|
17
|
+
path: string;
|
|
18
|
+
/** skill根目录(用于解析references等) */
|
|
19
|
+
baseDir: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Skill 完整内容
|
|
23
|
+
*/
|
|
24
|
+
export interface SkillContent {
|
|
25
|
+
/** 元数据 */
|
|
26
|
+
metadata: SkillMetadata;
|
|
27
|
+
/** SKILL.md的markdown内容 */
|
|
28
|
+
content: string;
|
|
29
|
+
/** references目录下的文件列表 */
|
|
30
|
+
references: string[];
|
|
31
|
+
/** scripts目录下的文件列表 */
|
|
32
|
+
scripts: string[];
|
|
33
|
+
/** assets目录下的文件列表 */
|
|
34
|
+
assets: string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sandbox 配置
|
|
38
|
+
* 参考 docs/sandbox-support-evaluation.md 中的设计
|
|
39
|
+
*/
|
|
40
|
+
export interface SandboxConfig {
|
|
41
|
+
/** 是否启用sandbox隔离(默认false,本地开发直接执行) */
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
/** 工作目录 */
|
|
44
|
+
workDir?: string;
|
|
45
|
+
/** 是否强制边界检查 */
|
|
46
|
+
enforceBoundary?: boolean;
|
|
47
|
+
/** 允许访问的路径白名单 */
|
|
48
|
+
allowPaths?: string[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 技能基本信息
|
|
52
|
+
*/
|
|
53
|
+
export interface SkillInfo {
|
|
54
|
+
/** 技能名称 */
|
|
55
|
+
name: string;
|
|
56
|
+
/** 技能描述 */
|
|
57
|
+
description: string;
|
|
58
|
+
/** SKILL.md路径 */
|
|
59
|
+
path: string;
|
|
60
|
+
/** 技能根目录 */
|
|
61
|
+
baseDir: string;
|
|
62
|
+
/** 创建时间 */
|
|
63
|
+
createdAt?: string;
|
|
64
|
+
/** 更新时间 */
|
|
65
|
+
updatedAt?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 技能详细信息
|
|
69
|
+
*/
|
|
70
|
+
export interface SkillDetail extends SkillInfo {
|
|
71
|
+
/** 文件树结构 */
|
|
72
|
+
files: SkillFileTree;
|
|
73
|
+
/** references目录文件 */
|
|
74
|
+
references: string[];
|
|
75
|
+
/** scripts目录文件 */
|
|
76
|
+
scripts: string[];
|
|
77
|
+
/** assets目录文件 */
|
|
78
|
+
assets: string[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 文件树节点
|
|
82
|
+
*/
|
|
83
|
+
export interface SkillFileTree {
|
|
84
|
+
/** 文件/目录名 */
|
|
85
|
+
name: string;
|
|
86
|
+
/** 类型 */
|
|
87
|
+
type: 'file' | 'dir';
|
|
88
|
+
/** 相对于技能根目录的路径 */
|
|
89
|
+
path: string;
|
|
90
|
+
/** 文件大小(字节) */
|
|
91
|
+
size?: number;
|
|
92
|
+
/** 修改时间 */
|
|
93
|
+
modifiedTime?: string;
|
|
94
|
+
/** 子节点(目录) */
|
|
95
|
+
children?: SkillFileTree[];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 创建技能选项
|
|
99
|
+
*/
|
|
100
|
+
export interface CreateSkillOptions {
|
|
101
|
+
/** 技能名称(必须与目录名一致) */
|
|
102
|
+
name: string;
|
|
103
|
+
/** 技能描述 */
|
|
104
|
+
description?: string;
|
|
105
|
+
/** 模板类型 */
|
|
106
|
+
template?: 'basic' | 'advanced';
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Archived技能信息
|
|
110
|
+
*/
|
|
111
|
+
export interface ArchivedSkillInfo {
|
|
112
|
+
/** 原始技能名称 */
|
|
113
|
+
originalName: string;
|
|
114
|
+
/** archived目录中的名称(含时间戳) */
|
|
115
|
+
archivedName: string;
|
|
116
|
+
/** archived目录中的完整路径 */
|
|
117
|
+
archivedPath: string;
|
|
118
|
+
/** 归档时间 */
|
|
119
|
+
archivedAt: string;
|
|
120
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills 元数据XML生成器
|
|
3
|
+
*
|
|
4
|
+
* 设计原则 (UNIX哲学):
|
|
5
|
+
* - 简洁: 只负责生成XML格式的skills元数据
|
|
6
|
+
* - 模块化: 单一职责,易于测试和维护
|
|
7
|
+
* - 兼容: 完全兼容openskills项目的XML格式
|
|
8
|
+
*/
|
|
9
|
+
import type { SkillMetadata } from './types';
|
|
10
|
+
/**
|
|
11
|
+
* 生成skills元数据XML格式(参考openskills)
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateSkillsMetadataXml(skills: SkillMetadata[]): string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Skills 元数据XML生成器
|
|
4
|
+
*
|
|
5
|
+
* 设计原则 (UNIX哲学):
|
|
6
|
+
* - 简洁: 只负责生成XML格式的skills元数据
|
|
7
|
+
* - 模块化: 单一职责,易于测试和维护
|
|
8
|
+
* - 兼容: 完全兼容openskills项目的XML格式
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.generateSkillsMetadataXml = generateSkillsMetadataXml;
|
|
12
|
+
/**
|
|
13
|
+
* 生成skills元数据XML格式(参考openskills)
|
|
14
|
+
*/
|
|
15
|
+
function generateSkillsMetadataXml(skills) {
|
|
16
|
+
if (skills.length === 0) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
const skillTags = skills
|
|
20
|
+
.map(s => `<skill>
|
|
21
|
+
<name>${escapeXml(s.name)}</name>
|
|
22
|
+
<description>${escapeXml(s.description)}</description>
|
|
23
|
+
<location>project</location>
|
|
24
|
+
</skill>`)
|
|
25
|
+
.join('\n\n');
|
|
26
|
+
return `
|
|
27
|
+
<skills_system priority="1">
|
|
28
|
+
|
|
29
|
+
## Available Skills
|
|
30
|
+
|
|
31
|
+
<!-- SKILLS_TABLE_START -->
|
|
32
|
+
<usage>
|
|
33
|
+
When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
|
|
34
|
+
|
|
35
|
+
How to use skills:
|
|
36
|
+
- Invoke: skills(action="load", skill_name="<skill-name>")
|
|
37
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
38
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
39
|
+
|
|
40
|
+
Hot Reload:
|
|
41
|
+
- Each time you reload a known skill, it will load the latest state of the skill information
|
|
42
|
+
- To load a skill, invoke: skills(action="load", skill_name="<skill-name>")
|
|
43
|
+
- The skill content will be loaded with the latest state from the skills directory
|
|
44
|
+
|
|
45
|
+
Usage notes:
|
|
46
|
+
- Only use skills listed in <available_skills> below
|
|
47
|
+
- Do not invoke a skill that is already loaded in your context
|
|
48
|
+
- Each skill invocation is stateless
|
|
49
|
+
</usage>
|
|
50
|
+
|
|
51
|
+
<available_skills>
|
|
52
|
+
|
|
53
|
+
${skillTags}
|
|
54
|
+
|
|
55
|
+
</available_skills>
|
|
56
|
+
<!-- SKILLS_TABLE_END -->
|
|
57
|
+
|
|
58
|
+
</skills_system>`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 转义XML特殊字符
|
|
62
|
+
*/
|
|
63
|
+
function escapeXml(text) {
|
|
64
|
+
return text
|
|
65
|
+
.replace(/&/g, '&')
|
|
66
|
+
.replace(/</g, '<')
|
|
67
|
+
.replace(/>/g, '>')
|
|
68
|
+
.replace(/"/g, '"')
|
|
69
|
+
.replace(/'/g, ''');
|
|
70
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Hooks } from './hooks';
|
|
2
|
+
export type PermissionDecisionMode = 'auto' | 'approval' | 'readonly' | (string & {});
|
|
3
|
+
export interface PermissionConfig {
|
|
4
|
+
mode: PermissionDecisionMode;
|
|
5
|
+
requireApprovalTools?: string[];
|
|
6
|
+
allowTools?: string[];
|
|
7
|
+
denyTools?: string[];
|
|
8
|
+
metadata?: Record<string, any>;
|
|
9
|
+
}
|
|
10
|
+
export interface SubAgentConfig {
|
|
11
|
+
templates?: string[];
|
|
12
|
+
depth: number;
|
|
13
|
+
inheritConfig?: boolean;
|
|
14
|
+
overrides?: {
|
|
15
|
+
permission?: PermissionConfig;
|
|
16
|
+
todo?: TodoConfig;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface TodoConfig {
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
remindIntervalSteps?: number;
|
|
22
|
+
storagePath?: string;
|
|
23
|
+
reminderOnStart?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface AgentTemplateDefinition {
|
|
26
|
+
id: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
desc?: string;
|
|
29
|
+
version?: string;
|
|
30
|
+
systemPrompt: string;
|
|
31
|
+
model?: string;
|
|
32
|
+
sandbox?: Record<string, any>;
|
|
33
|
+
tools?: '*' | string[];
|
|
34
|
+
permission?: PermissionConfig;
|
|
35
|
+
runtime?: TemplateRuntimeConfig;
|
|
36
|
+
hooks?: Hooks;
|
|
37
|
+
metadata?: Record<string, any>;
|
|
38
|
+
}
|
|
39
|
+
export interface TemplateRuntimeConfig {
|
|
40
|
+
exposeThinking?: boolean;
|
|
41
|
+
retainThinking?: boolean;
|
|
42
|
+
multimodalContinuation?: 'history';
|
|
43
|
+
multimodalRetention?: {
|
|
44
|
+
keepRecent?: number;
|
|
45
|
+
};
|
|
46
|
+
todo?: TodoConfig;
|
|
47
|
+
subagents?: SubAgentConfig;
|
|
48
|
+
metadata?: Record<string, any>;
|
|
49
|
+
}
|
|
50
|
+
export declare class AgentTemplateRegistry {
|
|
51
|
+
private templates;
|
|
52
|
+
register(template: AgentTemplateDefinition): void;
|
|
53
|
+
bulkRegister(templates: AgentTemplateDefinition[]): void;
|
|
54
|
+
has(id: string): boolean;
|
|
55
|
+
get(id: string): AgentTemplateDefinition;
|
|
56
|
+
list(): AgentTemplateDefinition[];
|
|
57
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentTemplateRegistry = void 0;
|
|
4
|
+
class AgentTemplateRegistry {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.templates = new Map();
|
|
7
|
+
}
|
|
8
|
+
register(template) {
|
|
9
|
+
if (!template.id)
|
|
10
|
+
throw new Error('Template id is required');
|
|
11
|
+
if (!template.systemPrompt || !template.systemPrompt.trim()) {
|
|
12
|
+
throw new Error(`Template ${template.id} must provide a non-empty systemPrompt`);
|
|
13
|
+
}
|
|
14
|
+
this.templates.set(template.id, template);
|
|
15
|
+
}
|
|
16
|
+
bulkRegister(templates) {
|
|
17
|
+
for (const tpl of templates) {
|
|
18
|
+
this.register(tpl);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
has(id) {
|
|
22
|
+
return this.templates.has(id);
|
|
23
|
+
}
|
|
24
|
+
get(id) {
|
|
25
|
+
const tpl = this.templates.get(id);
|
|
26
|
+
if (!tpl) {
|
|
27
|
+
throw new Error(`Template not found: ${id}`);
|
|
28
|
+
}
|
|
29
|
+
return tpl;
|
|
30
|
+
}
|
|
31
|
+
list() {
|
|
32
|
+
return Array.from(this.templates.values());
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.AgentTemplateRegistry = AgentTemplateRegistry;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Scheduler } from './scheduler';
|
|
2
|
+
export interface TimeBridgeOptions {
|
|
3
|
+
scheduler: Scheduler;
|
|
4
|
+
driftToleranceMs?: number;
|
|
5
|
+
logger?: (msg: string, meta?: Record<string, any>) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare class TimeBridge {
|
|
8
|
+
private readonly scheduler;
|
|
9
|
+
private readonly driftTolerance;
|
|
10
|
+
private readonly logger?;
|
|
11
|
+
private readonly timers;
|
|
12
|
+
constructor(opts: TimeBridgeOptions);
|
|
13
|
+
everyMinutes(minutes: number, callback: () => void | Promise<void>): string;
|
|
14
|
+
cron(expr: string, callback: () => void | Promise<void>): string;
|
|
15
|
+
stop(timerId: string): void;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
private generateId;
|
|
18
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimeBridge = void 0;
|
|
4
|
+
class TimeBridge {
|
|
5
|
+
constructor(opts) {
|
|
6
|
+
this.timers = new Map();
|
|
7
|
+
this.scheduler = opts.scheduler;
|
|
8
|
+
this.driftTolerance = opts.driftToleranceMs ?? 5000;
|
|
9
|
+
this.logger = opts.logger;
|
|
10
|
+
}
|
|
11
|
+
everyMinutes(minutes, callback) {
|
|
12
|
+
if (!Number.isFinite(minutes) || minutes <= 0) {
|
|
13
|
+
throw new Error('everyMinutes: interval must be positive');
|
|
14
|
+
}
|
|
15
|
+
const interval = minutes * 60 * 1000;
|
|
16
|
+
const id = this.generateId('minutes');
|
|
17
|
+
const scheduleNext = () => {
|
|
18
|
+
const due = Date.now() + interval;
|
|
19
|
+
const handle = setTimeout(() => tick(due), interval);
|
|
20
|
+
entry.cancel = () => clearTimeout(handle);
|
|
21
|
+
};
|
|
22
|
+
const spec = `every:${minutes}m`;
|
|
23
|
+
const tick = (due) => {
|
|
24
|
+
this.scheduler.enqueue(async () => {
|
|
25
|
+
const drift = Math.abs(Date.now() - due);
|
|
26
|
+
if (drift > this.driftTolerance) {
|
|
27
|
+
this.logger?.('timebridge:drift', { id, drift, expectedInterval: interval });
|
|
28
|
+
}
|
|
29
|
+
await callback();
|
|
30
|
+
this.scheduler.notifyExternalTrigger({ taskId: id, spec, kind: 'time' });
|
|
31
|
+
});
|
|
32
|
+
scheduleNext();
|
|
33
|
+
};
|
|
34
|
+
const entry = {
|
|
35
|
+
id,
|
|
36
|
+
cancel: () => undefined,
|
|
37
|
+
};
|
|
38
|
+
this.timers.set(id, entry);
|
|
39
|
+
scheduleNext();
|
|
40
|
+
return id;
|
|
41
|
+
}
|
|
42
|
+
cron(expr, callback) {
|
|
43
|
+
const parts = expr.trim().split(/\s+/);
|
|
44
|
+
if (parts.length !== 5) {
|
|
45
|
+
throw new Error(`Unsupported cron expression: ${expr}`);
|
|
46
|
+
}
|
|
47
|
+
const minute = Number(parts[0]);
|
|
48
|
+
const hour = Number(parts[1]);
|
|
49
|
+
if (!Number.isInteger(minute) || !Number.isInteger(hour)) {
|
|
50
|
+
throw new Error(`Cron expression must be numeric minutes/hours: ${expr}`);
|
|
51
|
+
}
|
|
52
|
+
const id = this.generateId('cron');
|
|
53
|
+
const scheduleNext = () => {
|
|
54
|
+
const now = new Date();
|
|
55
|
+
const next = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0, 0);
|
|
56
|
+
if (next <= now) {
|
|
57
|
+
next.setDate(next.getDate() + 1);
|
|
58
|
+
}
|
|
59
|
+
const due = next.getTime();
|
|
60
|
+
const delay = Math.max(0, due - Date.now());
|
|
61
|
+
const handle = setTimeout(() => tick(due), delay);
|
|
62
|
+
entry.cancel = () => clearTimeout(handle);
|
|
63
|
+
};
|
|
64
|
+
const tick = (due) => {
|
|
65
|
+
this.scheduler.enqueue(async () => {
|
|
66
|
+
const drift = Math.abs(Date.now() - due);
|
|
67
|
+
if (drift > this.driftTolerance) {
|
|
68
|
+
this.logger?.('timebridge:drift', { id, drift, spec: expr });
|
|
69
|
+
}
|
|
70
|
+
await callback();
|
|
71
|
+
this.scheduler.notifyExternalTrigger({ taskId: id, spec: expr, kind: 'cron' });
|
|
72
|
+
});
|
|
73
|
+
scheduleNext();
|
|
74
|
+
};
|
|
75
|
+
const entry = {
|
|
76
|
+
id,
|
|
77
|
+
cancel: () => undefined,
|
|
78
|
+
};
|
|
79
|
+
this.timers.set(id, entry);
|
|
80
|
+
scheduleNext();
|
|
81
|
+
return id;
|
|
82
|
+
}
|
|
83
|
+
stop(timerId) {
|
|
84
|
+
const entry = this.timers.get(timerId);
|
|
85
|
+
if (!entry)
|
|
86
|
+
return;
|
|
87
|
+
entry.cancel();
|
|
88
|
+
this.timers.delete(timerId);
|
|
89
|
+
}
|
|
90
|
+
dispose() {
|
|
91
|
+
for (const entry of this.timers.values()) {
|
|
92
|
+
entry.cancel();
|
|
93
|
+
}
|
|
94
|
+
this.timers.clear();
|
|
95
|
+
}
|
|
96
|
+
generateId(prefix) {
|
|
97
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.TimeBridge = TimeBridge;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Store } from '../infra/store';
|
|
2
|
+
export type TodoStatus = 'pending' | 'in_progress' | 'completed';
|
|
3
|
+
export interface TodoItem {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
status: TodoStatus;
|
|
7
|
+
assignee?: string;
|
|
8
|
+
notes?: string;
|
|
9
|
+
createdAt: number;
|
|
10
|
+
updatedAt: number;
|
|
11
|
+
}
|
|
12
|
+
export interface TodoSnapshot {
|
|
13
|
+
todos: TodoItem[];
|
|
14
|
+
version: number;
|
|
15
|
+
updatedAt: number;
|
|
16
|
+
}
|
|
17
|
+
export type TodoInput = Omit<TodoItem, 'createdAt' | 'updatedAt'> & {
|
|
18
|
+
createdAt?: number;
|
|
19
|
+
updatedAt?: number;
|
|
20
|
+
};
|
|
21
|
+
export declare class TodoService {
|
|
22
|
+
private readonly store;
|
|
23
|
+
private readonly agentId;
|
|
24
|
+
private snapshot;
|
|
25
|
+
constructor(store: Store, agentId: string);
|
|
26
|
+
load(): Promise<void>;
|
|
27
|
+
list(): TodoItem[];
|
|
28
|
+
setTodos(todos: TodoInput[]): Promise<void>;
|
|
29
|
+
update(todo: TodoInput): Promise<void>;
|
|
30
|
+
delete(id: string): Promise<void>;
|
|
31
|
+
private validateTodos;
|
|
32
|
+
private persist;
|
|
33
|
+
private normalize;
|
|
34
|
+
}
|