@abassey/aid 0.1.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.
- package/dist/agents/index.cjs +741 -0
- package/dist/agents/index.d.cts +78 -0
- package/dist/agents/index.d.ts +78 -0
- package/dist/agents/index.js +741 -0
- package/dist/ai-AWJOUXFM.js +9 -0
- package/dist/ai-DOAYJKKI.cjs +9 -0
- package/dist/chunk-2TNYBUNK.js +124 -0
- package/dist/chunk-3LGKZRGY.cjs +124 -0
- package/dist/chunk-AUR2BBB5.cjs +1436 -0
- package/dist/chunk-IJLTRQF4.cjs +276 -0
- package/dist/chunk-JPD7UBAZ.js +58 -0
- package/dist/chunk-M4RQALTT.js +276 -0
- package/dist/chunk-NB65IHJE.cjs +58 -0
- package/dist/chunk-YNIEOBDF.js +1436 -0
- package/dist/client/index.cjs +18 -0
- package/dist/client/index.d.cts +8 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +18 -0
- package/dist/errors-CUVTnseb.d.ts +13 -0
- package/dist/errors-CgCce4cK.d.cts +158 -0
- package/dist/errors-CgCce4cK.d.ts +158 -0
- package/dist/errors-zAPbTlpe.d.cts +13 -0
- package/dist/eval/index.cjs +308 -0
- package/dist/eval/index.d.cts +106 -0
- package/dist/eval/index.d.ts +106 -0
- package/dist/eval/index.js +308 -0
- package/dist/index.cjs +35 -0
- package/dist/index.d.cts +107 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +35 -0
- package/dist/middleware/index.cjs +201 -0
- package/dist/middleware/index.d.cts +36 -0
- package/dist/middleware/index.d.ts +36 -0
- package/dist/middleware/index.js +201 -0
- package/dist/observability/index.cjs +147 -0
- package/dist/observability/index.d.cts +30 -0
- package/dist/observability/index.d.ts +30 -0
- package/dist/observability/index.js +147 -0
- package/dist/react/index.cjs +253 -0
- package/dist/react/index.d.cts +64 -0
- package/dist/react/index.d.ts +64 -0
- package/dist/react/index.js +253 -0
- package/dist/serve/index.cjs +545 -0
- package/dist/serve/index.d.cts +69 -0
- package/dist/serve/index.d.ts +69 -0
- package/dist/serve/index.js +545 -0
- package/dist/types-BJReASS-.d.cts +196 -0
- package/dist/types-BJReASS-.d.ts +196 -0
- package/dist/types-CguX3F16.d.cts +173 -0
- package/dist/types-CrFH-_qp.d.cts +68 -0
- package/dist/types-DvdzPmW0.d.ts +173 -0
- package/dist/types-qfE32ADy.d.ts +68 -0
- package/package.json +144 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
|
|
2
|
+
|
|
3
|
+
var _chunkAUR2BBB5cjs = require('../chunk-AUR2BBB5.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunk3LGKZRGYcjs = require('../chunk-3LGKZRGY.cjs');
|
|
8
|
+
|
|
9
|
+
// src/serve/index.ts
|
|
10
|
+
var _http = require('http'); var _http2 = _interopRequireDefault(_http);
|
|
11
|
+
|
|
12
|
+
// src/serve/router.ts
|
|
13
|
+
function matchRoute(routes, method, url) {
|
|
14
|
+
const path = (_nullishCoalesce(url.split("?")[0], () => ( url))).replace(/\/+$/, "") || "/";
|
|
15
|
+
const pathSegments = path.split("/").filter(Boolean);
|
|
16
|
+
const patternMatches = [];
|
|
17
|
+
for (const route of routes) {
|
|
18
|
+
const patternSegments = route.pattern.split("/").filter(Boolean);
|
|
19
|
+
if (patternSegments.length !== pathSegments.length) continue;
|
|
20
|
+
const params = {};
|
|
21
|
+
let isMatch = true;
|
|
22
|
+
for (let i = 0; i < patternSegments.length; i++) {
|
|
23
|
+
const seg = patternSegments[i];
|
|
24
|
+
if (seg.startsWith(":")) {
|
|
25
|
+
params[seg.slice(1)] = pathSegments[i];
|
|
26
|
+
} else if (seg !== pathSegments[i]) {
|
|
27
|
+
isMatch = false;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (isMatch) {
|
|
32
|
+
patternMatches.push({ route, params });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (patternMatches.length === 0) {
|
|
36
|
+
return { matched: false, params: {}, status: 404 };
|
|
37
|
+
}
|
|
38
|
+
const methodMatch = patternMatches.find(
|
|
39
|
+
(m) => m.route.method === method
|
|
40
|
+
);
|
|
41
|
+
if (methodMatch) {
|
|
42
|
+
return {
|
|
43
|
+
matched: true,
|
|
44
|
+
route: methodMatch.route,
|
|
45
|
+
params: methodMatch.params
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const allowedMethods = [
|
|
49
|
+
...new Set(patternMatches.map((m) => m.route.method))
|
|
50
|
+
];
|
|
51
|
+
return {
|
|
52
|
+
matched: false,
|
|
53
|
+
params: {},
|
|
54
|
+
status: 405,
|
|
55
|
+
allowedMethods
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/serve/sse.ts
|
|
60
|
+
var SSE_HEADERS = {
|
|
61
|
+
"Content-Type": "text/event-stream",
|
|
62
|
+
"Cache-Control": "no-cache",
|
|
63
|
+
"Connection": "keep-alive"
|
|
64
|
+
};
|
|
65
|
+
function sendEvent(res, data) {
|
|
66
|
+
res.write(`data: ${JSON.stringify(data)}
|
|
67
|
+
|
|
68
|
+
`);
|
|
69
|
+
}
|
|
70
|
+
async function writeStreamSSE(res, stream) {
|
|
71
|
+
res.writeHead(200, SSE_HEADERS);
|
|
72
|
+
let closed = false;
|
|
73
|
+
res.on("close", () => {
|
|
74
|
+
closed = true;
|
|
75
|
+
stream.abort();
|
|
76
|
+
});
|
|
77
|
+
try {
|
|
78
|
+
for await (const chunk of stream) {
|
|
79
|
+
if (closed) break;
|
|
80
|
+
if (chunk.done && chunk.response) {
|
|
81
|
+
sendEvent(res, {
|
|
82
|
+
type: "done",
|
|
83
|
+
text: chunk.response.text,
|
|
84
|
+
model: chunk.response.model,
|
|
85
|
+
tokens: chunk.response.tokens,
|
|
86
|
+
cost: chunk.response.cost,
|
|
87
|
+
latencyMs: chunk.response.latencyMs
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
sendEvent(res, { type: "text", text: chunk.delta });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch (err) {
|
|
94
|
+
if (!closed) {
|
|
95
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
96
|
+
const code = err instanceof _chunk3LGKZRGYcjs.AidError ? err.code : "provider_error";
|
|
97
|
+
sendEvent(res, { type: "error", code, message });
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
if (!closed) {
|
|
101
|
+
res.end();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function writeAgentSSE(res, agent, task) {
|
|
106
|
+
res.writeHead(200, SSE_HEADERS);
|
|
107
|
+
let closed = false;
|
|
108
|
+
res.on("close", () => {
|
|
109
|
+
closed = true;
|
|
110
|
+
});
|
|
111
|
+
const send = (data) => {
|
|
112
|
+
if (!closed) sendEvent(res, data);
|
|
113
|
+
};
|
|
114
|
+
const onStepStart = (payload) => {
|
|
115
|
+
send({ type: "step:start", step: payload.step });
|
|
116
|
+
};
|
|
117
|
+
const onStepEnd = (payload) => {
|
|
118
|
+
send({ type: "step:end", step: payload.step });
|
|
119
|
+
};
|
|
120
|
+
const onToolCall = (payload) => {
|
|
121
|
+
send({ type: "tool:call", name: payload.name, args: payload.args });
|
|
122
|
+
};
|
|
123
|
+
const onToolResult = (payload) => {
|
|
124
|
+
send({ type: "tool:result", name: payload.name, result: payload.result });
|
|
125
|
+
};
|
|
126
|
+
const onMessage = (payload) => {
|
|
127
|
+
send({ type: "text", text: payload.content });
|
|
128
|
+
};
|
|
129
|
+
const onError = (payload) => {
|
|
130
|
+
send({ type: "error", code: payload.error.code, message: payload.error.message });
|
|
131
|
+
};
|
|
132
|
+
agent.on("step:start", onStepStart);
|
|
133
|
+
agent.on("step:end", onStepEnd);
|
|
134
|
+
agent.on("tool:call", onToolCall);
|
|
135
|
+
agent.on("tool:result", onToolResult);
|
|
136
|
+
agent.on("message", onMessage);
|
|
137
|
+
agent.on("error", onError);
|
|
138
|
+
const cleanup = () => {
|
|
139
|
+
agent.off("step:start", onStepStart);
|
|
140
|
+
agent.off("step:end", onStepEnd);
|
|
141
|
+
agent.off("tool:call", onToolCall);
|
|
142
|
+
agent.off("tool:result", onToolResult);
|
|
143
|
+
agent.off("message", onMessage);
|
|
144
|
+
agent.off("error", onError);
|
|
145
|
+
};
|
|
146
|
+
try {
|
|
147
|
+
const result = await agent.run(task);
|
|
148
|
+
if (!closed) {
|
|
149
|
+
sendEvent(res, {
|
|
150
|
+
type: "done",
|
|
151
|
+
text: result.text,
|
|
152
|
+
tokens: result.tokens,
|
|
153
|
+
cost: result.cost,
|
|
154
|
+
steps: result.steps.length
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
if (!closed) {
|
|
159
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
160
|
+
const code = err instanceof _chunk3LGKZRGYcjs.AidError ? err.code : "provider_error";
|
|
161
|
+
sendEvent(res, { type: "error", code, message });
|
|
162
|
+
}
|
|
163
|
+
} finally {
|
|
164
|
+
cleanup();
|
|
165
|
+
if (!closed) {
|
|
166
|
+
res.end();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/serve/chat-store.ts
|
|
172
|
+
var _crypto = require('crypto');
|
|
173
|
+
var InMemoryChatStore = (_class = class {
|
|
174
|
+
__init() {this.sessions = /* @__PURE__ */ new Map()}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
constructor(options) {;_class.prototype.__init.call(this);
|
|
179
|
+
this.maxSessions = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.maxSessions]), () => ( 1e3));
|
|
180
|
+
this.sessionTtl = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _2 => _2.sessionTtl]), () => ( 36e5));
|
|
181
|
+
this.chatConfig = {
|
|
182
|
+
system: _optionalChain([options, 'optionalAccess', _3 => _3.system]),
|
|
183
|
+
model: _optionalChain([options, 'optionalAccess', _4 => _4.model]),
|
|
184
|
+
maxHistory: _optionalChain([options, 'optionalAccess', _5 => _5.maxHistory])
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
create(options) {
|
|
188
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
189
|
+
this.evictOldest();
|
|
190
|
+
}
|
|
191
|
+
const system = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.system]), () => ( this.chatConfig.system));
|
|
192
|
+
const model = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.model]), () => ( this.chatConfig.model));
|
|
193
|
+
const conversation = _chunkAUR2BBB5cjs.ai.conversation({
|
|
194
|
+
system,
|
|
195
|
+
model,
|
|
196
|
+
maxHistory: this.chatConfig.maxHistory
|
|
197
|
+
});
|
|
198
|
+
const now = Date.now();
|
|
199
|
+
const session = {
|
|
200
|
+
id: _crypto.randomUUID.call(void 0, ),
|
|
201
|
+
conversation,
|
|
202
|
+
createdAt: now,
|
|
203
|
+
lastActiveAt: now,
|
|
204
|
+
model,
|
|
205
|
+
system
|
|
206
|
+
};
|
|
207
|
+
this.sessions.set(session.id, session);
|
|
208
|
+
return session;
|
|
209
|
+
}
|
|
210
|
+
get(id) {
|
|
211
|
+
const session = this.sessions.get(id);
|
|
212
|
+
if (!session) return void 0;
|
|
213
|
+
if (Date.now() - session.lastActiveAt > this.sessionTtl) {
|
|
214
|
+
this.sessions.delete(id);
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
return session;
|
|
218
|
+
}
|
|
219
|
+
delete(id) {
|
|
220
|
+
return this.sessions.delete(id);
|
|
221
|
+
}
|
|
222
|
+
list() {
|
|
223
|
+
return Array.from(this.sessions.values()).map((s) => ({
|
|
224
|
+
id: s.id,
|
|
225
|
+
createdAt: s.createdAt,
|
|
226
|
+
lastActiveAt: s.lastActiveAt
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
evictOldest() {
|
|
230
|
+
let oldest;
|
|
231
|
+
for (const session of this.sessions.values()) {
|
|
232
|
+
if (!oldest || session.lastActiveAt < oldest.lastActiveAt) {
|
|
233
|
+
oldest = session;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (oldest) {
|
|
237
|
+
this.sessions.delete(oldest.id);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}, _class);
|
|
241
|
+
|
|
242
|
+
// src/serve/handler.ts
|
|
243
|
+
var MAX_BODY_SIZE = 1048576;
|
|
244
|
+
function sendJson(res, status, data) {
|
|
245
|
+
const body = JSON.stringify(data);
|
|
246
|
+
res.writeHead(status, {
|
|
247
|
+
"Content-Type": "application/json",
|
|
248
|
+
"Content-Length": Buffer.byteLength(body)
|
|
249
|
+
});
|
|
250
|
+
res.end(body);
|
|
251
|
+
}
|
|
252
|
+
function sendError(res, status, code, message) {
|
|
253
|
+
sendJson(res, status, { error: { code, message } });
|
|
254
|
+
}
|
|
255
|
+
function errorToStatus(code) {
|
|
256
|
+
switch (code) {
|
|
257
|
+
case "invalid_request":
|
|
258
|
+
return 400;
|
|
259
|
+
case "auth_error":
|
|
260
|
+
return 401;
|
|
261
|
+
case "not_found":
|
|
262
|
+
return 404;
|
|
263
|
+
case "rate_limit":
|
|
264
|
+
return 429;
|
|
265
|
+
case "timeout":
|
|
266
|
+
return 504;
|
|
267
|
+
default:
|
|
268
|
+
return 500;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function readBody(req) {
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
const chunks = [];
|
|
274
|
+
let size = 0;
|
|
275
|
+
req.on("data", (chunk) => {
|
|
276
|
+
size += chunk.length;
|
|
277
|
+
if (size > MAX_BODY_SIZE) {
|
|
278
|
+
req.destroy();
|
|
279
|
+
reject(new (0, _chunk3LGKZRGYcjs.AidError)("invalid_request", "Request body too large"));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
chunks.push(chunk);
|
|
283
|
+
});
|
|
284
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
285
|
+
req.on("error", reject);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
function applyCors(req, res, cors) {
|
|
289
|
+
if (!cors) return false;
|
|
290
|
+
if (cors === true) {
|
|
291
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
292
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
293
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
294
|
+
} else {
|
|
295
|
+
const origin = req.headers.origin;
|
|
296
|
+
if (origin && cors.origins.includes(origin)) {
|
|
297
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
298
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
299
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (req.method === "OPTIONS") {
|
|
303
|
+
res.writeHead(204);
|
|
304
|
+
res.end();
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
function createHandler(config) {
|
|
310
|
+
const routes = [];
|
|
311
|
+
const agents = _nullishCoalesce(config.agents, () => ( {}));
|
|
312
|
+
const chatConfig = config.chat === true ? {} : config.chat ? config.chat : void 0;
|
|
313
|
+
const chatStore = chatConfig ? new InMemoryChatStore({
|
|
314
|
+
maxSessions: chatConfig.maxSessions,
|
|
315
|
+
sessionTtl: chatConfig.sessionTtl,
|
|
316
|
+
system: chatConfig.system,
|
|
317
|
+
model: chatConfig.model,
|
|
318
|
+
maxHistory: chatConfig.maxHistory
|
|
319
|
+
}) : void 0;
|
|
320
|
+
const handleAi = async (_req, res, _params, body) => {
|
|
321
|
+
const { prompt, model, system, temperature, maxTokens } = body;
|
|
322
|
+
if (!prompt || typeof prompt !== "string") {
|
|
323
|
+
sendError(res, 400, "invalid_request", "Missing required field: prompt");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const response = await _chunkAUR2BBB5cjs.ai.call(void 0, prompt, { model, system, temperature, maxTokens });
|
|
327
|
+
sendJson(res, 200, {
|
|
328
|
+
text: response.text,
|
|
329
|
+
model: response.model,
|
|
330
|
+
tokens: response.tokens,
|
|
331
|
+
cost: response.cost,
|
|
332
|
+
latencyMs: response.latencyMs
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
const handleAiStream = async (_req, res, _params, body) => {
|
|
336
|
+
const { prompt, model, system, temperature, maxTokens } = body;
|
|
337
|
+
if (!prompt || typeof prompt !== "string") {
|
|
338
|
+
sendError(res, 400, "invalid_request", "Missing required field: prompt");
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const stream = _chunkAUR2BBB5cjs.ai.stream(prompt, { model, system, temperature, maxTokens });
|
|
342
|
+
await writeStreamSSE(res, stream);
|
|
343
|
+
};
|
|
344
|
+
const handleAgent = async (_req, res, params, body) => {
|
|
345
|
+
const agentName = params.name;
|
|
346
|
+
const agentInstance = agents[agentName];
|
|
347
|
+
if (!agentInstance) {
|
|
348
|
+
sendError(res, 404, "not_found", `Agent '${agentName}' not found`);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const { task } = body;
|
|
352
|
+
if (!task || typeof task !== "string") {
|
|
353
|
+
sendError(res, 400, "invalid_request", "Missing required field: task");
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const result = await agentInstance.run(task);
|
|
357
|
+
sendJson(res, 200, {
|
|
358
|
+
text: result.text,
|
|
359
|
+
model: _nullishCoalesce(agentInstance.config.model, () => ( "default")),
|
|
360
|
+
tokens: result.tokens,
|
|
361
|
+
cost: result.cost,
|
|
362
|
+
steps: result.steps.length
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
const handleAgentStream = async (_req, res, params, body) => {
|
|
366
|
+
const agentName = params.name;
|
|
367
|
+
const agentInstance = agents[agentName];
|
|
368
|
+
if (!agentInstance) {
|
|
369
|
+
sendError(res, 404, "not_found", `Agent '${agentName}' not found`);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const { task } = body;
|
|
373
|
+
if (!task || typeof task !== "string") {
|
|
374
|
+
sendError(res, 400, "invalid_request", "Missing required field: task");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
await writeAgentSSE(res, agentInstance, task);
|
|
378
|
+
};
|
|
379
|
+
const handleChatCreate = async (_req, res, _params, body) => {
|
|
380
|
+
const { system, model } = _nullishCoalesce(body, () => ( {}));
|
|
381
|
+
const session = chatStore.create({ system, model });
|
|
382
|
+
sendJson(res, 201, { sessionId: session.id });
|
|
383
|
+
};
|
|
384
|
+
const handleChatMessage = async (_req, res, params, body) => {
|
|
385
|
+
const session = chatStore.get(params.id);
|
|
386
|
+
if (!session) {
|
|
387
|
+
sendError(res, 404, "not_found", `Session '${params.id}' not found`);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const { message } = body;
|
|
391
|
+
if (!message || typeof message !== "string") {
|
|
392
|
+
sendError(res, 400, "invalid_request", "Missing required field: message");
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
session.lastActiveAt = Date.now();
|
|
396
|
+
const response = await session.conversation.say(message);
|
|
397
|
+
sendJson(res, 200, {
|
|
398
|
+
text: response.text,
|
|
399
|
+
model: response.model,
|
|
400
|
+
tokens: response.tokens,
|
|
401
|
+
cost: response.cost
|
|
402
|
+
});
|
|
403
|
+
};
|
|
404
|
+
const handleChatStream = async (_req, res, params, body) => {
|
|
405
|
+
const session = chatStore.get(params.id);
|
|
406
|
+
if (!session) {
|
|
407
|
+
sendError(res, 404, "not_found", `Session '${params.id}' not found`);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const { message } = body;
|
|
411
|
+
if (!message || typeof message !== "string") {
|
|
412
|
+
sendError(res, 400, "invalid_request", "Missing required field: message");
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
session.lastActiveAt = Date.now();
|
|
416
|
+
const saved = session.conversation.save();
|
|
417
|
+
const messages = [...saved.messages, { role: "user", content: message }];
|
|
418
|
+
const stream = _chunkAUR2BBB5cjs.ai.stream(message, {
|
|
419
|
+
system: saved.system || void 0,
|
|
420
|
+
model: session.model,
|
|
421
|
+
_messages: messages
|
|
422
|
+
});
|
|
423
|
+
await writeStreamSSE(res, stream);
|
|
424
|
+
};
|
|
425
|
+
const handleChatHistory = async (_req, res, params) => {
|
|
426
|
+
const session = chatStore.get(params.id);
|
|
427
|
+
if (!session) {
|
|
428
|
+
sendError(res, 404, "not_found", `Session '${params.id}' not found`);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
const saved = session.conversation.save();
|
|
432
|
+
sendJson(res, 200, {
|
|
433
|
+
sessionId: session.id,
|
|
434
|
+
messages: saved.messages,
|
|
435
|
+
createdAt: session.createdAt,
|
|
436
|
+
lastActiveAt: session.lastActiveAt
|
|
437
|
+
});
|
|
438
|
+
};
|
|
439
|
+
const handleChatDelete = async (_req, res, params) => {
|
|
440
|
+
const deleted = chatStore.delete(params.id);
|
|
441
|
+
if (!deleted) {
|
|
442
|
+
sendError(res, 404, "not_found", `Session '${params.id}' not found`);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
sendJson(res, 200, { deleted: true });
|
|
446
|
+
};
|
|
447
|
+
const handleHealth = async (_req, res) => {
|
|
448
|
+
sendJson(res, 200, { status: "ok" });
|
|
449
|
+
};
|
|
450
|
+
const handleModels = async (_req, res) => {
|
|
451
|
+
const models = Object.entries(_chunk3LGKZRGYcjs.MODEL_MAP).map(([alias, entry]) => ({
|
|
452
|
+
alias,
|
|
453
|
+
provider: entry.provider,
|
|
454
|
+
model: entry.model
|
|
455
|
+
}));
|
|
456
|
+
sendJson(res, 200, { models });
|
|
457
|
+
};
|
|
458
|
+
routes.push({ method: "GET", pattern: "/health", handler: handleHealth });
|
|
459
|
+
routes.push({ method: "GET", pattern: "/models", handler: handleModels });
|
|
460
|
+
if (config.ai) {
|
|
461
|
+
routes.push({ method: "POST", pattern: "/ai", handler: handleAi });
|
|
462
|
+
routes.push({ method: "POST", pattern: "/ai/stream", handler: handleAiStream });
|
|
463
|
+
}
|
|
464
|
+
if (config.agents && Object.keys(config.agents).length > 0) {
|
|
465
|
+
routes.push({ method: "POST", pattern: "/agents/:name", handler: handleAgent });
|
|
466
|
+
routes.push({ method: "POST", pattern: "/agents/:name/stream", handler: handleAgentStream });
|
|
467
|
+
}
|
|
468
|
+
if (chatStore) {
|
|
469
|
+
routes.push({ method: "POST", pattern: "/chat", handler: handleChatCreate });
|
|
470
|
+
routes.push({ method: "POST", pattern: "/chat/:id", handler: handleChatMessage });
|
|
471
|
+
routes.push({ method: "POST", pattern: "/chat/:id/stream", handler: handleChatStream });
|
|
472
|
+
routes.push({ method: "GET", pattern: "/chat/:id", handler: handleChatHistory });
|
|
473
|
+
routes.push({ method: "DELETE", pattern: "/chat/:id", handler: handleChatDelete });
|
|
474
|
+
}
|
|
475
|
+
return (req, res) => {
|
|
476
|
+
const handled = applyCors(req, res, config.cors);
|
|
477
|
+
if (handled) return;
|
|
478
|
+
const method = _nullishCoalesce(req.method, () => ( "GET"));
|
|
479
|
+
const url = _nullishCoalesce(req.url, () => ( "/"));
|
|
480
|
+
const match = matchRoute(routes, method, url);
|
|
481
|
+
if (!match.matched) {
|
|
482
|
+
if (match.status === 405 && match.allowedMethods) {
|
|
483
|
+
res.setHeader("Allow", match.allowedMethods.join(", "));
|
|
484
|
+
sendError(res, 405, "invalid_request", "Method not allowed");
|
|
485
|
+
} else {
|
|
486
|
+
sendError(res, 404, "not_found", "Not found");
|
|
487
|
+
}
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const needsBody = ["POST", "PUT", "PATCH"].includes(method);
|
|
491
|
+
const dispatch = async () => {
|
|
492
|
+
let body = {};
|
|
493
|
+
if (needsBody) {
|
|
494
|
+
try {
|
|
495
|
+
const raw = await readBody(req);
|
|
496
|
+
body = raw.length > 0 ? JSON.parse(raw) : {};
|
|
497
|
+
} catch (err) {
|
|
498
|
+
if (err instanceof _chunk3LGKZRGYcjs.AidError) {
|
|
499
|
+
sendError(res, 400, err.code, err.message);
|
|
500
|
+
} else {
|
|
501
|
+
sendError(res, 400, "invalid_request", "Invalid JSON in request body");
|
|
502
|
+
}
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
await match.route.handler(req, res, match.params, body);
|
|
507
|
+
};
|
|
508
|
+
dispatch().catch((err) => {
|
|
509
|
+
if (err instanceof _chunk3LGKZRGYcjs.AidError) {
|
|
510
|
+
sendError(res, errorToStatus(err.code), err.code, err.message);
|
|
511
|
+
} else {
|
|
512
|
+
const message = err instanceof Error ? err.message : "Internal server error";
|
|
513
|
+
sendError(res, 500, "serve_error", message);
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/serve/index.ts
|
|
520
|
+
function serve(config = {}) {
|
|
521
|
+
const handler = createHandler(config);
|
|
522
|
+
const port = _nullishCoalesce(config.port, () => ( 3e3));
|
|
523
|
+
let server = null;
|
|
524
|
+
return {
|
|
525
|
+
handler,
|
|
526
|
+
async listen() {
|
|
527
|
+
server = _http2.default.createServer(handler);
|
|
528
|
+
return new Promise((resolve) => {
|
|
529
|
+
server.listen(port, resolve);
|
|
530
|
+
});
|
|
531
|
+
},
|
|
532
|
+
async close() {
|
|
533
|
+
if (!server) return;
|
|
534
|
+
return new Promise((resolve, reject) => {
|
|
535
|
+
server.close((err) => err ? reject(err) : resolve());
|
|
536
|
+
server = null;
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
exports.InMemoryChatStore = InMemoryChatStore; exports.createHandler = createHandler; exports.serve = serve;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { a as Agent } from '../types-CguX3F16.cjs';
|
|
3
|
+
import { j as Conversation } from '../types-BJReASS-.cjs';
|
|
4
|
+
import '../errors-zAPbTlpe.cjs';
|
|
5
|
+
|
|
6
|
+
interface ServeConfig {
|
|
7
|
+
ai?: boolean;
|
|
8
|
+
agents?: Record<string, Agent>;
|
|
9
|
+
chat?: boolean | ChatConfig;
|
|
10
|
+
port?: number;
|
|
11
|
+
cors?: boolean | CorsConfig;
|
|
12
|
+
}
|
|
13
|
+
interface ChatConfig {
|
|
14
|
+
system?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
maxHistory?: number;
|
|
17
|
+
maxSessions?: number;
|
|
18
|
+
sessionTtl?: number;
|
|
19
|
+
}
|
|
20
|
+
interface CorsConfig {
|
|
21
|
+
origins: string[];
|
|
22
|
+
}
|
|
23
|
+
interface ServeApp {
|
|
24
|
+
listen(): Promise<void>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
handler: RequestHandler;
|
|
27
|
+
}
|
|
28
|
+
type RequestHandler = (req: IncomingMessage, res: ServerResponse) => void;
|
|
29
|
+
interface ChatSession {
|
|
30
|
+
id: string;
|
|
31
|
+
conversation: Conversation;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
lastActiveAt: number;
|
|
34
|
+
model?: string;
|
|
35
|
+
system?: string;
|
|
36
|
+
}
|
|
37
|
+
interface ChatSessionMeta {
|
|
38
|
+
id: string;
|
|
39
|
+
createdAt: number;
|
|
40
|
+
lastActiveAt: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare function createHandler(config: ServeConfig): RequestHandler;
|
|
44
|
+
|
|
45
|
+
declare class InMemoryChatStore {
|
|
46
|
+
private sessions;
|
|
47
|
+
private maxSessions;
|
|
48
|
+
private sessionTtl;
|
|
49
|
+
private chatConfig;
|
|
50
|
+
constructor(options?: {
|
|
51
|
+
maxSessions?: number;
|
|
52
|
+
sessionTtl?: number;
|
|
53
|
+
system?: string;
|
|
54
|
+
model?: string;
|
|
55
|
+
maxHistory?: number;
|
|
56
|
+
});
|
|
57
|
+
create(options?: {
|
|
58
|
+
system?: string;
|
|
59
|
+
model?: string;
|
|
60
|
+
}): ChatSession;
|
|
61
|
+
get(id: string): ChatSession | undefined;
|
|
62
|
+
delete(id: string): boolean;
|
|
63
|
+
list(): ChatSessionMeta[];
|
|
64
|
+
private evictOldest;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare function serve(config?: ServeConfig): ServeApp;
|
|
68
|
+
|
|
69
|
+
export { type ChatConfig, type ChatSession, type ChatSessionMeta, type CorsConfig, InMemoryChatStore, type RequestHandler, type ServeApp, type ServeConfig, createHandler, serve };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { a as Agent } from '../types-DvdzPmW0.js';
|
|
3
|
+
import { j as Conversation } from '../types-BJReASS-.js';
|
|
4
|
+
import '../errors-CUVTnseb.js';
|
|
5
|
+
|
|
6
|
+
interface ServeConfig {
|
|
7
|
+
ai?: boolean;
|
|
8
|
+
agents?: Record<string, Agent>;
|
|
9
|
+
chat?: boolean | ChatConfig;
|
|
10
|
+
port?: number;
|
|
11
|
+
cors?: boolean | CorsConfig;
|
|
12
|
+
}
|
|
13
|
+
interface ChatConfig {
|
|
14
|
+
system?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
maxHistory?: number;
|
|
17
|
+
maxSessions?: number;
|
|
18
|
+
sessionTtl?: number;
|
|
19
|
+
}
|
|
20
|
+
interface CorsConfig {
|
|
21
|
+
origins: string[];
|
|
22
|
+
}
|
|
23
|
+
interface ServeApp {
|
|
24
|
+
listen(): Promise<void>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
handler: RequestHandler;
|
|
27
|
+
}
|
|
28
|
+
type RequestHandler = (req: IncomingMessage, res: ServerResponse) => void;
|
|
29
|
+
interface ChatSession {
|
|
30
|
+
id: string;
|
|
31
|
+
conversation: Conversation;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
lastActiveAt: number;
|
|
34
|
+
model?: string;
|
|
35
|
+
system?: string;
|
|
36
|
+
}
|
|
37
|
+
interface ChatSessionMeta {
|
|
38
|
+
id: string;
|
|
39
|
+
createdAt: number;
|
|
40
|
+
lastActiveAt: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare function createHandler(config: ServeConfig): RequestHandler;
|
|
44
|
+
|
|
45
|
+
declare class InMemoryChatStore {
|
|
46
|
+
private sessions;
|
|
47
|
+
private maxSessions;
|
|
48
|
+
private sessionTtl;
|
|
49
|
+
private chatConfig;
|
|
50
|
+
constructor(options?: {
|
|
51
|
+
maxSessions?: number;
|
|
52
|
+
sessionTtl?: number;
|
|
53
|
+
system?: string;
|
|
54
|
+
model?: string;
|
|
55
|
+
maxHistory?: number;
|
|
56
|
+
});
|
|
57
|
+
create(options?: {
|
|
58
|
+
system?: string;
|
|
59
|
+
model?: string;
|
|
60
|
+
}): ChatSession;
|
|
61
|
+
get(id: string): ChatSession | undefined;
|
|
62
|
+
delete(id: string): boolean;
|
|
63
|
+
list(): ChatSessionMeta[];
|
|
64
|
+
private evictOldest;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare function serve(config?: ServeConfig): ServeApp;
|
|
68
|
+
|
|
69
|
+
export { type ChatConfig, type ChatSession, type ChatSessionMeta, type CorsConfig, InMemoryChatStore, type RequestHandler, type ServeApp, type ServeConfig, createHandler, serve };
|