@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
package/README.md
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# @cicctencent/agent-midway
|
|
2
|
+
|
|
3
|
+
AI Workstation Core + Framework Adapters — 提供框架无关的 AI 核心能力,并内置 Express、Koa、Next.js、MidwayJS 适配层。
|
|
4
|
+
|
|
5
|
+
## 架构设计
|
|
6
|
+
|
|
7
|
+
`@cicctencent/agent-midway` 现在采用三层结构:
|
|
8
|
+
|
|
9
|
+
| 层级 | 目录 | 说明 |
|
|
10
|
+
|------|------|------|
|
|
11
|
+
| Core | `src/core` | 框架无关的 AI 门面、请求上下文、SSE、服务容器 |
|
|
12
|
+
| Adapters | `src/adapters` | Express、Koa、Next.js、MidwayJS 的挂载入口 |
|
|
13
|
+
| Midway Component | `src/component.ts` | 保留原有 MidwayJS 一行接入能力 |
|
|
14
|
+
|
|
15
|
+
核心能力通过 `AIServiceRegistry` 注入业务服务,例如 `agent`、`application`、`dataSource` 和自定义服务。适配层只负责请求解析、响应输出、SSE 和路由挂载。
|
|
16
|
+
|
|
17
|
+
## 快速接入
|
|
18
|
+
|
|
19
|
+
### 1. 安装依赖
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add @cicctencent/agent-midway
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. 在 configuration.ts 中引入
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { Configuration, App, MidwayContainer } from '@midwayjs/core';
|
|
29
|
+
import * as busboy from '@midwayjs/busboy';
|
|
30
|
+
import * as orm from '@midwayjs/typeorm';
|
|
31
|
+
import * as staticFile from '@midwayjs/static-file';
|
|
32
|
+
import * as baseMidwayjs from '@cicctencent/midwayjs-base';
|
|
33
|
+
import * as agentMidway from '@cicctencent/agent-midway'; // ← 一行引入
|
|
34
|
+
|
|
35
|
+
@Configuration({
|
|
36
|
+
imports: [
|
|
37
|
+
busboy,
|
|
38
|
+
staticFile,
|
|
39
|
+
baseMidwayjs,
|
|
40
|
+
orm,
|
|
41
|
+
aiMidway, // ← 自动注册全部 AI 控制器/服务/实体
|
|
42
|
+
],
|
|
43
|
+
importConfigs: [join(__dirname, './config')],
|
|
44
|
+
})
|
|
45
|
+
export class ContainerLifeCycle {
|
|
46
|
+
// ...
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. 配置(config/config.default.ts)
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
export default {
|
|
54
|
+
// ... 其他配置
|
|
55
|
+
|
|
56
|
+
// AI Workstation 组件配置
|
|
57
|
+
aiMidway: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
prefix: '/api',
|
|
60
|
+
dataDir: 'data',
|
|
61
|
+
features: {
|
|
62
|
+
agent: true,
|
|
63
|
+
chat: true,
|
|
64
|
+
agentProfile: true,
|
|
65
|
+
application: true,
|
|
66
|
+
mcpServer: true,
|
|
67
|
+
modelConfig: true,
|
|
68
|
+
settings: true,
|
|
69
|
+
security: true,
|
|
70
|
+
automation: true,
|
|
71
|
+
connectors: true,
|
|
72
|
+
a2a: true,
|
|
73
|
+
channels: true,
|
|
74
|
+
observability: true,
|
|
75
|
+
knowledgeBase: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// OpenAI 配置
|
|
80
|
+
openai: {
|
|
81
|
+
baseUrl: process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1',
|
|
82
|
+
apiKey: process.env.OPENAI_API_KEY || '',
|
|
83
|
+
model: process.env.OPENAI_MODEL || 'deepseek-chat',
|
|
84
|
+
maxTokens: 16384,
|
|
85
|
+
temperature: 0.2,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. 创建数据库表
|
|
91
|
+
|
|
92
|
+
组件使用以下 TypeORM 实体(自动注册):
|
|
93
|
+
|
|
94
|
+
| 表名 | 实体 | 说明 |
|
|
95
|
+
|------|------|------|
|
|
96
|
+
| `t_ai_application` | AIApplicationEntity | AI 应用 |
|
|
97
|
+
| `t_ai_agent_profile` | AIAgentProfileEntity | Agent 配置 |
|
|
98
|
+
| `t_ai_chat_workspace` | AIChatWorkspaceEntity | 聊天工作空间 |
|
|
99
|
+
| `t_ai_chat_thread` | AIChatThreadEntity | 聊天线程 |
|
|
100
|
+
| `t_ai_chat_message` | AIChatMessageEntity | 聊天消息 |
|
|
101
|
+
| `t_ai_mcp_server` | AIMCPServerEntity | MCP 服务器配置 |
|
|
102
|
+
| `t_ai_model_config` | AIModelConfigEntity | 模型配置 |
|
|
103
|
+
| `t_ai_knowledge_base` | AIKnowledgeBaseEntity | 知识库 |
|
|
104
|
+
| `t_ai_kb_document` | AIKBDocumentEntity | 知识库文档 |
|
|
105
|
+
|
|
106
|
+
### 5. 验证
|
|
107
|
+
|
|
108
|
+
启动服务后,访问以下 API:
|
|
109
|
+
|
|
110
|
+
- `GET /api/applications` — 应用列表
|
|
111
|
+
- `GET /api/agent-profiles` — Agent Profile 列表
|
|
112
|
+
- `GET /api/chat/workspaces` — 工作空间列表
|
|
113
|
+
- `GET /api/settings` — 全局设置
|
|
114
|
+
- `GET /api/observability/dashboard` — 可观测性仪表板
|
|
115
|
+
- `GET /.well-known/agent.json` — A2A Agent Card
|
|
116
|
+
|
|
117
|
+
## 功能模块
|
|
118
|
+
|
|
119
|
+
| 模块 | 路由前缀 | 说明 |
|
|
120
|
+
|------|---------|------|
|
|
121
|
+
| Agent 运行 | `/api/agent` | 流式/非流式运行、任务队列、abort/regenerate/fork |
|
|
122
|
+
| 聊天管理 | `/api/chat` | 工作空间/线程/消息 CRUD |
|
|
123
|
+
| Agent Profile | `/api/agent-profiles` | Agent 配置管理 |
|
|
124
|
+
| Application | `/api/applications` | 多应用隔离 |
|
|
125
|
+
| MCP Server | `/api/mcp-servers` | MCP 服务器管理 |
|
|
126
|
+
| 模型配置 | `/api/model-configs` | 多模型供应商配置 |
|
|
127
|
+
| 设置 | `/api/settings` | 全局设置 |
|
|
128
|
+
| 安全审计 | `/api/security` | 审计日志、工具风险、权限审批 |
|
|
129
|
+
| 自动化 | `/api/automations` | Cron 定时任务 |
|
|
130
|
+
| 连接器 | `/api/connectors` | 7种数据源适配器 + 工具发现 |
|
|
131
|
+
| A2A 协议 | `/.well-known/agent.json`, `/a2a` | Agent 间互操作 |
|
|
132
|
+
| IM 渠道 | `/api/channels` | 飞书/钉钉/企微 |
|
|
133
|
+
| 可观测性 | `/api/observability` | 链路追踪、指标、仪表板 |
|
|
134
|
+
| 知识库 | `/api/knowledge-bases` | 向量搜索 |
|
|
135
|
+
|
|
136
|
+
## 多框架适配
|
|
137
|
+
|
|
138
|
+
### Express
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import express from 'express';
|
|
142
|
+
import { mountExpressAI } from '@cicctencent/agent-midway';
|
|
143
|
+
|
|
144
|
+
const app = express();
|
|
145
|
+
app.use(express.json());
|
|
146
|
+
|
|
147
|
+
mountExpressAI(app, {
|
|
148
|
+
prefix: '/api',
|
|
149
|
+
services: {
|
|
150
|
+
agent: agentServerService,
|
|
151
|
+
application: applicationService,
|
|
152
|
+
dataSource,
|
|
153
|
+
},
|
|
154
|
+
resolveUser: req => ({
|
|
155
|
+
userId: String(req.raw.user?.id || 'anonymous'),
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Koa
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import Koa from 'koa';
|
|
164
|
+
import bodyParser from 'koa-bodyparser';
|
|
165
|
+
import { mountKoaAI } from '@cicctencent/agent-midway';
|
|
166
|
+
|
|
167
|
+
const app = new Koa();
|
|
168
|
+
app.use(bodyParser());
|
|
169
|
+
|
|
170
|
+
mountKoaAI(app, {
|
|
171
|
+
prefix: '/api',
|
|
172
|
+
services: {
|
|
173
|
+
agent: agentServerService,
|
|
174
|
+
application: applicationService,
|
|
175
|
+
},
|
|
176
|
+
resolveUser: ctx => ({
|
|
177
|
+
userId: String(ctx.raw.state?.user?.id || 'anonymous'),
|
|
178
|
+
}),
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Next.js App Router
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// app/api/ai/[...path]/route.ts
|
|
186
|
+
import { createNextAIHandlers } from '@cicctencent/agent-midway';
|
|
187
|
+
|
|
188
|
+
const handlers = createNextAIHandlers({
|
|
189
|
+
prefix: '/api/ai',
|
|
190
|
+
services: {
|
|
191
|
+
agent: agentServerService,
|
|
192
|
+
application: applicationService,
|
|
193
|
+
},
|
|
194
|
+
resolveUser: request => ({
|
|
195
|
+
userId: String(request.headers?.['x-user-id'] || 'anonymous'),
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export const GET = handlers.GET;
|
|
200
|
+
export const POST = handlers.POST;
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### MidwayJS
|
|
204
|
+
|
|
205
|
+
MidwayJS 继续支持原有组件方式:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import * as agentMidway from '@cicctencent/agent-midway';
|
|
209
|
+
|
|
210
|
+
@Configuration({
|
|
211
|
+
imports: [baseMidwayjs, orm, aiMidway],
|
|
212
|
+
})
|
|
213
|
+
export class ContainerLifeCycle {}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
也可以在 Midway 服务中使用 `createMidwayAIWorkstation()` 复用框架无关核心能力。
|
|
217
|
+
|
|
218
|
+
### 已内置路由
|
|
219
|
+
|
|
220
|
+
| 方法 | 路由 | 说明 |
|
|
221
|
+
|------|------|------|
|
|
222
|
+
| `POST` | `{prefix}/agent/run` | Agent SSE 流式运行 |
|
|
223
|
+
| `POST` | `{prefix}/agent/run/sync` | Agent 同步运行 |
|
|
224
|
+
| `GET` | `{prefix}/agent/reconnect/:threadId` | SSE 断线重连 |
|
|
225
|
+
| `POST` | `{prefix}/agent/abort/:threadId` | 中止 Agent |
|
|
226
|
+
| `GET` | `{prefix}/agent/health` | Agent 健康检查 |
|
|
227
|
+
|
|
228
|
+
## 按需开关
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
aiMidway: {
|
|
232
|
+
features: {
|
|
233
|
+
// 只用 Agent + Chat,不需要其他功能
|
|
234
|
+
agent: true,
|
|
235
|
+
chat: true,
|
|
236
|
+
agentProfile: true,
|
|
237
|
+
application: true,
|
|
238
|
+
mcpServer: false,
|
|
239
|
+
modelConfig: false,
|
|
240
|
+
settings: false,
|
|
241
|
+
security: false,
|
|
242
|
+
automation: false,
|
|
243
|
+
connectors: false,
|
|
244
|
+
a2a: false,
|
|
245
|
+
channels: false,
|
|
246
|
+
observability: false,
|
|
247
|
+
knowledgeBase: false,
|
|
248
|
+
},
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## 自定义扩展
|
|
253
|
+
|
|
254
|
+
### 覆盖服务
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { Provide } from '@midwayjs/core';
|
|
258
|
+
import { AgentProfileService } from '@cicctencent/agent-midway';
|
|
259
|
+
|
|
260
|
+
@Provide()
|
|
261
|
+
export class CustomAgentProfileService extends AgentProfileService {
|
|
262
|
+
async list(applicationId: number) {
|
|
263
|
+
// 自定义逻辑
|
|
264
|
+
return super.list(applicationId);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### 添加自定义工具
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { toolRegistry } from '@cicctencent/agent-midway';
|
|
273
|
+
|
|
274
|
+
toolRegistry.register({
|
|
275
|
+
id: 'my_tool',
|
|
276
|
+
description: 'My custom tool',
|
|
277
|
+
parameters: { type: 'object', properties: { input: { type: 'string' } } },
|
|
278
|
+
execute: async (args) => ({ result: args.input }),
|
|
279
|
+
});
|
|
280
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AIFrameworkAdapterOptions } from '../core/types';
|
|
2
|
+
export declare function createExpressAIRouter(options: AIFrameworkAdapterOptions): any;
|
|
3
|
+
export declare function mountExpressAI(app: any, options: AIFrameworkAdapterOptions): any;
|
|
4
|
+
export declare function expressAIRoutes(options: AIFrameworkAdapterOptions): {
|
|
5
|
+
prefix: string;
|
|
6
|
+
router: any;
|
|
7
|
+
route(path: string): string;
|
|
8
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createExpressAIRouter = createExpressAIRouter;
|
|
4
|
+
exports.mountExpressAI = mountExpressAI;
|
|
5
|
+
exports.expressAIRoutes = expressAIRoutes;
|
|
6
|
+
const ai_workstation_1 = require("../core/ai-workstation");
|
|
7
|
+
const sse_1 = require("../core/sse");
|
|
8
|
+
const shared_1 = require("./shared");
|
|
9
|
+
function createExpressAIRouter(options) {
|
|
10
|
+
let express;
|
|
11
|
+
try {
|
|
12
|
+
express = require('express');
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
throw new Error('createExpressAIRouter requires express to be installed by the host application.');
|
|
16
|
+
}
|
|
17
|
+
const core = (0, ai_workstation_1.createAIWorkstation)(options);
|
|
18
|
+
const router = express.Router();
|
|
19
|
+
router.post('/agent/run', async (req, res) => {
|
|
20
|
+
await core.runAgentStream((0, shared_1.createRequestContext)({
|
|
21
|
+
method: req.method,
|
|
22
|
+
path: req.path,
|
|
23
|
+
query: req.query,
|
|
24
|
+
params: req.params,
|
|
25
|
+
body: req.body,
|
|
26
|
+
headers: req.headers,
|
|
27
|
+
raw: req,
|
|
28
|
+
}), (0, sse_1.createNodeSSEWriter)(res));
|
|
29
|
+
});
|
|
30
|
+
router.post('/agent/run/sync', async (req, res) => {
|
|
31
|
+
const result = await core.runAgentSync((0, shared_1.createRequestContext)({
|
|
32
|
+
method: req.method,
|
|
33
|
+
path: req.path,
|
|
34
|
+
query: req.query,
|
|
35
|
+
params: req.params,
|
|
36
|
+
body: req.body,
|
|
37
|
+
headers: req.headers,
|
|
38
|
+
raw: req,
|
|
39
|
+
}));
|
|
40
|
+
(0, shared_1.sendJson)(res, result);
|
|
41
|
+
});
|
|
42
|
+
router.get('/agent/reconnect/:threadId', async (req, res) => {
|
|
43
|
+
await core.reconnectStream((0, shared_1.createRequestContext)({
|
|
44
|
+
method: req.method,
|
|
45
|
+
path: req.path,
|
|
46
|
+
query: req.query,
|
|
47
|
+
params: req.params,
|
|
48
|
+
headers: req.headers,
|
|
49
|
+
raw: req,
|
|
50
|
+
}), (0, sse_1.createNodeSSEWriter)(res));
|
|
51
|
+
});
|
|
52
|
+
router.post('/agent/abort/:threadId', async (req, res) => {
|
|
53
|
+
const result = await core.abortAgent((0, shared_1.createRequestContext)({
|
|
54
|
+
method: req.method,
|
|
55
|
+
path: req.path,
|
|
56
|
+
query: req.query,
|
|
57
|
+
params: req.params,
|
|
58
|
+
body: req.body,
|
|
59
|
+
headers: req.headers,
|
|
60
|
+
raw: req,
|
|
61
|
+
}));
|
|
62
|
+
(0, shared_1.sendJson)(res, result);
|
|
63
|
+
});
|
|
64
|
+
router.get('/agent/health', async (req, res) => {
|
|
65
|
+
const result = await core.health((0, shared_1.createRequestContext)({
|
|
66
|
+
method: req.method,
|
|
67
|
+
path: req.path,
|
|
68
|
+
query: req.query,
|
|
69
|
+
headers: req.headers,
|
|
70
|
+
raw: req,
|
|
71
|
+
}));
|
|
72
|
+
(0, shared_1.sendJson)(res, result);
|
|
73
|
+
});
|
|
74
|
+
return router;
|
|
75
|
+
}
|
|
76
|
+
function mountExpressAI(app, options) {
|
|
77
|
+
const core = (0, ai_workstation_1.createAIWorkstation)(options);
|
|
78
|
+
const router = createExpressAIRouter(options);
|
|
79
|
+
app.use(core.prefix, router);
|
|
80
|
+
return router;
|
|
81
|
+
}
|
|
82
|
+
function expressAIRoutes(options) {
|
|
83
|
+
const core = (0, ai_workstation_1.createAIWorkstation)(options);
|
|
84
|
+
return {
|
|
85
|
+
prefix: core.prefix,
|
|
86
|
+
router: createExpressAIRouter(options),
|
|
87
|
+
route(path) {
|
|
88
|
+
return (0, shared_1.joinRoute)(core.prefix, path);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./shared"), exports);
|
|
18
|
+
__exportStar(require("./express"), exports);
|
|
19
|
+
__exportStar(require("./koa"), exports);
|
|
20
|
+
__exportStar(require("./next"), exports);
|
|
21
|
+
__exportStar(require("./midway"), exports);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createKoaAIMiddleware = createKoaAIMiddleware;
|
|
4
|
+
exports.mountKoaAI = mountKoaAI;
|
|
5
|
+
const ai_workstation_1 = require("../core/ai-workstation");
|
|
6
|
+
const sse_1 = require("../core/sse");
|
|
7
|
+
const shared_1 = require("./shared");
|
|
8
|
+
function matchPath(pattern, path) {
|
|
9
|
+
const patternParts = pattern.split('/').filter(Boolean);
|
|
10
|
+
const pathParts = path.split('/').filter(Boolean);
|
|
11
|
+
if (patternParts.length !== pathParts.length)
|
|
12
|
+
return null;
|
|
13
|
+
const params = {};
|
|
14
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
15
|
+
const expected = patternParts[i];
|
|
16
|
+
const actual = pathParts[i];
|
|
17
|
+
if (expected.startsWith(':'))
|
|
18
|
+
params[expected.slice(1)] = actual;
|
|
19
|
+
else if (expected !== actual)
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return params;
|
|
23
|
+
}
|
|
24
|
+
function createKoaAIMiddleware(options) {
|
|
25
|
+
const core = (0, ai_workstation_1.createAIWorkstation)(options);
|
|
26
|
+
const routes = [
|
|
27
|
+
{ method: 'POST', path: `${core.prefix}/agent/run`, type: 'stream' },
|
|
28
|
+
{ method: 'POST', path: `${core.prefix}/agent/run/sync`, type: 'sync' },
|
|
29
|
+
{ method: 'GET', path: `${core.prefix}/agent/reconnect/:threadId`, type: 'reconnect' },
|
|
30
|
+
{ method: 'POST', path: `${core.prefix}/agent/abort/:threadId`, type: 'abort' },
|
|
31
|
+
{ method: 'GET', path: `${core.prefix}/agent/health`, type: 'health' },
|
|
32
|
+
];
|
|
33
|
+
return async function aiKoaMiddleware(ctx, next) {
|
|
34
|
+
const route = routes
|
|
35
|
+
.map(item => ({ ...item, params: matchPath(item.path, ctx.path) }))
|
|
36
|
+
.find(item => item.method === ctx.method && item.params);
|
|
37
|
+
if (!route)
|
|
38
|
+
return next();
|
|
39
|
+
const requestContext = (0, shared_1.createRequestContext)({
|
|
40
|
+
method: ctx.method,
|
|
41
|
+
path: ctx.path,
|
|
42
|
+
query: ctx.query,
|
|
43
|
+
params: route.params || {},
|
|
44
|
+
body: ctx.request?.body,
|
|
45
|
+
headers: ctx.headers,
|
|
46
|
+
raw: ctx,
|
|
47
|
+
});
|
|
48
|
+
if (route.type === 'stream') {
|
|
49
|
+
ctx.respond = false;
|
|
50
|
+
await core.runAgentStream(requestContext, (0, sse_1.createNodeSSEWriter)(ctx.res));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (route.type === 'reconnect') {
|
|
54
|
+
ctx.respond = false;
|
|
55
|
+
await core.reconnectStream(requestContext, (0, sse_1.createNodeSSEWriter)(ctx.res));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const result = route.type === 'sync'
|
|
59
|
+
? await core.runAgentSync(requestContext)
|
|
60
|
+
: route.type === 'abort'
|
|
61
|
+
? await core.abortAgent(requestContext)
|
|
62
|
+
: await core.health(requestContext);
|
|
63
|
+
if (ctx.body !== undefined || typeof ctx.set === 'function') {
|
|
64
|
+
ctx.body = result;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
(0, shared_1.sendJson)(ctx.res, result);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function mountKoaAI(app, options) {
|
|
72
|
+
const middleware = createKoaAIMiddleware(options);
|
|
73
|
+
app.use(middleware);
|
|
74
|
+
return middleware;
|
|
75
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AIFrameworkAdapterOptions } from '../core/types';
|
|
2
|
+
import { AIWorkstationComponent } from '../component';
|
|
3
|
+
export { AIWorkstationComponent };
|
|
4
|
+
export declare function createMidwayAIWorkstation(options: AIFrameworkAdapterOptions): import("../core/ai-workstation").AIWorkstationCore;
|
|
5
|
+
export declare const midwayAIComponent: typeof AIWorkstationComponent;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.midwayAIComponent = exports.AIWorkstationComponent = void 0;
|
|
4
|
+
exports.createMidwayAIWorkstation = createMidwayAIWorkstation;
|
|
5
|
+
const ai_workstation_1 = require("../core/ai-workstation");
|
|
6
|
+
const component_1 = require("../component");
|
|
7
|
+
Object.defineProperty(exports, "AIWorkstationComponent", { enumerable: true, get: function () { return component_1.AIWorkstationComponent; } });
|
|
8
|
+
function createMidwayAIWorkstation(options) {
|
|
9
|
+
return (0, ai_workstation_1.createAIWorkstation)(options);
|
|
10
|
+
}
|
|
11
|
+
exports.midwayAIComponent = component_1.AIWorkstationComponent;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AIFrameworkAdapterOptions } from '../core/types';
|
|
2
|
+
export declare function createNextAIHandlers(options: AIFrameworkAdapterOptions): {
|
|
3
|
+
GET: (request: Request, context?: {
|
|
4
|
+
params?: Record<string, string>;
|
|
5
|
+
}) => Promise<Response>;
|
|
6
|
+
POST: (request: Request, context?: {
|
|
7
|
+
params?: Record<string, string>;
|
|
8
|
+
}) => Promise<Response>;
|
|
9
|
+
handle: (request: Request, context?: {
|
|
10
|
+
params?: Record<string, string>;
|
|
11
|
+
}) => Promise<Response>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createNextAIHandlers = createNextAIHandlers;
|
|
4
|
+
const ai_workstation_1 = require("../core/ai-workstation");
|
|
5
|
+
const shared_1 = require("./shared");
|
|
6
|
+
class WebResponseSSEWriter {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.encoder = new TextEncoder();
|
|
9
|
+
this.ended = false;
|
|
10
|
+
this.stream = new ReadableStream({
|
|
11
|
+
start: controller => {
|
|
12
|
+
this.controller = controller;
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
get writableEnded() {
|
|
17
|
+
return this.ended;
|
|
18
|
+
}
|
|
19
|
+
setHeader(_name, _value) { }
|
|
20
|
+
flushHeaders() { }
|
|
21
|
+
write(data) {
|
|
22
|
+
if (this.ended)
|
|
23
|
+
return;
|
|
24
|
+
this.controller?.enqueue(this.encoder.encode(data));
|
|
25
|
+
}
|
|
26
|
+
end() {
|
|
27
|
+
if (this.ended)
|
|
28
|
+
return;
|
|
29
|
+
this.ended = true;
|
|
30
|
+
this.controller?.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function createNextAIHandlers(options) {
|
|
34
|
+
const core = (0, ai_workstation_1.createAIWorkstation)(options);
|
|
35
|
+
async function handle(request, context) {
|
|
36
|
+
const url = new URL(request.url);
|
|
37
|
+
const path = url.pathname;
|
|
38
|
+
const relativePath = path.startsWith(core.prefix) ? path.slice(core.prefix.length) || '/' : path;
|
|
39
|
+
const body = request.method === 'GET' ? undefined : await readJsonBody(request);
|
|
40
|
+
const requestContext = (0, shared_1.createRequestContext)({
|
|
41
|
+
method: request.method,
|
|
42
|
+
path,
|
|
43
|
+
query: Object.fromEntries(url.searchParams.entries()),
|
|
44
|
+
params: context?.params || {},
|
|
45
|
+
body,
|
|
46
|
+
headers: Object.fromEntries(request.headers.entries()),
|
|
47
|
+
raw: request,
|
|
48
|
+
});
|
|
49
|
+
if (request.method === 'POST' && relativePath === '/agent/run') {
|
|
50
|
+
const writer = new WebResponseSSEWriter();
|
|
51
|
+
core.runAgentStream(requestContext, writer).catch(error => {
|
|
52
|
+
writer.write(`data: ${JSON.stringify({ type: 'error', data: { message: error.message }, timestamp: Date.now() })}\n\n`);
|
|
53
|
+
writer.end();
|
|
54
|
+
});
|
|
55
|
+
return new Response(writer.stream, {
|
|
56
|
+
headers: {
|
|
57
|
+
'Content-Type': 'text/event-stream; charset=utf-8',
|
|
58
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
59
|
+
'Connection': 'keep-alive',
|
|
60
|
+
'X-Accel-Buffering': 'no',
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const result = request.method === 'POST' && relativePath === '/agent/run/sync'
|
|
65
|
+
? await core.runAgentSync(requestContext)
|
|
66
|
+
: request.method === 'POST' && relativePath.startsWith('/agent/abort')
|
|
67
|
+
? await core.abortAgent(requestContext)
|
|
68
|
+
: request.method === 'GET' && relativePath === '/agent/health'
|
|
69
|
+
? await core.health(requestContext)
|
|
70
|
+
: { ret: 1, msg: `Unsupported AI route: ${request.method} ${relativePath}` };
|
|
71
|
+
return Response.json(result);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
GET: handle,
|
|
75
|
+
POST: handle,
|
|
76
|
+
handle,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async function readJsonBody(request) {
|
|
80
|
+
const text = await request.text();
|
|
81
|
+
if (!text)
|
|
82
|
+
return undefined;
|
|
83
|
+
try {
|
|
84
|
+
return JSON.parse(text);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return text;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AIRequestContext } from '../core/types';
|
|
2
|
+
export declare function joinRoute(prefix: string, path: string): string;
|
|
3
|
+
export declare function createRequestContext(input: Partial<AIRequestContext>): AIRequestContext;
|
|
4
|
+
export declare function sendJson(res: any, payload: any): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.joinRoute = joinRoute;
|
|
4
|
+
exports.createRequestContext = createRequestContext;
|
|
5
|
+
exports.sendJson = sendJson;
|
|
6
|
+
function joinRoute(prefix, path) {
|
|
7
|
+
const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
|
|
8
|
+
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
9
|
+
return `${cleanPrefix}${cleanPath}`;
|
|
10
|
+
}
|
|
11
|
+
function createRequestContext(input) {
|
|
12
|
+
return {
|
|
13
|
+
method: input.method || 'GET',
|
|
14
|
+
path: input.path || '/',
|
|
15
|
+
query: input.query || {},
|
|
16
|
+
params: input.params || {},
|
|
17
|
+
body: input.body,
|
|
18
|
+
headers: input.headers || {},
|
|
19
|
+
raw: input.raw,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function sendJson(res, payload) {
|
|
23
|
+
if (typeof res.json === 'function') {
|
|
24
|
+
res.json(payload);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (typeof res.setHeader === 'function') {
|
|
28
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
29
|
+
}
|
|
30
|
+
res.end(JSON.stringify(payload));
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 钉钉渠道适配器
|
|
3
|
+
*
|
|
4
|
+
* 发送消息:调用 https://oapi.dingtalk.com/v1.0/robot/oToMessages/batchSend
|
|
5
|
+
* 接收消息:解析 {text:{content}, senderStaffId, conversationId}
|
|
6
|
+
*/
|
|
7
|
+
import type { ChannelAdapter, ChannelConfig, ChannelType, ReceivedMessage } from './types';
|
|
8
|
+
export declare class DingTalkAdapter implements ChannelAdapter {
|
|
9
|
+
readonly type: ChannelType;
|
|
10
|
+
private config;
|
|
11
|
+
init(config: ChannelConfig): Promise<void>;
|
|
12
|
+
/** 获取钉钉 access_token */
|
|
13
|
+
private getAccessToken;
|
|
14
|
+
sendMessage(config: ChannelConfig, receiveId: string, message: string): Promise<boolean>;
|
|
15
|
+
receiveMessage(body: any, _headers?: any): Promise<ReceivedMessage | null>;
|
|
16
|
+
getConfig(): ChannelConfig;
|
|
17
|
+
verifySignature(body: any, headers: any, config: ChannelConfig): boolean;
|
|
18
|
+
}
|