@shareai-lab/kode-sdk 2.7.1 → 2.7.2

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.
Files changed (97) hide show
  1. package/dist/core/agent/breakpoint-manager.js +36 -0
  2. package/dist/core/agent/message-queue.js +57 -0
  3. package/dist/core/agent/permission-manager.js +32 -0
  4. package/dist/core/agent/todo-manager.js +91 -0
  5. package/dist/core/agent/tool-runner.js +45 -0
  6. package/dist/core/agent.js +2035 -0
  7. package/dist/core/config.js +2 -0
  8. package/dist/core/context-manager.js +241 -0
  9. package/dist/core/errors.js +49 -0
  10. package/dist/core/events.js +329 -0
  11. package/dist/core/file-pool.d.ts +2 -0
  12. package/dist/core/file-pool.js +125 -0
  13. package/dist/core/hooks.js +71 -0
  14. package/dist/core/permission-modes.js +61 -0
  15. package/dist/core/pool.js +301 -0
  16. package/dist/core/room.js +57 -0
  17. package/dist/core/scheduler.js +58 -0
  18. package/dist/core/skills/index.js +20 -0
  19. package/dist/core/skills/management-manager.js +557 -0
  20. package/dist/core/skills/manager.js +243 -0
  21. package/dist/core/skills/operation-queue.js +113 -0
  22. package/dist/core/skills/sandbox-file-manager.js +183 -0
  23. package/dist/core/skills/types.js +9 -0
  24. package/dist/core/skills/xml-generator.js +70 -0
  25. package/dist/core/template.js +35 -0
  26. package/dist/core/time-bridge.js +100 -0
  27. package/dist/core/todo.js +89 -0
  28. package/dist/core/types.js +3 -0
  29. package/dist/index.js +148 -60461
  30. package/dist/infra/db/postgres/postgres-store.js +1073 -0
  31. package/dist/infra/db/sqlite/sqlite-store.js +800 -0
  32. package/dist/infra/e2b/e2b-fs.js +128 -0
  33. package/dist/infra/e2b/e2b-sandbox.js +156 -0
  34. package/dist/infra/e2b/e2b-template.js +105 -0
  35. package/dist/infra/e2b/index.js +9 -0
  36. package/dist/infra/e2b/types.js +2 -0
  37. package/dist/infra/provider.js +67 -0
  38. package/dist/infra/providers/anthropic.js +308 -0
  39. package/dist/infra/providers/core/errors.js +353 -0
  40. package/dist/infra/providers/core/fork.js +418 -0
  41. package/dist/infra/providers/core/index.js +76 -0
  42. package/dist/infra/providers/core/logger.js +191 -0
  43. package/dist/infra/providers/core/retry.js +189 -0
  44. package/dist/infra/providers/core/usage.js +376 -0
  45. package/dist/infra/providers/gemini.js +493 -0
  46. package/dist/infra/providers/index.js +83 -0
  47. package/dist/infra/providers/openai.js +662 -0
  48. package/dist/infra/providers/types.js +20 -0
  49. package/dist/infra/providers/utils.js +400 -0
  50. package/dist/infra/sandbox-factory.js +30 -0
  51. package/dist/infra/sandbox.js +243 -0
  52. package/dist/infra/store/factory.js +80 -0
  53. package/dist/infra/store/index.js +26 -0
  54. package/dist/infra/store/json-store.js +606 -0
  55. package/dist/infra/store/types.js +2 -0
  56. package/dist/infra/store.js +29 -0
  57. package/dist/tools/bash_kill/index.js +35 -0
  58. package/dist/tools/bash_kill/prompt.js +14 -0
  59. package/dist/tools/bash_logs/index.js +40 -0
  60. package/dist/tools/bash_logs/prompt.js +14 -0
  61. package/dist/tools/bash_run/index.js +61 -0
  62. package/dist/tools/bash_run/prompt.js +18 -0
  63. package/dist/tools/builtin.js +26 -0
  64. package/dist/tools/define.js +214 -0
  65. package/dist/tools/fs_edit/index.js +62 -0
  66. package/dist/tools/fs_edit/prompt.js +15 -0
  67. package/dist/tools/fs_glob/index.js +40 -0
  68. package/dist/tools/fs_glob/prompt.js +15 -0
  69. package/dist/tools/fs_grep/index.js +66 -0
  70. package/dist/tools/fs_grep/prompt.js +16 -0
  71. package/dist/tools/fs_multi_edit/index.js +106 -0
  72. package/dist/tools/fs_multi_edit/prompt.js +16 -0
  73. package/dist/tools/fs_read/index.js +40 -0
  74. package/dist/tools/fs_read/prompt.js +16 -0
  75. package/dist/tools/fs_write/index.js +40 -0
  76. package/dist/tools/fs_write/prompt.js +15 -0
  77. package/dist/tools/index.js +61 -0
  78. package/dist/tools/mcp.js +185 -0
  79. package/dist/tools/registry.js +26 -0
  80. package/dist/tools/scripts.js +205 -0
  81. package/dist/tools/skills.js +115 -0
  82. package/dist/tools/task_run/index.js +58 -0
  83. package/dist/tools/task_run/prompt.js +25 -0
  84. package/dist/tools/todo_read/index.js +29 -0
  85. package/dist/tools/todo_read/prompt.js +18 -0
  86. package/dist/tools/todo_write/index.js +42 -0
  87. package/dist/tools/todo_write/prompt.js +23 -0
  88. package/dist/tools/tool.js +211 -0
  89. package/dist/tools/toolkit.js +98 -0
  90. package/dist/tools/type-inference.js +207 -0
  91. package/dist/utils/agent-id.js +28 -0
  92. package/dist/utils/logger.js +44 -0
  93. package/dist/utils/session-id.js +64 -0
  94. package/package.json +7 -38
  95. package/dist/index.js.map +0 -7
  96. package/dist/index.mjs +0 -60385
  97. package/dist/index.mjs.map +0 -7
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ /**
3
+ * Skills 管理器
4
+ *
5
+ * 设计原则 (UNIX哲学):
6
+ * - 简洁: 只负责扫描和加载skills,不处理业务逻辑
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.SkillsManager = void 0;
45
+ const fs = __importStar(require("fs/promises"));
46
+ const path = __importStar(require("path"));
47
+ const logger_1 = require("../../utils/logger");
48
+ /**
49
+ * Skills 管理器
50
+ */
51
+ class SkillsManager {
52
+ constructor(skillsDir, allowedSkills) {
53
+ this.cache = new Map();
54
+ // 优先使用传入的路径,其次使用环境变量,最后使用默认路径
55
+ // 默认路径:程序当前工作目录下的 skills/
56
+ const envSkillsDir = process.env.SKILLS_DIR;
57
+ const defaultSkillsDir = path.join(process.cwd(), 'skills');
58
+ this.skillsDir = path.resolve(skillsDir ||
59
+ envSkillsDir ||
60
+ defaultSkillsDir);
61
+ // 设置允许加载的 skills 白名单
62
+ this.allowedSkills = allowedSkills;
63
+ logger_1.logger.log(`[SkillsManager] Initialized with skills directory: ${this.skillsDir}`);
64
+ if (this.allowedSkills) {
65
+ logger_1.logger.log(`[SkillsManager] Allowed skills whitelist: ${this.allowedSkills.join(', ')}`);
66
+ }
67
+ }
68
+ /**
69
+ * 扫描skills目录(支持热更新)
70
+ * 每次调用时重新扫描,确保读取最新数据
71
+ */
72
+ async scan() {
73
+ // 清空缓存
74
+ this.cache.clear();
75
+ try {
76
+ // 检查目录是否存在
77
+ const exists = await this.fileExists(this.skillsDir);
78
+ if (!exists) {
79
+ logger_1.logger.log(`[SkillsManager] Skills directory does not exist: ${this.skillsDir}`);
80
+ return [];
81
+ }
82
+ // 递归扫描skills目录
83
+ const entries = await this.scanDirectory(this.skillsDir);
84
+ // 提取每个skill的元数据
85
+ for (const entry of entries) {
86
+ const metadata = await this.parseSkillMetadata(entry);
87
+ if (metadata) {
88
+ // 如果设置了白名单,只加载白名单中的 skills
89
+ if (this.allowedSkills) {
90
+ if (this.allowedSkills.includes(metadata.name)) {
91
+ this.cache.set(metadata.name, metadata);
92
+ }
93
+ else {
94
+ logger_1.logger.log(`[SkillsManager] Skipping skill not in whitelist: ${metadata.name}`);
95
+ }
96
+ }
97
+ else {
98
+ // 没有设置白名单,加载所有 skills
99
+ this.cache.set(metadata.name, metadata);
100
+ }
101
+ }
102
+ }
103
+ logger_1.logger.log(`[SkillsManager] Scanned ${this.cache.size} skill(s)`);
104
+ return Array.from(this.cache.values());
105
+ }
106
+ catch (error) {
107
+ logger_1.logger.error(`[SkillsManager] Error scanning skills directory:`, error.message);
108
+ return [];
109
+ }
110
+ }
111
+ /**
112
+ * 获取所有skills的元数据列表(供LLM选择)
113
+ */
114
+ async getSkillsMetadata() {
115
+ // 每次调用时重新扫描,支持热更新
116
+ return await this.scan();
117
+ }
118
+ /**
119
+ * 加载指定skill的完整内容
120
+ */
121
+ async loadSkillContent(skillName) {
122
+ // 先扫描确保元数据最新
123
+ await this.scan();
124
+ const metadata = this.cache.get(skillName);
125
+ if (!metadata) {
126
+ return null;
127
+ }
128
+ try {
129
+ // 读取SKILL.md内容
130
+ const content = await fs.readFile(metadata.path, 'utf-8');
131
+ // 扫描子目录
132
+ const references = await this.listSubdirectory(metadata.baseDir, 'references');
133
+ const scripts = await this.listSubdirectory(metadata.baseDir, 'scripts');
134
+ const assets = await this.listSubdirectory(metadata.baseDir, 'assets');
135
+ return {
136
+ metadata,
137
+ content,
138
+ references,
139
+ scripts,
140
+ assets,
141
+ };
142
+ }
143
+ catch (error) {
144
+ logger_1.logger.error(`[SkillsManager] Error loading skill content:`, error.message);
145
+ return null;
146
+ }
147
+ }
148
+ /**
149
+ * 递归扫描目录,查找所有SKILL.md
150
+ */
151
+ async scanDirectory(dir) {
152
+ const skillFiles = [];
153
+ try {
154
+ const entries = await fs.readdir(dir, { withFileTypes: true });
155
+ for (const entry of entries) {
156
+ const fullPath = path.join(dir, entry.name);
157
+ if (entry.isDirectory()) {
158
+ // 检查是否有SKILL.md
159
+ const skillMdPath = path.join(fullPath, 'SKILL.md');
160
+ if (await this.fileExists(skillMdPath)) {
161
+ skillFiles.push(skillMdPath);
162
+ }
163
+ else {
164
+ // 递归扫描子目录
165
+ const subSkills = await this.scanDirectory(fullPath);
166
+ skillFiles.push(...subSkills);
167
+ }
168
+ }
169
+ }
170
+ }
171
+ catch (error) {
172
+ logger_1.logger.warn(`[SkillsManager] Error reading directory ${dir}:`, error.message);
173
+ }
174
+ return skillFiles;
175
+ }
176
+ /**
177
+ * 解析SKILL.md,提取元数据
178
+ */
179
+ async parseSkillMetadata(skillMdPath) {
180
+ try {
181
+ const content = await fs.readFile(skillMdPath, 'utf-8');
182
+ // 提取YAML frontmatter
183
+ const match = content.match(/^---\n([\s\S]+?)\n---/);
184
+ if (!match) {
185
+ logger_1.logger.warn(`[SkillsManager] Invalid SKILL.md (missing YAML frontmatter): ${skillMdPath}`);
186
+ return null;
187
+ }
188
+ const yaml = match[1];
189
+ const nameMatch = yaml.match(/^name:\s*(.+)$/m);
190
+ const descMatch = yaml.match(/^description:\s*(.+)$/m);
191
+ if (!nameMatch) {
192
+ logger_1.logger.warn(`[SkillsManager] Invalid SKILL.md (missing name): ${skillMdPath}`);
193
+ return null;
194
+ }
195
+ return {
196
+ name: nameMatch[1].trim(),
197
+ description: descMatch ? descMatch[1].trim() : '',
198
+ path: skillMdPath,
199
+ baseDir: path.dirname(skillMdPath),
200
+ };
201
+ }
202
+ catch (error) {
203
+ logger_1.logger.warn(`[SkillsManager] Error parsing ${skillMdPath}:`, error.message);
204
+ return null;
205
+ }
206
+ }
207
+ /**
208
+ * 列出子目录下的文件
209
+ */
210
+ async listSubdirectory(baseDir, subdir) {
211
+ const fullPath = path.join(baseDir, subdir);
212
+ if (!(await this.fileExists(fullPath))) {
213
+ return [];
214
+ }
215
+ const files = [];
216
+ try {
217
+ const entries = await fs.readdir(fullPath, { withFileTypes: true });
218
+ for (const entry of entries) {
219
+ if (entry.isFile()) {
220
+ files.push(path.join(fullPath, entry.name));
221
+ }
222
+ }
223
+ }
224
+ catch (error) {
225
+ // 目录不存在或无权限访问,返回空数组
226
+ logger_1.logger.debug(`[SkillsManager] Subdirectory not accessible: ${fullPath}`);
227
+ }
228
+ return files;
229
+ }
230
+ /**
231
+ * 检查文件是否存在
232
+ */
233
+ async fileExists(filePath) {
234
+ try {
235
+ await fs.access(filePath);
236
+ return true;
237
+ }
238
+ catch {
239
+ return false;
240
+ }
241
+ }
242
+ }
243
+ exports.SkillsManager = SkillsManager;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * 操作队列模块
4
+ *
5
+ * 设计原则 (UNIX哲学):
6
+ * - 简洁: 只负责队列管理,单一职责
7
+ * - 模块化: 独立的队列逻辑,易于测试和维护
8
+ * - 隔离: 与技能管理逻辑分离,专注于并发控制
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.OperationQueue = exports.OperationStatus = exports.OperationType = void 0;
12
+ const logger_1 = require("../../utils/logger");
13
+ /**
14
+ * 操作类型枚举
15
+ */
16
+ var OperationType;
17
+ (function (OperationType) {
18
+ OperationType["CREATE"] = "create";
19
+ OperationType["RENAME"] = "rename";
20
+ OperationType["EDIT"] = "edit";
21
+ OperationType["DELETE"] = "delete";
22
+ OperationType["RESTORE"] = "restore";
23
+ })(OperationType || (exports.OperationType = OperationType = {}));
24
+ /**
25
+ * 操作状态枚举
26
+ */
27
+ var OperationStatus;
28
+ (function (OperationStatus) {
29
+ OperationStatus["PENDING"] = "pending";
30
+ OperationStatus["PROCESSING"] = "processing";
31
+ OperationStatus["COMPLETED"] = "completed";
32
+ OperationStatus["FAILED"] = "failed";
33
+ })(OperationStatus || (exports.OperationStatus = OperationStatus = {}));
34
+ /**
35
+ * 操作队列类
36
+ *
37
+ * 职责:
38
+ * - 管理技能管理操作的并发执行
39
+ * - 按FIFO顺序处理操作
40
+ * - 防止操作冲突
41
+ */
42
+ class OperationQueue {
43
+ constructor() {
44
+ this.queue = [];
45
+ this.processing = false;
46
+ this.maxConcurrent = 1; // 串行执行,避免冲突
47
+ }
48
+ /**
49
+ * 入队操作
50
+ */
51
+ async enqueue(task) {
52
+ this.queue.push(task);
53
+ logger_1.logger.log(`[OperationQueue] 操作已入队: ${task.type} - ${task.targetSkill}`);
54
+ // 如果没有正在处理,启动处理(不等待,异步执行)
55
+ if (!this.processing) {
56
+ // 不使用await,让队列异步处理
57
+ this.processQueue().catch(error => {
58
+ logger_1.logger.error('[OperationQueue] Queue processing error:', error);
59
+ });
60
+ }
61
+ }
62
+ /**
63
+ * 出队操作
64
+ */
65
+ dequeue() {
66
+ return this.queue.shift() || null;
67
+ }
68
+ /**
69
+ * 处理队列
70
+ */
71
+ async processQueue() {
72
+ this.processing = true;
73
+ while (this.queue.length > 0) {
74
+ const task = this.dequeue();
75
+ if (!task)
76
+ break;
77
+ task.status = OperationStatus.PROCESSING;
78
+ task.startedAt = new Date();
79
+ try {
80
+ logger_1.logger.log(`[OperationQueue] 开始处理: ${task.type} - ${task.targetSkill}`);
81
+ await task.execute();
82
+ task.status = OperationStatus.COMPLETED;
83
+ task.completedAt = new Date();
84
+ logger_1.logger.log(`[OperationQueue] 操作完成: ${task.type} - ${task.targetSkill}`);
85
+ }
86
+ catch (error) {
87
+ task.status = OperationStatus.FAILED;
88
+ task.completedAt = new Date();
89
+ task.error = error;
90
+ logger_1.logger.error(`[OperationQueue] 操作失败: ${task.type} - ${task.targetSkill}`, error);
91
+ }
92
+ }
93
+ this.processing = false;
94
+ }
95
+ /**
96
+ * 获取队列状态
97
+ */
98
+ getQueueStatus() {
99
+ return {
100
+ length: this.queue.length,
101
+ processing: this.processing,
102
+ tasks: [...this.queue],
103
+ };
104
+ }
105
+ /**
106
+ * 清空队列
107
+ */
108
+ clear() {
109
+ this.queue = [];
110
+ logger_1.logger.log('[OperationQueue] 队列已清空');
111
+ }
112
+ }
113
+ exports.OperationQueue = OperationQueue;
@@ -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,9 @@
1
+ "use strict";
2
+ /**
3
+ * Skills 核心类型定义
4
+ *
5
+ * 设计原则 (UNIX哲学):
6
+ * - 简洁: 类型定义清晰,职责单一
7
+ * - 模块化: 类型独立,易于维护和扩展
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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, '&amp;')
66
+ .replace(/</g, '&lt;')
67
+ .replace(/>/g, '&gt;')
68
+ .replace(/"/g, '&quot;')
69
+ .replace(/'/g, '&apos;');
70
+ }
@@ -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;