@huyooo/ai-chat-bridge-elysia 0.1.0 → 0.3.4
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/dist/index.d.ts +88 -643
- package/dist/index.js +1 -395
- package/package.json +23 -15
- package/dist/index.cjs +0 -401
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -653
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,395 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HybridAgent, AVAILABLE_MODELS } from '@huyooo/ai-chat-core';
|
|
3
|
-
export { AVAILABLE_MODELS } from '@huyooo/ai-chat-core';
|
|
4
|
-
import { createStorage } from '@huyooo/ai-chat-storage';
|
|
5
|
-
|
|
6
|
-
// src/index.ts
|
|
7
|
-
var ChatRequestSchema = t.Object({
|
|
8
|
-
message: t.String(),
|
|
9
|
-
sessionId: t.Optional(t.String()),
|
|
10
|
-
images: t.Optional(t.Array(t.String())),
|
|
11
|
-
options: t.Optional(t.Object({
|
|
12
|
-
mode: t.Optional(t.Union([
|
|
13
|
-
t.Literal("agent"),
|
|
14
|
-
t.Literal("plan"),
|
|
15
|
-
t.Literal("ask")
|
|
16
|
-
])),
|
|
17
|
-
model: t.Optional(t.String()),
|
|
18
|
-
provider: t.Optional(t.Union([
|
|
19
|
-
t.Literal("doubao"),
|
|
20
|
-
t.Literal("deepseek")
|
|
21
|
-
])),
|
|
22
|
-
enableWebSearch: t.Optional(t.Boolean()),
|
|
23
|
-
enableDeepThinking: t.Optional(t.Boolean()),
|
|
24
|
-
thinkingBudget: t.Optional(t.Number())
|
|
25
|
-
}))
|
|
26
|
-
});
|
|
27
|
-
var SessionCreateSchema = t.Object({
|
|
28
|
-
title: t.Optional(t.String()),
|
|
29
|
-
model: t.Optional(t.String()),
|
|
30
|
-
mode: t.Optional(t.Union([
|
|
31
|
-
t.Literal("agent"),
|
|
32
|
-
t.Literal("plan"),
|
|
33
|
-
t.Literal("ask")
|
|
34
|
-
]))
|
|
35
|
-
});
|
|
36
|
-
var SessionUpdateSchema = t.Object({
|
|
37
|
-
title: t.Optional(t.String()),
|
|
38
|
-
model: t.Optional(t.String()),
|
|
39
|
-
mode: t.Optional(t.Union([
|
|
40
|
-
t.Literal("agent"),
|
|
41
|
-
t.Literal("plan"),
|
|
42
|
-
t.Literal("ask")
|
|
43
|
-
]))
|
|
44
|
-
});
|
|
45
|
-
var MessageSaveSchema = t.Object({
|
|
46
|
-
sessionId: t.String(),
|
|
47
|
-
role: t.Union([t.Literal("user"), t.Literal("assistant")]),
|
|
48
|
-
content: t.String(),
|
|
49
|
-
thinking: t.Optional(t.String()),
|
|
50
|
-
toolCalls: t.Optional(t.String()),
|
|
51
|
-
searchResults: t.Optional(t.String()),
|
|
52
|
-
operationIds: t.Optional(t.String())
|
|
53
|
-
});
|
|
54
|
-
function extractContext(headers) {
|
|
55
|
-
return {
|
|
56
|
-
appId: headers["x-app-id"] || void 0,
|
|
57
|
-
userId: headers["x-user-id"] || void 0
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
async function createElysiaBridge(options) {
|
|
61
|
-
const { prefix = "/api/chat", storage: storageConfig, ...agentConfig } = options;
|
|
62
|
-
const agent = new HybridAgent(agentConfig);
|
|
63
|
-
const storage = await createStorage(storageConfig || {
|
|
64
|
-
type: "sqlite",
|
|
65
|
-
sqlitePath: "./data/db.sqlite"
|
|
66
|
-
});
|
|
67
|
-
return new Elysia({ prefix }).get("/models", () => ({
|
|
68
|
-
models: AVAILABLE_MODELS
|
|
69
|
-
})).get("/stream", async function* ({ query, headers }) {
|
|
70
|
-
const message = query.message;
|
|
71
|
-
const images = query.images?.split(",").filter(Boolean);
|
|
72
|
-
const chatOptions = {};
|
|
73
|
-
if (query.mode) chatOptions.mode = query.mode;
|
|
74
|
-
if (query.model) chatOptions.model = query.model;
|
|
75
|
-
if (query.provider) chatOptions.provider = query.provider;
|
|
76
|
-
if (query.enableWebSearch !== void 0) {
|
|
77
|
-
chatOptions.enableWebSearch = query.enableWebSearch === "true";
|
|
78
|
-
}
|
|
79
|
-
if (query.thinkingMode) {
|
|
80
|
-
chatOptions.thinkingMode = query.thinkingMode;
|
|
81
|
-
}
|
|
82
|
-
if (query.thinkingBudget) {
|
|
83
|
-
chatOptions.thinkingBudget = parseInt(query.thinkingBudget);
|
|
84
|
-
}
|
|
85
|
-
for await (const progress of agent.chat(message, chatOptions, images)) {
|
|
86
|
-
yield `data: ${JSON.stringify(progress)}
|
|
87
|
-
|
|
88
|
-
`;
|
|
89
|
-
}
|
|
90
|
-
}, {
|
|
91
|
-
query: t.Object({
|
|
92
|
-
message: t.String(),
|
|
93
|
-
images: t.Optional(t.String()),
|
|
94
|
-
mode: t.Optional(t.String()),
|
|
95
|
-
model: t.Optional(t.String()),
|
|
96
|
-
provider: t.Optional(t.String()),
|
|
97
|
-
enableWebSearch: t.Optional(t.String()),
|
|
98
|
-
thinkingMode: t.Optional(t.String()),
|
|
99
|
-
thinkingBudget: t.Optional(t.String())
|
|
100
|
-
})
|
|
101
|
-
}).ws("/ws", {
|
|
102
|
-
body: t.Object({
|
|
103
|
-
type: t.Union([
|
|
104
|
-
t.Literal("chat"),
|
|
105
|
-
t.Literal("abort")
|
|
106
|
-
]),
|
|
107
|
-
message: t.Optional(t.String()),
|
|
108
|
-
images: t.Optional(t.Array(t.String())),
|
|
109
|
-
options: t.Optional(t.Object({
|
|
110
|
-
mode: t.Optional(t.String()),
|
|
111
|
-
model: t.Optional(t.String()),
|
|
112
|
-
provider: t.Optional(t.String()),
|
|
113
|
-
enableWebSearch: t.Optional(t.Boolean()),
|
|
114
|
-
thinkingMode: t.Optional(t.String()),
|
|
115
|
-
thinkingBudget: t.Optional(t.Number())
|
|
116
|
-
}))
|
|
117
|
-
}),
|
|
118
|
-
async message(ws, data) {
|
|
119
|
-
if (data.type === "abort") {
|
|
120
|
-
agent.abort();
|
|
121
|
-
ws.send({ type: "aborted", data: "\u8BF7\u6C42\u5DF2\u53D6\u6D88" });
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
if (data.type === "chat" && data.message) {
|
|
125
|
-
const chatOptions = {
|
|
126
|
-
mode: data.options?.mode,
|
|
127
|
-
model: data.options?.model,
|
|
128
|
-
provider: data.options?.provider,
|
|
129
|
-
enableWebSearch: data.options?.enableWebSearch,
|
|
130
|
-
thinkingMode: data.options?.thinkingMode,
|
|
131
|
-
thinkingBudget: data.options?.thinkingBudget
|
|
132
|
-
};
|
|
133
|
-
for await (const progress of agent.chat(
|
|
134
|
-
data.message,
|
|
135
|
-
chatOptions,
|
|
136
|
-
data.images
|
|
137
|
-
)) {
|
|
138
|
-
ws.send(progress);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}).post("/send", async ({ body }) => {
|
|
143
|
-
const results = [];
|
|
144
|
-
const chatOptions = body.options || {};
|
|
145
|
-
for await (const progress of agent.chat(
|
|
146
|
-
body.message,
|
|
147
|
-
chatOptions,
|
|
148
|
-
body.images
|
|
149
|
-
)) {
|
|
150
|
-
results.push(progress);
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
success: true,
|
|
154
|
-
results
|
|
155
|
-
};
|
|
156
|
-
}, {
|
|
157
|
-
body: ChatRequestSchema
|
|
158
|
-
}).post("/abort", () => {
|
|
159
|
-
agent.abort();
|
|
160
|
-
return { success: true, message: "\u4E2D\u65AD\u4FE1\u53F7\u5DF2\u53D1\u9001" };
|
|
161
|
-
}).post("/clear-agent", () => {
|
|
162
|
-
agent.clearHistory();
|
|
163
|
-
return { success: true };
|
|
164
|
-
}).get("/agent-history", () => ({
|
|
165
|
-
history: agent.getHistory()
|
|
166
|
-
})).post("/working-dir", ({ body }) => {
|
|
167
|
-
agent.setWorkingDir(body.dir);
|
|
168
|
-
return { success: true };
|
|
169
|
-
}, {
|
|
170
|
-
body: t.Object({
|
|
171
|
-
dir: t.String()
|
|
172
|
-
})
|
|
173
|
-
}).get("/config", () => ({
|
|
174
|
-
config: agent.getConfig()
|
|
175
|
-
})).get("/sessions", async ({ headers }) => {
|
|
176
|
-
const ctx = extractContext(headers);
|
|
177
|
-
const sessions = await storage.getSessions(ctx);
|
|
178
|
-
return { sessions };
|
|
179
|
-
}).get("/sessions/:id", async ({ params, headers }) => {
|
|
180
|
-
const ctx = extractContext(headers);
|
|
181
|
-
const session = await storage.getSession(params.id, ctx);
|
|
182
|
-
if (!session) {
|
|
183
|
-
return { error: "\u4F1A\u8BDD\u4E0D\u5B58\u5728" };
|
|
184
|
-
}
|
|
185
|
-
return { session };
|
|
186
|
-
}).post("/sessions", async ({ body, headers }) => {
|
|
187
|
-
const ctx = extractContext(headers);
|
|
188
|
-
const input = {
|
|
189
|
-
id: crypto.randomUUID(),
|
|
190
|
-
title: body.title || "\u65B0\u5BF9\u8BDD",
|
|
191
|
-
model: body.model || "doubao-seed-1-6-251015",
|
|
192
|
-
mode: body.mode || "agent"
|
|
193
|
-
};
|
|
194
|
-
const session = await storage.createSession(input, ctx);
|
|
195
|
-
return { session };
|
|
196
|
-
}, {
|
|
197
|
-
body: SessionCreateSchema
|
|
198
|
-
}).patch("/sessions/:id", async ({ params, body, headers }) => {
|
|
199
|
-
const ctx = extractContext(headers);
|
|
200
|
-
await storage.updateSession(params.id, body, ctx);
|
|
201
|
-
const session = await storage.getSession(params.id, ctx);
|
|
202
|
-
return { session };
|
|
203
|
-
}, {
|
|
204
|
-
body: SessionUpdateSchema
|
|
205
|
-
}).delete("/sessions/:id", async ({ params, headers }) => {
|
|
206
|
-
const ctx = extractContext(headers);
|
|
207
|
-
await storage.deleteSession(params.id, ctx);
|
|
208
|
-
return { success: true };
|
|
209
|
-
}).get("/sessions/:id/messages", async ({ params, headers }) => {
|
|
210
|
-
const ctx = extractContext(headers);
|
|
211
|
-
const messages = await storage.getMessages(params.id, ctx);
|
|
212
|
-
return { messages };
|
|
213
|
-
}).post("/messages", async ({ body, headers }) => {
|
|
214
|
-
const ctx = extractContext(headers);
|
|
215
|
-
const input = {
|
|
216
|
-
id: crypto.randomUUID(),
|
|
217
|
-
sessionId: body.sessionId,
|
|
218
|
-
role: body.role,
|
|
219
|
-
content: body.content,
|
|
220
|
-
thinking: body.thinking || null,
|
|
221
|
-
toolCalls: body.toolCalls || null,
|
|
222
|
-
searchResults: body.searchResults || null,
|
|
223
|
-
operationIds: body.operationIds || null
|
|
224
|
-
};
|
|
225
|
-
const message = await storage.saveMessage(input, ctx);
|
|
226
|
-
return { message };
|
|
227
|
-
}, {
|
|
228
|
-
body: MessageSaveSchema
|
|
229
|
-
}).delete("/sessions/:id/messages", async ({ params, query, headers }) => {
|
|
230
|
-
const ctx = extractContext(headers);
|
|
231
|
-
const timestamp = query.afterTimestamp ? parseInt(query.afterTimestamp) : 0;
|
|
232
|
-
if (timestamp) {
|
|
233
|
-
await storage.deleteMessagesAfter(params.id, new Date(timestamp), ctx);
|
|
234
|
-
}
|
|
235
|
-
return { success: true };
|
|
236
|
-
}, {
|
|
237
|
-
query: t.Object({
|
|
238
|
-
afterTimestamp: t.Optional(t.String())
|
|
239
|
-
})
|
|
240
|
-
}).get("/sessions/:id/operations", async ({ params, headers }) => {
|
|
241
|
-
const ctx = extractContext(headers);
|
|
242
|
-
const operations = await storage.getOperations(params.id, ctx);
|
|
243
|
-
return { operations };
|
|
244
|
-
}).get("/trash", async ({ headers }) => {
|
|
245
|
-
const ctx = extractContext(headers);
|
|
246
|
-
const items = await storage.getTrashItems?.(ctx) || [];
|
|
247
|
-
return { items };
|
|
248
|
-
}).post("/trash/:id/restore", async ({ params, headers }) => {
|
|
249
|
-
const ctx = extractContext(headers);
|
|
250
|
-
const item = await storage.restoreFromTrash?.(params.id, ctx);
|
|
251
|
-
return { item };
|
|
252
|
-
}).get("/health", () => ({ status: "ok" }));
|
|
253
|
-
}
|
|
254
|
-
function createWebAdapter(baseUrl) {
|
|
255
|
-
let abortController = null;
|
|
256
|
-
function getHeaders(ctx) {
|
|
257
|
-
const headers = {
|
|
258
|
-
"Content-Type": "application/json"
|
|
259
|
-
};
|
|
260
|
-
if (ctx?.appId) headers["X-App-Id"] = ctx.appId;
|
|
261
|
-
if (ctx?.userId) headers["X-User-Id"] = ctx.userId;
|
|
262
|
-
return headers;
|
|
263
|
-
}
|
|
264
|
-
return {
|
|
265
|
-
/** 获取可用模型 */
|
|
266
|
-
async getModels() {
|
|
267
|
-
const response = await fetch(`${baseUrl}/models`);
|
|
268
|
-
return response.json();
|
|
269
|
-
},
|
|
270
|
-
/** 发送消息(流式) */
|
|
271
|
-
async *sendMessage(message, options, images) {
|
|
272
|
-
abortController = new AbortController();
|
|
273
|
-
const url = new URL(`${baseUrl}/stream`);
|
|
274
|
-
url.searchParams.set("message", message);
|
|
275
|
-
if (images?.length) url.searchParams.set("images", images.join(","));
|
|
276
|
-
if (options?.mode) url.searchParams.set("mode", options.mode);
|
|
277
|
-
if (options?.model) url.searchParams.set("model", options.model);
|
|
278
|
-
if (options?.provider) url.searchParams.set("provider", options.provider);
|
|
279
|
-
if (options?.enableWebSearch !== void 0) {
|
|
280
|
-
url.searchParams.set("enableWebSearch", String(options.enableWebSearch));
|
|
281
|
-
}
|
|
282
|
-
if (options?.thinkingMode !== void 0) {
|
|
283
|
-
url.searchParams.set("thinkingMode", options.thinkingMode);
|
|
284
|
-
}
|
|
285
|
-
if (options?.thinkingBudget !== void 0) {
|
|
286
|
-
url.searchParams.set("thinkingBudget", String(options.thinkingBudget));
|
|
287
|
-
}
|
|
288
|
-
const response = await fetch(url.toString(), {
|
|
289
|
-
signal: abortController.signal
|
|
290
|
-
});
|
|
291
|
-
if (!response.ok) {
|
|
292
|
-
throw new Error(`HTTP error: ${response.status}`);
|
|
293
|
-
}
|
|
294
|
-
const reader = response.body.getReader();
|
|
295
|
-
const decoder = new TextDecoder();
|
|
296
|
-
let buffer = "";
|
|
297
|
-
while (true) {
|
|
298
|
-
const { done, value } = await reader.read();
|
|
299
|
-
if (done) break;
|
|
300
|
-
buffer += decoder.decode(value, { stream: true });
|
|
301
|
-
const lines = buffer.split("\n\n");
|
|
302
|
-
buffer = lines.pop() || "";
|
|
303
|
-
for (const line of lines) {
|
|
304
|
-
if (line.startsWith("data: ")) {
|
|
305
|
-
const progress = JSON.parse(line.slice(6));
|
|
306
|
-
yield progress;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
},
|
|
311
|
-
/** 中断当前请求 */
|
|
312
|
-
async cancel() {
|
|
313
|
-
abortController?.abort();
|
|
314
|
-
await fetch(`${baseUrl}/abort`, { method: "POST" });
|
|
315
|
-
},
|
|
316
|
-
/** 清空 Agent 对话历史 */
|
|
317
|
-
async clearAgentHistory() {
|
|
318
|
-
await fetch(`${baseUrl}/clear-agent`, { method: "POST" });
|
|
319
|
-
},
|
|
320
|
-
/** 获取 Agent 对话历史 */
|
|
321
|
-
async getAgentHistory() {
|
|
322
|
-
const response = await fetch(`${baseUrl}/agent-history`);
|
|
323
|
-
return response.json();
|
|
324
|
-
},
|
|
325
|
-
/** 设置工作目录 */
|
|
326
|
-
async setWorkingDir(dir) {
|
|
327
|
-
await fetch(`${baseUrl}/working-dir`, {
|
|
328
|
-
method: "POST",
|
|
329
|
-
headers: { "Content-Type": "application/json" },
|
|
330
|
-
body: JSON.stringify({ dir })
|
|
331
|
-
});
|
|
332
|
-
},
|
|
333
|
-
// ============ Sessions ============
|
|
334
|
-
/** 获取会话列表 */
|
|
335
|
-
async getSessions(ctx) {
|
|
336
|
-
const response = await fetch(`${baseUrl}/sessions`, {
|
|
337
|
-
headers: getHeaders(ctx)
|
|
338
|
-
});
|
|
339
|
-
return response.json();
|
|
340
|
-
},
|
|
341
|
-
/** 获取单个会话 */
|
|
342
|
-
async getSession(id, ctx) {
|
|
343
|
-
const response = await fetch(`${baseUrl}/sessions/${id}`, {
|
|
344
|
-
headers: getHeaders(ctx)
|
|
345
|
-
});
|
|
346
|
-
return response.json();
|
|
347
|
-
},
|
|
348
|
-
/** 创建会话 */
|
|
349
|
-
async createSession(data, ctx) {
|
|
350
|
-
const response = await fetch(`${baseUrl}/sessions`, {
|
|
351
|
-
method: "POST",
|
|
352
|
-
headers: getHeaders(ctx),
|
|
353
|
-
body: JSON.stringify(data)
|
|
354
|
-
});
|
|
355
|
-
return response.json();
|
|
356
|
-
},
|
|
357
|
-
/** 更新会话 */
|
|
358
|
-
async updateSession(id, data, ctx) {
|
|
359
|
-
const response = await fetch(`${baseUrl}/sessions/${id}`, {
|
|
360
|
-
method: "PATCH",
|
|
361
|
-
headers: getHeaders(ctx),
|
|
362
|
-
body: JSON.stringify(data)
|
|
363
|
-
});
|
|
364
|
-
return response.json();
|
|
365
|
-
},
|
|
366
|
-
/** 删除会话 */
|
|
367
|
-
async deleteSession(id, ctx) {
|
|
368
|
-
await fetch(`${baseUrl}/sessions/${id}`, {
|
|
369
|
-
method: "DELETE",
|
|
370
|
-
headers: getHeaders(ctx)
|
|
371
|
-
});
|
|
372
|
-
},
|
|
373
|
-
// ============ Messages ============
|
|
374
|
-
/** 获取会话消息 */
|
|
375
|
-
async getMessages(sessionId, ctx) {
|
|
376
|
-
const response = await fetch(`${baseUrl}/sessions/${sessionId}/messages`, {
|
|
377
|
-
headers: getHeaders(ctx)
|
|
378
|
-
});
|
|
379
|
-
return response.json();
|
|
380
|
-
},
|
|
381
|
-
/** 保存消息 */
|
|
382
|
-
async saveMessage(data, ctx) {
|
|
383
|
-
const response = await fetch(`${baseUrl}/messages`, {
|
|
384
|
-
method: "POST",
|
|
385
|
-
headers: getHeaders(ctx),
|
|
386
|
-
body: JSON.stringify(data)
|
|
387
|
-
});
|
|
388
|
-
return response.json();
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
export { createElysiaBridge, createWebAdapter };
|
|
394
|
-
//# sourceMappingURL=index.js.map
|
|
395
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import{Elysia as e,t}from"elysia";import{ChatRuntime as n,DEFAULT_MODEL as r,buildModelOptions as i}from"@huyooo/ai-chat-core";import{createStorage as a}from"@huyooo/ai-chat-storage";import{assetManager as o,createDefaultToolExecutor as s}from"@huyooo/ai-chat-host-node";const c=t.Object({message:t.String(),sessionId:t.Optional(t.String()),images:t.Optional(t.Array(t.String())),options:t.Optional(t.Object({mode:t.Optional(t.Union([t.Literal(`agent`),t.Literal(`ask`)])),model:t.Optional(t.String()),provider:t.Optional(t.Union([t.Literal(`ark_v1`),t.Literal(`deepseek_v1`),t.Literal(`qwen_v1`),t.Literal(`glm_v1`),t.Literal(`moonshot_v1`),t.Literal(`minimax_v1`),t.Literal(`vercel_gateway_v1`),t.Literal(`anthropic_v1`),t.Literal(`gemini_v1`),t.Literal(`openai_v1`),t.Literal(`grok_v1`)])),enableWebSearch:t.Optional(t.Boolean()),thinkingMode:t.Optional(t.Union([t.Literal(`enabled`),t.Literal(`disabled`)])),thinkingBudget:t.Optional(t.Number()),history:t.Optional(t.Array(t.Object({role:t.Union([t.Literal(`user`),t.Literal(`assistant`),t.Literal(`system`),t.Literal(`tool`)]),content:t.String(),reasoning_content:t.Optional(t.String()),tool_call_id:t.Optional(t.String()),tool_calls:t.Optional(t.Array(t.Object({id:t.String(),type:t.Literal(`function`),function:t.Object({name:t.String(),arguments:t.String()}),thought_signature:t.Optional(t.String())})))})))}))}),l=t.Object({title:t.Optional(t.String()),model:t.Optional(t.String()),mode:t.Optional(t.Union([t.Literal(`agent`),t.Literal(`ask`)])),webSearchEnabled:t.Optional(t.Boolean()),thinkingEnabled:t.Optional(t.Boolean()),hidden:t.Optional(t.Boolean())}),u=t.Object({title:t.Optional(t.String()),model:t.Optional(t.String()),mode:t.Optional(t.Union([t.Literal(`agent`),t.Literal(`ask`)])),webSearchEnabled:t.Optional(t.Boolean()),thinkingEnabled:t.Optional(t.Boolean()),hidden:t.Optional(t.Boolean())}),d=t.Object({role:t.Union([t.Literal(`user`),t.Literal(`assistant`),t.Literal(`system`)]),content:t.String(),atContextItems:t.Optional(t.Array(t.Any())),images:t.Optional(t.Array(t.String())),model:t.Optional(t.String()),mode:t.Optional(t.String()),webSearchEnabled:t.Optional(t.Boolean()),thinkingEnabled:t.Optional(t.Boolean()),parts:t.Optional(t.Array(t.Object({type:t.String(),payload:t.String()}))),operationIds:t.Optional(t.String())}),f=t.Object({content:t.Optional(t.String()),atContextItems:t.Optional(t.Union([t.Array(t.Any()),t.Null()])),parts:t.Optional(t.Array(t.Object({type:t.String(),payload:t.String()}))),operationIds:t.Optional(t.String()),usage:t.Optional(t.String()),duration:t.Optional(t.Number())});function p(e){return{appId:e[`x-app-id`]||void 0,userId:e[`x-user-id`]||void 0}}async function m(m){let{llm:h,tools:g,dataDir:_,assetsDir:v,metadataStore:y,preloadTools:b,prefix:x=`/api/chat`,cwd:S,maxIterations:C,maxDurationMs:w,maxToolCalls:T,maxTotalTokens:E,sqliteFactory:D}=m,O=S??process.cwd(),k=v??(_?`${_}/assets`:void 0),A=_?`${_}/data/db.sqlite`:`./data/db.sqlite`,j=await o({tools:g,assetsDir:k,metadataStore:y,preloadTools:b}),M=new n({llmConfig:h,cwd:O,maxIterations:C,maxDurationMs:w,maxToolCalls:T,maxTotalTokens:E,tools:j.tools},s(O));await j.bind(M);let N=await a({type:`sqlite`,sqlitePath:A,sqliteFactory:D});return{app:new e({prefix:x}).get(`/models`,()=>({models:i(h)})).get(`/tools`,async()=>(await M.ensureInitialized(),{tools:M.getAllTools()})).post(`/stream`,async function*({body:e}){let t={...e.options};for await(let n of M.chat(e.message,t,e.images))yield`data: ${JSON.stringify(n)}\n\n`},{body:c}).ws(`/ws`,{body:t.Object({type:t.Union([t.Literal(`chat`),t.Literal(`abort`)]),message:t.Optional(t.String()),images:t.Optional(t.Array(t.String())),options:t.Optional(t.Object({mode:t.Optional(t.String()),model:t.Optional(t.String()),provider:t.Optional(t.String()),enableWebSearch:t.Optional(t.Boolean()),thinkingMode:t.Optional(t.String()),history:t.Optional(t.Array(t.Object({role:t.String(),content:t.String(),reasoning_content:t.Optional(t.String()),tool_call_id:t.Optional(t.String()),tool_calls:t.Optional(t.Array(t.Object({id:t.String(),type:t.Literal(`function`),function:t.Object({name:t.String(),arguments:t.String()}),thought_signature:t.Optional(t.String())})))})))}))}),async message(e,t){if(t.type===`abort`){M.abort(),e.send({type:`aborted`,data:`请求已取消`});return}if(t.type===`chat`&&t.message){let n={mode:t.options?.mode,model:t.options?.model,provider:t.options?.provider,enableWebSearch:t.options?.enableWebSearch,thinkingMode:t.options?.thinkingMode,history:t.options?.history};for await(let r of M.chat(t.message,n,t.images))e.send(r)}}}).post(`/send`,async({body:e})=>{let t=[];for await(let n of M.chat(e.message,{...e.options},e.images))t.push(n);return{success:!0,results:t}},{body:c}).post(`/abort`,()=>(M.abort(),{success:!0,message:`中断信号已发送`})).post(`/cwd`,({body:e})=>(M.setCwd(e.dir),{success:!0}),{body:t.Object({dir:t.String()})}).get(`/config`,()=>({config:M.getConfig()})).get(`/at/chats`,async({query:e,headers:t})=>{let n=p(t),r=e.limit?Number(e.limit):void 0,i=typeof e.query==`string`?e.query:``;return N.searchAtChats(i,{limit:r},n)}).get(`/sessions`,async({headers:e})=>{let t=p(e);return{sessions:await N.getSessions(t)}}).get(`/sessions/:id`,async({params:e,headers:t})=>{let n=p(t),r=await N.getSession(e.id,n);return r?{session:r}:{error:`会话不存在`}}).post(`/sessions`,async({body:e,headers:t})=>{let n=p(t),i={id:crypto.randomUUID(),title:e.title||`新对话`,model:e.model||r,mode:e.mode||`agent`,webSearchEnabled:e.webSearchEnabled??!0,thinkingEnabled:e.thinkingEnabled??!0,hidden:e.hidden??!1};return{session:await N.createSession(i,n)}},{body:l}).patch(`/sessions/:id`,async({params:e,body:t,headers:n})=>{let r=p(n);return await N.updateSession(e.id,t,r),{session:await N.getSession(e.id,r)}},{body:u}).delete(`/sessions/:id`,async({params:e,headers:t})=>{let n=p(t);return await N.deleteSession(e.id,n),{success:!0}}).get(`/sessions/:id/messages`,async({params:e,headers:t})=>{let n=p(t);return{messages:await N.getMessages(e.id,n)}}).get(`/sessions/:id/messages/page`,async({params:e,query:t,headers:n})=>{let r=p(n),i=t.limit?Number(t.limit):void 0,a=t.beforeSequence?Number(t.beforeSequence):void 0;return await N.getMessagesPage(e.id,{limit:i,beforeSequence:a},r)}).post(`/sessions/:id/messages`,async({params:e,body:t,headers:n})=>{let r=p(n),i=crypto.randomUUID(),a={id:i,clientId:i,sessionId:e.id,role:t.role,content:t.content,atContextItems:t.atContextItems||null,images:t.images||[],model:t.model||null,mode:t.mode||null,webSearchEnabled:t.webSearchEnabled??null,thinkingEnabled:t.thinkingEnabled??null,parts:t.parts||[],operationIds:t.operationIds||null};return{message:await N.saveMessage(a,r)}},{body:d}).patch(`/messages/:id`,async({params:e,body:t,headers:n})=>{let r=p(n),i={};return t.content!==void 0&&(i.content=t.content),t.atContextItems!==void 0&&(i.atContextItems=t.atContextItems),t.parts!==void 0&&(i.parts=t.parts),t.operationIds!==void 0&&(i.operationIds=t.operationIds),t.usage!==void 0&&(i.usage=t.usage),t.duration!==void 0&&(i.duration=t.duration),await N.updateMessage(e.id,i,r),{success:!0}},{body:f}).delete(`/sessions/:id/messages/after/:messageId`,async({params:e,headers:t})=>{let n=p(t);return await N.deleteMessagesAfterMessageId(e.id,e.messageId,n),{success:!0}}).get(`/sessions/:id/operations`,async({params:e,headers:t})=>{let n=p(t);return{operations:await N.getOperations(e.id,n)}}).get(`/trash`,async({headers:e})=>{let t=p(e);return{items:await N.getTrashItems?.(t)||[]}}).post(`/trash/:id/restore`,async({params:e,headers:t})=>{let n=p(t);return{item:await N.restoreFromTrash?.(e.id,n)}}).get(`/settings`,async({headers:e})=>{let t=p(e);return{settings:await N.getUserSettings(t)}}).get(`/settings/:key`,async({params:e,headers:t})=>{let n=p(t);return{value:await N.getUserSetting(e.key,n)}}).put(`/settings/:key`,async({params:e,body:t,headers:n})=>{let r=p(n);return await N.setUserSetting(e.key,t.value,r),{success:!0}},{body:t.Object({value:t.String()})}).delete(`/settings/:key`,async({params:e,headers:t})=>{let n=p(t);return await N.deleteUserSetting(e.key,n),{success:!0}}).get(`/health`,()=>({status:`ok`})),agent:M,storage:N,assetManager:j}}export{i as buildModelOptions,m as createElysiaChat};
|
package/package.json
CHANGED
|
@@ -1,42 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huyooo/ai-chat-bridge-elysia",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "AI Chat Elysia Bridge - HTTP/WebSocket integration for Elysia.js",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.js"
|
|
13
|
-
"require": "./dist/index.cjs"
|
|
12
|
+
"import": "./dist/index.js"
|
|
14
13
|
}
|
|
15
14
|
},
|
|
16
15
|
"files": [
|
|
17
16
|
"dist"
|
|
18
17
|
],
|
|
19
18
|
"scripts": {
|
|
20
|
-
"build": "
|
|
21
|
-
"
|
|
19
|
+
"build": "npm run clean && npm run build:js && npm run build:types",
|
|
20
|
+
"build:js": "tsdown",
|
|
21
|
+
"build:types": "tsc -b tsconfig.json --emitDeclarationOnly",
|
|
22
|
+
"dev": "tsdown --watch",
|
|
22
23
|
"start": "tsx example/server.ts",
|
|
23
24
|
"typecheck": "tsc --noEmit",
|
|
24
|
-
"clean": "rm -rf dist"
|
|
25
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest"
|
|
25
28
|
},
|
|
26
29
|
"dependencies": {
|
|
27
|
-
"@huyooo/ai-chat-core": "
|
|
28
|
-
"@huyooo/ai-chat-
|
|
30
|
+
"@huyooo/ai-chat-core": "^0.3.4",
|
|
31
|
+
"@huyooo/ai-chat-host-node": "^0.3.4",
|
|
32
|
+
"@huyooo/ai-chat-storage": "^0.3.4",
|
|
33
|
+
"@huyooo/ai-chat-tools-node": "^0.3.4"
|
|
29
34
|
},
|
|
30
35
|
"peerDependencies": {
|
|
31
|
-
"
|
|
36
|
+
"better-sqlite3": ">=9.0.0",
|
|
37
|
+
"elysia": ">=1.4.0"
|
|
32
38
|
},
|
|
33
39
|
"devDependencies": {
|
|
34
|
-
"@elysiajs/node": "^1.
|
|
40
|
+
"@elysiajs/node": "^1.4.2",
|
|
35
41
|
"@types/node": "^22.0.0",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
42
|
+
"better-sqlite3": ">=9.0.0",
|
|
43
|
+
"elysia": "^1.4.19",
|
|
44
|
+
"tsdown": "^0.21.0",
|
|
38
45
|
"tsx": "^4.0.0",
|
|
39
|
-
"typescript": "^5.0.0"
|
|
46
|
+
"typescript": "^5.0.0",
|
|
47
|
+
"vitest": "^4.0.18"
|
|
40
48
|
},
|
|
41
49
|
"keywords": [
|
|
42
50
|
"ai",
|
|
@@ -48,7 +56,7 @@
|
|
|
48
56
|
"bridge"
|
|
49
57
|
],
|
|
50
58
|
"author": "huyooo",
|
|
51
|
-
"license": "
|
|
59
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
52
60
|
"publishConfig": {
|
|
53
61
|
"access": "public"
|
|
54
62
|
}
|