@cicctencent/agent-server 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +93 -16
  2. package/dist/cjs/agent/agent-server.d.ts.map +1 -1
  3. package/dist/cjs/agent/agent-server.js +50 -15
  4. package/dist/cjs/agent/agent-server.js.map +1 -1
  5. package/dist/cjs/index.d.ts +2 -0
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js +23 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/service/cache.service.d.ts +69 -0
  10. package/dist/cjs/service/cache.service.d.ts.map +1 -0
  11. package/dist/cjs/service/cache.service.js +243 -0
  12. package/dist/cjs/service/cache.service.js.map +1 -0
  13. package/dist/cjs/service/engine-pool.d.ts +15 -2
  14. package/dist/cjs/service/engine-pool.d.ts.map +1 -1
  15. package/dist/cjs/service/engine-pool.js +15 -4
  16. package/dist/cjs/service/engine-pool.js.map +1 -1
  17. package/dist/cjs/spi/adapters.d.ts +163 -0
  18. package/dist/cjs/spi/adapters.d.ts.map +1 -0
  19. package/dist/cjs/spi/adapters.js +341 -0
  20. package/dist/cjs/spi/adapters.js.map +1 -0
  21. package/dist/cjs/spi/examples/typeorm-example.d.ts +208 -0
  22. package/dist/cjs/spi/examples/typeorm-example.d.ts.map +1 -0
  23. package/dist/cjs/spi/examples/typeorm-example.js +274 -0
  24. package/dist/cjs/spi/examples/typeorm-example.js.map +1 -0
  25. package/dist/cjs/spi/index.d.ts +194 -0
  26. package/dist/cjs/spi/index.d.ts.map +1 -0
  27. package/dist/cjs/spi/index.js +227 -0
  28. package/dist/cjs/spi/index.js.map +1 -0
  29. package/dist/cjs/spi/storage.d.ts +109 -0
  30. package/dist/cjs/spi/storage.d.ts.map +1 -0
  31. package/dist/cjs/spi/storage.js +344 -0
  32. package/dist/cjs/spi/storage.js.map +1 -0
  33. package/dist/cjs/spi/types.d.ts +317 -0
  34. package/dist/cjs/spi/types.d.ts.map +1 -0
  35. package/dist/cjs/spi/types.js +6 -0
  36. package/dist/cjs/spi/types.js.map +1 -0
  37. package/dist/cjs/types.d.ts +63 -8
  38. package/dist/cjs/types.d.ts.map +1 -1
  39. package/dist/esm/agent/agent-server.d.ts.map +1 -1
  40. package/dist/esm/agent/agent-server.js +50 -15
  41. package/dist/esm/agent/agent-server.js.map +1 -1
  42. package/dist/esm/index.d.ts +2 -0
  43. package/dist/esm/index.d.ts.map +1 -1
  44. package/dist/esm/index.js +8 -0
  45. package/dist/esm/index.js.map +1 -1
  46. package/dist/esm/service/cache.service.d.ts +69 -0
  47. package/dist/esm/service/cache.service.d.ts.map +1 -0
  48. package/dist/esm/service/cache.service.js +237 -0
  49. package/dist/esm/service/cache.service.js.map +1 -0
  50. package/dist/esm/service/engine-pool.d.ts +15 -2
  51. package/dist/esm/service/engine-pool.d.ts.map +1 -1
  52. package/dist/esm/service/engine-pool.js +15 -4
  53. package/dist/esm/service/engine-pool.js.map +1 -1
  54. package/dist/esm/spi/adapters.d.ts +163 -0
  55. package/dist/esm/spi/adapters.d.ts.map +1 -0
  56. package/dist/esm/spi/adapters.js +329 -0
  57. package/dist/esm/spi/adapters.js.map +1 -0
  58. package/dist/esm/spi/examples/typeorm-example.d.ts +208 -0
  59. package/dist/esm/spi/examples/typeorm-example.d.ts.map +1 -0
  60. package/dist/esm/spi/examples/typeorm-example.js +315 -0
  61. package/dist/esm/spi/examples/typeorm-example.js.map +1 -0
  62. package/dist/esm/spi/index.d.ts +194 -0
  63. package/dist/esm/spi/index.d.ts.map +1 -0
  64. package/dist/esm/spi/index.js +215 -0
  65. package/dist/esm/spi/index.js.map +1 -0
  66. package/dist/esm/spi/storage.d.ts +109 -0
  67. package/dist/esm/spi/storage.d.ts.map +1 -0
  68. package/dist/esm/spi/storage.js +301 -0
  69. package/dist/esm/spi/storage.js.map +1 -0
  70. package/dist/esm/spi/types.d.ts +317 -0
  71. package/dist/esm/spi/types.d.ts.map +1 -0
  72. package/dist/esm/spi/types.js +5 -0
  73. package/dist/esm/spi/types.js.map +1 -0
  74. package/dist/esm/types.d.ts +63 -8
  75. package/dist/esm/types.d.ts.map +1 -1
  76. package/package.json +1 -1
@@ -0,0 +1,208 @@
1
+ import type { ChatStoreProvider, BaseThreadEntity, BaseMessageEntity, BaseSettingsEntity, ListStorageAdapter } from '../types.js';
2
+ /**
3
+ * BI 项目的 Thread 实体(TypeORM)
4
+ * 注意:字段可能与 agent-server 默认实体不同
5
+ */
6
+ interface BIThreadEntity extends BaseThreadEntity {
7
+ id: number;
8
+ workspaceId?: number;
9
+ userId?: number;
10
+ agentType?: string;
11
+ modelConfig?: string;
12
+ createdAt: Date;
13
+ updatedAt: Date;
14
+ }
15
+ /**
16
+ * BI 项目的 Message 实体(TypeORM)
17
+ */
18
+ interface BIMessageEntity extends BaseMessageEntity {
19
+ id: number;
20
+ threadId: number;
21
+ tokens?: number;
22
+ latency?: number;
23
+ model?: string;
24
+ createdAt: Date;
25
+ }
26
+ /**
27
+ * BI 项目的 Settings 实体
28
+ */
29
+ interface BISettingsEntity extends BaseSettingsEntity {
30
+ id: number;
31
+ userId: number;
32
+ theme: string;
33
+ language: string;
34
+ modelProviders: Array<{
35
+ id: string;
36
+ name: string;
37
+ provider: string;
38
+ model: string;
39
+ apiKey?: string;
40
+ baseUrl?: string;
41
+ }>;
42
+ createdAt: Date;
43
+ updatedAt: Date;
44
+ }
45
+ /**
46
+ * TypeORM 列表存储适配器
47
+ * 将 TypeORM Repository 包装为 ListStorageAdapter
48
+ */
49
+ declare class TypeORMListStorage<T extends {
50
+ id: number | string;
51
+ }> implements ListStorageAdapter<T> {
52
+ private data;
53
+ list(): Promise<T[]>;
54
+ findById(id: number | string): Promise<T | null>;
55
+ add(entity: T): Promise<T>;
56
+ update(id: number | string, data: Partial<T>): Promise<T | null>;
57
+ remove(id: number | string): Promise<boolean>;
58
+ }
59
+ /**
60
+ * BI 项目的 ChatStoreProvider 实现
61
+ * 使用 TypeORM Repository 作为底层存储
62
+ */
63
+ declare class TypeORMChatStoreProvider implements ChatStoreProvider<BIThreadEntity, BIMessageEntity> {
64
+ private threadStorage;
65
+ private messageStorages;
66
+ constructor();
67
+ private getMessageStorage;
68
+ getThreads(workspaceId?: number | string): Promise<BIThreadEntity[]>;
69
+ getThread(id: number | string): Promise<BIThreadEntity | undefined>;
70
+ createThread(data: Partial<BIThreadEntity>): Promise<BIThreadEntity>;
71
+ updateThread(id: number | string, data: Partial<BIThreadEntity>): Promise<BIThreadEntity | undefined>;
72
+ deleteThread(id: number | string): Promise<boolean>;
73
+ getMessages(threadId: number | string, options?: {
74
+ limit?: number;
75
+ offset?: number;
76
+ }): Promise<{
77
+ items: BIMessageEntity[];
78
+ total: number;
79
+ hasMore: boolean;
80
+ }>;
81
+ addMessage(data: Partial<BIMessageEntity> & {
82
+ threadId: number | string;
83
+ role: string;
84
+ content: string;
85
+ }): Promise<BIMessageEntity>;
86
+ updateMessage(threadId: number | string, id: number | string, data: Partial<BIMessageEntity>): Promise<BIMessageEntity | undefined>;
87
+ deleteMessage(threadId: number | string, id: number | string): Promise<boolean>;
88
+ clearThreadMessages(threadId: number | string): Promise<void>;
89
+ buildThreadHistory(threadId: number | string, limit?: number): Promise<any[]>;
90
+ }
91
+ /**
92
+ * MidwayJS Agent 服务示例
93
+ * 使用 SPI 适配到 MidwayJS + TypeORM
94
+ *
95
+ * 在实际项目中,这会是:
96
+ *
97
+ * @Provide()
98
+ * @Scope(ScopeEnum.Singleton)
99
+ * export class AgentService {
100
+ * @Inject()
101
+ * threadRepository: Repository<BIThreadEntity>;
102
+ *
103
+ * @Inject()
104
+ * messageRepository: Repository<BIMessageEntity>;
105
+ *
106
+ * private server: AgentServer;
107
+ *
108
+ * @Init()
109
+ * async init() {
110
+ * const chatStoreProvider = new TypeORMChatStoreProvider(
111
+ * this.threadRepository,
112
+ * this.messageRepository
113
+ * );
114
+ *
115
+ * this.server = createAgentServer({
116
+ * llmProvider: await this.createLLMProvider(),
117
+ * chatStoreProvider,
118
+ * // 使用 Koa 适配器
119
+ * createSSEResponseAdapter: (ctx) => new KoaSSEAdapter(ctx),
120
+ * });
121
+ * }
122
+ *
123
+ * @Get('/chat/stream')
124
+ * async chatStream(@Ctx() ctx: Context, @Query() query: { message: string }) {
125
+ * const adapter = new KoaSSEAdapter(ctx);
126
+ * await this.server.runAgentStream(adapter, { content: query.message });
127
+ * }
128
+ * }
129
+ */
130
+ export { TypeORMListStorage, TypeORMChatStoreProvider, BIThreadEntity, BIMessageEntity, BISettingsEntity, };
131
+ /**
132
+ * ## 使用说明
133
+ *
134
+ * ### 1. 在 MidwayJS 项目中使用 agent-server
135
+ *
136
+ * ```typescript
137
+ * // src/service/agent.service.ts
138
+ * import { Provide, Scope, ScopeEnum, Inject, Init, Get, Ctx, Query } from '@midwayjs/core';
139
+ * import { Context } from '@midwayjs/koa';
140
+ * import { createAgentServer, KoaSSEAdapter, type AgentServer } from '@cicctencent/agent-server';
141
+ * import { TypeORMChatStoreProvider } from './spi/typeorm-chat-provider';
142
+ *
143
+ * @Provide()
144
+ * @Scope(ScopeEnum.Singleton)
145
+ * export class AgentService {
146
+ * @Inject()
147
+ * threadRepository: Repository<ThreadEntity>;
148
+ *
149
+ * @Inject()
150
+ * messageRepository: Repository<MessageEntity>;
151
+ *
152
+ * private server: AgentServer;
153
+ *
154
+ * @Init()
155
+ * async init() {
156
+ * // 使用 TypeORM 存储适配器
157
+ * const chatStoreProvider = new TypeORMChatStoreProvider(
158
+ * this.threadRepository,
159
+ * this.messageRepository
160
+ * );
161
+ *
162
+ * this.server = createAgentServer({
163
+ * llmProvider: await this.createLLMProvider(),
164
+ * chatStoreProvider, // 替换默认 JSON 文件存储
165
+ * });
166
+ * }
167
+ *
168
+ * @Get('/chat/stream')
169
+ * async chatStream(@Ctx() ctx: Context, @Query() query: { message: string }) {
170
+ * // 使用 Koa/MidwayJS SSE 适配器
171
+ * const adapter = new KoaSSEAdapter(ctx);
172
+ * await this.server.runAgentStream(adapter, { content: query.message });
173
+ * }
174
+ * }
175
+ * ```
176
+ *
177
+ * ### 2. 自定义实体字段
178
+ *
179
+ * agent-server 现在支持泛型实体类型,你可以:
180
+ * - 使用自己的实体结构(如 TypeORM 实体)
181
+ * - 自定义字段(如 userId, modelConfig 等)
182
+ * - 使用不同的 ID 类型(number / string / UUID)
183
+ *
184
+ * ### 3. 组件级使用(不依赖工厂)
185
+ *
186
+ * 如果不想使用 createAgentServer 工厂,可以只导入需要的组件:
187
+ *
188
+ * ```typescript
189
+ * import {
190
+ * MemoryService,
191
+ * writeSSE,
192
+ * createBuiltinTools,
193
+ * KoaSSEAdapter
194
+ * } from '@cicctencent/agent-server';
195
+ *
196
+ * // 只使用需要的组件
197
+ * const memoryService = new MemoryService('./data');
198
+ * const tools = createBuiltinTools();
199
+ *
200
+ * // 在 MidwayJS 中使用 SSE
201
+ * @Get('/stream')
202
+ * async stream(@Ctx() ctx: Context) {
203
+ * const adapter = new KoaSSEAdapter(ctx);
204
+ * writeSSE(adapter, 'start', { message: 'Hello' });
205
+ * }
206
+ * ```
207
+ */
208
+ //# sourceMappingURL=typeorm-example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm-example.d.ts","sourceRoot":"","sources":["../../../../src/spi/examples/typeorm-example.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,315 @@
1
+ // ============================================================
2
+ // TypeORM SPI 实现示例 — BI 项目可参考此实现
3
+ // ============================================================
4
+ // ============================================================
5
+ // TypeORM 存储适配器实现
6
+ // ============================================================
7
+ /**
8
+ * TypeORM 列表存储适配器
9
+ * 将 TypeORM Repository 包装为 ListStorageAdapter
10
+ */
11
+ class TypeORMListStorage {
12
+ // 在实际项目中,这里会是 TypeORM Repository
13
+ // constructor(private repository: Repository<T>) {}
14
+ // 模拟 TypeORM Repository(示例)
15
+ data = [];
16
+ async list() {
17
+ // 实际实现: return this.repository.find();
18
+ return this.data;
19
+ }
20
+ async findById(id) {
21
+ // 实际实现: return this.repository.findOne({ where: { id } });
22
+ return this.data.find(item => item.id === id) ?? null;
23
+ }
24
+ async add(entity) {
25
+ // 实际实现: return this.repository.save(entity);
26
+ this.data.push(entity);
27
+ return entity;
28
+ }
29
+ async update(id, data) {
30
+ // 实际实现:
31
+ // const entity = await this.repository.findOne({ where: { id } });
32
+ // if (!entity) return null;
33
+ // Object.assign(entity, data);
34
+ // return this.repository.save(entity);
35
+ const idx = this.data.findIndex(item => item.id === id);
36
+ if (idx === -1)
37
+ return null;
38
+ this.data[idx] = { ...this.data[idx], ...data };
39
+ return this.data[idx];
40
+ }
41
+ async remove(id) {
42
+ // 实际实现:
43
+ // const result = await this.repository.delete(id);
44
+ // return result.affected > 0;
45
+ const idx = this.data.findIndex(item => item.id === id);
46
+ if (idx === -1)
47
+ return false;
48
+ this.data.splice(idx, 1);
49
+ return true;
50
+ }
51
+ }
52
+ // ============================================================
53
+ // TypeORM ChatStoreProvider 实现
54
+ // ============================================================
55
+ /**
56
+ * BI 项目的 ChatStoreProvider 实现
57
+ * 使用 TypeORM Repository 作为底层存储
58
+ */
59
+ class TypeORMChatStoreProvider {
60
+ // 在实际项目中,这里会是 TypeORM Repository
61
+ threadStorage;
62
+ messageStorages = new Map();
63
+ constructor(
64
+ // threadRepository: Repository<BIThreadEntity>,
65
+ // messageRepository: Repository<BIMessageEntity>
66
+ ) {
67
+ this.threadStorage = new TypeORMListStorage();
68
+ }
69
+ getMessageStorage(threadId) {
70
+ if (!this.messageStorages.has(threadId)) {
71
+ this.messageStorages.set(threadId, new TypeORMListStorage());
72
+ }
73
+ return this.messageStorages.get(threadId);
74
+ }
75
+ // ===== Thread CRUD =====
76
+ // 注意:TypeORM 实现使用异步方法
77
+ async getThreads(workspaceId) {
78
+ // 实际 TypeORM 实现:
79
+ // if (workspaceId) {
80
+ // return this.threadRepository.find({ where: { workspaceId } });
81
+ // }
82
+ // return this.threadRepository.find();
83
+ const all = await this.threadStorage.list();
84
+ return all;
85
+ }
86
+ async getThread(id) {
87
+ // 实际 TypeORM 实现:
88
+ // return this.threadRepository.findOne({ where: { id } });
89
+ const result = await this.threadStorage.findById(id);
90
+ return result;
91
+ }
92
+ async createThread(data) {
93
+ // 实际 TypeORM 实现:
94
+ // const thread = this.threadRepository.create(data);
95
+ // return this.threadRepository.save(thread);
96
+ const now = new Date();
97
+ const thread = {
98
+ id: Date.now(),
99
+ title: data.title || '新对话',
100
+ workspaceId: data.workspaceId,
101
+ userId: data.userId,
102
+ status: 'active',
103
+ createdAt: now,
104
+ updatedAt: now,
105
+ };
106
+ await this.threadStorage.add(thread);
107
+ return thread;
108
+ }
109
+ async updateThread(id, data) {
110
+ // 实际 TypeORM 实现:
111
+ // const thread = await this.threadRepository.findOne({ where: { id } });
112
+ // if (!thread) return null;
113
+ // Object.assign(thread, data, { updatedAt: new Date() });
114
+ // return this.threadRepository.save(thread);
115
+ const result = await this.threadStorage.update(id, { ...data, updatedAt: new Date() });
116
+ return result;
117
+ }
118
+ async deleteThread(id) {
119
+ // 实际 TypeORM 实现:
120
+ // const result = await this.threadRepository.delete(id);
121
+ // return result.affected > 0;
122
+ return this.threadStorage.remove(id);
123
+ }
124
+ // ===== Message CRUD =====
125
+ async getMessages(threadId, options) {
126
+ // 实际 TypeORM 实现:
127
+ // const [items, total] = await this.messageRepository.findAndCount({
128
+ // where: { threadId },
129
+ // order: { createdAt: 'DESC' },
130
+ // skip: options?.offset || 0,
131
+ // take: options?.limit || 50,
132
+ // });
133
+ // return { items, total, hasMore: (options?.offset || 0) + items.length < total };
134
+ const storage = this.getMessageStorage(Number(threadId));
135
+ const all = await storage.list();
136
+ const limit = options?.limit || 50;
137
+ const offset = options?.offset || 0;
138
+ const items = all.slice(offset, offset + limit);
139
+ return { items, total: all.length, hasMore: offset + items.length < all.length };
140
+ }
141
+ async addMessage(data) {
142
+ // 实际 TypeORM 实现:
143
+ // const msg = this.messageRepository.create({
144
+ // threadId: data.threadId,
145
+ // role: data.role,
146
+ // content: data.content,
147
+ // createdAt: new Date(),
148
+ // });
149
+ // return this.messageRepository.save(msg);
150
+ const storage = this.getMessageStorage(Number(data.threadId));
151
+ const msg = {
152
+ id: Date.now(),
153
+ threadId: Number(data.threadId),
154
+ role: data.role,
155
+ content: data.content,
156
+ createdAt: new Date(),
157
+ };
158
+ await storage.add(msg);
159
+ return msg;
160
+ }
161
+ async updateMessage(threadId, id, data) {
162
+ // 实际 TypeORM 实现:
163
+ // const msg = await this.messageRepository.findOne({ where: { id, threadId } });
164
+ // if (!msg) return null;
165
+ // Object.assign(msg, data);
166
+ // return this.messageRepository.save(msg);
167
+ const storage = this.getMessageStorage(Number(threadId));
168
+ const result = await storage.update(id, data);
169
+ return result;
170
+ }
171
+ async deleteMessage(threadId, id) {
172
+ // 实际 TypeORM 实现:
173
+ // const result = await this.messageRepository.delete({ id, threadId });
174
+ // return result.affected > 0;
175
+ const storage = this.getMessageStorage(Number(threadId));
176
+ return storage.remove(id);
177
+ }
178
+ async clearThreadMessages(threadId) {
179
+ // 实际 TypeORM 实现:
180
+ // await this.messageRepository.delete({ threadId });
181
+ this.messageStorages.delete(Number(threadId));
182
+ }
183
+ // ===== 历史重建 =====
184
+ async buildThreadHistory(threadId, limit) {
185
+ const { items } = await this.getMessages(threadId, { limit: limit || 20 });
186
+ return items.map(msg => ({
187
+ role: msg.role,
188
+ content: msg.content,
189
+ }));
190
+ }
191
+ }
192
+ // ============================================================
193
+ // MidwayJS 服务实现示例
194
+ // ============================================================
195
+ /**
196
+ * MidwayJS Agent 服务示例
197
+ * 使用 SPI 适配到 MidwayJS + TypeORM
198
+ *
199
+ * 在实际项目中,这会是:
200
+ *
201
+ * @Provide()
202
+ * @Scope(ScopeEnum.Singleton)
203
+ * export class AgentService {
204
+ * @Inject()
205
+ * threadRepository: Repository<BIThreadEntity>;
206
+ *
207
+ * @Inject()
208
+ * messageRepository: Repository<BIMessageEntity>;
209
+ *
210
+ * private server: AgentServer;
211
+ *
212
+ * @Init()
213
+ * async init() {
214
+ * const chatStoreProvider = new TypeORMChatStoreProvider(
215
+ * this.threadRepository,
216
+ * this.messageRepository
217
+ * );
218
+ *
219
+ * this.server = createAgentServer({
220
+ * llmProvider: await this.createLLMProvider(),
221
+ * chatStoreProvider,
222
+ * // 使用 Koa 适配器
223
+ * createSSEResponseAdapter: (ctx) => new KoaSSEAdapter(ctx),
224
+ * });
225
+ * }
226
+ *
227
+ * @Get('/chat/stream')
228
+ * async chatStream(@Ctx() ctx: Context, @Query() query: { message: string }) {
229
+ * const adapter = new KoaSSEAdapter(ctx);
230
+ * await this.server.runAgentStream(adapter, { content: query.message });
231
+ * }
232
+ * }
233
+ */
234
+ // ============================================================
235
+ // 导出示例实现
236
+ // ============================================================
237
+ export { TypeORMListStorage, TypeORMChatStoreProvider, };
238
+ /**
239
+ * ## 使用说明
240
+ *
241
+ * ### 1. 在 MidwayJS 项目中使用 agent-server
242
+ *
243
+ * ```typescript
244
+ * // src/service/agent.service.ts
245
+ * import { Provide, Scope, ScopeEnum, Inject, Init, Get, Ctx, Query } from '@midwayjs/core';
246
+ * import { Context } from '@midwayjs/koa';
247
+ * import { createAgentServer, KoaSSEAdapter, type AgentServer } from '@cicctencent/agent-server';
248
+ * import { TypeORMChatStoreProvider } from './spi/typeorm-chat-provider';
249
+ *
250
+ * @Provide()
251
+ * @Scope(ScopeEnum.Singleton)
252
+ * export class AgentService {
253
+ * @Inject()
254
+ * threadRepository: Repository<ThreadEntity>;
255
+ *
256
+ * @Inject()
257
+ * messageRepository: Repository<MessageEntity>;
258
+ *
259
+ * private server: AgentServer;
260
+ *
261
+ * @Init()
262
+ * async init() {
263
+ * // 使用 TypeORM 存储适配器
264
+ * const chatStoreProvider = new TypeORMChatStoreProvider(
265
+ * this.threadRepository,
266
+ * this.messageRepository
267
+ * );
268
+ *
269
+ * this.server = createAgentServer({
270
+ * llmProvider: await this.createLLMProvider(),
271
+ * chatStoreProvider, // 替换默认 JSON 文件存储
272
+ * });
273
+ * }
274
+ *
275
+ * @Get('/chat/stream')
276
+ * async chatStream(@Ctx() ctx: Context, @Query() query: { message: string }) {
277
+ * // 使用 Koa/MidwayJS SSE 适配器
278
+ * const adapter = new KoaSSEAdapter(ctx);
279
+ * await this.server.runAgentStream(adapter, { content: query.message });
280
+ * }
281
+ * }
282
+ * ```
283
+ *
284
+ * ### 2. 自定义实体字段
285
+ *
286
+ * agent-server 现在支持泛型实体类型,你可以:
287
+ * - 使用自己的实体结构(如 TypeORM 实体)
288
+ * - 自定义字段(如 userId, modelConfig 等)
289
+ * - 使用不同的 ID 类型(number / string / UUID)
290
+ *
291
+ * ### 3. 组件级使用(不依赖工厂)
292
+ *
293
+ * 如果不想使用 createAgentServer 工厂,可以只导入需要的组件:
294
+ *
295
+ * ```typescript
296
+ * import {
297
+ * MemoryService,
298
+ * writeSSE,
299
+ * createBuiltinTools,
300
+ * KoaSSEAdapter
301
+ * } from '@cicctencent/agent-server';
302
+ *
303
+ * // 只使用需要的组件
304
+ * const memoryService = new MemoryService('./data');
305
+ * const tools = createBuiltinTools();
306
+ *
307
+ * // 在 MidwayJS 中使用 SSE
308
+ * @Get('/stream')
309
+ * async stream(@Ctx() ctx: Context) {
310
+ * const adapter = new KoaSSEAdapter(ctx);
311
+ * writeSSE(adapter, 'start', { message: 'Hello' });
312
+ * }
313
+ * ```
314
+ */
315
+ //# sourceMappingURL=typeorm-example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeorm-example.js","sourceRoot":"","sources":["../../../../src/spi/examples/typeorm-example.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,iCAAiC;AACjC,+DAA+D;AAoE/D,+DAA+D;AAC/D,kBAAkB;AAClB,+DAA+D;AAE/D;;;GAGG;AACH,MAAM,kBAAkB;IACtB,iCAAiC;IACjC,oDAAoD;IAEpD,4BAA4B;IACpB,IAAI,GAAQ,EAAE,CAAC;IAEvB,KAAK,CAAC,IAAI;QACR,uCAAuC;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAmB;QAChC,2DAA2D;QAC3D,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAS;QACjB,6CAA6C;QAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAmB,EAAE,IAAgB;QAChD,SAAS;QACT,mEAAmE;QACnE,4BAA4B;QAC5B,+BAA+B;QAC/B,uCAAuC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EAAO,CAAC;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAmB;QAC9B,SAAS;QACT,mDAAmD;QACnD,8BAA8B;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,+DAA+D;AAC/D,+BAA+B;AAC/B,+DAA+D;AAE/D;;;GAGG;AACH,MAAM,wBAAwB;IAC5B,iCAAiC;IACzB,aAAa,CAAqC;IAClD,eAAe,GAAqD,IAAI,GAAG,EAAE,CAAC;IAEtF;IACE,gDAAgD;IAChD,iDAAiD;;QAEjD,IAAI,CAAC,aAAa,GAAG,IAAI,kBAAkB,EAAkB,CAAC;IAChE,CAAC;IAEO,iBAAiB,CAAC,QAAgB;QACxC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,kBAAkB,EAAmB,CAAC,CAAC;QAChF,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;IAC7C,CAAC;IAED,0BAA0B;IAC1B,sBAAsB;IAEtB,KAAK,CAAC,UAAU,CAAC,WAA6B;QAC5C,iBAAiB;QACjB,qBAAqB;QACrB,mEAAmE;QACnE,IAAI;QACJ,uCAAuC;QACvC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,GAAuB,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAmB;QACjC,kBAAkB;QAClB,2DAA2D;QAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,MAAoC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAA6B;QAC9C,iBAAiB;QACjB,qDAAqD;QACrD,6CAA6C;QAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAmB;YAC7B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;YAC1B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;SACf,CAAC;QACF,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAmB,EAAE,IAA6B;QACnE,iBAAiB;QACjB,yEAAyE;QACzE,4BAA4B;QAC5B,0DAA0D;QAC1D,6CAA6C;QAC7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACvF,OAAO,MAAoC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAmB;QACpC,iBAAiB;QACjB,yDAAyD;QACzD,8BAA8B;QAC9B,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,2BAA2B;IAE3B,KAAK,CAAC,WAAW,CAAC,QAAyB,EAAE,OAA6C;QAKxF,iBAAiB;QACjB,qEAAqE;QACrE,yBAAyB;QACzB,kCAAkC;QAClC,gCAAgC;QAChC,gCAAgC;QAChC,MAAM;QACN,mFAAmF;QACnF,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAsB,CAAC;QACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAA6F;QAC5G,iBAAiB;QACjB,8CAA8C;QAC9C,6BAA6B;QAC7B,qBAAqB;QACrB,2BAA2B;QAC3B,2BAA2B;QAC3B,MAAM;QACN,2CAA2C;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9D,MAAM,GAAG,GAAoB;YAC3B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC/B,IAAI,EAAE,IAAI,CAAC,IAAuC;YAClD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QACF,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAyB,EAAE,EAAmB,EAAE,IAA8B;QAChG,iBAAiB;QACjB,iFAAiF;QACjF,yBAAyB;QACzB,4BAA4B;QAC5B,2CAA2C;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC9C,OAAO,MAAqC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAyB,EAAE,EAAmB;QAChE,iBAAiB;QACjB,wEAAwE;QACxE,8BAA8B;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,QAAyB;QACjD,iBAAiB;QACjB,qDAAqD;QACrD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,mBAAmB;IAEnB,KAAK,CAAC,kBAAkB,CAAC,QAAyB,EAAE,KAAc;QAChE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3E,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC,CAAC;IACN,CAAC;CACF;AAED,+DAA+D;AAC/D,kBAAkB;AAClB,+DAA+D;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,+DAA+D;AAC/D,SAAS;AACT,+DAA+D;AAE/D,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAIzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG"}