@cloudbase/agent-server 0.0.11 → 0.0.13

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @cloudbase/agent-server
2
2
 
3
+ ## 1.0.1-alpha.6
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.6
14
+
3
15
  ## 1.0.1-alpha.5
4
16
 
5
17
  ### 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
@@ -4,7 +4,8 @@ import expressLib, { Express } from 'express';
4
4
  import * as _ag_ui_client from '@ag-ui/client';
5
5
  import { AbstractAgent, RunAgentInput } from '@ag-ui/client';
6
6
  import cors from 'cors';
7
- import { SendMessageInput } from '@cloudbase/agent-shared';
7
+ import { Logger, SendMessageInput } from '@cloudbase/agent-shared';
8
+ export { LogFn, Logger, createConsoleLogger, noopLogger } from '@cloudbase/agent-shared';
8
9
  import { Repeater } from '@repeaterjs/repeater';
9
10
  import * as _whatwg_node_server from '@whatwg-node/server';
10
11
  import { OpenAI } from 'openai';
@@ -16,6 +17,10 @@ import { OpenAI } from 'openai';
16
17
  interface AgentCreatorContext {
17
18
  /** The incoming HTTP request (Web Standard Request) */
18
19
  request: Request;
20
+ /** Logger instance for this request (with requestId context). Only available when using AGUI routes. */
21
+ logger?: Logger;
22
+ /** Unique request ID for tracing. Only available when using AGUI routes. */
23
+ requestId?: string;
19
24
  }
20
25
  type AgentCreatorRet = {
21
26
  agent: AbstractAgent | {
@@ -34,6 +39,20 @@ interface ICreateServer {
34
39
  cors?: boolean | cors.CorsOptions;
35
40
  useAGUI?: boolean;
36
41
  aguiOptions?: AGUIOptions;
42
+ /**
43
+ * Logger instance for structured logging.
44
+ *
45
+ * @default noopLogger (silent - no output)
46
+ *
47
+ * @example
48
+ * // Development: see all logs
49
+ * createExpressServer({ createAgent, logger: console });
50
+ *
51
+ * // Production: structured JSON logs
52
+ * import pino from 'pino';
53
+ * createExpressServer({ createAgent, logger: pino({ level: 'info' }) });
54
+ */
55
+ logger?: Logger;
37
56
  }
38
57
  interface IRun extends ICreateServer {
39
58
  port?: number | string;
@@ -43,7 +62,7 @@ interface ICreateExpressRoutes extends Omit<ICreateServer, "cors"> {
43
62
  }
44
63
  declare function run(props: IRun): void;
45
64
  declare function createExpressServer(props: ICreateServer): Express;
46
- declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, }: ICreateExpressRoutes): expressLib.Express;
65
+ declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, logger: _logger, }: ICreateExpressRoutes): expressLib.Express;
47
66
  interface AGUIOptions {
48
67
  runtimeOptions?: Partial<CopilotRuntimeOptions>;
49
68
  endpointOptions?: Partial<CreateCopilotRuntimeServerOptions>;
@@ -86,10 +105,21 @@ declare function handler$1(input: RunAgentInput, agent: AbstractAgent): Repeater
86
105
  rawEvent?: any;
87
106
  }, any, unknown>;
88
107
 
89
- declare function createServerAdapter$1(createAgent: AgentCreator): _whatwg_node_server.ServerAdapter<{}, _whatwg_node_server.ServerAdapterBaseObject<{}, (request: Request) => Promise<Response>>>;
108
+ /**
109
+ * Options for createServerAdapter
110
+ */
111
+ interface CreateServerAdapterOptions {
112
+ /**
113
+ * Logger instance for structured logging.
114
+ * @default noopLogger (silent)
115
+ */
116
+ logger?: Logger;
117
+ }
118
+ declare function createServerAdapter$1(createAgent: AgentCreator, options?: CreateServerAdapterOptions): _whatwg_node_server.ServerAdapter<{}, _whatwg_node_server.ServerAdapterBaseObject<{}, (request: Request) => Promise<Response>>>;
90
119
 
120
+ type index$3_CreateServerAdapterOptions = CreateServerAdapterOptions;
91
121
  declare namespace index$3 {
92
- export { createServerAdapter$1 as createServerAdapter, handler$1 as handler };
122
+ export { type index$3_CreateServerAdapterOptions as CreateServerAdapterOptions, createServerAdapter$1 as createServerAdapter, handler$1 as handler };
93
123
  }
94
124
 
95
125
  declare const serverAdapter: _whatwg_node_server.ServerAdapter<{}, _whatwg_node_server.ServerAdapterBaseObject<{}, () => Response>>;
@@ -119,4 +149,43 @@ declare namespace index {
119
149
  export { index$2 as healthz, index$1 as openai, index$4 as sendMessage, index$3 as sendMessageAGUI };
120
150
  }
121
151
 
122
- export { type AgentCreator, type AgentCreatorContext, index as agui, createExpressRoutes, createExpressServer, run };
152
+ /**
153
+ * Generates a unique request ID for tracing.
154
+ *
155
+ * The request ID is used to:
156
+ * 1. Correlate all logs from a single request
157
+ * 2. Include in error responses for debugging
158
+ * 3. Trace requests across distributed systems
159
+ *
160
+ * @param prefix - Optional prefix for the request ID (default: 'req')
161
+ * @returns A unique request ID string
162
+ *
163
+ * @example
164
+ * generateRequestId() // => 'req-a1b2c3d4-e5f6-7890-abcd-ef1234567890'
165
+ * generateRequestId('agui') // => 'agui-a1b2c3d4-e5f6-7890-abcd-ef1234567890'
166
+ */
167
+ declare function generateRequestId(prefix?: string): string;
168
+ /**
169
+ * Extracts request ID from incoming request headers.
170
+ * Supports common request ID header conventions.
171
+ *
172
+ * Header priority (first found wins):
173
+ * 1. x-request-id
174
+ * 2. x-correlation-id
175
+ * 3. x-trace-id
176
+ *
177
+ * @param headers - Request headers (Headers object or plain object)
178
+ * @returns The request ID from headers, or undefined if not found
179
+ */
180
+ declare function extractRequestId(headers: Headers | Record<string, string | string[] | undefined>): string | undefined;
181
+ /**
182
+ * Gets or generates a request ID.
183
+ * First tries to extract from headers, then generates a new one.
184
+ *
185
+ * @param headers - Request headers
186
+ * @param prefix - Prefix for generated IDs (default: 'req')
187
+ * @returns Request ID (either extracted or generated)
188
+ */
189
+ declare function getOrGenerateRequestId(headers: Headers | Record<string, string | string[] | undefined>, prefix?: string): string;
190
+
191
+ export { type AgentCreator, type AgentCreatorContext, index as agui, createExpressRoutes, createExpressServer, extractRequestId, generateRequestId, getOrGenerateRequestId, run };
package/dist/index.js CHANGED
@@ -30,8 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
32
  agui: () => agui_exports,
33
+ createConsoleLogger: () => import_agent_shared2.createConsoleLogger,
33
34
  createExpressRoutes: () => createExpressRoutes,
34
35
  createExpressServer: () => createExpressServer,
36
+ extractRequestId: () => extractRequestId,
37
+ generateRequestId: () => generateRequestId,
38
+ getOrGenerateRequestId: () => getOrGenerateRequestId,
39
+ noopLogger: () => import_agent_shared2.noopLogger,
35
40
  run: () => run
36
41
  });
37
42
  module.exports = __toCommonJS(index_exports);
@@ -231,36 +236,173 @@ function handler2(input, agent) {
231
236
  // src/agui/sendMessageAGUI/server.ts
232
237
  var import_server3 = require("@whatwg-node/server");
233
238
  var import_client2 = require("@ag-ui/client");
234
- function createServerAdapter2(createAgent) {
239
+ var import_uuid3 = require("uuid");
240
+
241
+ // src/logger/index.ts
242
+ var import_agent_shared2 = require("@cloudbase/agent-shared");
243
+
244
+ // src/logger/request-id.ts
245
+ var import_uuid2 = require("uuid");
246
+ function generateRequestId(prefix = "req") {
247
+ return `${prefix}-${(0, import_uuid2.v4)()}`;
248
+ }
249
+ function extractRequestId(headers) {
250
+ const headerNames = ["x-request-id", "x-correlation-id", "x-trace-id"];
251
+ for (const name of headerNames) {
252
+ let value;
253
+ if (headers instanceof Headers) {
254
+ value = headers.get(name) || void 0;
255
+ } else {
256
+ const raw = headers[name];
257
+ value = Array.isArray(raw) ? raw[0] : raw;
258
+ }
259
+ if (value) {
260
+ return value;
261
+ }
262
+ }
263
+ return void 0;
264
+ }
265
+ function getOrGenerateRequestId(headers, prefix = "req") {
266
+ return extractRequestId(headers) || generateRequestId(prefix);
267
+ }
268
+
269
+ // src/agui/sendMessageAGUI/server.ts
270
+ function createServerAdapter2(createAgent, options) {
271
+ var _a;
272
+ const { logger: parentLogger = import_agent_shared2.noopLogger } = options ?? {};
273
+ const adapterLogger = ((_a = parentLogger.child) == null ? void 0 : _a.call(parentLogger, { component: "sendMessageAGUI" })) ?? parentLogger;
235
274
  return (0, import_server3.createServerAdapter)(async (request) => {
236
- const input = import_client2.RunAgentInputSchema.parse(await request.json());
237
- const { agent: unknownAgent, cleanup } = await Promise.resolve(
238
- createAgent({ request })
275
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
276
+ const requestId = getOrGenerateRequestId(request.headers, "agui");
277
+ const logger = ((_a2 = adapterLogger.child) == null ? void 0 : _a2.call(adapterLogger, { requestId })) ?? adapterLogger;
278
+ (_b = logger.info) == null ? void 0 : _b.call(logger, "Request received");
279
+ const inputRes = await safeAsync(async () => {
280
+ const rawInput = await request.json();
281
+ const inputWithDefaults = {
282
+ tools: [],
283
+ context: [],
284
+ state: {},
285
+ forwardedProps: {},
286
+ ...rawInput,
287
+ runId: typeof rawInput.runId === "string" && rawInput.runId ? rawInput.runId : (0, import_uuid3.v4)()
288
+ };
289
+ return import_client2.RunAgentInputSchema.parse(inputWithDefaults);
290
+ });
291
+ if ("error" in inputRes) {
292
+ const { error } = inputRes;
293
+ (_c = logger.warn) == null ? void 0 : _c.call(
294
+ logger,
295
+ { err: error instanceof Error ? error.message : String(error) },
296
+ "Input validation failed"
297
+ );
298
+ return new Response(
299
+ JSON.stringify({
300
+ error: error instanceof Error ? error.message : String(error),
301
+ requestId
302
+ }),
303
+ {
304
+ status: 400,
305
+ headers: { "Content-Type": "application/json" }
306
+ }
307
+ );
308
+ }
309
+ const input = inputRes.result;
310
+ const lastUserMessage = input.messages.filter((m) => m.role === "user").pop();
311
+ (_f = logger.debug) == null ? void 0 : _f.call(
312
+ logger,
313
+ {
314
+ runId: input.runId,
315
+ threadId: input.threadId,
316
+ messageCount: input.messages.length,
317
+ toolCount: ((_d = input.tools) == null ? void 0 : _d.length) ?? 0,
318
+ tools: (_e = input.tools) == null ? void 0 : _e.map((t) => t.name),
319
+ lastUserMessage: typeof (lastUserMessage == null ? void 0 : lastUserMessage.content) === "string" ? lastUserMessage.content.slice(0, 200) : void 0
320
+ },
321
+ "Input validated"
239
322
  );
240
- const agent = "toAGUIAgent" in unknownAgent ? unknownAgent.toAGUIAgent() : unknownAgent;
241
- const events = handler2(input, agent);
323
+ (_g = logger.trace) == null ? void 0 : _g.call(logger, { input }, "Full request input");
324
+ const createAgentRes = await safeAsync(async () => {
325
+ const res = await Promise.resolve(
326
+ createAgent({ request, logger, requestId })
327
+ );
328
+ return {
329
+ cleanup: res.cleanup,
330
+ agent: "toAGUIAgent" in res.agent ? res.agent.toAGUIAgent() : res.agent
331
+ };
332
+ });
333
+ if ("error" in createAgentRes) {
334
+ const { error } = createAgentRes;
335
+ (_h = logger.error) == null ? void 0 : _h.call(logger, { err: error }, "Agent creation failed");
336
+ return new Response(
337
+ JSON.stringify({
338
+ error: error instanceof Error ? error.message : String(error),
339
+ requestId
340
+ }),
341
+ {
342
+ status: 500,
343
+ headers: { "Content-Type": "application/json" }
344
+ }
345
+ );
346
+ }
347
+ const events = handler2(inputRes.result, createAgentRes.result.agent);
242
348
  let heartbeat;
349
+ let cleanupCalled = false;
350
+ const safeCleanup = () => {
351
+ var _a3, _b2, _c2;
352
+ if (!cleanupCalled) {
353
+ cleanupCalled = true;
354
+ try {
355
+ (_b2 = (_a3 = createAgentRes.result).cleanup) == null ? void 0 : _b2.call(_a3);
356
+ } catch (e) {
357
+ (_c2 = logger.error) == null ? void 0 : _c2.call(logger, { err: e }, "Cleanup error");
358
+ }
359
+ }
360
+ };
243
361
  const stream = new ReadableStream({
244
362
  async start(controller) {
363
+ var _a3, _b2, _c2, _d2;
245
364
  const encoder = new TextEncoder();
246
365
  heartbeat = setInterval(() => {
247
366
  controller.enqueue(encoder.encode(":ping\n\n"));
248
367
  }, 15 * 1e3);
368
+ let eventCount = 0;
249
369
  try {
250
370
  for await (const event of events) {
371
+ eventCount++;
372
+ (_a3 = logger.debug) == null ? void 0 : _a3.call(
373
+ logger,
374
+ { eventType: event.type, eventCount },
375
+ "Emitting SSE event"
376
+ );
377
+ (_b2 = logger.trace) == null ? void 0 : _b2.call(logger, { aguiEvent: event }, "SSE event content");
251
378
  const sseChunk = `data: ${JSON.stringify(event)}
252
379
 
253
380
  `;
254
381
  controller.enqueue(encoder.encode(sseChunk));
255
382
  }
383
+ (_c2 = logger.info) == null ? void 0 : _c2.call(logger, { eventCount }, "Request completed");
384
+ } catch (error) {
385
+ (_d2 = logger.error) == null ? void 0 : _d2.call(logger, { err: error }, "Stream error");
386
+ const errorEvent = {
387
+ type: import_client2.EventType.RUN_ERROR,
388
+ message: error instanceof Error ? error.message : String(error)
389
+ };
390
+ controller.enqueue(
391
+ encoder.encode(`data: ${JSON.stringify(errorEvent)}
392
+
393
+ `)
394
+ );
256
395
  } finally {
257
396
  if (heartbeat) clearInterval(heartbeat);
258
397
  controller.close();
259
- cleanup == null ? void 0 : cleanup();
398
+ safeCleanup();
260
399
  }
261
400
  },
262
401
  cancel() {
402
+ var _a3;
403
+ (_a3 = logger.info) == null ? void 0 : _a3.call(logger, "Request cancelled by client");
263
404
  if (heartbeat) clearInterval(heartbeat);
405
+ safeCleanup();
264
406
  }
265
407
  });
266
408
  const headers = new Headers({
@@ -271,6 +413,15 @@ function createServerAdapter2(createAgent) {
271
413
  return new Response(stream, { status: 200, headers });
272
414
  });
273
415
  }
416
+ async function safeAsync(fn) {
417
+ try {
418
+ return {
419
+ result: await fn()
420
+ };
421
+ } catch (error) {
422
+ return { error };
423
+ }
424
+ }
274
425
 
275
426
  // src/agui/healthz/index.ts
276
427
  var healthz_exports = {};
@@ -288,7 +439,7 @@ __export(openai_exports, {
288
439
  });
289
440
 
290
441
  // src/agui/openai/handler.ts
291
- var import_uuid2 = require("uuid");
442
+ var import_uuid4 = require("uuid");
292
443
  var import_repeater3 = require("@repeaterjs/repeater");
293
444
  function handler3(input, agent) {
294
445
  var _a;
@@ -300,12 +451,12 @@ function handler3(input, agent) {
300
451
  description: tool.function.description,
301
452
  parameters: tool.function.parameters
302
453
  })),
303
- conversationId: (0, import_uuid2.v4)()
454
+ conversationId: (0, import_uuid4.v4)()
304
455
  },
305
456
  agent
306
457
  );
307
458
  return new import_repeater3.Repeater(async (push, stop) => {
308
- const id = (0, import_uuid2.v4)();
459
+ const id = (0, import_uuid4.v4)();
309
460
  let tools = [];
310
461
  let lastWithToolCall = false;
311
462
  let maxIndex = 0;
@@ -502,16 +653,22 @@ function createExpressRoutes({
502
653
  basePath: _basePath,
503
654
  express,
504
655
  useAGUI: _useAGUI,
505
- aguiOptions
656
+ aguiOptions,
657
+ logger: _logger
506
658
  }) {
659
+ var _a, _b, _c;
507
660
  const useAGUI = _useAGUI ?? true;
661
+ const logger = _logger ?? import_agent_shared2.noopLogger;
508
662
  const basePath = _basePath ?? (process.env.TENCENTCLOUD_RUNENV === "SCF" ? "/v1/aibot/bots/:agentId/" : "/");
509
- const sendMessageServerAdapter = useAGUI ? sendMessageAGUI_exports.createServerAdapter(createAgent) : sendMessage_exports.createServerAdapter(createAgent);
663
+ const serverLogger = ((_a = logger.child) == null ? void 0 : _a.call(logger, { component: "server" })) ?? logger;
664
+ (_b = serverLogger.debug) == null ? void 0 : _b.call(serverLogger, { basePath, useAGUI }, "Initializing server routes");
665
+ const sendMessageServerAdapter = useAGUI ? sendMessageAGUI_exports.createServerAdapter(createAgent, { logger: serverLogger }) : sendMessage_exports.createServerAdapter(createAgent);
510
666
  if (useAGUI) {
511
667
  createAGUIRoute({
512
668
  basePath,
513
669
  express,
514
670
  createAgent,
671
+ logger: serverLogger,
515
672
  ...aguiOptions || {}
516
673
  });
517
674
  }
@@ -520,6 +677,7 @@ function createExpressRoutes({
520
677
  express.use(`${basePath}send-message`, sendMessageServerAdapter);
521
678
  express.use(`${basePath}healthz`, healthzServerAdapter);
522
679
  express.use(`${basePath}chat/completions`, openaiServerAdapter);
680
+ (_c = serverLogger.info) == null ? void 0 : _c.call(serverLogger, { basePath }, "Server routes initialized");
523
681
  return express;
524
682
  }
525
683
  var AGUIRpcHandlerPromise = null;
@@ -528,11 +686,13 @@ function getAGUIRpcHandler({
528
686
  runtimeOptions,
529
687
  basePath,
530
688
  endpointOptions,
531
- request
689
+ request,
690
+ logger,
691
+ requestId
532
692
  }) {
533
693
  if (AGUIRpcHandlerPromise) return AGUIRpcHandlerPromise;
534
694
  AGUIRpcHandlerPromise = (async () => {
535
- const { agent } = await createAgent({ request });
695
+ const { agent } = await createAgent({ request, logger, requestId });
536
696
  const templateAgent = "toAGUIAgent" in agent ? agent.toAGUIAgent() : agent;
537
697
  templateAgent.clone = agentCloneFn;
538
698
  const runtime = new import_runtime.CopilotRuntime({
@@ -555,12 +715,21 @@ function createAGUIRoute({
555
715
  basePath,
556
716
  createAgent,
557
717
  runtimeOptions,
558
- endpointOptions
718
+ endpointOptions,
719
+ logger
559
720
  }) {
721
+ var _a;
722
+ const routeLogger = ((_a = logger.child) == null ? void 0 : _a.call(logger, { component: "agui-route" })) ?? logger;
560
723
  express.post(`${basePath}agui`, import_express.default.json(), async (req, res) => {
724
+ var _a2, _b;
561
725
  const webRequest = (0, import_server8.normalizeNodeRequest)(req, DefaultFetchAPI);
726
+ const requestId = getOrGenerateRequestId(webRequest.headers, "agui");
727
+ const requestLogger = ((_a2 = routeLogger.child) == null ? void 0 : _a2.call(routeLogger, { requestId })) ?? routeLogger;
728
+ (_b = requestLogger.info) == null ? void 0 : _b.call(requestLogger, { path: `${basePath}agui` }, "Request received");
562
729
  const { agent: rawAgent, cleanup } = await createAgent({
563
- request: webRequest
730
+ request: webRequest,
731
+ logger: requestLogger,
732
+ requestId
564
733
  });
565
734
  const preparedAgent = "toAGUIAgent" in rawAgent ? rawAgent.toAGUIAgent() : rawAgent;
566
735
  preparedAgent.clone = agentCloneFn;
@@ -569,7 +738,9 @@ function createAGUIRoute({
569
738
  basePath,
570
739
  runtimeOptions,
571
740
  endpointOptions,
572
- request: webRequest
741
+ request: webRequest,
742
+ logger: requestLogger,
743
+ requestId
573
744
  });
574
745
  preparedAgentStorage.run(preparedAgent, () => {
575
746
  rpcHandler(req, res);
@@ -585,7 +756,12 @@ function isCorsOptions(cors2) {
585
756
  // Annotate the CommonJS export names for ESM import in node:
586
757
  0 && (module.exports = {
587
758
  agui,
759
+ createConsoleLogger,
588
760
  createExpressRoutes,
589
761
  createExpressServer,
762
+ extractRequestId,
763
+ generateRequestId,
764
+ getOrGenerateRequestId,
765
+ noopLogger,
590
766
  run
591
767
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/agent-server",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist/",
@@ -21,7 +21,7 @@
21
21
  "openai": "6.3.0",
22
22
  "uuid": "^10.0.0",
23
23
  "zod": "^4.1.12",
24
- "@cloudbase/agent-shared": "^0.0.11"
24
+ "@cloudbase/agent-shared": "^0.0.13"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/cors": "^2.8.19",