@cloudbase/agent-server 1.0.1-alpha.7 → 1.0.1-alpha.9
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/CHANGELOG.md +24 -0
- package/README.md +253 -0
- package/dist/index.d.ts +126 -5
- package/dist/index.js +389 -25
- package/package.json +10 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @cloudbase/agent-server
|
|
2
2
|
|
|
3
|
+
## 1.0.1-alpha.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- alpha release 0.1.2-alpha.1
|
|
8
|
+
- Update all public packages to version 0.1.2-alpha.1
|
|
9
|
+
- Trigger automated alpha release workflow
|
|
10
|
+
- Includes latest features and improvements
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- @cloudbase/agent-shared@1.0.1-alpha.8
|
|
14
|
+
|
|
15
|
+
## 1.0.1-alpha.7
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- alpha release 0.1.2-alpha.1
|
|
20
|
+
- Update all public packages to version 0.1.2-alpha.1
|
|
21
|
+
- Trigger automated alpha release workflow
|
|
22
|
+
- Includes latest features and improvements
|
|
23
|
+
|
|
24
|
+
- Updated dependencies
|
|
25
|
+
- @cloudbase/agent-shared@1.0.1-alpha.7
|
|
26
|
+
|
|
3
27
|
## 1.0.1-alpha.6
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# @cloudbase/agent-server
|
|
2
|
+
|
|
3
|
+
将 AG-UI 兼容的 Agent 部署为 HTTP 服务。
|
|
4
|
+
|
|
5
|
+
## 什么是 AG-UI?
|
|
6
|
+
|
|
7
|
+
[AG-UI](https://ag-ui.com/) 是一个开放、轻量级、基于事件的协议,用于标准化 AI Agent 与用户界面的交互。它让 Agent 可以:
|
|
8
|
+
|
|
9
|
+
- 实时流式对话
|
|
10
|
+
- 双向状态同步
|
|
11
|
+
- 前端工具集成(Client Tools)
|
|
12
|
+
- 人机协作(Human-in-the-loop)
|
|
13
|
+
|
|
14
|
+
## 这个包解决什么问题?
|
|
15
|
+
|
|
16
|
+
- **快速部署 Agent 为 HTTP 服务**:一行代码将 Agent 部署为支持 AG-UI 协议的 HTTP 服务
|
|
17
|
+
- **多端点支持**:自动创建 `/send-message`、`/healthz` 等端点
|
|
18
|
+
- **云函数兼容**:自动适配腾讯云开发 HTTP 云函数环境
|
|
19
|
+
|
|
20
|
+
### 架构图
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart LR
|
|
24
|
+
Client[AG-UI 客户端] -->|AG-UI 协议| Server["@cloudbase/agent-server"]
|
|
25
|
+
Server --> Adapter[Adapter<br/>LangGraph / LangChain]
|
|
26
|
+
Adapter --> Agent[Agent 框架]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 配合使用
|
|
30
|
+
|
|
31
|
+
| 包名 | 作用 |
|
|
32
|
+
|------|------|
|
|
33
|
+
| `@cloudbase/agent-adapter-langgraph` | LangGraph 工作流适配器 |
|
|
34
|
+
| `@cloudbase/agent-adapter-langchain` | LangChain Agent 适配器 |
|
|
35
|
+
| `express` | HTTP 服务框架 |
|
|
36
|
+
|
|
37
|
+
## 安装
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm add @cloudbase/agent-server express
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 快速开始
|
|
44
|
+
|
|
45
|
+
### 方式一:使用 run(最简单)
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { run } from "@cloudbase/agent-server";
|
|
49
|
+
import { LanggraphAgent } from "@cloudbase/agent-adapter-langgraph";
|
|
50
|
+
import { workflow } from "./workflow.js"; // 你的 LangGraph 工作流
|
|
51
|
+
|
|
52
|
+
run({
|
|
53
|
+
createAgent: () => ({
|
|
54
|
+
agent: new LanggraphAgent({ workflow }),
|
|
55
|
+
}),
|
|
56
|
+
port: 9000,
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 方式二:使用 createExpressServer
|
|
61
|
+
|
|
62
|
+
创建一个配置好的 Express 应用:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createExpressServer } from "@cloudbase/agent-server";
|
|
66
|
+
import { LanggraphAgent } from "@cloudbase/agent-adapter-langgraph";
|
|
67
|
+
import { workflow } from "./workflow.js";
|
|
68
|
+
|
|
69
|
+
const app = createExpressServer({
|
|
70
|
+
createAgent: () => ({
|
|
71
|
+
agent: new LanggraphAgent({ workflow }),
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
app.listen(9000, () => console.log("Listening on 9000!"));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 方式三:使用 createExpressRoutes
|
|
79
|
+
|
|
80
|
+
将路由挂载到现有的 Express 应用:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { createExpressRoutes } from "@cloudbase/agent-server";
|
|
84
|
+
import { LanggraphAgent } from "@cloudbase/agent-adapter-langgraph";
|
|
85
|
+
import { workflow } from "./workflow.js";
|
|
86
|
+
import express from "express";
|
|
87
|
+
|
|
88
|
+
const app = express();
|
|
89
|
+
|
|
90
|
+
createExpressRoutes({
|
|
91
|
+
createAgent: () => ({
|
|
92
|
+
agent: new LanggraphAgent({ workflow }),
|
|
93
|
+
}),
|
|
94
|
+
express: app,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
app.listen(9000, () => console.log("Listening on 9000!"));
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API 参考
|
|
101
|
+
|
|
102
|
+
### run
|
|
103
|
+
|
|
104
|
+
创建并启动 HTTP 服务。
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
run({
|
|
108
|
+
createAgent,
|
|
109
|
+
port: 9000,
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**参数:**
|
|
114
|
+
|
|
115
|
+
| 参数 | 类型 | 说明 |
|
|
116
|
+
|------|------|------|
|
|
117
|
+
| `createAgent` | `AgentCreator` | Agent 创建函数,见下方说明 |
|
|
118
|
+
| `port` | `number \| string` | 监听端口 |
|
|
119
|
+
| `basePath` | `string` | 可选,路由基础路径,默认为 `/`,云函数环境默认为 `/v1/aibot/bots/:agentId/` |
|
|
120
|
+
| `cors` | `boolean \| CorsOptions` | 可选,CORS 配置,默认启用 |
|
|
121
|
+
| `logger` | `Logger` | 可选,日志实例,用于记录服务端日志 |
|
|
122
|
+
|
|
123
|
+
### createExpressServer
|
|
124
|
+
|
|
125
|
+
创建一个配置好的 Express 应用。
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const app = createExpressServer({
|
|
129
|
+
createAgent,
|
|
130
|
+
cors: true, // 可选,默认启用 CORS
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**参数:**
|
|
135
|
+
|
|
136
|
+
| 参数 | 类型 | 说明 |
|
|
137
|
+
|------|------|------|
|
|
138
|
+
| `createAgent` | `AgentCreator` | Agent 创建函数,见下方说明 |
|
|
139
|
+
| `basePath` | `string` | 可选,路由基础路径 |
|
|
140
|
+
| `cors` | `boolean \| CorsOptions` | 可选,CORS 配置,默认启用 |
|
|
141
|
+
| `logger` | `Logger` | 可选,日志实例,用于记录服务端日志 |
|
|
142
|
+
|
|
143
|
+
### createExpressRoutes
|
|
144
|
+
|
|
145
|
+
将 AG-UI 路由挂载到现有的 Express 应用。
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
createExpressRoutes({
|
|
149
|
+
createAgent,
|
|
150
|
+
express: app,
|
|
151
|
+
basePath, // 可选
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**参数:**
|
|
156
|
+
|
|
157
|
+
| 参数 | 类型 | 说明 |
|
|
158
|
+
|------|------|------|
|
|
159
|
+
| `createAgent` | `AgentCreator` | Agent 创建函数,见下方说明 |
|
|
160
|
+
| `express` | `Express` | Express 应用实例 |
|
|
161
|
+
| `basePath` | `string` | 可选,路由基础路径,默认为 `/`,云函数环境默认为 `/v1/aibot/bots/:agentId/` |
|
|
162
|
+
| `logger` | `Logger` | 可选,日志实例,用于记录服务端日志 |
|
|
163
|
+
|
|
164
|
+
## 自动创建的端点
|
|
165
|
+
|
|
166
|
+
| 端点 | 说明 |
|
|
167
|
+
|------|------|
|
|
168
|
+
| `{basePath}send-message` | AG-UI 消息发送端点 |
|
|
169
|
+
| `{basePath}healthz` | 健康检查端点 |
|
|
170
|
+
|
|
171
|
+
## createAgent 参数
|
|
172
|
+
|
|
173
|
+
`createAgent` 返回一个对象:
|
|
174
|
+
- `agent`:符合 [AG-UI 协议](https://docs.ag-ui.com) 的 Agent
|
|
175
|
+
- `cleanup`:可选,请求结束后的清理函数
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
type AgentCreator = (context?: {
|
|
179
|
+
request: Request; // 当前 HTTP 请求(Web Standard Request)
|
|
180
|
+
logger?: Logger; // 日志实例(带 requestId 上下文)
|
|
181
|
+
requestId?: string; // 请求追踪 ID
|
|
182
|
+
}) => AgentCreatorResult | Promise<AgentCreatorResult>; // 支持异步
|
|
183
|
+
|
|
184
|
+
type AgentCreatorResult = {
|
|
185
|
+
agent: AbstractAgent | { toAGUIAgent(): AbstractAgent }; // AG-UI 兼容的 Agent
|
|
186
|
+
cleanup?: () => void; // 可选,清理函数
|
|
187
|
+
};
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
使用适配器将你的 Agent 框架转换为 AG-UI 兼容的 Agent:
|
|
191
|
+
|
|
192
|
+
| 适配器 | 包名 | 说明 |
|
|
193
|
+
|--------|------|------|
|
|
194
|
+
| `LanggraphAgent` | `@cloudbase/agent-adapter-langgraph` | LangGraph 工作流适配器 |
|
|
195
|
+
| `LangchainAgent` | `@cloudbase/agent-adapter-langchain` | LangChain Agent 适配器 |
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { LanggraphAgent } from "@cloudbase/agent-adapter-langgraph";
|
|
199
|
+
|
|
200
|
+
createAgent: () => ({
|
|
201
|
+
agent: new LanggraphAgent({ workflow }),
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**高级用法:** `createAgent` 可以接收请求上下文,也支持异步:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
createAgent: async (context) => {
|
|
209
|
+
console.log("Request ID:", context.requestId);
|
|
210
|
+
return { agent: new LanggraphAgent({ workflow }) };
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Logger
|
|
215
|
+
|
|
216
|
+
`logger` 参数用于记录服务端日志。需要实现以下接口:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
interface Logger {
|
|
220
|
+
info?(message: string): void;
|
|
221
|
+
info?(obj: object, message?: string): void;
|
|
222
|
+
debug?(message: string): void;
|
|
223
|
+
debug?(obj: object, message?: string): void;
|
|
224
|
+
warn?(message: string): void;
|
|
225
|
+
warn?(obj: object, message?: string): void;
|
|
226
|
+
error?(message: string): void;
|
|
227
|
+
error?(obj: object, message?: string): void;
|
|
228
|
+
trace?(message: string): void;
|
|
229
|
+
trace?(obj: object, message?: string): void;
|
|
230
|
+
child?(bindings: object): Logger; // 创建带上下文的子 logger
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**示例:**
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// 开发环境:使用 console
|
|
238
|
+
run({ createAgent, logger: console, port: 9000 });
|
|
239
|
+
|
|
240
|
+
// 生产环境:使用 pino
|
|
241
|
+
import pino from "pino";
|
|
242
|
+
run({ createAgent, logger: pino({ level: "info" }), port: 9000 });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## 文档
|
|
246
|
+
|
|
247
|
+
📚 完整文档请参阅 [云开发 Agent 开发指南](https://docs.cloudbase.net/ai/agent-development/)
|
|
248
|
+
|
|
249
|
+
## 相关资源
|
|
250
|
+
|
|
251
|
+
- [AG-UI 协议](https://docs.cloudbase.net/ai/agent-development/ag-ui-protocol)
|
|
252
|
+
- [框架开发指南](https://docs.cloudbase.net/ai/agent-development/frameworks/)
|
|
253
|
+
- [部署指南](https://docs.cloudbase.net/ai/agent-development/deploy/)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import * as _cloudbase_agent_observability_server from '@cloudbase/agent-observability/server';
|
|
1
2
|
import { CreateCopilotRuntimeServerOptions } from '@copilotkit/runtime';
|
|
2
3
|
import { CopilotRuntimeOptions } from '@copilotkit/runtime/v2';
|
|
3
4
|
import expressLib, { Express } from 'express';
|
|
4
5
|
import * as _ag_ui_client from '@ag-ui/client';
|
|
5
6
|
import { AbstractAgent, RunAgentInput } from '@ag-ui/client';
|
|
6
7
|
import cors from 'cors';
|
|
7
|
-
import { SendMessageInput } from '@cloudbase/agent-shared';
|
|
8
|
+
import { Logger, SendMessageInput } from '@cloudbase/agent-shared';
|
|
9
|
+
export { LogFn, Logger, createConsoleLogger, isErrorWithCode, noopLogger } from '@cloudbase/agent-shared';
|
|
8
10
|
import { Repeater } from '@repeaterjs/repeater';
|
|
9
11
|
import * as _whatwg_node_server from '@whatwg-node/server';
|
|
10
12
|
import { OpenAI } from 'openai';
|
|
@@ -16,6 +18,10 @@ import { OpenAI } from 'openai';
|
|
|
16
18
|
interface AgentCreatorContext {
|
|
17
19
|
/** The incoming HTTP request (Web Standard Request) */
|
|
18
20
|
request: Request;
|
|
21
|
+
/** Logger instance for this request (with requestId context). Only available when using AGUI routes. */
|
|
22
|
+
logger?: Logger;
|
|
23
|
+
/** Unique request ID for tracing. Only available when using AGUI routes. */
|
|
24
|
+
requestId?: string;
|
|
19
25
|
}
|
|
20
26
|
type AgentCreatorRet = {
|
|
21
27
|
agent: AbstractAgent | {
|
|
@@ -34,16 +40,61 @@ interface ICreateServer {
|
|
|
34
40
|
cors?: boolean | cors.CorsOptions;
|
|
35
41
|
useAGUI?: boolean;
|
|
36
42
|
aguiOptions?: AGUIOptions;
|
|
43
|
+
/**
|
|
44
|
+
* Logger instance for structured logging.
|
|
45
|
+
*
|
|
46
|
+
* @default noopLogger (silent - no output)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Development: see all logs
|
|
50
|
+
* createExpressServer({ createAgent, logger: console });
|
|
51
|
+
*
|
|
52
|
+
* // Production: structured JSON logs
|
|
53
|
+
* import pino from 'pino';
|
|
54
|
+
* createExpressServer({ createAgent, logger: pino({ level: 'info' }) });
|
|
55
|
+
*/
|
|
56
|
+
logger?: Logger;
|
|
57
|
+
/**
|
|
58
|
+
* Observability configuration for trace exporters.
|
|
59
|
+
*
|
|
60
|
+
* Requires @cloudbase/agent-observability package to be installed.
|
|
61
|
+
* If the package is not installed, this option is silently ignored.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Console exporter (from env AUTO_TRACES_STDOUT)
|
|
65
|
+
* createExpressServer({ createAgent, observability: { type: 'console' } });
|
|
66
|
+
*
|
|
67
|
+
* // OTLP exporter (Langfuse, Jaeger, etc.)
|
|
68
|
+
* createExpressServer({
|
|
69
|
+
* createAgent,
|
|
70
|
+
* observability: {
|
|
71
|
+
* type: 'otlp',
|
|
72
|
+
* url: 'https://cloud.langfuse.com/api/public/otlp/v1/traces',
|
|
73
|
+
* headers: { 'Authorization': 'Basic xxx' }
|
|
74
|
+
* }
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* // Multiple exporters
|
|
78
|
+
* createExpressServer({
|
|
79
|
+
* createAgent,
|
|
80
|
+
* observability: [
|
|
81
|
+
* { type: 'console' },
|
|
82
|
+
* { type: 'otlp', url: 'http://localhost:4318/v1/traces' }
|
|
83
|
+
* ]
|
|
84
|
+
* });
|
|
85
|
+
*/
|
|
86
|
+
observability?: _cloudbase_agent_observability_server.ObservabilityConfig | _cloudbase_agent_observability_server.ObservabilityConfig[];
|
|
37
87
|
}
|
|
38
88
|
interface IRun extends ICreateServer {
|
|
39
89
|
port?: number | string;
|
|
40
90
|
}
|
|
41
91
|
interface ICreateExpressRoutes extends Omit<ICreateServer, "cors"> {
|
|
42
92
|
express: Express;
|
|
93
|
+
observability?: ICreateServer['observability'];
|
|
43
94
|
}
|
|
44
95
|
declare function run(props: IRun): void;
|
|
45
96
|
declare function createExpressServer(props: ICreateServer): Express;
|
|
46
|
-
declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, }: ICreateExpressRoutes): expressLib.Express;
|
|
97
|
+
declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, logger: _logger, observability, }: ICreateExpressRoutes): expressLib.Express;
|
|
47
98
|
interface AGUIOptions {
|
|
48
99
|
runtimeOptions?: Partial<CopilotRuntimeOptions>;
|
|
49
100
|
endpointOptions?: Partial<CreateCopilotRuntimeServerOptions>;
|
|
@@ -86,10 +137,21 @@ declare function handler$1(input: RunAgentInput, agent: AbstractAgent): Repeater
|
|
|
86
137
|
rawEvent?: any;
|
|
87
138
|
}, any, unknown>;
|
|
88
139
|
|
|
89
|
-
|
|
140
|
+
/**
|
|
141
|
+
* Options for createServerAdapter
|
|
142
|
+
*/
|
|
143
|
+
interface CreateServerAdapterOptions {
|
|
144
|
+
/**
|
|
145
|
+
* Logger instance for structured logging.
|
|
146
|
+
* @default noopLogger (silent)
|
|
147
|
+
*/
|
|
148
|
+
logger?: Logger;
|
|
149
|
+
}
|
|
150
|
+
declare function createServerAdapter$1(createAgent: AgentCreator, options?: CreateServerAdapterOptions): _whatwg_node_server.ServerAdapter<{}, _whatwg_node_server.ServerAdapterBaseObject<{}, (request: Request) => Promise<Response>>>;
|
|
90
151
|
|
|
152
|
+
type index$3_CreateServerAdapterOptions = CreateServerAdapterOptions;
|
|
91
153
|
declare namespace index$3 {
|
|
92
|
-
export { createServerAdapter$1 as createServerAdapter, handler$1 as handler };
|
|
154
|
+
export { type index$3_CreateServerAdapterOptions as CreateServerAdapterOptions, createServerAdapter$1 as createServerAdapter, handler$1 as handler };
|
|
93
155
|
}
|
|
94
156
|
|
|
95
157
|
declare const serverAdapter: _whatwg_node_server.ServerAdapter<{}, _whatwg_node_server.ServerAdapterBaseObject<{}, () => Response>>;
|
|
@@ -119,4 +181,63 @@ declare namespace index {
|
|
|
119
181
|
export { index$2 as healthz, index$1 as openai, index$4 as sendMessage, index$3 as sendMessageAGUI };
|
|
120
182
|
}
|
|
121
183
|
|
|
122
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Generates a unique request ID for tracing.
|
|
186
|
+
*
|
|
187
|
+
* The request ID is used to:
|
|
188
|
+
* 1. Correlate all logs from a single request
|
|
189
|
+
* 2. Include in error responses for debugging
|
|
190
|
+
* 3. Trace requests across distributed systems
|
|
191
|
+
*
|
|
192
|
+
* @param prefix - Optional prefix for the request ID (default: 'req')
|
|
193
|
+
* @returns A unique request ID string
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* generateRequestId() // => 'req-a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
|
197
|
+
* generateRequestId('agui') // => 'agui-a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
|
198
|
+
*/
|
|
199
|
+
declare function generateRequestId(prefix?: string): string;
|
|
200
|
+
/**
|
|
201
|
+
* Extracts request ID from incoming request headers.
|
|
202
|
+
* Supports common request ID header conventions.
|
|
203
|
+
*
|
|
204
|
+
* Header priority (first found wins):
|
|
205
|
+
* 1. x-request-id
|
|
206
|
+
* 2. x-correlation-id
|
|
207
|
+
* 3. x-trace-id
|
|
208
|
+
*
|
|
209
|
+
* @param headers - Request headers (Headers object or plain object)
|
|
210
|
+
* @returns The request ID from headers, or undefined if not found
|
|
211
|
+
*/
|
|
212
|
+
declare function extractRequestId(headers: Headers | Record<string, string | string[] | undefined>): string | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* Gets or generates a request ID.
|
|
215
|
+
* First tries to extract from headers, then generates a new one.
|
|
216
|
+
*
|
|
217
|
+
* @param headers - Request headers
|
|
218
|
+
* @param prefix - Prefix for generated IDs (default: 'req')
|
|
219
|
+
* @returns Request ID (either extracted or generated)
|
|
220
|
+
*/
|
|
221
|
+
declare function getOrGenerateRequestId(headers: Headers | Record<string, string | string[] | undefined>, prefix?: string): string;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* AG-Kit Error Handling
|
|
225
|
+
*
|
|
226
|
+
* Error handling follows these rules:
|
|
227
|
+
* 1. Pre-stream errors: Return JSON `{error: {code, message}, requestId}`
|
|
228
|
+
* 2. In-stream errors: Emit RunError event `{type: "RUN_ERROR", code, message}`
|
|
229
|
+
*
|
|
230
|
+
* Adapters can:
|
|
231
|
+
* - Directly emit RunError events into the stream
|
|
232
|
+
* - Throw errors with a `code` property (server extracts and converts to RunError)
|
|
233
|
+
* - Throw other errors (server uses fallback INTERNAL_ERROR code)
|
|
234
|
+
*/
|
|
235
|
+
declare const ErrorCode: {
|
|
236
|
+
/** Invalid request format or parameters (400) */
|
|
237
|
+
readonly INVALID_REQUEST: "INVALID_REQUEST";
|
|
238
|
+
/** Internal server error (500) */
|
|
239
|
+
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
240
|
+
};
|
|
241
|
+
type ErrorCodeType = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
242
|
+
|
|
243
|
+
export { type AgentCreator, type AgentCreatorContext, ErrorCode, type ErrorCodeType, index as agui, createExpressRoutes, createExpressServer, extractRequestId, generateRequestId, getOrGenerateRequestId, run };
|
package/dist/index.js
CHANGED
|
@@ -29,9 +29,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
// src/index.ts
|
|
30
30
|
var index_exports = {};
|
|
31
31
|
__export(index_exports, {
|
|
32
|
+
ErrorCode: () => ErrorCode,
|
|
32
33
|
agui: () => agui_exports,
|
|
34
|
+
createConsoleLogger: () => import_agent_shared2.createConsoleLogger,
|
|
33
35
|
createExpressRoutes: () => createExpressRoutes,
|
|
34
36
|
createExpressServer: () => createExpressServer,
|
|
37
|
+
extractRequestId: () => extractRequestId,
|
|
38
|
+
generateRequestId: () => generateRequestId,
|
|
39
|
+
getOrGenerateRequestId: () => getOrGenerateRequestId,
|
|
40
|
+
isErrorWithCode: () => import_agent_shared3.isErrorWithCode,
|
|
41
|
+
noopLogger: () => import_agent_shared2.noopLogger,
|
|
35
42
|
run: () => run
|
|
36
43
|
});
|
|
37
44
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -231,9 +238,199 @@ function handler2(input, agent) {
|
|
|
231
238
|
// src/agui/sendMessageAGUI/server.ts
|
|
232
239
|
var import_server3 = require("@whatwg-node/server");
|
|
233
240
|
var import_client2 = require("@ag-ui/client");
|
|
241
|
+
var import_uuid3 = require("uuid");
|
|
242
|
+
|
|
243
|
+
// src/logger/index.ts
|
|
244
|
+
var import_agent_shared2 = require("@cloudbase/agent-shared");
|
|
245
|
+
|
|
246
|
+
// src/logger/request-id.ts
|
|
234
247
|
var import_uuid2 = require("uuid");
|
|
235
|
-
function
|
|
248
|
+
function generateRequestId(prefix = "req") {
|
|
249
|
+
return `${prefix}-${(0, import_uuid2.v4)()}`;
|
|
250
|
+
}
|
|
251
|
+
function extractRequestId(headers) {
|
|
252
|
+
const headerNames = ["x-request-id", "x-correlation-id", "x-trace-id"];
|
|
253
|
+
for (const name of headerNames) {
|
|
254
|
+
let value;
|
|
255
|
+
if (headers instanceof Headers) {
|
|
256
|
+
value = headers.get(name) || void 0;
|
|
257
|
+
} else {
|
|
258
|
+
const raw = headers[name];
|
|
259
|
+
value = Array.isArray(raw) ? raw[0] : raw;
|
|
260
|
+
}
|
|
261
|
+
if (value) {
|
|
262
|
+
return value;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
function getOrGenerateRequestId(headers, prefix = "req") {
|
|
268
|
+
return extractRequestId(headers) || generateRequestId(prefix);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/agui/sendMessageAGUI/schemas.ts
|
|
272
|
+
var import_v4 = require("zod/v4");
|
|
273
|
+
var FunctionCallSchema = import_v4.z.object({
|
|
274
|
+
name: import_v4.z.string(),
|
|
275
|
+
arguments: import_v4.z.string()
|
|
276
|
+
});
|
|
277
|
+
var ToolCallSchema = import_v4.z.object({
|
|
278
|
+
id: import_v4.z.string(),
|
|
279
|
+
type: import_v4.z.literal("function"),
|
|
280
|
+
function: FunctionCallSchema
|
|
281
|
+
});
|
|
282
|
+
var ToolSchema = import_v4.z.object({
|
|
283
|
+
name: import_v4.z.string(),
|
|
284
|
+
description: import_v4.z.string(),
|
|
285
|
+
parameters: import_v4.z.any()
|
|
286
|
+
});
|
|
287
|
+
var TextInputContentSchema = import_v4.z.object({
|
|
288
|
+
type: import_v4.z.literal("text"),
|
|
289
|
+
text: import_v4.z.string()
|
|
290
|
+
});
|
|
291
|
+
var BinaryInputContentObjectSchema = import_v4.z.object({
|
|
292
|
+
type: import_v4.z.literal("binary"),
|
|
293
|
+
mimeType: import_v4.z.string(),
|
|
294
|
+
id: import_v4.z.string().optional(),
|
|
295
|
+
url: import_v4.z.string().optional(),
|
|
296
|
+
data: import_v4.z.string().optional(),
|
|
297
|
+
filename: import_v4.z.string().optional()
|
|
298
|
+
});
|
|
299
|
+
var ensureBinaryPayload = (value, ctx) => {
|
|
300
|
+
if (!value.id && !value.url && !value.data) {
|
|
301
|
+
ctx.addIssue({
|
|
302
|
+
code: import_v4.z.ZodIssueCode.custom,
|
|
303
|
+
message: "BinaryInputContent requires at least one of id, url, or data.",
|
|
304
|
+
path: ["id"]
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
var BinaryInputContentSchema = BinaryInputContentObjectSchema.superRefine((value, ctx) => {
|
|
309
|
+
ensureBinaryPayload(value, ctx);
|
|
310
|
+
});
|
|
311
|
+
var InputContentBaseSchema = import_v4.z.discriminatedUnion("type", [
|
|
312
|
+
TextInputContentSchema,
|
|
313
|
+
BinaryInputContentObjectSchema
|
|
314
|
+
]);
|
|
315
|
+
var InputContentSchema = InputContentBaseSchema.superRefine(
|
|
316
|
+
(value, ctx) => {
|
|
317
|
+
if (value.type === "binary") {
|
|
318
|
+
ensureBinaryPayload(value, ctx);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
var BaseMessageSchema = import_v4.z.object({
|
|
323
|
+
id: import_v4.z.string(),
|
|
324
|
+
role: import_v4.z.string(),
|
|
325
|
+
content: import_v4.z.string().optional(),
|
|
326
|
+
name: import_v4.z.string().optional()
|
|
327
|
+
});
|
|
328
|
+
var DeveloperMessageSchema = BaseMessageSchema.extend({
|
|
329
|
+
role: import_v4.z.literal("developer"),
|
|
330
|
+
content: import_v4.z.string()
|
|
331
|
+
});
|
|
332
|
+
var SystemMessageSchema = BaseMessageSchema.extend({
|
|
333
|
+
role: import_v4.z.literal("system"),
|
|
334
|
+
content: import_v4.z.string()
|
|
335
|
+
});
|
|
336
|
+
var AssistantMessageSchema = BaseMessageSchema.extend({
|
|
337
|
+
role: import_v4.z.literal("assistant"),
|
|
338
|
+
content: import_v4.z.string().optional(),
|
|
339
|
+
toolCalls: import_v4.z.array(ToolCallSchema).optional()
|
|
340
|
+
});
|
|
341
|
+
var UserMessageSchema = BaseMessageSchema.extend({
|
|
342
|
+
role: import_v4.z.literal("user"),
|
|
343
|
+
content: import_v4.z.union([import_v4.z.string(), import_v4.z.array(InputContentSchema)])
|
|
344
|
+
});
|
|
345
|
+
var ToolMessageSchema = import_v4.z.object({
|
|
346
|
+
id: import_v4.z.string(),
|
|
347
|
+
content: import_v4.z.string(),
|
|
348
|
+
role: import_v4.z.literal("tool"),
|
|
349
|
+
toolCallId: import_v4.z.string(),
|
|
350
|
+
error: import_v4.z.string().optional()
|
|
351
|
+
});
|
|
352
|
+
var ActivityMessageSchema = import_v4.z.object({
|
|
353
|
+
id: import_v4.z.string(),
|
|
354
|
+
role: import_v4.z.literal("activity"),
|
|
355
|
+
activityType: import_v4.z.string(),
|
|
356
|
+
content: import_v4.z.record(import_v4.z.string(), import_v4.z.any())
|
|
357
|
+
});
|
|
358
|
+
var MessageSchema = import_v4.z.discriminatedUnion("role", [
|
|
359
|
+
DeveloperMessageSchema,
|
|
360
|
+
SystemMessageSchema,
|
|
361
|
+
AssistantMessageSchema,
|
|
362
|
+
UserMessageSchema,
|
|
363
|
+
ToolMessageSchema,
|
|
364
|
+
ActivityMessageSchema
|
|
365
|
+
]);
|
|
366
|
+
var ContextSchema = import_v4.z.object({
|
|
367
|
+
description: import_v4.z.string(),
|
|
368
|
+
value: import_v4.z.string()
|
|
369
|
+
});
|
|
370
|
+
var ServerRunAgentInputSchema = import_v4.z.object({
|
|
371
|
+
threadId: import_v4.z.string().optional(),
|
|
372
|
+
// Modified: optional instead of required
|
|
373
|
+
runId: import_v4.z.string(),
|
|
374
|
+
parentRunId: import_v4.z.string().optional(),
|
|
375
|
+
state: import_v4.z.any(),
|
|
376
|
+
messages: import_v4.z.array(MessageSchema),
|
|
377
|
+
tools: import_v4.z.array(ToolSchema),
|
|
378
|
+
context: import_v4.z.array(ContextSchema),
|
|
379
|
+
forwardedProps: import_v4.z.any()
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// src/errors/index.ts
|
|
383
|
+
var import_agent_shared3 = require("@cloudbase/agent-shared");
|
|
384
|
+
var ErrorCode = {
|
|
385
|
+
/** Invalid request format or parameters (400) */
|
|
386
|
+
INVALID_REQUEST: "INVALID_REQUEST",
|
|
387
|
+
/** Internal server error (500) */
|
|
388
|
+
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// src/agui/sendMessageAGUI/server.ts
|
|
392
|
+
var startObservation;
|
|
393
|
+
var setupObservability;
|
|
394
|
+
var observabilityLoadAttempted = false;
|
|
395
|
+
async function loadObservability() {
|
|
396
|
+
if (!observabilityLoadAttempted) {
|
|
397
|
+
observabilityLoadAttempted = true;
|
|
398
|
+
try {
|
|
399
|
+
const obs = await import("@cloudbase/agent-observability");
|
|
400
|
+
const obsServer = await import("@cloudbase/agent-observability/server");
|
|
401
|
+
startObservation = obs.startObservation;
|
|
402
|
+
setupObservability = obsServer.setupObservability;
|
|
403
|
+
return true;
|
|
404
|
+
} catch (e) {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return !!startObservation;
|
|
409
|
+
}
|
|
410
|
+
async function ensureObservabilityReady() {
|
|
411
|
+
if (!setupObservability) return false;
|
|
412
|
+
try {
|
|
413
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
414
|
+
setTimeout(() => reject(new Error("Observability setup timeout")), 2e3);
|
|
415
|
+
});
|
|
416
|
+
await Promise.race([
|
|
417
|
+
setupObservability(),
|
|
418
|
+
timeoutPromise
|
|
419
|
+
]);
|
|
420
|
+
return true;
|
|
421
|
+
} catch (e) {
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function createServerAdapter2(createAgent, options) {
|
|
426
|
+
var _a;
|
|
427
|
+
const { logger: parentLogger = import_agent_shared2.noopLogger } = options ?? {};
|
|
428
|
+
const adapterLogger = ((_a = parentLogger.child) == null ? void 0 : _a.call(parentLogger, { component: "sendMessageAGUI" })) ?? parentLogger;
|
|
236
429
|
return (0, import_server3.createServerAdapter)(async (request) => {
|
|
430
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
431
|
+
const requestId = getOrGenerateRequestId(request.headers, "agui");
|
|
432
|
+
const logger = ((_a2 = adapterLogger.child) == null ? void 0 : _a2.call(adapterLogger, { requestId })) ?? adapterLogger;
|
|
433
|
+
(_b = logger.info) == null ? void 0 : _b.call(logger, "Request received");
|
|
237
434
|
const inputRes = await safeAsync(async () => {
|
|
238
435
|
const rawInput = await request.json();
|
|
239
436
|
const inputWithDefaults = {
|
|
@@ -242,16 +439,24 @@ function createServerAdapter2(createAgent) {
|
|
|
242
439
|
state: {},
|
|
243
440
|
forwardedProps: {},
|
|
244
441
|
...rawInput,
|
|
245
|
-
runId: typeof rawInput.runId === "string" && rawInput.runId ? rawInput.runId : (0,
|
|
442
|
+
runId: typeof rawInput.runId === "string" && rawInput.runId ? rawInput.runId : (0, import_uuid3.v4)()
|
|
246
443
|
};
|
|
247
|
-
return
|
|
444
|
+
return ServerRunAgentInputSchema.parse(inputWithDefaults);
|
|
248
445
|
});
|
|
249
446
|
if ("error" in inputRes) {
|
|
250
447
|
const { error } = inputRes;
|
|
251
|
-
|
|
448
|
+
(_c = logger.warn) == null ? void 0 : _c.call(
|
|
449
|
+
logger,
|
|
450
|
+
{ err: error instanceof Error ? error.message : String(error) },
|
|
451
|
+
"Input validation failed"
|
|
452
|
+
);
|
|
252
453
|
return new Response(
|
|
253
454
|
JSON.stringify({
|
|
254
|
-
error:
|
|
455
|
+
error: {
|
|
456
|
+
code: ErrorCode.INVALID_REQUEST,
|
|
457
|
+
message: error instanceof Error ? error.message : String(error)
|
|
458
|
+
},
|
|
459
|
+
requestId
|
|
255
460
|
}),
|
|
256
461
|
{
|
|
257
462
|
status: 400,
|
|
@@ -259,8 +464,25 @@ function createServerAdapter2(createAgent) {
|
|
|
259
464
|
}
|
|
260
465
|
);
|
|
261
466
|
}
|
|
467
|
+
const input = inputRes.result;
|
|
468
|
+
const lastUserMessage = input.messages.filter((m) => m.role === "user").pop();
|
|
469
|
+
(_f = logger.debug) == null ? void 0 : _f.call(
|
|
470
|
+
logger,
|
|
471
|
+
{
|
|
472
|
+
runId: input.runId,
|
|
473
|
+
threadId: input.threadId,
|
|
474
|
+
messageCount: input.messages.length,
|
|
475
|
+
toolCount: ((_d = input.tools) == null ? void 0 : _d.length) ?? 0,
|
|
476
|
+
tools: (_e = input.tools) == null ? void 0 : _e.map((t) => t.name),
|
|
477
|
+
lastUserMessage: typeof (lastUserMessage == null ? void 0 : lastUserMessage.content) === "string" ? lastUserMessage.content.slice(0, 200) : void 0
|
|
478
|
+
},
|
|
479
|
+
"Input validated"
|
|
480
|
+
);
|
|
481
|
+
(_g = logger.trace) == null ? void 0 : _g.call(logger, { input }, "Full request input");
|
|
262
482
|
const createAgentRes = await safeAsync(async () => {
|
|
263
|
-
const res = await Promise.resolve(
|
|
483
|
+
const res = await Promise.resolve(
|
|
484
|
+
createAgent({ request, logger, requestId })
|
|
485
|
+
);
|
|
264
486
|
return {
|
|
265
487
|
cleanup: res.cleanup,
|
|
266
488
|
agent: "toAGUIAgent" in res.agent ? res.agent.toAGUIAgent() : res.agent
|
|
@@ -268,10 +490,16 @@ function createServerAdapter2(createAgent) {
|
|
|
268
490
|
});
|
|
269
491
|
if ("error" in createAgentRes) {
|
|
270
492
|
const { error } = createAgentRes;
|
|
271
|
-
|
|
493
|
+
(_h = logger.error) == null ? void 0 : _h.call(logger, { err: error }, "Agent creation failed");
|
|
494
|
+
const errorCode = (0, import_agent_shared3.isErrorWithCode)(error) ? error.code : ErrorCode.INTERNAL_ERROR;
|
|
495
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
272
496
|
return new Response(
|
|
273
497
|
JSON.stringify({
|
|
274
|
-
error:
|
|
498
|
+
error: {
|
|
499
|
+
code: errorCode,
|
|
500
|
+
message: errorMessage
|
|
501
|
+
},
|
|
502
|
+
requestId
|
|
275
503
|
}),
|
|
276
504
|
{
|
|
277
505
|
status: 500,
|
|
@@ -279,38 +507,116 @@ function createServerAdapter2(createAgent) {
|
|
|
279
507
|
}
|
|
280
508
|
);
|
|
281
509
|
}
|
|
282
|
-
const
|
|
283
|
-
let
|
|
510
|
+
const hasObservability = await loadObservability();
|
|
511
|
+
let serverSpan = null;
|
|
512
|
+
let serverContextData = null;
|
|
513
|
+
if (hasObservability && startObservation) {
|
|
514
|
+
try {
|
|
515
|
+
const isReady = await ensureObservabilityReady();
|
|
516
|
+
if (isReady) {
|
|
517
|
+
serverSpan = startObservation(
|
|
518
|
+
"AG-UI.Server",
|
|
519
|
+
{
|
|
520
|
+
"http.method": request.method,
|
|
521
|
+
"http.url": request.url,
|
|
522
|
+
"http.host": request.headers.get("host") || "unknown",
|
|
523
|
+
"http.user_agent": request.headers.get("user-agent") || "unknown",
|
|
524
|
+
"agui.thread_id": inputRes.result.threadId,
|
|
525
|
+
"agui.run_id": inputRes.result.runId
|
|
526
|
+
},
|
|
527
|
+
{ asType: "span" }
|
|
528
|
+
);
|
|
529
|
+
const spanContext = serverSpan.otelSpan.spanContext();
|
|
530
|
+
serverContextData = {
|
|
531
|
+
traceId: spanContext.traceId,
|
|
532
|
+
spanId: spanContext.spanId,
|
|
533
|
+
traceFlags: spanContext.traceFlags
|
|
534
|
+
};
|
|
535
|
+
inputRes.result.forwardedProps = {
|
|
536
|
+
...inputRes.result.forwardedProps,
|
|
537
|
+
__agui_server_context: serverContextData
|
|
538
|
+
};
|
|
539
|
+
(_i = logger.debug) == null ? void 0 : _i.call(logger, "\u2713 Server span created:", {
|
|
540
|
+
traceId: serverContextData.traceId,
|
|
541
|
+
spanId: serverContextData.spanId
|
|
542
|
+
});
|
|
543
|
+
} else {
|
|
544
|
+
(_j = logger.debug) == null ? void 0 : _j.call(logger, "Observability not ready, skipping span creation");
|
|
545
|
+
}
|
|
546
|
+
} catch (e) {
|
|
547
|
+
(_k = logger.debug) == null ? void 0 : _k.call(logger, "Failed to create server span:", e);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
284
550
|
let cleanupCalled = false;
|
|
285
551
|
const safeCleanup = () => {
|
|
286
|
-
var
|
|
552
|
+
var _a3, _b2, _c2;
|
|
287
553
|
if (!cleanupCalled) {
|
|
288
554
|
cleanupCalled = true;
|
|
289
555
|
try {
|
|
290
|
-
(
|
|
556
|
+
(_b2 = (_a3 = createAgentRes.result).cleanup) == null ? void 0 : _b2.call(_a3);
|
|
291
557
|
} catch (e) {
|
|
292
|
-
|
|
558
|
+
(_c2 = logger.error) == null ? void 0 : _c2.call(logger, { err: e }, "Cleanup error");
|
|
293
559
|
}
|
|
294
560
|
}
|
|
295
561
|
};
|
|
562
|
+
const eventsResult = safe(
|
|
563
|
+
() => handler2(
|
|
564
|
+
inputRes.result,
|
|
565
|
+
createAgentRes.result.agent
|
|
566
|
+
)
|
|
567
|
+
);
|
|
568
|
+
if ("error" in eventsResult) {
|
|
569
|
+
const { error } = eventsResult;
|
|
570
|
+
(_l = logger.error) == null ? void 0 : _l.call(logger, { err: error }, "Run agent failed");
|
|
571
|
+
const errorCode = (0, import_agent_shared3.isErrorWithCode)(error) ? error.code : ErrorCode.INTERNAL_ERROR;
|
|
572
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
573
|
+
return new Response(
|
|
574
|
+
JSON.stringify({
|
|
575
|
+
error: {
|
|
576
|
+
code: errorCode,
|
|
577
|
+
message: errorMessage
|
|
578
|
+
},
|
|
579
|
+
requestId
|
|
580
|
+
}),
|
|
581
|
+
{
|
|
582
|
+
status: 500,
|
|
583
|
+
headers: { "Content-Type": "application/json" }
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
const { result: events } = eventsResult;
|
|
588
|
+
let heartbeat;
|
|
296
589
|
const stream = new ReadableStream({
|
|
297
590
|
async start(controller) {
|
|
591
|
+
var _a3, _b2, _c2, _d2, _e2;
|
|
298
592
|
const encoder = new TextEncoder();
|
|
299
593
|
heartbeat = setInterval(() => {
|
|
300
594
|
controller.enqueue(encoder.encode(":ping\n\n"));
|
|
301
595
|
}, 15 * 1e3);
|
|
596
|
+
let eventCount = 0;
|
|
302
597
|
try {
|
|
303
598
|
for await (const event of events) {
|
|
599
|
+
eventCount++;
|
|
600
|
+
(_a3 = logger.debug) == null ? void 0 : _a3.call(
|
|
601
|
+
logger,
|
|
602
|
+
{ eventType: event.type, eventCount },
|
|
603
|
+
"Emitting SSE event"
|
|
604
|
+
);
|
|
605
|
+
(_b2 = logger.trace) == null ? void 0 : _b2.call(logger, { aguiEvent: event }, "SSE event content");
|
|
304
606
|
const sseChunk = `data: ${JSON.stringify(event)}
|
|
305
607
|
|
|
306
608
|
`;
|
|
307
609
|
controller.enqueue(encoder.encode(sseChunk));
|
|
308
610
|
}
|
|
611
|
+
(_c2 = logger.info) == null ? void 0 : _c2.call(logger, { eventCount }, "Request completed");
|
|
309
612
|
} catch (error) {
|
|
310
|
-
|
|
613
|
+
(_d2 = logger.error) == null ? void 0 : _d2.call(logger, { err: error }, "Stream error");
|
|
614
|
+
const errorCode = (0, import_agent_shared3.isErrorWithCode)(error) ? error.code : ErrorCode.INTERNAL_ERROR;
|
|
615
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
311
616
|
const errorEvent = {
|
|
312
617
|
type: import_client2.EventType.RUN_ERROR,
|
|
313
|
-
|
|
618
|
+
code: errorCode,
|
|
619
|
+
message: errorMessage
|
|
314
620
|
};
|
|
315
621
|
controller.enqueue(
|
|
316
622
|
encoder.encode(`data: ${JSON.stringify(errorEvent)}
|
|
@@ -321,11 +627,21 @@ function createServerAdapter2(createAgent) {
|
|
|
321
627
|
if (heartbeat) clearInterval(heartbeat);
|
|
322
628
|
controller.close();
|
|
323
629
|
safeCleanup();
|
|
630
|
+
if (serverSpan) {
|
|
631
|
+
serverSpan.end();
|
|
632
|
+
(_e2 = logger.debug) == null ? void 0 : _e2.call(logger, "\u2713 Server span ended");
|
|
633
|
+
}
|
|
324
634
|
}
|
|
325
635
|
},
|
|
326
636
|
cancel() {
|
|
637
|
+
var _a3, _b2;
|
|
638
|
+
(_a3 = logger.info) == null ? void 0 : _a3.call(logger, "Request cancelled by client");
|
|
327
639
|
if (heartbeat) clearInterval(heartbeat);
|
|
328
640
|
safeCleanup();
|
|
641
|
+
if (serverSpan) {
|
|
642
|
+
serverSpan.end();
|
|
643
|
+
(_b2 = logger.debug) == null ? void 0 : _b2.call(logger, "\u2713 Server span ended (cancelled)");
|
|
644
|
+
}
|
|
329
645
|
}
|
|
330
646
|
});
|
|
331
647
|
const headers = new Headers({
|
|
@@ -345,6 +661,15 @@ async function safeAsync(fn) {
|
|
|
345
661
|
return { error };
|
|
346
662
|
}
|
|
347
663
|
}
|
|
664
|
+
function safe(fn) {
|
|
665
|
+
try {
|
|
666
|
+
return {
|
|
667
|
+
result: fn()
|
|
668
|
+
};
|
|
669
|
+
} catch (error) {
|
|
670
|
+
return { error };
|
|
671
|
+
}
|
|
672
|
+
}
|
|
348
673
|
|
|
349
674
|
// src/agui/healthz/index.ts
|
|
350
675
|
var healthz_exports = {};
|
|
@@ -362,7 +687,7 @@ __export(openai_exports, {
|
|
|
362
687
|
});
|
|
363
688
|
|
|
364
689
|
// src/agui/openai/handler.ts
|
|
365
|
-
var
|
|
690
|
+
var import_uuid4 = require("uuid");
|
|
366
691
|
var import_repeater3 = require("@repeaterjs/repeater");
|
|
367
692
|
function handler3(input, agent) {
|
|
368
693
|
var _a;
|
|
@@ -374,12 +699,12 @@ function handler3(input, agent) {
|
|
|
374
699
|
description: tool.function.description,
|
|
375
700
|
parameters: tool.function.parameters
|
|
376
701
|
})),
|
|
377
|
-
conversationId: (0,
|
|
702
|
+
conversationId: (0, import_uuid4.v4)()
|
|
378
703
|
},
|
|
379
704
|
agent
|
|
380
705
|
);
|
|
381
706
|
return new import_repeater3.Repeater(async (push, stop) => {
|
|
382
|
-
const id = (0,
|
|
707
|
+
const id = (0, import_uuid4.v4)();
|
|
383
708
|
let tools = [];
|
|
384
709
|
let lastWithToolCall = false;
|
|
385
710
|
let maxIndex = 0;
|
|
@@ -543,6 +868,13 @@ var import_cors = __toESM(require("cors"));
|
|
|
543
868
|
var import_async_hooks = require("async_hooks");
|
|
544
869
|
var import_server8 = require("@whatwg-node/server");
|
|
545
870
|
var DefaultFetchAPI = __toESM(require("@whatwg-node/fetch"));
|
|
871
|
+
async function setupObservabilityIfAvailable(configs) {
|
|
872
|
+
try {
|
|
873
|
+
const { setupObservability: setupObservability2 } = await import("@cloudbase/agent-observability/server");
|
|
874
|
+
await setupObservability2(configs);
|
|
875
|
+
} catch (error) {
|
|
876
|
+
}
|
|
877
|
+
}
|
|
546
878
|
var preparedAgentStorage = new import_async_hooks.AsyncLocalStorage();
|
|
547
879
|
function agentCloneFn() {
|
|
548
880
|
const preparedAgent = preparedAgentStorage.getStore();
|
|
@@ -576,16 +908,27 @@ function createExpressRoutes({
|
|
|
576
908
|
basePath: _basePath,
|
|
577
909
|
express,
|
|
578
910
|
useAGUI: _useAGUI,
|
|
579
|
-
aguiOptions
|
|
911
|
+
aguiOptions,
|
|
912
|
+
logger: _logger,
|
|
913
|
+
observability
|
|
580
914
|
}) {
|
|
915
|
+
var _a, _b, _c;
|
|
581
916
|
const useAGUI = _useAGUI ?? true;
|
|
917
|
+
const logger = _logger ?? import_agent_shared2.noopLogger;
|
|
582
918
|
const basePath = _basePath ?? (process.env.TENCENTCLOUD_RUNENV === "SCF" ? "/v1/aibot/bots/:agentId/" : "/");
|
|
583
|
-
const
|
|
919
|
+
const serverLogger = ((_a = logger.child) == null ? void 0 : _a.call(logger, { component: "server" })) ?? logger;
|
|
920
|
+
(_b = serverLogger.debug) == null ? void 0 : _b.call(serverLogger, { basePath, useAGUI }, "Initializing server routes");
|
|
921
|
+
if (observability) {
|
|
922
|
+
setupObservabilityIfAvailable(observability).catch(() => {
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
const sendMessageServerAdapter = useAGUI ? sendMessageAGUI_exports.createServerAdapter(createAgent, { logger: serverLogger }) : sendMessage_exports.createServerAdapter(createAgent);
|
|
584
926
|
if (useAGUI) {
|
|
585
927
|
createAGUIRoute({
|
|
586
928
|
basePath,
|
|
587
929
|
express,
|
|
588
930
|
createAgent,
|
|
931
|
+
logger: serverLogger,
|
|
589
932
|
...aguiOptions || {}
|
|
590
933
|
});
|
|
591
934
|
}
|
|
@@ -594,6 +937,7 @@ function createExpressRoutes({
|
|
|
594
937
|
express.use(`${basePath}send-message`, sendMessageServerAdapter);
|
|
595
938
|
express.use(`${basePath}healthz`, healthzServerAdapter);
|
|
596
939
|
express.use(`${basePath}chat/completions`, openaiServerAdapter);
|
|
940
|
+
(_c = serverLogger.info) == null ? void 0 : _c.call(serverLogger, { basePath }, "Server routes initialized");
|
|
597
941
|
return express;
|
|
598
942
|
}
|
|
599
943
|
var AGUIRpcHandlerPromise = null;
|
|
@@ -602,11 +946,13 @@ function getAGUIRpcHandler({
|
|
|
602
946
|
runtimeOptions,
|
|
603
947
|
basePath,
|
|
604
948
|
endpointOptions,
|
|
605
|
-
request
|
|
949
|
+
request,
|
|
950
|
+
logger,
|
|
951
|
+
requestId
|
|
606
952
|
}) {
|
|
607
953
|
if (AGUIRpcHandlerPromise) return AGUIRpcHandlerPromise;
|
|
608
954
|
AGUIRpcHandlerPromise = (async () => {
|
|
609
|
-
const { agent } = await createAgent({ request });
|
|
955
|
+
const { agent } = await createAgent({ request, logger, requestId });
|
|
610
956
|
const templateAgent = "toAGUIAgent" in agent ? agent.toAGUIAgent() : agent;
|
|
611
957
|
templateAgent.clone = agentCloneFn;
|
|
612
958
|
const runtime = new import_runtime.CopilotRuntime({
|
|
@@ -629,12 +975,21 @@ function createAGUIRoute({
|
|
|
629
975
|
basePath,
|
|
630
976
|
createAgent,
|
|
631
977
|
runtimeOptions,
|
|
632
|
-
endpointOptions
|
|
978
|
+
endpointOptions,
|
|
979
|
+
logger
|
|
633
980
|
}) {
|
|
981
|
+
var _a;
|
|
982
|
+
const routeLogger = ((_a = logger.child) == null ? void 0 : _a.call(logger, { component: "agui-route" })) ?? logger;
|
|
634
983
|
express.post(`${basePath}agui`, import_express.default.json(), async (req, res) => {
|
|
984
|
+
var _a2, _b;
|
|
635
985
|
const webRequest = (0, import_server8.normalizeNodeRequest)(req, DefaultFetchAPI);
|
|
986
|
+
const requestId = getOrGenerateRequestId(webRequest.headers, "agui");
|
|
987
|
+
const requestLogger = ((_a2 = routeLogger.child) == null ? void 0 : _a2.call(routeLogger, { requestId })) ?? routeLogger;
|
|
988
|
+
(_b = requestLogger.info) == null ? void 0 : _b.call(requestLogger, { path: `${basePath}agui` }, "Request received");
|
|
636
989
|
const { agent: rawAgent, cleanup } = await createAgent({
|
|
637
|
-
request: webRequest
|
|
990
|
+
request: webRequest,
|
|
991
|
+
logger: requestLogger,
|
|
992
|
+
requestId
|
|
638
993
|
});
|
|
639
994
|
const preparedAgent = "toAGUIAgent" in rawAgent ? rawAgent.toAGUIAgent() : rawAgent;
|
|
640
995
|
preparedAgent.clone = agentCloneFn;
|
|
@@ -643,7 +998,9 @@ function createAGUIRoute({
|
|
|
643
998
|
basePath,
|
|
644
999
|
runtimeOptions,
|
|
645
1000
|
endpointOptions,
|
|
646
|
-
request: webRequest
|
|
1001
|
+
request: webRequest,
|
|
1002
|
+
logger: requestLogger,
|
|
1003
|
+
requestId
|
|
647
1004
|
});
|
|
648
1005
|
preparedAgentStorage.run(preparedAgent, () => {
|
|
649
1006
|
rpcHandler(req, res);
|
|
@@ -658,8 +1015,15 @@ function isCorsOptions(cors2) {
|
|
|
658
1015
|
}
|
|
659
1016
|
// Annotate the CommonJS export names for ESM import in node:
|
|
660
1017
|
0 && (module.exports = {
|
|
1018
|
+
ErrorCode,
|
|
661
1019
|
agui,
|
|
1020
|
+
createConsoleLogger,
|
|
662
1021
|
createExpressRoutes,
|
|
663
1022
|
createExpressServer,
|
|
1023
|
+
extractRequestId,
|
|
1024
|
+
generateRequestId,
|
|
1025
|
+
getOrGenerateRequestId,
|
|
1026
|
+
isErrorWithCode,
|
|
1027
|
+
noopLogger,
|
|
664
1028
|
run
|
|
665
1029
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/agent-server",
|
|
3
|
-
"version": "1.0.1-alpha.
|
|
3
|
+
"version": "1.0.1-alpha.9",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/",
|
|
@@ -20,13 +20,19 @@
|
|
|
20
20
|
"express": "^5.1.0",
|
|
21
21
|
"openai": "6.3.0",
|
|
22
22
|
"uuid": "^10.0.0",
|
|
23
|
-
"
|
|
24
|
-
|
|
23
|
+
"@cloudbase/agent-shared": "^1.0.1-alpha.9"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"zod": "^3.25.0 || ^4.0.0"
|
|
27
|
+
},
|
|
28
|
+
"optionalDependencies": {
|
|
29
|
+
"@cloudbase/agent-observability": "1.0.1-alpha.9"
|
|
25
30
|
},
|
|
26
31
|
"devDependencies": {
|
|
27
32
|
"@types/cors": "^2.8.19",
|
|
28
33
|
"@types/express": "^5.0.3",
|
|
29
|
-
"tsup": "^8.5.0"
|
|
34
|
+
"tsup": "^8.5.0",
|
|
35
|
+
"zod": "^4.0.0"
|
|
30
36
|
},
|
|
31
37
|
"scripts": {
|
|
32
38
|
"test": "echo \"Error: no test specified\" && exit 1",
|