@cicctencent/agent-midway 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +280 -0
- package/dist/adapters/express.d.ts +8 -0
- package/dist/adapters/express.js +91 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/koa.d.ts +3 -0
- package/dist/adapters/koa.js +75 -0
- package/dist/adapters/midway.d.ts +5 -0
- package/dist/adapters/midway.js +11 -0
- package/dist/adapters/next.d.ts +12 -0
- package/dist/adapters/next.js +89 -0
- package/dist/adapters/shared.d.ts +4 -0
- package/dist/adapters/shared.js +31 -0
- package/dist/channel/dingtalk.d.ts +18 -0
- package/dist/channel/dingtalk.js +68 -0
- package/dist/channel/feishu.d.ts +20 -0
- package/dist/channel/feishu.js +96 -0
- package/dist/channel/index.d.ts +46 -0
- package/dist/channel/index.js +311 -0
- package/dist/channel/types.d.ts +77 -0
- package/dist/channel/types.js +7 -0
- package/dist/channel/wecom.d.ts +22 -0
- package/dist/channel/wecom.js +106 -0
- package/dist/component.d.ts +49 -0
- package/dist/component.js +129 -0
- package/dist/connector/calendar-adapter.d.ts +19 -0
- package/dist/connector/calendar-adapter.js +236 -0
- package/dist/connector/db-adapter.d.ts +28 -0
- package/dist/connector/db-adapter.js +193 -0
- package/dist/connector/email-adapter.d.ts +23 -0
- package/dist/connector/email-adapter.js +192 -0
- package/dist/connector/fs-adapter.d.ts +15 -0
- package/dist/connector/fs-adapter.js +199 -0
- package/dist/connector/http-adapter.d.ts +29 -0
- package/dist/connector/http-adapter.js +181 -0
- package/dist/connector/index.d.ts +24 -0
- package/dist/connector/index.js +454 -0
- package/dist/connector/mcp-adapter.d.ts +27 -0
- package/dist/connector/mcp-adapter.js +156 -0
- package/dist/connector/mq-adapter.d.ts +25 -0
- package/dist/connector/mq-adapter.js +181 -0
- package/dist/connector/types.d.ts +205 -0
- package/dist/connector/types.js +9 -0
- package/dist/controller/a2a.controller.d.ts +41 -0
- package/dist/controller/a2a.controller.js +150 -0
- package/dist/controller/agent-profile.controller.d.ts +97 -0
- package/dist/controller/agent-profile.controller.js +200 -0
- package/dist/controller/agent.controller.d.ts +199 -0
- package/dist/controller/agent.controller.js +414 -0
- package/dist/controller/application.controller.d.ts +113 -0
- package/dist/controller/application.controller.js +217 -0
- package/dist/controller/automation.controller.d.ts +113 -0
- package/dist/controller/automation.controller.js +246 -0
- package/dist/controller/channel.controller.d.ts +73 -0
- package/dist/controller/channel.controller.js +183 -0
- package/dist/controller/chat.controller.d.ts +188 -0
- package/dist/controller/chat.controller.js +375 -0
- package/dist/controller/connector.controller.d.ts +134 -0
- package/dist/controller/connector.controller.js +257 -0
- package/dist/controller/knowledge-base.controller.d.ts +157 -0
- package/dist/controller/knowledge-base.controller.js +278 -0
- package/dist/controller/mcp-server.controller.d.ts +115 -0
- package/dist/controller/mcp-server.controller.js +236 -0
- package/dist/controller/model-config.controller.d.ts +139 -0
- package/dist/controller/model-config.controller.js +274 -0
- package/dist/controller/observability.controller.d.ts +124 -0
- package/dist/controller/observability.controller.js +142 -0
- package/dist/controller/security.controller.d.ts +91 -0
- package/dist/controller/security.controller.js +172 -0
- package/dist/controller/settings.controller.d.ts +83 -0
- package/dist/controller/settings.controller.js +280 -0
- package/dist/core/ai-workstation.d.ts +17 -0
- package/dist/core/ai-workstation.js +129 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +20 -0
- package/dist/core/service-container.d.ts +12 -0
- package/dist/core/service-container.js +54 -0
- package/dist/core/sse.d.ts +6 -0
- package/dist/core/sse.js +56 -0
- package/dist/core/types.d.ts +72 -0
- package/dist/core/types.js +2 -0
- package/dist/dto/agent.dto.d.ts +21 -0
- package/dist/dto/agent.dto.js +79 -0
- package/dist/dto/ai-config.dto.d.ts +67 -0
- package/dist/dto/ai-config.dto.js +249 -0
- package/dist/dto/chat.dto.d.ts +40 -0
- package/dist/dto/chat.dto.js +122 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.js +195 -0
- package/dist/memory/db-store.d.ts +33 -0
- package/dist/memory/db-store.js +143 -0
- package/dist/memory/index.d.ts +187 -0
- package/dist/memory/index.js +443 -0
- package/dist/model/ai-agent-profile.entity.d.ts +32 -0
- package/dist/model/ai-agent-profile.entity.js +289 -0
- package/dist/model/ai-application.entity.d.ts +20 -0
- package/dist/model/ai-application.entity.js +166 -0
- package/dist/model/ai-chat-memory.entity.d.ts +16 -0
- package/dist/model/ai-chat-memory.entity.js +123 -0
- package/dist/model/ai-chat-message.entity.d.ts +16 -0
- package/dist/model/ai-chat-message.entity.js +122 -0
- package/dist/model/ai-chat-skill.entity.d.ts +19 -0
- package/dist/model/ai-chat-skill.entity.js +155 -0
- package/dist/model/ai-chat-thread.entity.d.ts +15 -0
- package/dist/model/ai-chat-thread.entity.js +113 -0
- package/dist/model/ai-chat-workspace.entity.d.ts +17 -0
- package/dist/model/ai-chat-workspace.entity.js +136 -0
- package/dist/model/ai-kb-document.entity.d.ts +16 -0
- package/dist/model/ai-kb-document.entity.js +122 -0
- package/dist/model/ai-knowledge-base.entity.d.ts +22 -0
- package/dist/model/ai-knowledge-base.entity.js +185 -0
- package/dist/model/ai-mcp-server.entity.d.ts +23 -0
- package/dist/model/ai-mcp-server.entity.js +198 -0
- package/dist/model/ai-model-config.entity.d.ts +24 -0
- package/dist/model/ai-model-config.entity.js +200 -0
- package/dist/service/a2a.service.d.ts +142 -0
- package/dist/service/a2a.service.js +537 -0
- package/dist/service/agent-profile.service.d.ts +34 -0
- package/dist/service/agent-profile.service.js +110 -0
- package/dist/service/agent-server.service.d.ts +91 -0
- package/dist/service/agent-server.service.js +634 -0
- package/dist/service/agent-task-queue.service.d.ts +98 -0
- package/dist/service/agent-task-queue.service.js +283 -0
- package/dist/service/ai-chat.service.d.ts +103 -0
- package/dist/service/ai-chat.service.js +431 -0
- package/dist/service/ai-skill.service.d.ts +116 -0
- package/dist/service/ai-skill.service.js +457 -0
- package/dist/service/application.service.d.ts +42 -0
- package/dist/service/application.service.js +139 -0
- package/dist/service/automation.service.d.ts +37 -0
- package/dist/service/automation.service.js +196 -0
- package/dist/service/connector.service.d.ts +136 -0
- package/dist/service/connector.service.js +524 -0
- package/dist/service/knowledge-base.service.d.ts +138 -0
- package/dist/service/knowledge-base.service.js +528 -0
- package/dist/service/mcp-server.service.d.ts +39 -0
- package/dist/service/mcp-server.service.js +143 -0
- package/dist/service/model-config.service.d.ts +57 -0
- package/dist/service/model-config.service.js +168 -0
- package/dist/service/observability.service.d.ts +145 -0
- package/dist/service/observability.service.js +281 -0
- package/dist/service/openai.service.d.ts +88 -0
- package/dist/service/openai.service.js +406 -0
- package/dist/service/prompt-builder.service.d.ts +50 -0
- package/dist/service/prompt-builder.service.js +246 -0
- package/dist/tools/code-exec.tool.d.ts +37 -0
- package/dist/tools/code-exec.tool.js +162 -0
- package/dist/tools/datetime.tool.d.ts +21 -0
- package/dist/tools/datetime.tool.js +379 -0
- package/dist/tools/http-request.tool.d.ts +43 -0
- package/dist/tools/http-request.tool.js +455 -0
- package/dist/tools/registry.d.ts +71 -0
- package/dist/tools/registry.js +77 -0
- package/dist/tools/text-process.tool.d.ts +7 -0
- package/dist/tools/text-process.tool.js +366 -0
- package/dist/tools/web-search.tool.d.ts +28 -0
- package/dist/tools/web-search.tool.js +304 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +7 -0
- package/package.json +69 -0
|
@@ -0,0 +1,457 @@
|
|
|
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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
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;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
var AISkillService_1;
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.AISkillService = void 0;
|
|
47
|
+
const core_1 = require("@midwayjs/core");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
/**
|
|
51
|
+
* AI Skill 管理 Service(本地文件版)
|
|
52
|
+
*
|
|
53
|
+
* 从 data/skills/ 目录递归加载 Markdown 文件作为 Skills。
|
|
54
|
+
* 每个 .md 文件使用 YAML frontmatter 定义元数据,正文为 Skill 内容。
|
|
55
|
+
*
|
|
56
|
+
* 支持两种注入方式:
|
|
57
|
+
* - prompt: 将 skill 内容拼接到 system prompt
|
|
58
|
+
* - tool: 将 skill 注册为 Tool,AI 主动调用获取内容
|
|
59
|
+
* - both: 两者兼具
|
|
60
|
+
*
|
|
61
|
+
* 缓存策略:
|
|
62
|
+
* - 文件加载结果缓存在内存中,TTL 5 分钟
|
|
63
|
+
* - 文件变更后自动刷新缓存
|
|
64
|
+
*/
|
|
65
|
+
let AISkillService = AISkillService_1 = class AISkillService {
|
|
66
|
+
constructor() {
|
|
67
|
+
/** skills 根目录 */
|
|
68
|
+
this.skillsDir = '';
|
|
69
|
+
/** 加载的 Skills */
|
|
70
|
+
this.skills = [];
|
|
71
|
+
/** 自增 ID 计数器 */
|
|
72
|
+
this.nextId = 1;
|
|
73
|
+
/** 上次扫描时间 */
|
|
74
|
+
this._lastScanTime = 0;
|
|
75
|
+
}
|
|
76
|
+
get lastScanTime() {
|
|
77
|
+
return this._lastScanTime;
|
|
78
|
+
}
|
|
79
|
+
async init() {
|
|
80
|
+
// 解析 skills 目录:基于应用根目录,不受源文件位置影响
|
|
81
|
+
this.skillsDir = path.join(this.app.getAppDir(), 'data/skills');
|
|
82
|
+
await this.reloadSkills();
|
|
83
|
+
}
|
|
84
|
+
// ===================== 文件扫描与解析 =====================
|
|
85
|
+
/** 重新扫描并加载所有 Skills */
|
|
86
|
+
async reloadSkills() {
|
|
87
|
+
this.skills = [];
|
|
88
|
+
this.nextId = 1;
|
|
89
|
+
if (!fs.existsSync(this.skillsDir)) {
|
|
90
|
+
console.warn(`[AISkillService] Skills 目录不存在: ${this.skillsDir}`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const files = this.scanDirectory(this.skillsDir);
|
|
94
|
+
for (const filePath of files) {
|
|
95
|
+
try {
|
|
96
|
+
const skill = this.parseSkillFile(filePath);
|
|
97
|
+
if (skill) {
|
|
98
|
+
this.skills.push(skill);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
console.error(`[AISkillService] 解析 Skill 文件失败: ${filePath}`, e.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// 按 sort 排序
|
|
106
|
+
this.skills.sort((a, b) => a.sort - b.sort);
|
|
107
|
+
this._lastScanTime = Date.now();
|
|
108
|
+
this.clearCache();
|
|
109
|
+
console.log(`[AISkillService] 已加载 ${this.skills.length} 个 Skills`);
|
|
110
|
+
}
|
|
111
|
+
/** 递归扫描目录获取所有 .md 文件 */
|
|
112
|
+
scanDirectory(dir) {
|
|
113
|
+
const results = [];
|
|
114
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
const fullPath = path.join(dir, entry.name);
|
|
117
|
+
if (entry.isDirectory()) {
|
|
118
|
+
results.push(...this.scanDirectory(fullPath));
|
|
119
|
+
}
|
|
120
|
+
else if (entry.isFile() &&
|
|
121
|
+
entry.name.endsWith('.md') &&
|
|
122
|
+
entry.name !== 'README.md') {
|
|
123
|
+
results.push(fullPath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return results;
|
|
127
|
+
}
|
|
128
|
+
/** 解析单个 Skill 文件 */
|
|
129
|
+
parseSkillFile(filePath) {
|
|
130
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
131
|
+
const { frontmatter, body } = this.parseFrontmatter(raw);
|
|
132
|
+
if (!frontmatter.name) {
|
|
133
|
+
console.warn(`[AISkillService] 文件缺少 name 字段,跳过: ${filePath}`);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const relativePath = path.relative(this.skillsDir, filePath);
|
|
137
|
+
return {
|
|
138
|
+
id: this.nextId++,
|
|
139
|
+
name: frontmatter.name || '',
|
|
140
|
+
description: frontmatter.description || '',
|
|
141
|
+
category: frontmatter.category || 'prompt',
|
|
142
|
+
contentType: 'text',
|
|
143
|
+
content: body.trim(),
|
|
144
|
+
agentTypes: frontmatter.agentTypes || '',
|
|
145
|
+
injectionMode: frontmatter.injectionMode || 'prompt',
|
|
146
|
+
sort: Number(frontmatter.sort) || 100,
|
|
147
|
+
isActive: 1,
|
|
148
|
+
isDeleted: 0,
|
|
149
|
+
toolSchema: frontmatter.toolSchema
|
|
150
|
+
? JSON.parse(frontmatter.toolSchema)
|
|
151
|
+
: undefined,
|
|
152
|
+
filePath: relativePath,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** 解析 YAML frontmatter */
|
|
156
|
+
parseFrontmatter(raw) {
|
|
157
|
+
const fmRegex = /^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/;
|
|
158
|
+
const match = raw.match(fmRegex);
|
|
159
|
+
if (!match) {
|
|
160
|
+
return { frontmatter: {}, body: raw };
|
|
161
|
+
}
|
|
162
|
+
const fmBlock = match[1];
|
|
163
|
+
const body = match[2];
|
|
164
|
+
const frontmatter = {};
|
|
165
|
+
// 简单 YAML key: value 解析
|
|
166
|
+
for (const line of fmBlock.split('\n')) {
|
|
167
|
+
const colonIdx = line.indexOf(':');
|
|
168
|
+
if (colonIdx > 0) {
|
|
169
|
+
const key = line.substring(0, colonIdx).trim();
|
|
170
|
+
const value = line.substring(colonIdx + 1).trim();
|
|
171
|
+
frontmatter[key] = value;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return { frontmatter, body };
|
|
175
|
+
}
|
|
176
|
+
// ===================== 缓存管理 =====================
|
|
177
|
+
clearCache() {
|
|
178
|
+
AISkillService_1.cache.clear();
|
|
179
|
+
}
|
|
180
|
+
getFromCache(key) {
|
|
181
|
+
const cached = AISkillService_1.cache.get(key);
|
|
182
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
183
|
+
return cached.data;
|
|
184
|
+
}
|
|
185
|
+
if (cached)
|
|
186
|
+
AISkillService_1.cache.delete(key);
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
setCache(key, data) {
|
|
190
|
+
AISkillService_1.cache.set(key, {
|
|
191
|
+
data,
|
|
192
|
+
expiresAt: Date.now() + AISkillService_1.CACHE_TTL,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// ===================== 查询接口 =====================
|
|
196
|
+
/** 查询所有 Skills */
|
|
197
|
+
async getSkills(options) {
|
|
198
|
+
await this.ensureLoaded();
|
|
199
|
+
let result = this.skills.filter(s => s.isActive === 1);
|
|
200
|
+
if (options?.category) {
|
|
201
|
+
result = result.filter(s => s.category === options.category);
|
|
202
|
+
}
|
|
203
|
+
if (options?.agentType) {
|
|
204
|
+
result = result.filter(s => this.matchesAgentType(s, options.agentType));
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
/** 获取单个 Skill */
|
|
209
|
+
async getSkill(id) {
|
|
210
|
+
await this.ensureLoaded();
|
|
211
|
+
return this.skills.find(s => s.id === id) || null;
|
|
212
|
+
}
|
|
213
|
+
/** 根据 name 获取 Skill */
|
|
214
|
+
async getSkillByName(name) {
|
|
215
|
+
await this.ensureLoaded();
|
|
216
|
+
return this.skills.find(s => s.name === name) || null;
|
|
217
|
+
}
|
|
218
|
+
// ===================== CRUD(文件操作) =====================
|
|
219
|
+
/** 创建 Skill(写入新文件) */
|
|
220
|
+
async createSkill(data) {
|
|
221
|
+
const name = data.name || `skill-${Date.now()}`;
|
|
222
|
+
const category = data.category || 'prompt';
|
|
223
|
+
const fileName = `${name}.md`;
|
|
224
|
+
const dirPath = path.join(this.skillsDir, category === 'component'
|
|
225
|
+
? 'components'
|
|
226
|
+
: category === 'datasource'
|
|
227
|
+
? 'datasources'
|
|
228
|
+
: category === 'rule'
|
|
229
|
+
? 'rules'
|
|
230
|
+
: 'prompts');
|
|
231
|
+
// 确保目录存在
|
|
232
|
+
if (!fs.existsSync(dirPath)) {
|
|
233
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
234
|
+
}
|
|
235
|
+
const filePath = path.join(dirPath, fileName);
|
|
236
|
+
const content = this.buildSkillFileContent({
|
|
237
|
+
name,
|
|
238
|
+
description: data.description || '',
|
|
239
|
+
category,
|
|
240
|
+
agentTypes: data.agentTypes || '',
|
|
241
|
+
injectionMode: data.injectionMode || 'prompt',
|
|
242
|
+
sort: data.sort || 100,
|
|
243
|
+
}, data.content || '');
|
|
244
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
245
|
+
await this.reloadSkills();
|
|
246
|
+
return this.skills.find(s => s.name === name) || null;
|
|
247
|
+
}
|
|
248
|
+
/** 更新 Skill(覆写文件) */
|
|
249
|
+
async updateSkill(id, data) {
|
|
250
|
+
const skill = this.skills.find(s => s.id === id);
|
|
251
|
+
if (!skill)
|
|
252
|
+
return null;
|
|
253
|
+
const filePath = path.join(this.skillsDir, skill.filePath);
|
|
254
|
+
const content = this.buildSkillFileContent({
|
|
255
|
+
name: data.name ?? skill.name,
|
|
256
|
+
description: data.description ?? skill.description,
|
|
257
|
+
category: data.category ?? skill.category,
|
|
258
|
+
agentTypes: data.agentTypes ?? skill.agentTypes,
|
|
259
|
+
injectionMode: data.injectionMode ?? skill.injectionMode,
|
|
260
|
+
sort: data.sort ?? skill.sort,
|
|
261
|
+
}, data.content ?? skill.content);
|
|
262
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
263
|
+
await this.reloadSkills();
|
|
264
|
+
return (this.skills.find(s => s.name === (data.name || skill.name)) || null);
|
|
265
|
+
}
|
|
266
|
+
/** 删除 Skill(删除文件) */
|
|
267
|
+
async deleteSkill(id) {
|
|
268
|
+
const skill = this.skills.find(s => s.id === id);
|
|
269
|
+
if (!skill)
|
|
270
|
+
return;
|
|
271
|
+
const filePath = path.join(this.skillsDir, skill.filePath);
|
|
272
|
+
if (fs.existsSync(filePath)) {
|
|
273
|
+
fs.unlinkSync(filePath);
|
|
274
|
+
}
|
|
275
|
+
await this.reloadSkills();
|
|
276
|
+
}
|
|
277
|
+
/** 生成 Skill 文件内容 */
|
|
278
|
+
buildSkillFileContent(meta, body) {
|
|
279
|
+
return [
|
|
280
|
+
'---',
|
|
281
|
+
`name: ${meta.name}`,
|
|
282
|
+
`description: ${meta.description}`,
|
|
283
|
+
`category: ${meta.category}`,
|
|
284
|
+
`agentTypes: ${meta.agentTypes}`,
|
|
285
|
+
`injectionMode: ${meta.injectionMode}`,
|
|
286
|
+
`sort: ${meta.sort}`,
|
|
287
|
+
'---',
|
|
288
|
+
'',
|
|
289
|
+
body,
|
|
290
|
+
].join('\n');
|
|
291
|
+
}
|
|
292
|
+
// ===================== 运行时加载 =====================
|
|
293
|
+
/** 确保 Skills 已加载 */
|
|
294
|
+
async ensureLoaded() {
|
|
295
|
+
if (this.skills.length === 0) {
|
|
296
|
+
await this.reloadSkills();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* 获取指定 Agent 类型的 Skills
|
|
301
|
+
*/
|
|
302
|
+
async getSkillsForAgent(agentType, injectionMode) {
|
|
303
|
+
const cacheKey = `skills:${agentType}:${injectionMode || 'all'}`;
|
|
304
|
+
const cached = this.getFromCache(cacheKey);
|
|
305
|
+
if (cached)
|
|
306
|
+
return cached;
|
|
307
|
+
await this.ensureLoaded();
|
|
308
|
+
let filtered = this.skills.filter(s => s.isActive === 1);
|
|
309
|
+
// 注入方式过滤
|
|
310
|
+
if (injectionMode) {
|
|
311
|
+
if (injectionMode === 'both') {
|
|
312
|
+
filtered = filtered.filter(s => s.injectionMode === 'both' ||
|
|
313
|
+
s.injectionMode === 'prompt' ||
|
|
314
|
+
s.injectionMode === 'tool');
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
filtered = filtered.filter(s => s.injectionMode === injectionMode ||
|
|
318
|
+
s.injectionMode === 'both');
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// 按 agentType 过滤
|
|
322
|
+
const result = filtered.filter(s => this.matchesAgentType(s, agentType));
|
|
323
|
+
this.setCache(cacheKey, result);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* 构建 Skill Context(用于注入到 system prompt)
|
|
328
|
+
*/
|
|
329
|
+
async buildSkillContext(agentType) {
|
|
330
|
+
const cacheKey = `context:${agentType}`;
|
|
331
|
+
const cached = this.getFromCache(cacheKey);
|
|
332
|
+
if (cached)
|
|
333
|
+
return cached;
|
|
334
|
+
const skills = await this.getSkillsForAgent(agentType, 'prompt');
|
|
335
|
+
if (skills.length === 0)
|
|
336
|
+
return '';
|
|
337
|
+
const parts = [];
|
|
338
|
+
// 按 category 分组
|
|
339
|
+
const groups = this.groupByCategory(skills);
|
|
340
|
+
for (const [category, items] of groups) {
|
|
341
|
+
const categoryLabel = {
|
|
342
|
+
component: '可用组件',
|
|
343
|
+
datasource: '可用数据源',
|
|
344
|
+
prompt: '扩展说明',
|
|
345
|
+
rule: '规则约束',
|
|
346
|
+
tool: '可调用工具',
|
|
347
|
+
};
|
|
348
|
+
parts.push(`\n## ${categoryLabel[category] || category}`);
|
|
349
|
+
for (const skill of items) {
|
|
350
|
+
parts.push(skill.content);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const context = parts.join('\n');
|
|
354
|
+
this.setCache(cacheKey, context);
|
|
355
|
+
return context;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* 将 Skills 转换为 ToolDefinition(供 Agent 自动调用)
|
|
359
|
+
*/
|
|
360
|
+
async getSkillsAsTools(agentType) {
|
|
361
|
+
const cacheKey = `tools:${agentType}`;
|
|
362
|
+
const cached = this.getFromCache(cacheKey);
|
|
363
|
+
if (cached)
|
|
364
|
+
return cached;
|
|
365
|
+
const skills = await this.getSkillsForAgent(agentType, 'tool');
|
|
366
|
+
const tools = skills.map(skill => this.skillToTool(skill));
|
|
367
|
+
this.setCache(cacheKey, tools);
|
|
368
|
+
return tools;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* 预览指定 Agent 的 Skills Context
|
|
372
|
+
*/
|
|
373
|
+
async previewSkillContext(agentType) {
|
|
374
|
+
const all = await this.getSkillsForAgent(agentType);
|
|
375
|
+
const promptSkills = all.filter(s => s.injectionMode === 'prompt' || s.injectionMode === 'both');
|
|
376
|
+
const toolSkills = all.filter(s => s.injectionMode === 'tool' || s.injectionMode === 'both');
|
|
377
|
+
return {
|
|
378
|
+
agentType,
|
|
379
|
+
total: all.length,
|
|
380
|
+
promptSkills: promptSkills.length,
|
|
381
|
+
toolSkills: toolSkills.length,
|
|
382
|
+
context: await this.buildSkillContext(agentType),
|
|
383
|
+
tools: toolSkills.map(s => ({
|
|
384
|
+
id: `skill_${s.id}`,
|
|
385
|
+
name: s.name,
|
|
386
|
+
description: s.description,
|
|
387
|
+
})),
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
// ===================== 私有方法 =====================
|
|
391
|
+
/** 判断 skill 是否匹配指定 agent 类型 */
|
|
392
|
+
matchesAgentType(skill, agentType) {
|
|
393
|
+
if (agentType === 'all' || agentType === '*')
|
|
394
|
+
return true;
|
|
395
|
+
if (!skill.agentTypes)
|
|
396
|
+
return true;
|
|
397
|
+
const types = skill.agentTypes.split(',').map(t => t.trim());
|
|
398
|
+
return types.some(t => {
|
|
399
|
+
if (t === '*')
|
|
400
|
+
return true;
|
|
401
|
+
if (t === agentType)
|
|
402
|
+
return true;
|
|
403
|
+
if (agentType.startsWith(t + '-'))
|
|
404
|
+
return true;
|
|
405
|
+
return false;
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/** 按 category 分组 */
|
|
409
|
+
groupByCategory(skills) {
|
|
410
|
+
const groups = new Map();
|
|
411
|
+
for (const skill of skills) {
|
|
412
|
+
const list = groups.get(skill.category) || [];
|
|
413
|
+
list.push(skill);
|
|
414
|
+
groups.set(skill.category, list);
|
|
415
|
+
}
|
|
416
|
+
return groups;
|
|
417
|
+
}
|
|
418
|
+
/** 将 Skill 转换为 ToolDefinition */
|
|
419
|
+
skillToTool(skill) {
|
|
420
|
+
return {
|
|
421
|
+
id: `skill_${skill.id}`,
|
|
422
|
+
name: skill.name,
|
|
423
|
+
description: skill.description || `获取 ${skill.name} 的详细内容`,
|
|
424
|
+
category: 'utility',
|
|
425
|
+
parameters: skill.toolSchema || {
|
|
426
|
+
type: 'object',
|
|
427
|
+
properties: {},
|
|
428
|
+
},
|
|
429
|
+
async execute() {
|
|
430
|
+
return {
|
|
431
|
+
skillId: skill.id,
|
|
432
|
+
name: skill.name,
|
|
433
|
+
content: skill.content,
|
|
434
|
+
contentType: skill.contentType,
|
|
435
|
+
};
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
exports.AISkillService = AISkillService;
|
|
441
|
+
/** 缓存 */
|
|
442
|
+
AISkillService.cache = new Map();
|
|
443
|
+
AISkillService.CACHE_TTL = 5 * 60 * 1000;
|
|
444
|
+
__decorate([
|
|
445
|
+
(0, core_1.App)(),
|
|
446
|
+
__metadata("design:type", Object)
|
|
447
|
+
], AISkillService.prototype, "app", void 0);
|
|
448
|
+
__decorate([
|
|
449
|
+
(0, core_1.Init)(),
|
|
450
|
+
__metadata("design:type", Function),
|
|
451
|
+
__metadata("design:paramtypes", []),
|
|
452
|
+
__metadata("design:returntype", Promise)
|
|
453
|
+
], AISkillService.prototype, "init", null);
|
|
454
|
+
exports.AISkillService = AISkillService = AISkillService_1 = __decorate([
|
|
455
|
+
(0, core_1.Provide)(),
|
|
456
|
+
(0, core_1.Scope)(core_1.ScopeEnum.Singleton)
|
|
457
|
+
], AISkillService);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { BaseService } from '@cicctencent/midwayjs-base';
|
|
2
|
+
import { DataSource, Repository } from 'typeorm';
|
|
3
|
+
import AIApplicationEntity from '../model/ai-application.entity';
|
|
4
|
+
/**
|
|
5
|
+
* AI 应用服务
|
|
6
|
+
* 管理应用配置、Agent Profile 绑定等
|
|
7
|
+
*/
|
|
8
|
+
export declare class ApplicationService extends BaseService {
|
|
9
|
+
dataSource: DataSource;
|
|
10
|
+
private repo?;
|
|
11
|
+
get model(): Repository<AIApplicationEntity>;
|
|
12
|
+
/** 获取所有应用 */
|
|
13
|
+
list(options?: {
|
|
14
|
+
status?: string;
|
|
15
|
+
}): Promise<AIApplicationEntity[]>;
|
|
16
|
+
/** 获取单个应用 */
|
|
17
|
+
get(id: number): Promise<AIApplicationEntity>;
|
|
18
|
+
/** 根据 Key 获取应用 */
|
|
19
|
+
getByKey(key: string): Promise<AIApplicationEntity>;
|
|
20
|
+
/** 获取默认应用 */
|
|
21
|
+
getDefault(): Promise<AIApplicationEntity>;
|
|
22
|
+
/** 创建应用 */
|
|
23
|
+
create(data: Partial<AIApplicationEntity>): Promise<AIApplicationEntity>;
|
|
24
|
+
/** 更新应用 */
|
|
25
|
+
update(id: number, data: Partial<AIApplicationEntity>): Promise<AIApplicationEntity>;
|
|
26
|
+
/** 删除应用 */
|
|
27
|
+
delete(id: number): Promise<void>;
|
|
28
|
+
/** 设置为默认 */
|
|
29
|
+
setDefault(id: number): Promise<AIApplicationEntity>;
|
|
30
|
+
/** 归档应用 */
|
|
31
|
+
archive(id: number): Promise<AIApplicationEntity>;
|
|
32
|
+
/** 激活应用 */
|
|
33
|
+
activate(id: number): Promise<AIApplicationEntity>;
|
|
34
|
+
/** 获取应用完整配置(包含 Agent Profile) */
|
|
35
|
+
getFullConfig(idOrKey: number | string): Promise<{
|
|
36
|
+
application: AIApplicationEntity;
|
|
37
|
+
agentProfiles: any[];
|
|
38
|
+
defaultProfile: any;
|
|
39
|
+
}>;
|
|
40
|
+
/** 解析应用(支持 ID 或 Key) */
|
|
41
|
+
resolveApp(idOrKey: number | string): Promise<AIApplicationEntity>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ApplicationService = void 0;
|
|
16
|
+
const core_1 = require("@midwayjs/core");
|
|
17
|
+
const midwayjs_base_1 = require("@cicctencent/midwayjs-base");
|
|
18
|
+
const typeorm_1 = require("@midwayjs/typeorm");
|
|
19
|
+
const typeorm_2 = require("typeorm");
|
|
20
|
+
const ai_application_entity_1 = __importDefault(require("../model/ai-application.entity"));
|
|
21
|
+
/**
|
|
22
|
+
* AI 应用服务
|
|
23
|
+
* 管理应用配置、Agent Profile 绑定等
|
|
24
|
+
*/
|
|
25
|
+
let ApplicationService = class ApplicationService extends midwayjs_base_1.BaseService {
|
|
26
|
+
get model() {
|
|
27
|
+
if (this.repo)
|
|
28
|
+
return this.repo;
|
|
29
|
+
return (this.repo = this.dataSource.getRepository(ai_application_entity_1.default));
|
|
30
|
+
}
|
|
31
|
+
/** 获取所有应用 */
|
|
32
|
+
async list(options) {
|
|
33
|
+
const where = {};
|
|
34
|
+
if (options?.status) {
|
|
35
|
+
where.status = options.status;
|
|
36
|
+
}
|
|
37
|
+
return this.model.find({
|
|
38
|
+
where,
|
|
39
|
+
order: { isDefault: 'DESC', createTime: 'DESC' },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** 获取单个应用 */
|
|
43
|
+
async get(id) {
|
|
44
|
+
return this.model.findOne({ where: { id } });
|
|
45
|
+
}
|
|
46
|
+
/** 根据 Key 获取应用 */
|
|
47
|
+
async getByKey(key) {
|
|
48
|
+
return this.model.findOne({ where: { key } });
|
|
49
|
+
}
|
|
50
|
+
/** 获取默认应用 */
|
|
51
|
+
async getDefault() {
|
|
52
|
+
return this.model.findOne({
|
|
53
|
+
where: { isDefault: 1, status: 'active' },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/** 创建应用 */
|
|
57
|
+
async create(data) {
|
|
58
|
+
// 如果设置为默认,先清除其他默认
|
|
59
|
+
if (data.isDefault === 1) {
|
|
60
|
+
await this.model.update({ isDefault: 1 }, { isDefault: 0 });
|
|
61
|
+
}
|
|
62
|
+
const app = this.model.create(data);
|
|
63
|
+
return this.model.save(app);
|
|
64
|
+
}
|
|
65
|
+
/** 更新应用 */
|
|
66
|
+
async update(id, data) {
|
|
67
|
+
// 如果设置为默认,先清除其他默认
|
|
68
|
+
if (data.isDefault === 1) {
|
|
69
|
+
await this.model.update({ isDefault: 1 }, { isDefault: 0 });
|
|
70
|
+
}
|
|
71
|
+
await this.model.update({ id }, data);
|
|
72
|
+
return this.get(id);
|
|
73
|
+
}
|
|
74
|
+
/** 删除应用 */
|
|
75
|
+
async delete(id) {
|
|
76
|
+
await this.model.delete({ id });
|
|
77
|
+
}
|
|
78
|
+
/** 设置为默认 */
|
|
79
|
+
async setDefault(id) {
|
|
80
|
+
await this.model.update({ isDefault: 1 }, { isDefault: 0 });
|
|
81
|
+
await this.model.update({ id }, { isDefault: 1 });
|
|
82
|
+
return this.get(id);
|
|
83
|
+
}
|
|
84
|
+
/** 归档应用 */
|
|
85
|
+
async archive(id) {
|
|
86
|
+
await this.model.update({ id }, { status: 'archived' });
|
|
87
|
+
return this.get(id);
|
|
88
|
+
}
|
|
89
|
+
/** 激活应用 */
|
|
90
|
+
async activate(id) {
|
|
91
|
+
await this.model.update({ id }, { status: 'active' });
|
|
92
|
+
return this.get(id);
|
|
93
|
+
}
|
|
94
|
+
/** 获取应用完整配置(包含 Agent Profile) */
|
|
95
|
+
async getFullConfig(idOrKey) {
|
|
96
|
+
const app = typeof idOrKey === 'number'
|
|
97
|
+
? await this.get(idOrKey)
|
|
98
|
+
: await this.getByKey(idOrKey);
|
|
99
|
+
if (!app)
|
|
100
|
+
return null;
|
|
101
|
+
// 加载关联的 Agent Profile
|
|
102
|
+
let agentProfiles = [];
|
|
103
|
+
if (app.agentProfileIds && app.agentProfileIds.length > 0) {
|
|
104
|
+
agentProfiles = await this.dataSource.query('SELECT * FROM t_agent_profile WHERE id IN (?)', [app.agentProfileIds]);
|
|
105
|
+
}
|
|
106
|
+
// 加载默认 Agent Profile
|
|
107
|
+
let defaultProfile = null;
|
|
108
|
+
if (app.defaultAgentProfileId) {
|
|
109
|
+
const profiles = await this.dataSource.query('SELECT * FROM t_agent_profile WHERE id = ?', [app.defaultAgentProfileId]);
|
|
110
|
+
defaultProfile = profiles[0] || null;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
application: app,
|
|
114
|
+
agentProfiles,
|
|
115
|
+
defaultProfile,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** 解析应用(支持 ID 或 Key) */
|
|
119
|
+
async resolveApp(idOrKey) {
|
|
120
|
+
if (typeof idOrKey === 'number') {
|
|
121
|
+
return this.get(idOrKey);
|
|
122
|
+
}
|
|
123
|
+
// 尝试解析为数字
|
|
124
|
+
const num = parseInt(idOrKey, 10);
|
|
125
|
+
if (!isNaN(num)) {
|
|
126
|
+
return this.get(num);
|
|
127
|
+
}
|
|
128
|
+
// 按 Key 查找
|
|
129
|
+
return this.getByKey(idOrKey);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
exports.ApplicationService = ApplicationService;
|
|
133
|
+
__decorate([
|
|
134
|
+
(0, typeorm_1.InjectDataSource)('default'),
|
|
135
|
+
__metadata("design:type", typeorm_2.DataSource)
|
|
136
|
+
], ApplicationService.prototype, "dataSource", void 0);
|
|
137
|
+
exports.ApplicationService = ApplicationService = __decorate([
|
|
138
|
+
(0, core_1.Provide)()
|
|
139
|
+
], ApplicationService);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BaseService } from '@cicctencent/midwayjs-base';
|
|
2
|
+
import type { DataSource } from 'typeorm';
|
|
3
|
+
import { AgentServerService } from './agent-server.service';
|
|
4
|
+
/** 自动化任务实体(从 DB 查询) */
|
|
5
|
+
interface AutomationEntity {
|
|
6
|
+
id: number;
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
type: string;
|
|
10
|
+
config: any;
|
|
11
|
+
status: string;
|
|
12
|
+
schedule?: string;
|
|
13
|
+
prompt?: string;
|
|
14
|
+
agent_profile_id?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class AutomationService extends BaseService {
|
|
17
|
+
dataSource: DataSource;
|
|
18
|
+
agentServerService: AgentServerService;
|
|
19
|
+
private initialized;
|
|
20
|
+
/** 初始化自动化调度器:加载所有已启用任务并注册 cron */
|
|
21
|
+
initAutomationScheduler(): Promise<void>;
|
|
22
|
+
/** 确保调度器已初始化 */
|
|
23
|
+
ensureInitialized(): Promise<void>;
|
|
24
|
+
/** 为单个任务注册 cron 调度 */
|
|
25
|
+
scheduleJob(automation: AutomationEntity): void;
|
|
26
|
+
/** 注销调度 */
|
|
27
|
+
unscheduleJob(id: number): void;
|
|
28
|
+
/** 实际执行自动化任务:创建 Agent 会话 + 运行 Agent + 记录结果 */
|
|
29
|
+
executeAutomation(id: number, triggerType?: 'schedule' | 'manual'): Promise<string>;
|
|
30
|
+
/** 刷新所有调度 */
|
|
31
|
+
refreshScheduler(): Promise<void>;
|
|
32
|
+
/** 获取活跃任务数 */
|
|
33
|
+
getActiveJobCount(): number;
|
|
34
|
+
/** 停止所有调度任务(服务关闭时调用) */
|
|
35
|
+
stopAll(): void;
|
|
36
|
+
}
|
|
37
|
+
export {};
|