@next-open-ai/openclawx 0.6.6

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 (198) hide show
  1. package/README.md +523 -0
  2. package/apps/desktop/README.md +210 -0
  3. package/apps/desktop/renderer/dist/assets/index-CYkSfhcp.css +10 -0
  4. package/apps/desktop/renderer/dist/assets/index-FI6O25Ms.js +89 -0
  5. package/apps/desktop/renderer/dist/index.html +22 -0
  6. package/dist/cli/cli.d.ts +2 -0
  7. package/dist/cli/cli.js +198 -0
  8. package/dist/cli/service.d.ts +13 -0
  9. package/dist/cli/service.js +243 -0
  10. package/dist/cli.d.ts +5 -0
  11. package/dist/cli.js +5 -0
  12. package/dist/core/agent/agent-dir.d.ts +14 -0
  13. package/dist/core/agent/agent-dir.js +75 -0
  14. package/dist/core/agent/agent-manager.d.ts +64 -0
  15. package/dist/core/agent/agent-manager.js +278 -0
  16. package/dist/core/agent/config-manager.d.ts +25 -0
  17. package/dist/core/agent/config-manager.js +84 -0
  18. package/dist/core/agent/run.d.ts +26 -0
  19. package/dist/core/agent/run.js +65 -0
  20. package/dist/core/agent/skills.d.ts +20 -0
  21. package/dist/core/agent/skills.js +86 -0
  22. package/dist/core/config/desktop-config.d.ts +90 -0
  23. package/dist/core/config/desktop-config.js +521 -0
  24. package/dist/core/config/provider-support-default.d.ts +21 -0
  25. package/dist/core/config/provider-support-default.js +57 -0
  26. package/dist/core/installer/index.d.ts +1 -0
  27. package/dist/core/installer/index.js +1 -0
  28. package/dist/core/installer/skill-installer.d.ts +39 -0
  29. package/dist/core/installer/skill-installer.js +215 -0
  30. package/dist/core/mcp/adapter.d.ts +17 -0
  31. package/dist/core/mcp/adapter.js +49 -0
  32. package/dist/core/mcp/client.d.ts +24 -0
  33. package/dist/core/mcp/client.js +70 -0
  34. package/dist/core/mcp/config.d.ts +22 -0
  35. package/dist/core/mcp/config.js +69 -0
  36. package/dist/core/mcp/index.d.ts +18 -0
  37. package/dist/core/mcp/index.js +20 -0
  38. package/dist/core/mcp/operator.d.ts +15 -0
  39. package/dist/core/mcp/operator.js +72 -0
  40. package/dist/core/mcp/transport/index.d.ts +11 -0
  41. package/dist/core/mcp/transport/index.js +16 -0
  42. package/dist/core/mcp/transport/sse.d.ts +20 -0
  43. package/dist/core/mcp/transport/sse.js +82 -0
  44. package/dist/core/mcp/transport/stdio.d.ts +32 -0
  45. package/dist/core/mcp/transport/stdio.js +132 -0
  46. package/dist/core/mcp/types.d.ts +72 -0
  47. package/dist/core/mcp/types.js +5 -0
  48. package/dist/core/memory/build-summary.d.ts +6 -0
  49. package/dist/core/memory/build-summary.js +27 -0
  50. package/dist/core/memory/compaction-extension.d.ts +6 -0
  51. package/dist/core/memory/compaction-extension.js +23 -0
  52. package/dist/core/memory/embedding.d.ts +4 -0
  53. package/dist/core/memory/embedding.js +15 -0
  54. package/dist/core/memory/index.d.ts +29 -0
  55. package/dist/core/memory/index.js +70 -0
  56. package/dist/core/memory/remote-embedding.d.ts +10 -0
  57. package/dist/core/memory/remote-embedding.js +36 -0
  58. package/dist/core/memory/types.d.ts +16 -0
  59. package/dist/core/memory/types.js +1 -0
  60. package/dist/core/memory/vector-store.d.ts +15 -0
  61. package/dist/core/memory/vector-store.js +65 -0
  62. package/dist/core/tools/bookmark-tool.d.ts +9 -0
  63. package/dist/core/tools/bookmark-tool.js +118 -0
  64. package/dist/core/tools/browser-tool.d.ts +10 -0
  65. package/dist/core/tools/browser-tool.js +362 -0
  66. package/dist/core/tools/index.d.ts +4 -0
  67. package/dist/core/tools/index.js +4 -0
  68. package/dist/core/tools/install-skill-tool.d.ts +6 -0
  69. package/dist/core/tools/install-skill-tool.js +53 -0
  70. package/dist/core/tools/save-experience-tool.d.ts +5 -0
  71. package/dist/core/tools/save-experience-tool.js +54 -0
  72. package/dist/gateway/auth-hooks.d.ts +17 -0
  73. package/dist/gateway/auth-hooks.js +19 -0
  74. package/dist/gateway/backend-url.d.ts +2 -0
  75. package/dist/gateway/backend-url.js +11 -0
  76. package/dist/gateway/channel-handler.d.ts +6 -0
  77. package/dist/gateway/channel-handler.js +3 -0
  78. package/dist/gateway/clients.d.ts +5 -0
  79. package/dist/gateway/clients.js +4 -0
  80. package/dist/gateway/connection-handler.d.ts +6 -0
  81. package/dist/gateway/connection-handler.js +48 -0
  82. package/dist/gateway/index.d.ts +3 -0
  83. package/dist/gateway/index.js +2 -0
  84. package/dist/gateway/message-handler.d.ts +5 -0
  85. package/dist/gateway/message-handler.js +65 -0
  86. package/dist/gateway/methods/agent-cancel.d.ts +10 -0
  87. package/dist/gateway/methods/agent-cancel.js +17 -0
  88. package/dist/gateway/methods/agent-chat.d.ts +8 -0
  89. package/dist/gateway/methods/agent-chat.js +148 -0
  90. package/dist/gateway/methods/connect.d.ts +9 -0
  91. package/dist/gateway/methods/connect.js +18 -0
  92. package/dist/gateway/methods/install-skill-from-path.d.ts +13 -0
  93. package/dist/gateway/methods/install-skill-from-path.js +15 -0
  94. package/dist/gateway/methods/install-skill-from-upload.d.ts +14 -0
  95. package/dist/gateway/methods/install-skill-from-upload.js +13 -0
  96. package/dist/gateway/methods/run-scheduled-task.d.ts +15 -0
  97. package/dist/gateway/methods/run-scheduled-task.js +127 -0
  98. package/dist/gateway/paths.d.ts +20 -0
  99. package/dist/gateway/paths.js +19 -0
  100. package/dist/gateway/server.d.ts +8 -0
  101. package/dist/gateway/server.js +190 -0
  102. package/dist/gateway/sse-handler.d.ts +6 -0
  103. package/dist/gateway/sse-handler.js +3 -0
  104. package/dist/gateway/types.d.ts +90 -0
  105. package/dist/gateway/types.js +1 -0
  106. package/dist/gateway/utils.d.ts +22 -0
  107. package/dist/gateway/utils.js +67 -0
  108. package/dist/gateway/voice-handler.d.ts +12 -0
  109. package/dist/gateway/voice-handler.js +18 -0
  110. package/dist/index.d.ts +5 -0
  111. package/dist/index.js +5 -0
  112. package/dist/server/agent-config/agent-config.controller.d.ts +30 -0
  113. package/dist/server/agent-config/agent-config.controller.js +83 -0
  114. package/dist/server/agent-config/agent-config.module.d.ts +2 -0
  115. package/dist/server/agent-config/agent-config.module.js +19 -0
  116. package/dist/server/agent-config/agent-config.service.d.ts +53 -0
  117. package/dist/server/agent-config/agent-config.service.js +213 -0
  118. package/dist/server/agents/agents.controller.d.ts +41 -0
  119. package/dist/server/agents/agents.controller.js +118 -0
  120. package/dist/server/agents/agents.gateway.d.ts +21 -0
  121. package/dist/server/agents/agents.gateway.js +103 -0
  122. package/dist/server/agents/agents.module.d.ts +2 -0
  123. package/dist/server/agents/agents.module.js +20 -0
  124. package/dist/server/agents/agents.service.d.ts +63 -0
  125. package/dist/server/agents/agents.service.js +169 -0
  126. package/dist/server/app.module.d.ts +2 -0
  127. package/dist/server/app.module.js +38 -0
  128. package/dist/server/auth/auth.controller.d.ts +20 -0
  129. package/dist/server/auth/auth.controller.js +64 -0
  130. package/dist/server/auth/auth.module.d.ts +2 -0
  131. package/dist/server/auth/auth.module.js +19 -0
  132. package/dist/server/bootstrap.d.ts +15 -0
  133. package/dist/server/bootstrap.js +38 -0
  134. package/dist/server/config/config.controller.d.ts +73 -0
  135. package/dist/server/config/config.controller.js +95 -0
  136. package/dist/server/config/config.module.d.ts +2 -0
  137. package/dist/server/config/config.module.js +21 -0
  138. package/dist/server/config/config.service.d.ts +82 -0
  139. package/dist/server/config/config.service.js +123 -0
  140. package/dist/server/database/database.module.d.ts +2 -0
  141. package/dist/server/database/database.module.js +18 -0
  142. package/dist/server/database/database.service.d.ts +26 -0
  143. package/dist/server/database/database.service.js +253 -0
  144. package/dist/server/main.d.ts +1 -0
  145. package/dist/server/main.js +9 -0
  146. package/dist/server/saved-items/saved-items.controller.d.ts +57 -0
  147. package/dist/server/saved-items/saved-items.controller.js +229 -0
  148. package/dist/server/saved-items/saved-items.module.d.ts +2 -0
  149. package/dist/server/saved-items/saved-items.module.js +25 -0
  150. package/dist/server/saved-items/saved-items.service.d.ts +31 -0
  151. package/dist/server/saved-items/saved-items.service.js +105 -0
  152. package/dist/server/saved-items/tags.controller.d.ts +30 -0
  153. package/dist/server/saved-items/tags.controller.js +85 -0
  154. package/dist/server/saved-items/tags.service.d.ts +24 -0
  155. package/dist/server/saved-items/tags.service.js +84 -0
  156. package/dist/server/skills/skills.controller.d.ts +63 -0
  157. package/dist/server/skills/skills.controller.js +194 -0
  158. package/dist/server/skills/skills.module.d.ts +2 -0
  159. package/dist/server/skills/skills.module.js +22 -0
  160. package/dist/server/skills/skills.service.d.ts +65 -0
  161. package/dist/server/skills/skills.service.js +388 -0
  162. package/dist/server/tasks/tasks.controller.d.ts +52 -0
  163. package/dist/server/tasks/tasks.controller.js +163 -0
  164. package/dist/server/tasks/tasks.module.d.ts +2 -0
  165. package/dist/server/tasks/tasks.module.js +23 -0
  166. package/dist/server/tasks/tasks.service.d.ts +86 -0
  167. package/dist/server/tasks/tasks.service.js +327 -0
  168. package/dist/server/usage/usage.controller.d.ts +12 -0
  169. package/dist/server/usage/usage.controller.js +46 -0
  170. package/dist/server/usage/usage.module.d.ts +2 -0
  171. package/dist/server/usage/usage.module.js +19 -0
  172. package/dist/server/usage/usage.service.d.ts +21 -0
  173. package/dist/server/usage/usage.service.js +55 -0
  174. package/dist/server/users/users.controller.d.ts +35 -0
  175. package/dist/server/users/users.controller.js +69 -0
  176. package/dist/server/users/users.module.d.ts +2 -0
  177. package/dist/server/users/users.module.js +19 -0
  178. package/dist/server/users/users.service.d.ts +39 -0
  179. package/dist/server/users/users.service.js +140 -0
  180. package/dist/server/workspace/workspace.controller.d.ts +24 -0
  181. package/dist/server/workspace/workspace.controller.js +132 -0
  182. package/dist/server/workspace/workspace.module.d.ts +2 -0
  183. package/dist/server/workspace/workspace.module.js +21 -0
  184. package/dist/server/workspace/workspace.service.d.ts +36 -0
  185. package/dist/server/workspace/workspace.service.js +142 -0
  186. package/package.json +90 -0
  187. package/skills/agent-browser/SKILL.md +207 -0
  188. package/skills/agent-browser/references/authentication.md +202 -0
  189. package/skills/agent-browser/references/commands.md +259 -0
  190. package/skills/agent-browser/references/proxy-support.md +188 -0
  191. package/skills/agent-browser/references/session-management.md +193 -0
  192. package/skills/agent-browser/references/snapshot-refs.md +194 -0
  193. package/skills/agent-browser/references/video-recording.md +173 -0
  194. package/skills/agent-browser/templates/authenticated-session.sh +97 -0
  195. package/skills/agent-browser/templates/capture-workflow.sh +69 -0
  196. package/skills/agent-browser/templates/form-automation.sh +62 -0
  197. package/skills/find-skills/SKILL.md +140 -0
  198. package/skills/url-bookmark/SKILL.md +36 -0
@@ -0,0 +1,388 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable, ConflictException, NotFoundException, BadRequestException } from '@nestjs/common';
11
+ import { DEFAULT_AGENT_ID } from '../agent-config/agent-config.service.js';
12
+ import { readdir, readFile, stat, mkdir, writeFile, rm, cp, realpath } from 'fs/promises';
13
+ import { join, resolve, basename } from 'path';
14
+ import { existsSync } from 'fs';
15
+ import { tmpdir } from 'os';
16
+ import { randomUUID } from 'crypto';
17
+ import { exec } from 'child_process';
18
+ import { promisify } from 'util';
19
+ import { getOpenbotAgentDir, getOpenbotWorkspaceDir } from '../../core/agent/agent-dir.js';
20
+ const execAsync = promisify(exec);
21
+ /** 工作区技能名仅允许英文、数字、下划线、连字符 */
22
+ const SKILL_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
23
+ /**
24
+ * 系统技能目录:仅两条规则,不做复杂搜索。
25
+ * - 运行时/打包:由桌面 main 或部署方设置 OPENBOT_SYSTEM_SKILLS_DIR,用该目录。
26
+ * - 开发/测试:未设置时仅尝试「当前工作目录下的 skills」(从项目根启动时即项目目录下的 skills)。
27
+ */
28
+ function resolveSystemSkillsDir() {
29
+ const envDir = process.env.OPENBOT_SYSTEM_SKILLS_DIR?.trim();
30
+ if (envDir) {
31
+ const abs = resolve(envDir);
32
+ if (existsSync(abs))
33
+ return abs;
34
+ return null;
35
+ }
36
+ const cwdSkills = resolve(process.cwd(), 'skills');
37
+ if (existsSync(cwdSkills))
38
+ return cwdSkills;
39
+ return null;
40
+ }
41
+ /** 技能目录与来源:全局=OPENBOT_AGENT_DIR/skills,系统=项目根/skills,工作区=OPENBOT_WORKSPACE_DIR/xxx/skills */
42
+ let SkillsService = class SkillsService {
43
+ /** 待扫描的目录列表 */
44
+ skillPaths = [];
45
+ constructor() {
46
+ const cwd = process.cwd();
47
+ const workspaceName = process.env.OPENBOT_WORKSPACE || 'default';
48
+ // 全局技能:OPENBOT_AGENT_DIR/skills(默认 ~/.openbot/agent/skills)
49
+ const globalSkillsDir = join(getOpenbotAgentDir(), 'skills');
50
+ // 系统技能:OPENBOT_SYSTEM_SKILLS_DIR 或 cwd/skills(仅此两种)
51
+ const systemSkillsDir = resolveSystemSkillsDir();
52
+ // 工作区技能:OPENBOT_WORKSPACE_DIR/<name>/skills(默认 ~/.openbot/workspace/xxx/skills)
53
+ const workspaceSkillsDir = join(getOpenbotWorkspaceDir(), workspaceName, 'skills');
54
+ if (existsSync(globalSkillsDir)) {
55
+ this.skillPaths.push({ path: globalSkillsDir, source: 'global' });
56
+ }
57
+ if (systemSkillsDir) {
58
+ this.skillPaths.push({ path: systemSkillsDir, source: 'system' });
59
+ }
60
+ if (existsSync(workspaceSkillsDir)) {
61
+ this.skillPaths.push({ path: workspaceSkillsDir, source: 'workspace' });
62
+ }
63
+ }
64
+ /** 指定工作区的 skills 目录绝对路径(受 OPENBOT_WORKSPACE_DIR 影响) */
65
+ getWorkspaceSkillsDir(workspaceName) {
66
+ return join(getOpenbotWorkspaceDir(), workspaceName, 'skills');
67
+ }
68
+ /** 全局技能目录(受 OPENBOT_AGENT_DIR 影响,默认 ~/.openbot/agent/skills) */
69
+ getGlobalSkillsDir() {
70
+ return join(getOpenbotAgentDir(), 'skills');
71
+ }
72
+ /** 仅返回全局技能(OPENBOT_AGENT_DIR/skills) */
73
+ async getGlobalSkills() {
74
+ const skillPath = this.getGlobalSkillsDir();
75
+ if (!existsSync(skillPath))
76
+ return [];
77
+ const skills = [];
78
+ try {
79
+ const entries = await readdir(skillPath);
80
+ for (const entry of entries) {
81
+ const fullPath = join(skillPath, entry);
82
+ const stats = await stat(fullPath);
83
+ if (stats.isDirectory()) {
84
+ const skillMdPath = join(fullPath, 'SKILL.md');
85
+ if (existsSync(skillMdPath)) {
86
+ const content = await readFile(skillMdPath, 'utf-8');
87
+ skills.push(this.parseSkillFile(entry, content, fullPath, 'global'));
88
+ }
89
+ }
90
+ }
91
+ }
92
+ catch (error) {
93
+ console.error('Error reading global skills:', error);
94
+ }
95
+ return skills;
96
+ }
97
+ /** 删除全局技能 */
98
+ async deleteGlobalSkill(name) {
99
+ const skillDir = join(this.getGlobalSkillsDir(), name);
100
+ if (!existsSync(skillDir)) {
101
+ throw new NotFoundException('技能不存在');
102
+ }
103
+ await rm(skillDir, { recursive: true });
104
+ }
105
+ /**
106
+ * 通过 npx skills add 安装技能到指定目录。
107
+ * @param url 安装地址(Git 简写、URL 或 owner/repo@skill)
108
+ * @param options.scope 'global' 安装到 OPENBOT_AGENT_DIR/skills;'workspace' 安装到指定工作区的 skills
109
+ * @param options.workspace 当 scope 为 'workspace' 时的工作区名(对应 OPENBOT_WORKSPACE_DIR/<workspace>/skills)
110
+ */
111
+ async installSkillByUrl(url, options) {
112
+ if (!url || !url.trim()) {
113
+ throw new BadRequestException('安装地址不能为空');
114
+ }
115
+ const scope = options?.scope ?? 'global';
116
+ const workspaceName = options?.workspace ?? 'default';
117
+ const targetDir = scope === 'workspace'
118
+ ? this.getWorkspaceSkillsDir(workspaceName)
119
+ : this.getGlobalSkillsDir();
120
+ console.log(`[install_skill] 开始安装: url=${url.trim()}, scope=${scope}, workspace=${workspaceName}, 目标目录=${targetDir}`);
121
+ const tempDir = join(tmpdir(), `openbot-skills-${randomUUID()}`);
122
+ // skills CLI 实际安装到 tempDir/.agents/skills,-a pi 时可能用 .pi/skills,两处都尝试
123
+ const tempAgentsSkills = join(tempDir, '.agents', 'skills');
124
+ const tempPiSkills = join(tempDir, '.pi', 'skills');
125
+ let stdout = '';
126
+ let stderr = '';
127
+ const copiedNames = [];
128
+ try {
129
+ await mkdir(tempPiSkills, { recursive: true });
130
+ const { stdout: out, stderr: err } = await execAsync(`npx skills add "${url.trim()}" -a pi -y`, { cwd: tempDir, maxBuffer: 4 * 1024 * 1024 });
131
+ stdout = out || '';
132
+ stderr = err || '';
133
+ await mkdir(targetDir, { recursive: true });
134
+ const sourceDir = existsSync(tempAgentsSkills) ? tempAgentsSkills : tempPiSkills;
135
+ const entries = await readdir(sourceDir).catch(() => []);
136
+ for (const entry of entries) {
137
+ const src = join(sourceDir, entry);
138
+ const entryStat = await stat(src).catch(() => null);
139
+ if (!entryStat?.isDirectory())
140
+ continue;
141
+ const dest = join(targetDir, entry);
142
+ const srcResolved = await realpath(src).catch(() => src);
143
+ await cp(srcResolved, dest, { recursive: true });
144
+ copiedNames.push(entry);
145
+ }
146
+ }
147
+ finally {
148
+ await rm(tempDir, { recursive: true, force: true }).catch(() => { });
149
+ }
150
+ console.log(`[install_skill] 安装完成: 最终目录=${targetDir}, 技能名=${copiedNames.join(', ') || '(无)'}`);
151
+ return { stdout, stderr, installDir: targetDir };
152
+ }
153
+ /**
154
+ * 从本地目录安装技能:将指定目录复制到目标 skills 目录。
155
+ * @param localPath 本地技能目录绝对路径(须包含 SKILL.md)
156
+ * @param options.scope 'global' 安装到全局;'workspace' 安装到指定工作区
157
+ * @param options.workspace 当 scope 为 'workspace' 时的工作区名
158
+ */
159
+ async installSkillFromPath(localPath, options) {
160
+ const pathToUse = resolve(localPath.trim());
161
+ if (!existsSync(pathToUse)) {
162
+ throw new BadRequestException('本地路径不存在');
163
+ }
164
+ const pathStat = await stat(pathToUse);
165
+ if (!pathStat.isDirectory()) {
166
+ throw new BadRequestException('请选择技能目录');
167
+ }
168
+ const skillMdPath = join(pathToUse, 'SKILL.md');
169
+ if (!existsSync(skillMdPath)) {
170
+ throw new BadRequestException('该目录下未找到 SKILL.md,不是有效的技能目录');
171
+ }
172
+ const scope = options?.scope ?? 'global';
173
+ const workspaceName = options?.workspace ?? 'default';
174
+ const targetDir = scope === 'workspace'
175
+ ? this.getWorkspaceSkillsDir(workspaceName)
176
+ : this.getGlobalSkillsDir();
177
+ const baseName = basename(pathToUse) || 'skill';
178
+ if (!baseName || !SKILL_NAME_REGEX.test(baseName)) {
179
+ throw new BadRequestException('技能目录名须为英文、数字、下划线或连字符');
180
+ }
181
+ const destPath = join(targetDir, baseName);
182
+ try {
183
+ await mkdir(targetDir, { recursive: true });
184
+ if (existsSync(destPath)) {
185
+ await rm(destPath, { recursive: true });
186
+ }
187
+ const srcResolved = await realpath(pathToUse).catch(() => pathToUse);
188
+ await cp(srcResolved, destPath, { recursive: true });
189
+ }
190
+ catch (err) {
191
+ const msg = err instanceof Error ? err.message : String(err);
192
+ throw new BadRequestException(`复制失败: ${msg}`);
193
+ }
194
+ console.log(`[install_skill_from_path] 已安装: ${pathToUse} -> ${destPath}`);
195
+ return { installDir: targetDir, name: baseName };
196
+ }
197
+ async getSkills() {
198
+ const skills = [];
199
+ for (const { path: skillPath, source } of this.skillPaths) {
200
+ try {
201
+ const entries = await readdir(skillPath);
202
+ for (const entry of entries) {
203
+ const fullPath = join(skillPath, entry);
204
+ const stats = await stat(fullPath);
205
+ if (stats.isDirectory()) {
206
+ const skillMdPath = join(fullPath, 'SKILL.md');
207
+ if (existsSync(skillMdPath)) {
208
+ const content = await readFile(skillMdPath, 'utf-8');
209
+ const skill = this.parseSkillFile(entry, content, fullPath, source);
210
+ skills.push(skill);
211
+ }
212
+ }
213
+ }
214
+ }
215
+ catch (error) {
216
+ console.error(`Error reading skills from ${skillPath}:`, error);
217
+ }
218
+ }
219
+ return skills;
220
+ }
221
+ async getSkill(name) {
222
+ const skills = await this.getSkills();
223
+ return skills.find(s => s.name === name) || null;
224
+ }
225
+ async getSkillContent(name) {
226
+ const skill = await this.getSkill(name);
227
+ if (!skill)
228
+ return null;
229
+ try {
230
+ const skillMdPath = join(skill.path, 'SKILL.md');
231
+ return await readFile(skillMdPath, 'utf-8');
232
+ }
233
+ catch (error) {
234
+ console.error(`Error reading skill content for ${name}:`, error);
235
+ return null;
236
+ }
237
+ }
238
+ /** 仅返回指定工作区下的技能(文件目录管理,不涉及 SQLite) */
239
+ async getSkillsForWorkspace(workspaceName) {
240
+ const skillPath = this.getWorkspaceSkillsDir(workspaceName);
241
+ if (!existsSync(skillPath)) {
242
+ if (workspaceName === DEFAULT_AGENT_ID || workspaceName === 'default') {
243
+ try {
244
+ await mkdir(skillPath, { recursive: true });
245
+ }
246
+ catch (e) {
247
+ console.warn(`[skills] 创建 default 工作区技能目录失败: ${skillPath}`, e);
248
+ }
249
+ }
250
+ if (!existsSync(skillPath)) {
251
+ console.warn(`[skills] 工作区技能目录不存在,返回空列表: workspace=${workspaceName}, path=${skillPath}`);
252
+ return [];
253
+ }
254
+ }
255
+ const skills = [];
256
+ try {
257
+ const entries = await readdir(skillPath);
258
+ for (const entry of entries) {
259
+ const fullPath = join(skillPath, entry);
260
+ try {
261
+ const stats = await stat(fullPath);
262
+ if (!stats.isDirectory())
263
+ continue;
264
+ const skillMdPath = join(fullPath, 'SKILL.md');
265
+ const skillJsonPath = join(fullPath, 'skill.json');
266
+ const packageJsonPath = join(fullPath, 'package.json');
267
+ if (existsSync(skillMdPath)) {
268
+ const content = await readFile(skillMdPath, 'utf-8');
269
+ skills.push(this.parseSkillFile(entry, content, fullPath, 'workspace'));
270
+ }
271
+ else if (existsSync(skillJsonPath)) {
272
+ const skill = await this.parseSkillJson(entry, skillJsonPath, fullPath);
273
+ if (skill)
274
+ skills.push(skill);
275
+ }
276
+ else if (existsSync(packageJsonPath)) {
277
+ const skill = await this.parseSkillJson(entry, packageJsonPath, fullPath);
278
+ if (skill)
279
+ skills.push(skill);
280
+ }
281
+ }
282
+ catch (entryError) {
283
+ if (entryError?.code !== 'ENOENT') {
284
+ console.warn(`Skipping workspace skill entry ${entry}:`, entryError?.message ?? entryError);
285
+ }
286
+ }
287
+ }
288
+ }
289
+ catch (error) {
290
+ console.error(`Error reading workspace skills from ${skillPath}:`, error);
291
+ }
292
+ return skills;
293
+ }
294
+ /** 从 skill.json 或 package.json 解析出 Skill(兼容无 SKILL.md 的 npm 风格技能目录) */
295
+ async parseSkillJson(entryName, jsonPath, fullPath) {
296
+ try {
297
+ const content = await readFile(jsonPath, 'utf-8');
298
+ const data = JSON.parse(content);
299
+ const name = (data.name || entryName).trim() || entryName;
300
+ const description = (data.description || '').trim() || 'No description available';
301
+ return { name: entryName, description, path: fullPath, source: 'workspace' };
302
+ }
303
+ catch {
304
+ return null;
305
+ }
306
+ }
307
+ async getSkillContentForWorkspace(workspaceName, name) {
308
+ const skillPath = this.getWorkspaceSkillsDir(workspaceName);
309
+ const fullPath = join(skillPath, name);
310
+ const skillMdPath = join(fullPath, 'SKILL.md');
311
+ const readmePath = join(fullPath, 'README.md');
312
+ if (existsSync(skillMdPath)) {
313
+ try {
314
+ return await readFile(skillMdPath, 'utf-8');
315
+ }
316
+ catch {
317
+ return null;
318
+ }
319
+ }
320
+ if (existsSync(readmePath)) {
321
+ try {
322
+ return await readFile(readmePath, 'utf-8');
323
+ }
324
+ catch {
325
+ return null;
326
+ }
327
+ }
328
+ return null;
329
+ }
330
+ /** 在工作区下新增技能(创建目录 + SKILL.md) */
331
+ async addSkill(workspaceName, name, options) {
332
+ if (!name || !SKILL_NAME_REGEX.test(name)) {
333
+ throw new BadRequestException('技能名必须为英文、数字、下划线或连字符');
334
+ }
335
+ const skillDir = join(this.getWorkspaceSkillsDir(workspaceName), name);
336
+ if (existsSync(skillDir)) {
337
+ throw new ConflictException('该技能名已存在');
338
+ }
339
+ await mkdir(skillDir, { recursive: true });
340
+ const description = options?.description ?? 'No description available';
341
+ const body = options?.content ?? '';
342
+ const content = `---\ndescription: ${description}\n---\n\n${body}`;
343
+ await writeFile(join(skillDir, 'SKILL.md'), content, 'utf-8');
344
+ return this.parseSkillFile(name, content, skillDir, 'workspace');
345
+ }
346
+ /** 删除工作区下的技能目录;主智能体(default)下的 Skill 不可删除 */
347
+ async deleteSkill(workspaceName, name) {
348
+ if (workspaceName === DEFAULT_AGENT_ID || workspaceName === 'default') {
349
+ throw new BadRequestException('主智能体下的 Skill 不可删除');
350
+ }
351
+ const skillDir = join(this.getWorkspaceSkillsDir(workspaceName), name);
352
+ if (!existsSync(skillDir)) {
353
+ throw new NotFoundException('技能不存在');
354
+ }
355
+ await rm(skillDir, { recursive: true });
356
+ }
357
+ parseSkillFile(name, content, path, source = 'system') {
358
+ // Extract YAML frontmatter
359
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
360
+ let description = 'No description available';
361
+ let metadata = {};
362
+ if (frontmatterMatch) {
363
+ const frontmatter = frontmatterMatch[1];
364
+ const descMatch = frontmatter.match(/description:\s*(.+)/);
365
+ if (descMatch) {
366
+ description = descMatch[1].trim();
367
+ }
368
+ // Parse other metadata
369
+ const categoryMatch = frontmatter.match(/category:\s*(.+)/);
370
+ if (categoryMatch) {
371
+ metadata.category = categoryMatch[1].trim();
372
+ }
373
+ }
374
+ return {
375
+ name,
376
+ description,
377
+ path,
378
+ category: metadata.category,
379
+ source,
380
+ metadata,
381
+ };
382
+ }
383
+ };
384
+ SkillsService = __decorate([
385
+ Injectable(),
386
+ __metadata("design:paramtypes", [])
387
+ ], SkillsService);
388
+ export { SkillsService };
@@ -0,0 +1,52 @@
1
+ import { TasksService, ScheduledTask, RepeatRule } from './tasks.service.js';
2
+ export declare class TasksController {
3
+ private readonly tasksService;
4
+ constructor(tasksService: TasksService);
5
+ list(): {
6
+ success: boolean;
7
+ data: ScheduledTask[];
8
+ };
9
+ getDue(atStr?: string): {
10
+ success: boolean;
11
+ data: ScheduledTask[];
12
+ };
13
+ getExecution(eid: string): {
14
+ success: boolean;
15
+ data: import("./tasks.service.js").TaskExecution;
16
+ };
17
+ listExecutions(id: string): {
18
+ success: boolean;
19
+ data: import("./tasks.service.js").TaskExecution[];
20
+ };
21
+ clearExecutions(id: string): {
22
+ success: boolean;
23
+ data: {
24
+ deleted: number;
25
+ };
26
+ };
27
+ get(id: string): {
28
+ success: boolean;
29
+ data: ScheduledTask;
30
+ };
31
+ create(body: {
32
+ workspace: string;
33
+ message: string;
34
+ scheduleType: 'once' | 'cron';
35
+ runAt?: number;
36
+ cronExpr?: string;
37
+ repeatRule?: RepeatRule;
38
+ }): {
39
+ success: boolean;
40
+ data: ScheduledTask;
41
+ };
42
+ update(id: string, body: Partial<Pick<ScheduledTask, 'message' | 'enabled' | 'scheduleType' | 'runAt' | 'cronExpr' | 'repeatRuleJson'>>): {
43
+ success: boolean;
44
+ data: ScheduledTask;
45
+ };
46
+ delete(id: string): {
47
+ success: boolean;
48
+ };
49
+ markRan(id: string): {
50
+ success: boolean;
51
+ };
52
+ }
@@ -0,0 +1,163 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Controller, Get, Post, Put, Delete, Body, Param, Query, HttpException, HttpStatus, } from '@nestjs/common';
14
+ import { TasksService } from './tasks.service.js';
15
+ let TasksController = class TasksController {
16
+ tasksService;
17
+ constructor(tasksService) {
18
+ this.tasksService = tasksService;
19
+ }
20
+ list() {
21
+ const data = this.tasksService.list();
22
+ return { success: true, data };
23
+ }
24
+ getDue(atStr) {
25
+ const at = atStr ? new Date(atStr) : new Date();
26
+ const data = this.tasksService.getDueTasks(at);
27
+ return { success: true, data };
28
+ }
29
+ getExecution(eid) {
30
+ const execution = this.tasksService.getExecution(eid);
31
+ if (!execution) {
32
+ throw new HttpException('Execution not found', HttpStatus.NOT_FOUND);
33
+ }
34
+ return { success: true, data: execution };
35
+ }
36
+ listExecutions(id) {
37
+ const task = this.tasksService.get(id);
38
+ if (!task) {
39
+ throw new HttpException('Task not found', HttpStatus.NOT_FOUND);
40
+ }
41
+ const data = this.tasksService.listExecutions(id);
42
+ return { success: true, data };
43
+ }
44
+ clearExecutions(id) {
45
+ const task = this.tasksService.get(id);
46
+ if (!task) {
47
+ throw new HttpException('Task not found', HttpStatus.NOT_FOUND);
48
+ }
49
+ const deleted = this.tasksService.deleteExecutionsByTaskId(id);
50
+ return { success: true, data: { deleted } };
51
+ }
52
+ get(id) {
53
+ const task = this.tasksService.get(id);
54
+ if (!task) {
55
+ throw new HttpException('Task not found', HttpStatus.NOT_FOUND);
56
+ }
57
+ return { success: true, data: task };
58
+ }
59
+ create(body) {
60
+ const task = this.tasksService.create({
61
+ workspace: body.workspace ?? 'default',
62
+ message: body.message,
63
+ scheduleType: body.scheduleType,
64
+ runAt: body.runAt,
65
+ cronExpr: body.cronExpr,
66
+ repeatRule: body.repeatRule,
67
+ });
68
+ return { success: true, data: task };
69
+ }
70
+ update(id, body) {
71
+ const task = this.tasksService.update(id, body);
72
+ if (!task) {
73
+ throw new HttpException('Task not found', HttpStatus.NOT_FOUND);
74
+ }
75
+ return { success: true, data: task };
76
+ }
77
+ delete(id) {
78
+ const ok = this.tasksService.delete(id);
79
+ if (!ok) {
80
+ throw new HttpException('Task not found', HttpStatus.NOT_FOUND);
81
+ }
82
+ return { success: true };
83
+ }
84
+ markRan(id) {
85
+ this.tasksService.markRan(id);
86
+ return { success: true };
87
+ }
88
+ };
89
+ __decorate([
90
+ Get(),
91
+ __metadata("design:type", Function),
92
+ __metadata("design:paramtypes", []),
93
+ __metadata("design:returntype", void 0)
94
+ ], TasksController.prototype, "list", null);
95
+ __decorate([
96
+ Get('due'),
97
+ __param(0, Query('at')),
98
+ __metadata("design:type", Function),
99
+ __metadata("design:paramtypes", [String]),
100
+ __metadata("design:returntype", void 0)
101
+ ], TasksController.prototype, "getDue", null);
102
+ __decorate([
103
+ Get('executions/:eid'),
104
+ __param(0, Param('eid')),
105
+ __metadata("design:type", Function),
106
+ __metadata("design:paramtypes", [String]),
107
+ __metadata("design:returntype", void 0)
108
+ ], TasksController.prototype, "getExecution", null);
109
+ __decorate([
110
+ Get(':id/executions'),
111
+ __param(0, Param('id')),
112
+ __metadata("design:type", Function),
113
+ __metadata("design:paramtypes", [String]),
114
+ __metadata("design:returntype", void 0)
115
+ ], TasksController.prototype, "listExecutions", null);
116
+ __decorate([
117
+ Delete(':id/executions'),
118
+ __param(0, Param('id')),
119
+ __metadata("design:type", Function),
120
+ __metadata("design:paramtypes", [String]),
121
+ __metadata("design:returntype", void 0)
122
+ ], TasksController.prototype, "clearExecutions", null);
123
+ __decorate([
124
+ Get(':id'),
125
+ __param(0, Param('id')),
126
+ __metadata("design:type", Function),
127
+ __metadata("design:paramtypes", [String]),
128
+ __metadata("design:returntype", void 0)
129
+ ], TasksController.prototype, "get", null);
130
+ __decorate([
131
+ Post(),
132
+ __param(0, Body()),
133
+ __metadata("design:type", Function),
134
+ __metadata("design:paramtypes", [Object]),
135
+ __metadata("design:returntype", void 0)
136
+ ], TasksController.prototype, "create", null);
137
+ __decorate([
138
+ Put(':id'),
139
+ __param(0, Param('id')),
140
+ __param(1, Body()),
141
+ __metadata("design:type", Function),
142
+ __metadata("design:paramtypes", [String, Object]),
143
+ __metadata("design:returntype", void 0)
144
+ ], TasksController.prototype, "update", null);
145
+ __decorate([
146
+ Delete(':id'),
147
+ __param(0, Param('id')),
148
+ __metadata("design:type", Function),
149
+ __metadata("design:paramtypes", [String]),
150
+ __metadata("design:returntype", void 0)
151
+ ], TasksController.prototype, "delete", null);
152
+ __decorate([
153
+ Post(':id/ran'),
154
+ __param(0, Param('id')),
155
+ __metadata("design:type", Function),
156
+ __metadata("design:paramtypes", [String]),
157
+ __metadata("design:returntype", void 0)
158
+ ], TasksController.prototype, "markRan", null);
159
+ TasksController = __decorate([
160
+ Controller('tasks'),
161
+ __metadata("design:paramtypes", [TasksService])
162
+ ], TasksController);
163
+ export { TasksController };
@@ -0,0 +1,2 @@
1
+ export declare class TasksModule {
2
+ }
@@ -0,0 +1,23 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Module } from '@nestjs/common';
8
+ import { TasksService } from './tasks.service.js';
9
+ import { TasksController } from './tasks.controller.js';
10
+ import { AgentsModule } from '../agents/agents.module.js';
11
+ import { ConfigModule } from '../config/config.module.js';
12
+ import { UsageModule } from '../usage/usage.module.js';
13
+ let TasksModule = class TasksModule {
14
+ };
15
+ TasksModule = __decorate([
16
+ Module({
17
+ imports: [AgentsModule, ConfigModule, UsageModule],
18
+ controllers: [TasksController],
19
+ providers: [TasksService],
20
+ exports: [TasksService],
21
+ })
22
+ ], TasksModule);
23
+ export { TasksModule };