@theokit/http 0.4.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/README.md +172 -0
- package/dist/app.d.ts +67 -0
- package/dist/app.js +11 -0
- package/dist/app.js.map +1 -0
- package/dist/chunk-34KOKJ5M.js +71 -0
- package/dist/chunk-34KOKJ5M.js.map +1 -0
- package/dist/chunk-3PGQVQWG.js +276 -0
- package/dist/chunk-3PGQVQWG.js.map +1 -0
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/chunk-HLW7YKZE.js +99 -0
- package/dist/chunk-HLW7YKZE.js.map +1 -0
- package/dist/chunk-LKNI6QEP.js +20 -0
- package/dist/chunk-LKNI6QEP.js.map +1 -0
- package/dist/chunk-LWCNTZN6.js +87 -0
- package/dist/chunk-LWCNTZN6.js.map +1 -0
- package/dist/chunk-SMWUPP2C.js +125 -0
- package/dist/chunk-SMWUPP2C.js.map +1 -0
- package/dist/chunk-TBMGRXH5.js +477 -0
- package/dist/chunk-TBMGRXH5.js.map +1 -0
- package/dist/chunk-U46H4CGF.js +34 -0
- package/dist/chunk-U46H4CGF.js.map +1 -0
- package/dist/exception-filter-chain-BCSQ3MZ2.js +10 -0
- package/dist/exception-filter-chain-BCSQ3MZ2.js.map +1 -0
- package/dist/index.d.ts +1047 -0
- package/dist/index.js +761 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor-chain-6S3PUV7J.js +9 -0
- package/dist/interceptor-chain-6S3PUV7J.js.map +1 -0
- package/dist/middleware-consumer-ljxK1fU_.d.ts +58 -0
- package/dist/runtime-node.d.ts +21 -0
- package/dist/runtime-node.js +12 -0
- package/dist/runtime-node.js.map +1 -0
- package/dist/theokit-plugin.d.ts +65 -0
- package/dist/theokit-plugin.js +432 -0
- package/dist/theokit-plugin.js.map +1 -0
- package/dist/types-CGthbcon.d.ts +19 -0
- package/package.json +58 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createExecutionContext,
|
|
3
|
+
walkControllerMetadata
|
|
4
|
+
} from "./chunk-SMWUPP2C.js";
|
|
5
|
+
import {
|
|
6
|
+
createNodeAdapter
|
|
7
|
+
} from "./chunk-HLW7YKZE.js";
|
|
8
|
+
import {
|
|
9
|
+
ForbiddenException,
|
|
10
|
+
HttpException
|
|
11
|
+
} from "./chunk-3PGQVQWG.js";
|
|
12
|
+
import {
|
|
13
|
+
__name
|
|
14
|
+
} from "./chunk-7QVYU63E.js";
|
|
15
|
+
|
|
16
|
+
// src/app.ts
|
|
17
|
+
import "reflect-metadata";
|
|
18
|
+
var TheoApp = class _TheoApp {
|
|
19
|
+
static {
|
|
20
|
+
__name(this, "TheoApp");
|
|
21
|
+
}
|
|
22
|
+
serverHandle;
|
|
23
|
+
routes = [];
|
|
24
|
+
frontendHtml;
|
|
25
|
+
startTime = Date.now();
|
|
26
|
+
healthPath;
|
|
27
|
+
readyPath;
|
|
28
|
+
readinessChecks;
|
|
29
|
+
constructor(opts) {
|
|
30
|
+
const hp = opts?.healthPath ?? "/__theo/health";
|
|
31
|
+
const rp = opts?.readyPath ?? "/__theo/ready";
|
|
32
|
+
if (hp.startsWith("/api/")) throw new Error(`[TheoApp] healthPath "${hp}" must not start with /api/ \u2014 would collide with user routes`);
|
|
33
|
+
if (rp.startsWith("/api/")) throw new Error(`[TheoApp] readyPath "${rp}" must not start with /api/ \u2014 would collide with user routes`);
|
|
34
|
+
this.healthPath = hp;
|
|
35
|
+
this.readyPath = rp;
|
|
36
|
+
this.readinessChecks = opts?.readinessChecks ?? [];
|
|
37
|
+
const adapter = createNodeAdapter();
|
|
38
|
+
this.serverHandle = adapter.createServer((request) => this.handleRequest(request));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a TheoKit application with Spring Boot-style DI.
|
|
42
|
+
*
|
|
43
|
+
* EC-7: async because Container may resolve async factories (Agent.create).
|
|
44
|
+
* EC-2: Registration order guaranteed: providers → controllers → agents.
|
|
45
|
+
*/
|
|
46
|
+
static async create(opts) {
|
|
47
|
+
const app = new _TheoApp(opts);
|
|
48
|
+
const registry = /* @__PURE__ */ new Map();
|
|
49
|
+
if (opts.module) {
|
|
50
|
+
const moduleMeta = Reflect.getMetadata("usetheo:di:module", opts.module);
|
|
51
|
+
if (moduleMeta) {
|
|
52
|
+
const allModules = [
|
|
53
|
+
opts.module,
|
|
54
|
+
...moduleMeta.imports ?? []
|
|
55
|
+
];
|
|
56
|
+
for (const Mod of allModules) {
|
|
57
|
+
const meta = Reflect.getMetadata("usetheo:di:module", Mod);
|
|
58
|
+
if (!meta) continue;
|
|
59
|
+
for (const Prov of meta.providers ?? []) {
|
|
60
|
+
if (!registry.has(Prov)) {
|
|
61
|
+
registry.set(Prov, new Prov());
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (opts.providers) {
|
|
68
|
+
for (const Prov of opts.providers) {
|
|
69
|
+
if (!registry.has(Prov)) {
|
|
70
|
+
registry.set(Prov, new Prov());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const Controller of opts.controllers) {
|
|
75
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", Controller) ?? [];
|
|
76
|
+
const args = paramTypes.map((pt) => {
|
|
77
|
+
const dep = registry.get(pt);
|
|
78
|
+
if (!dep) {
|
|
79
|
+
throw new Error(`[TheoApp] Cannot resolve ${pt.name} for ${Controller.name}. Add ${pt.name} to providers (or to @Module({ providers: [...] })).`);
|
|
80
|
+
}
|
|
81
|
+
return dep;
|
|
82
|
+
});
|
|
83
|
+
const instance = new Controller(...args);
|
|
84
|
+
const postConstruct = Reflect.getMetadata("usetheo:di:post-construct", Controller);
|
|
85
|
+
if (postConstruct && typeof instance[postConstruct] === "function") {
|
|
86
|
+
const result = instance[postConstruct]();
|
|
87
|
+
if (result instanceof Promise) await result;
|
|
88
|
+
}
|
|
89
|
+
const walks = walkControllerMetadata(Controller);
|
|
90
|
+
for (const w of walks) {
|
|
91
|
+
app.routes.push({
|
|
92
|
+
walk: w,
|
|
93
|
+
instance
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
app.routes.sort((a, b) => {
|
|
98
|
+
const aP = a.walk.fullPath.includes(":");
|
|
99
|
+
const bP = b.walk.fullPath.includes(":");
|
|
100
|
+
if (aP !== bP) return aP ? 1 : -1;
|
|
101
|
+
return 0;
|
|
102
|
+
});
|
|
103
|
+
for (const entry of app.routes) {
|
|
104
|
+
const paramNames = [];
|
|
105
|
+
const regexStr = entry.walk.fullPath.replace(/:(\w+)/g, (_m, name) => {
|
|
106
|
+
paramNames.push(name);
|
|
107
|
+
return "([^/]+)";
|
|
108
|
+
});
|
|
109
|
+
entry.compiledPattern = new RegExp(`^${regexStr}$`);
|
|
110
|
+
entry.compiledParamNames = paramNames;
|
|
111
|
+
entry.needsBody = entry.walk.paramEntries.some((p) => p.source === "body");
|
|
112
|
+
}
|
|
113
|
+
if (opts.html) app.frontendHtml = opts.html;
|
|
114
|
+
if (opts.agents?.length) {
|
|
115
|
+
await app.autoWireAgents(opts.agents, registry, opts);
|
|
116
|
+
}
|
|
117
|
+
return app;
|
|
118
|
+
}
|
|
119
|
+
async listen(port) {
|
|
120
|
+
return new Promise((resolve) => {
|
|
121
|
+
this.serverHandle.listen(port, () => {
|
|
122
|
+
console.log(`TheoKit app listening on http://localhost:${port}`);
|
|
123
|
+
resolve();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
getServerHandle() {
|
|
128
|
+
return this.serverHandle;
|
|
129
|
+
}
|
|
130
|
+
async close() {
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
this.serverHandle.close(() => {
|
|
133
|
+
resolve();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// ── Auto-wire agents (the "SpringApplication.run()" moment) ──
|
|
138
|
+
agentRoutes = [];
|
|
139
|
+
async autoWireAgents(agentClasses, registry, opts) {
|
|
140
|
+
const importFn = new Function("specifier", "return import(specifier)");
|
|
141
|
+
let walkAgentMetadata, compileAgent, generateAgentRoutes, getMixins, createRealAgentStreamFn;
|
|
142
|
+
try {
|
|
143
|
+
const mod = await importFn("@theokit/agents");
|
|
144
|
+
walkAgentMetadata = mod.walkAgentMetadata;
|
|
145
|
+
compileAgent = mod.compileAgent;
|
|
146
|
+
generateAgentRoutes = mod.generateAgentRoutes;
|
|
147
|
+
getMixins = mod.getMixins;
|
|
148
|
+
createRealAgentStreamFn = mod.createRealAgentStream;
|
|
149
|
+
} catch {
|
|
150
|
+
throw new Error("[TheoApp] @theokit/agents is required when agents[] is provided. Install: npm install @theokit/agents");
|
|
151
|
+
}
|
|
152
|
+
const apiKey = opts.llmApiKey ?? process.env.OPENROUTER_API_KEY ?? "";
|
|
153
|
+
for (const AgentClass of agentClasses) {
|
|
154
|
+
const mixins = getMixins(AgentClass);
|
|
155
|
+
const allToolboxes = [
|
|
156
|
+
...mixins
|
|
157
|
+
];
|
|
158
|
+
for (const [Cls] of registry) {
|
|
159
|
+
if (Reflect.getMetadata(/* @__PURE__ */ Symbol.for("theokit:agents:toolbox"), Cls)) {
|
|
160
|
+
if (!allToolboxes.includes(Cls)) allToolboxes.push(Cls);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const walk = walkAgentMetadata(AgentClass, allToolboxes);
|
|
164
|
+
const toolboxInstances = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const tb of walk.toolboxes) {
|
|
166
|
+
let instance = registry.get(tb.class);
|
|
167
|
+
if (!instance) {
|
|
168
|
+
instance = new tb.class();
|
|
169
|
+
registry.set(tb.class, instance);
|
|
170
|
+
}
|
|
171
|
+
toolboxInstances.set(tb.class, instance);
|
|
172
|
+
}
|
|
173
|
+
const compiled = compileAgent(walk, toolboxInstances);
|
|
174
|
+
let createRun;
|
|
175
|
+
if (opts.agentStreamFactory) {
|
|
176
|
+
createRun = opts.agentStreamFactory(walk, compiled.tools, apiKey, opts.llmModel);
|
|
177
|
+
} else if (apiKey && createRealAgentStreamFn !== void 0) {
|
|
178
|
+
createRun = createRealAgentStreamFn(walk, compiled.tools, apiKey, opts.llmModel);
|
|
179
|
+
} else {
|
|
180
|
+
createRun = this.createFallbackStream(walk.agentConfig.name, apiKey);
|
|
181
|
+
}
|
|
182
|
+
const routes = generateAgentRoutes({
|
|
183
|
+
walkResult: walk,
|
|
184
|
+
compiledOptions: compiled,
|
|
185
|
+
createRun
|
|
186
|
+
});
|
|
187
|
+
for (const route of routes) {
|
|
188
|
+
const paramNames = [];
|
|
189
|
+
const regexStr = route.path.replace(/:(\w+)/g, (_m, name) => {
|
|
190
|
+
paramNames.push(name);
|
|
191
|
+
return "([^/]+)";
|
|
192
|
+
});
|
|
193
|
+
this.agentRoutes.push({
|
|
194
|
+
method: route.method,
|
|
195
|
+
pattern: new RegExp(`^${regexStr}$`),
|
|
196
|
+
paramNames,
|
|
197
|
+
handler: route.handler,
|
|
198
|
+
guards: walk.guards ?? [],
|
|
199
|
+
agentClass: AgentClass,
|
|
200
|
+
methodName: walk.mainLoop?.propertyKey ?? "run"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
console.log(` \u{1F916} Agent "${walk.agentConfig.name}" mounted at ${walk.route}/chat (${compiled.tools.length} tools)`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async handleReadinessCheck() {
|
|
207
|
+
if (this.readinessChecks.length === 0) {
|
|
208
|
+
return jsonResponse(200, {
|
|
209
|
+
status: "ready",
|
|
210
|
+
checks: []
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
const results = await Promise.all(this.readinessChecks.map(async (check) => {
|
|
214
|
+
try {
|
|
215
|
+
return await Promise.race([
|
|
216
|
+
check(),
|
|
217
|
+
new Promise((resolve) => setTimeout(() => resolve({
|
|
218
|
+
name: "unknown",
|
|
219
|
+
healthy: false,
|
|
220
|
+
message: "Readiness check timed out (5s)"
|
|
221
|
+
}), 5e3))
|
|
222
|
+
]);
|
|
223
|
+
} catch (err) {
|
|
224
|
+
return {
|
|
225
|
+
name: "unknown",
|
|
226
|
+
healthy: false,
|
|
227
|
+
message: err instanceof Error ? err.message : "Check failed"
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}));
|
|
231
|
+
const allHealthy = results.every((r) => r.healthy);
|
|
232
|
+
return jsonResponse(allHealthy ? 200 : 503, {
|
|
233
|
+
status: allHealthy ? "ready" : "not_ready",
|
|
234
|
+
checks: results
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
createFallbackStream(agentName, apiKey) {
|
|
238
|
+
const msg = !apiKey ? "Set OPENROUTER_API_KEY environment variable or pass llmApiKey to TheoApp.create()" : "Pass agentStreamFactory to TheoApp.create() to connect your LLM provider";
|
|
239
|
+
return (_message, _sessionId) => {
|
|
240
|
+
const events = [
|
|
241
|
+
{
|
|
242
|
+
type: "run_started",
|
|
243
|
+
runId: `run-${Date.now()}`,
|
|
244
|
+
agentName
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
type: "error",
|
|
248
|
+
code: "AGENT_NOT_WIRED",
|
|
249
|
+
message: msg,
|
|
250
|
+
retryable: false
|
|
251
|
+
}
|
|
252
|
+
];
|
|
253
|
+
return {
|
|
254
|
+
[Symbol.asyncIterator]: () => {
|
|
255
|
+
let i = 0;
|
|
256
|
+
return {
|
|
257
|
+
next: /* @__PURE__ */ __name(() => Promise.resolve(i < events.length ? {
|
|
258
|
+
value: events[i++],
|
|
259
|
+
done: false
|
|
260
|
+
} : {
|
|
261
|
+
value: void 0,
|
|
262
|
+
done: true
|
|
263
|
+
}), "next")
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
// ── Web Standard request handler ──────────────────
|
|
270
|
+
async handleRequest(request) {
|
|
271
|
+
const pathname = new URL(request.url).pathname;
|
|
272
|
+
if (request.method === "GET") {
|
|
273
|
+
if (pathname === this.healthPath) {
|
|
274
|
+
return jsonResponse(200, {
|
|
275
|
+
status: "ok",
|
|
276
|
+
uptime: (Date.now() - this.startTime) / 1e3,
|
|
277
|
+
timestamp: Date.now()
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
if (pathname === this.readyPath) {
|
|
281
|
+
return this.handleReadinessCheck();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (request.method === "GET") {
|
|
285
|
+
if ((pathname === "/" || pathname === "/index.html") && this.frontendHtml) {
|
|
286
|
+
return new Response(this.frontendHtml, {
|
|
287
|
+
status: 200,
|
|
288
|
+
headers: {
|
|
289
|
+
"content-type": "text/html; charset=utf-8"
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
for (const route of this.agentRoutes) {
|
|
295
|
+
if (request.method.toUpperCase() === route.method && route.pattern.test(pathname)) {
|
|
296
|
+
if (route.guards.length > 0) {
|
|
297
|
+
const ctx = createExecutionContext(request, route.agentClass, route.methodName);
|
|
298
|
+
for (const GuardCtor of route.guards) {
|
|
299
|
+
const guard = new GuardCtor();
|
|
300
|
+
if (!await guard.canActivate(ctx)) {
|
|
301
|
+
const ex = new ForbiddenException("Forbidden resource");
|
|
302
|
+
return jsonResponse(ex.statusCode, ex.toJSON());
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return route.handler(request);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const url = new URL(request.url);
|
|
310
|
+
const method = request.method.toUpperCase();
|
|
311
|
+
const match = this.findRoute(method, url.pathname);
|
|
312
|
+
if (!match) {
|
|
313
|
+
return jsonResponse(404, {
|
|
314
|
+
error: {
|
|
315
|
+
code: "NOT_FOUND",
|
|
316
|
+
message: `No route for ${method} ${url.pathname}`
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
const { entry, params } = match;
|
|
321
|
+
try {
|
|
322
|
+
const ctx = createExecutionContext(request, entry.instance.constructor, entry.walk.propertyKey);
|
|
323
|
+
for (const GuardCtor of entry.walk.guards) {
|
|
324
|
+
const guard = new GuardCtor();
|
|
325
|
+
if (!await guard.canActivate(ctx)) {
|
|
326
|
+
const ex = new ForbiddenException("Forbidden resource");
|
|
327
|
+
return jsonResponse(ex.statusCode, ex.toJSON());
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
let body;
|
|
331
|
+
if (entry.needsBody && [
|
|
332
|
+
"POST",
|
|
333
|
+
"PUT",
|
|
334
|
+
"PATCH"
|
|
335
|
+
].includes(method)) {
|
|
336
|
+
try {
|
|
337
|
+
const text = await request.text();
|
|
338
|
+
body = text ? JSON.parse(text) : void 0;
|
|
339
|
+
} catch {
|
|
340
|
+
body = void 0;
|
|
341
|
+
}
|
|
342
|
+
if (entry.walk.bodySchema && body !== void 0) {
|
|
343
|
+
const result2 = entry.walk.bodySchema.safeParse(body);
|
|
344
|
+
if (!result2.success) {
|
|
345
|
+
return jsonResponse(422, {
|
|
346
|
+
error: {
|
|
347
|
+
code: "VALIDATION_ERROR",
|
|
348
|
+
issues: result2.error.issues
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
body = result2.data;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const args = this.buildArgs(entry.walk.paramEntries, request, body, params, Object.fromEntries(url.searchParams));
|
|
356
|
+
if (entry.walk.redirect) {
|
|
357
|
+
return new Response(null, {
|
|
358
|
+
status: entry.walk.redirect.status,
|
|
359
|
+
headers: {
|
|
360
|
+
location: entry.walk.redirect.url
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
const handlerFn = entry.instance[entry.walk.propertyKey];
|
|
365
|
+
let result;
|
|
366
|
+
if (entry.walk.interceptors.length > 0) {
|
|
367
|
+
const { runInterceptors } = await import("./interceptor-chain-6S3PUV7J.js");
|
|
368
|
+
result = await runInterceptors(entry.walk.interceptors, () => handlerFn.apply(entry.instance, args), request);
|
|
369
|
+
} else {
|
|
370
|
+
result = await handlerFn.apply(entry.instance, args);
|
|
371
|
+
}
|
|
372
|
+
return buildResponse(result, entry.walk, method);
|
|
373
|
+
} catch (err) {
|
|
374
|
+
if (entry.walk.filters.length > 0) {
|
|
375
|
+
const { runExceptionFilters } = await import("./exception-filter-chain-BCSQ3MZ2.js");
|
|
376
|
+
return runExceptionFilters(err, entry.walk.filters, request);
|
|
377
|
+
}
|
|
378
|
+
if (err instanceof HttpException) {
|
|
379
|
+
return jsonResponse(err.statusCode, err.toJSON());
|
|
380
|
+
}
|
|
381
|
+
console.error("[theokit] Internal error:", err instanceof Error ? err.message : err);
|
|
382
|
+
return jsonResponse(500, {
|
|
383
|
+
error: {
|
|
384
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
385
|
+
message: "Internal Server Error"
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
findRoute(method, pathname) {
|
|
391
|
+
for (const entry of this.routes) {
|
|
392
|
+
if (entry.walk.verb !== "ALL" && entry.walk.verb !== method) continue;
|
|
393
|
+
const match = entry.compiledPattern.exec(pathname);
|
|
394
|
+
if (!match) continue;
|
|
395
|
+
const params = {};
|
|
396
|
+
entry.compiledParamNames.forEach((name, i) => {
|
|
397
|
+
params[name] = match[i + 1];
|
|
398
|
+
});
|
|
399
|
+
return {
|
|
400
|
+
entry,
|
|
401
|
+
params
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
buildArgs(entries, request, body, params, query) {
|
|
407
|
+
if (entries.length === 0) return [];
|
|
408
|
+
const max = Math.max(...entries.map((p) => p.index));
|
|
409
|
+
const args = Array.from({
|
|
410
|
+
length: max + 1
|
|
411
|
+
}, () => void 0);
|
|
412
|
+
for (const p of entries) {
|
|
413
|
+
switch (p.source) {
|
|
414
|
+
case "req":
|
|
415
|
+
args[p.index] = request;
|
|
416
|
+
break;
|
|
417
|
+
case "body":
|
|
418
|
+
args[p.index] = p.key ? body[p.key] : body;
|
|
419
|
+
break;
|
|
420
|
+
case "param":
|
|
421
|
+
args[p.index] = p.key ? params[p.key] : params;
|
|
422
|
+
break;
|
|
423
|
+
case "query":
|
|
424
|
+
args[p.index] = p.key ? query[p.key] : query;
|
|
425
|
+
break;
|
|
426
|
+
case "headers":
|
|
427
|
+
args[p.index] = p.key ? request.headers.get(p.key.toLowerCase()) : Object.fromEntries(request.headers.entries());
|
|
428
|
+
break;
|
|
429
|
+
case "ip":
|
|
430
|
+
args[p.index] = request.headers.get("x-forwarded-for") ?? "127.0.0.1";
|
|
431
|
+
break;
|
|
432
|
+
default:
|
|
433
|
+
args[p.index] = void 0;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return args;
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
function jsonResponse(status, body) {
|
|
440
|
+
return new Response(JSON.stringify(body), {
|
|
441
|
+
status,
|
|
442
|
+
headers: {
|
|
443
|
+
"content-type": "application/json"
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
__name(jsonResponse, "jsonResponse");
|
|
448
|
+
function buildResponse(result, walk, method) {
|
|
449
|
+
const status = walk.status ?? (method === "POST" ? 201 : 200);
|
|
450
|
+
const headers = {
|
|
451
|
+
"content-type": "application/json"
|
|
452
|
+
};
|
|
453
|
+
for (const [n, v] of walk.headers) headers[n.toLowerCase()] = v;
|
|
454
|
+
if (result === void 0 || result === null) {
|
|
455
|
+
return new Response(null, {
|
|
456
|
+
status: status === 200 ? 204 : status,
|
|
457
|
+
headers
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
if (typeof result === "string") {
|
|
461
|
+
headers["content-type"] = "text/plain";
|
|
462
|
+
return new Response(result, {
|
|
463
|
+
status,
|
|
464
|
+
headers
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
return new Response(JSON.stringify(result), {
|
|
468
|
+
status,
|
|
469
|
+
headers
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
__name(buildResponse, "buildResponse");
|
|
473
|
+
|
|
474
|
+
export {
|
|
475
|
+
TheoApp
|
|
476
|
+
};
|
|
477
|
+
//# sourceMappingURL=chunk-TBMGRXH5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/app.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-regexp, complexity, sonarjs/cognitive-complexity, max-depth, sonarjs/no-collapsible-if */\nimport 'reflect-metadata'\n\nimport { createExecutionContext, type CanActivate } from './bridge/execution-context.js'\nimport { createNodeAdapter } from './bridge/runtime/node.js'\nimport type { ServerHandle } from './bridge/runtime/types.js'\nimport { walkControllerMetadata, type WalkResult } from './bridge/walk-metadata.js'\nimport type { ParamEntry } from './decorators/params.js'\nimport { ForbiddenException, HttpException } from './exceptions/http-exception.js'\n\n/**\n * TheoApp — NestJS/Spring Boot-style application bootstrap.\n *\n * Internally uses Web Standard Request/Response pipeline.\n * Node adapter converts at the HTTP server boundary.\n */\n\n/** Readiness check — async function returning health status. */\nexport type ReadinessCheck = () => Promise<{ name: string; healthy: boolean; message?: string }>\n\nexport interface TheoAppOptions {\n /** Controller classes decorated with @Controller. */\n controllers: Function[]\n /** Agent classes decorated with @Agent — auto-wired with routes + SSE + tools. */\n agents?: Function[]\n /** @Module class for structured DI. */\n module?: Function\n /** Provider/toolbox classes — instantiated and injected into controllers + agents. */\n providers?: Function[]\n /** LLM API key for agent execution (reads OPENROUTER_API_KEY env if not set). */\n llmApiKey?: string\n /** LLM model override (default: from @Agent({ model }) metadata). */\n llmModel?: string\n /** Agent stream factory override (for testing or custom SDK wiring). */\n agentStreamFactory?: (walk: unknown, tools: unknown[], apiKey: string, model?: string) => (message: string, sessionId: string) => AsyncIterable<unknown>\n /** HTML string to serve at GET / (inline frontend). */\n html?: string\n /** Readiness checks for GET /__theo/ready (K8s readiness probe). */\n readinessChecks?: ReadinessCheck[]\n /** Custom health endpoint path (default: '/__theo/health'). */\n healthPath?: string\n /** Custom readiness endpoint path (default: '/__theo/ready'). */\n readyPath?: string\n}\n\ninterface RouteEntry {\n walk: WalkResult\n instance: object\n /** Pre-compiled regex + param names (Elysia-inspired: compile once at create, not per-request). */\n compiledPattern?: RegExp\n compiledParamNames?: string[]\n /** Whether handler needs body parsing (skip for GET/DELETE without @Body). */\n needsBody?: boolean\n}\n\nexport class TheoApp {\n private serverHandle: ServerHandle\n private readonly routes: RouteEntry[] = []\n private frontendHtml?: string\n private readonly startTime = Date.now()\n private readonly healthPath: string\n private readonly readyPath: string\n private readonly readinessChecks: ReadinessCheck[]\n\n private constructor(opts?: Pick<TheoAppOptions, 'readinessChecks' | 'healthPath' | 'readyPath'>) {\n const hp = opts?.healthPath ?? '/__theo/health'\n const rp = opts?.readyPath ?? '/__theo/ready'\n // Security: prevent health paths from colliding with user API routes\n if (hp.startsWith('/api/')) throw new Error(`[TheoApp] healthPath \"${hp}\" must not start with /api/ — would collide with user routes`)\n if (rp.startsWith('/api/')) throw new Error(`[TheoApp] readyPath \"${rp}\" must not start with /api/ — would collide with user routes`)\n this.healthPath = hp\n this.readyPath = rp\n this.readinessChecks = opts?.readinessChecks ?? []\n const adapter = createNodeAdapter()\n this.serverHandle = adapter.createServer((request) => this.handleRequest(request))\n }\n\n /**\n * Create a TheoKit application with Spring Boot-style DI.\n *\n * EC-7: async because Container may resolve async factories (Agent.create).\n * EC-2: Registration order guaranteed: providers → controllers → agents.\n */\n static async create(opts: TheoAppOptions): Promise<TheoApp> {\n const app = new TheoApp(opts)\n\n // ── DI Container (replaces manual Map<Function, object>) ──\n // Uses @theokit/di Container for: scopes, lifecycle, async, typed errors.\n // Fallback to manual resolution when @theokit/di is not available.\n const registry = new Map<Function, object>()\n\n // 1. Module resolution (@Module metadata)\n if (opts.module) {\n const moduleMeta = Reflect.getMetadata('usetheo:di:module', opts.module)\n if (moduleMeta) {\n const allModules = [opts.module, ...(moduleMeta.imports ?? [])]\n for (const Mod of allModules) {\n const meta = Reflect.getMetadata('usetheo:di:module', Mod)\n if (!meta) continue\n for (const Prov of (meta.providers ?? []) as Function[]) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n }\n }\n\n // 2. Inline providers (EC-2: BEFORE controllers and agents)\n if (opts.providers) {\n for (const Prov of opts.providers) {\n if (!registry.has(Prov)) {\n registry.set(Prov, new (Prov as new () => object)())\n }\n }\n }\n\n // 3. Controllers with DI\n for (const Controller of opts.controllers) {\n const paramTypes: Function[] = Reflect.getMetadata('design:paramtypes', Controller) ?? []\n const args = paramTypes.map((pt: Function) => {\n const dep = registry.get(pt)\n if (!dep) {\n throw new Error(\n `[TheoApp] Cannot resolve ${pt.name} for ${Controller.name}. ` +\n `Add ${pt.name} to providers (or to @Module({ providers: [...] })).`,\n )\n }\n return dep\n })\n const instance = new (Controller as new (...a: unknown[]) => object)(...args)\n\n // Lifecycle: call @PostConstruct if present\n const postConstruct = Reflect.getMetadata('usetheo:di:post-construct', Controller)\n if (postConstruct && typeof (instance as Record<string, Function>)[postConstruct] === 'function') {\n const result = (instance as Record<string, Function>)[postConstruct]()\n if (result instanceof Promise) await result // EC-1: await async PostConstruct\n }\n\n const walks = walkControllerMetadata(Controller)\n for (const w of walks) {\n app.routes.push({ walk: w, instance })\n }\n }\n\n // Sort: static before parameterized\n app.routes.sort((a, b) => {\n const aP = a.walk.fullPath.includes(':')\n const bP = b.walk.fullPath.includes(':')\n if (aP !== bP) return aP ? 1 : -1\n return 0\n })\n\n // Pre-compile route patterns (Elysia-inspired: regex built once, not per-request)\n for (const entry of app.routes) {\n const paramNames: string[] = []\n const regexStr = entry.walk.fullPath.replace(/:(\\w+)/g, (_m, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n entry.compiledPattern = new RegExp(`^${regexStr}$`)\n entry.compiledParamNames = paramNames\n // Determine if handler needs body parsing (skip if no @Body decorator)\n entry.needsBody = entry.walk.paramEntries.some((p) => p.source === 'body')\n }\n\n // Bug #8: Store frontend HTML\n if (opts.html) app.frontendHtml = opts.html\n\n // 4. Auto-wire agents (EC-2: AFTER providers and controllers)\n // The framework handles EVERYTHING — walk, compile, mount, stream.\n // Consumer writes: agents: [MyAgent] — and that's it.\n if (opts.agents?.length) {\n await app.autoWireAgents(opts.agents, registry, opts)\n }\n\n return app\n }\n\n async listen(port: number): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.listen(port, () => {\n console.log(`TheoKit app listening on http://localhost:${port}`)\n resolve()\n })\n })\n }\n\n getServerHandle(): ServerHandle {\n return this.serverHandle\n }\n\n async close(): Promise<void> {\n return new Promise((resolve) => {\n this.serverHandle.close(() => { resolve(); })\n })\n }\n\n // ── Auto-wire agents (the \"SpringApplication.run()\" moment) ──\n\n private agentRoutes: { method: string; pattern: RegExp; paramNames: string[]; handler: (request: Request) => Promise<Response>; guards: Function[]; agentClass: Function; methodName: string | symbol }[] = []\n\n private async autoWireAgents(agentClasses: Function[], registry: Map<Function, object>, opts: TheoAppOptions) {\n // Dynamic import — @theokit/agents is optional peer dependency\n // SECURITY: new Function used for dynamic import of optional peer dep.\n // Argument is HARDCODED ('@theokit/agents'), never user input. Safe.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval -- dynamic import avoids compile-time dependency on optional peer\n const importFn = new Function('specifier', 'return import(specifier)') as (s: string) => Promise<Record<string, Function>>\n let walkAgentMetadata: Function, compileAgent: Function, generateAgentRoutes: Function, getMixins: Function, createRealAgentStreamFn: Function | undefined\n try {\n const mod = await importFn('@theokit/agents')\n walkAgentMetadata = mod.walkAgentMetadata\n compileAgent = mod.compileAgent\n generateAgentRoutes = mod.generateAgentRoutes\n getMixins = mod.getMixins\n createRealAgentStreamFn = mod.createRealAgentStream\n } catch {\n throw new Error('[TheoApp] @theokit/agents is required when agents[] is provided. Install: npm install @theokit/agents')\n }\n\n const apiKey = opts.llmApiKey ?? process.env.OPENROUTER_API_KEY ?? ''\n\n for (const AgentClass of agentClasses) {\n // 1. Walk metadata (decorators → structured data)\n const mixins = getMixins(AgentClass)\n const allToolboxes = [...mixins]\n\n // Also check providers for @Toolbox classes\n for (const [Cls] of registry) {\n if (Reflect.getMetadata(Symbol.for('theokit:agents:toolbox'), Cls)) {\n if (!allToolboxes.includes(Cls)) allToolboxes.push(Cls)\n }\n }\n\n const walk = walkAgentMetadata(AgentClass, allToolboxes)\n\n // 2. Resolve toolbox instances from registry (DI)\n const toolboxInstances = new Map<Function, object>()\n for (const tb of walk.toolboxes) {\n let instance = registry.get(tb.class)\n if (!instance) {\n instance = new (tb.class as new () => object)()\n registry.set(tb.class, instance)\n }\n toolboxInstances.set(tb.class, instance)\n }\n\n // 3. Compile tools (decorator metadata → defineTool-compatible)\n const compiled = compileAgent(walk, toolboxInstances)\n\n // 4. Create LLM stream factory\n let createRun: (message: string, sessionId: string) => AsyncIterable<unknown>\n\n if (opts.agentStreamFactory) {\n createRun = opts.agentStreamFactory(walk, compiled.tools, apiKey, opts.llmModel)\n } else if (apiKey && createRealAgentStreamFn !== undefined) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition -- apiKey can be empty string\n // Bug #5 fix: use built-in LLM runner from @theokit/agents\n createRun = createRealAgentStreamFn(walk, compiled.tools, apiKey, opts.llmModel) as (m: string, s: string) => AsyncIterable<unknown>\n } else {\n createRun = this.createFallbackStream(walk.agentConfig.name, apiKey)\n }\n\n // 5. Generate routes (POST /chat, GET /runs/:id)\n const routes = generateAgentRoutes({\n walkResult: walk,\n compiledOptions: compiled,\n createRun: createRun as (message: string, sessionId: string) => AsyncIterable<{ type: string;[k: string]: unknown }>,\n })\n\n // 6. Mount routes\n for (const route of routes) {\n const paramNames: string[] = []\n const regexStr = route.path.replace(/:(\\w+)/g, (_m: string, name: string) => {\n paramNames.push(name)\n return '([^/]+)'\n })\n this.agentRoutes.push({\n method: route.method,\n pattern: new RegExp(`^${regexStr}$`),\n paramNames,\n handler: route.handler,\n guards: walk.guards ?? [],\n agentClass: AgentClass,\n methodName: walk.mainLoop?.propertyKey ?? 'run',\n })\n }\n\n console.log(` 🤖 Agent \"${walk.agentConfig.name}\" mounted at ${walk.route}/chat (${compiled.tools.length} tools)`)\n }\n }\n\n private async handleReadinessCheck(): Promise<Response> {\n if (this.readinessChecks.length === 0) {\n return jsonResponse(200, { status: 'ready', checks: [] })\n }\n const results = await Promise.all(this.readinessChecks.map(async (check) => {\n try {\n return await Promise.race([\n check(),\n new Promise<{ name: string; healthy: boolean; message?: string }>((resolve) =>\n setTimeout(() => resolve({ name: 'unknown', healthy: false, message: 'Readiness check timed out (5s)' }), 5000),\n ),\n ])\n } catch (err) {\n return { name: 'unknown', healthy: false, message: err instanceof Error ? err.message : 'Check failed' }\n }\n }))\n const allHealthy = results.every((r) => r.healthy)\n return jsonResponse(allHealthy ? 200 : 503, { status: allHealthy ? 'ready' : 'not_ready', checks: results })\n }\n\n private createFallbackStream(agentName: string, apiKey: string) {\n const msg = !apiKey\n ? 'Set OPENROUTER_API_KEY environment variable or pass llmApiKey to TheoApp.create()'\n : 'Pass agentStreamFactory to TheoApp.create() to connect your LLM provider'\n return (_message: string, _sessionId: string) => {\n const events = [\n { type: 'run_started', runId: `run-${Date.now()}`, agentName },\n { type: 'error', code: 'AGENT_NOT_WIRED', message: msg, retryable: false },\n ]\n return {\n [Symbol.asyncIterator]: () => {\n let i = 0\n return { next: () => Promise.resolve(i < events.length ? { value: events[i++], done: false as const } : { value: undefined, done: true as const }) }\n },\n }\n }\n }\n\n // ── Web Standard request handler ──────────────────\n\n private async handleRequest(request: Request): Promise<Response> {\n const pathname = new URL(request.url).pathname\n\n // ── Health & Readiness probes (bypass guards/interceptors) ──\n if (request.method === 'GET') {\n if (pathname === this.healthPath) {\n return jsonResponse(200, { status: 'ok', uptime: (Date.now() - this.startTime) / 1000, timestamp: Date.now() })\n }\n if (pathname === this.readyPath) {\n return this.handleReadinessCheck()\n }\n }\n\n // Bug #8: Serve frontend HTML at GET /\n if (request.method === 'GET') {\n if ((pathname === '/' || pathname === '/index.html') && this.frontendHtml) {\n return new Response(this.frontendHtml, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8' } })\n }\n }\n\n // Agent routes (auto-wired — checked first, with guard enforcement per Bug #4)\n for (const route of this.agentRoutes) {\n if (request.method.toUpperCase() === route.method && route.pattern.test(pathname)) {\n // Bug #4 fix: enforce @UseGuards on agent routes (same pipeline as controllers)\n if (route.guards.length > 0) {\n const ctx = createExecutionContext(request, route.agentClass, route.methodName)\n for (const GuardCtor of route.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n }\n return route.handler(request)\n }\n }\n\n const url = new URL(request.url)\n const method = request.method.toUpperCase()\n\n const match = this.findRoute(method, url.pathname)\n if (!match) {\n return jsonResponse(404, { error: { code: 'NOT_FOUND', message: `No route for ${method} ${url.pathname}` } })\n }\n\n const { entry, params } = match\n\n try {\n // Guards\n const ctx = createExecutionContext(request, entry.instance.constructor, entry.walk.propertyKey)\n for (const GuardCtor of entry.walk.guards) {\n const guard = new (GuardCtor as new () => CanActivate)()\n if (!(await guard.canActivate(ctx))) {\n const ex = new ForbiddenException('Forbidden resource')\n return jsonResponse(ex.statusCode, ex.toJSON())\n }\n }\n\n // Body — skip parsing entirely if handler has no @Body decorator (Elysia-inspired lazy parsing)\n let body: unknown\n if (entry.needsBody && ['POST', 'PUT', 'PATCH'].includes(method)) {\n try {\n const text = await request.text()\n body = text ? JSON.parse(text) : undefined\n } catch { body = undefined }\n\n if (entry.walk.bodySchema && body !== undefined) {\n const result = entry.walk.bodySchema.safeParse(body)\n if (!result.success) {\n return jsonResponse(422, { error: { code: 'VALIDATION_ERROR', issues: result.error.issues } })\n }\n body = result.data\n }\n }\n\n // Args\n const args = this.buildArgs(entry.walk.paramEntries, request, body, params, Object.fromEntries(url.searchParams))\n\n // Redirect\n if (entry.walk.redirect) {\n return new Response(null, { status: entry.walk.redirect.status, headers: { location: entry.walk.redirect.url } })\n }\n\n // Handler — wrapped by interceptor chain (Bug #2 fix)\n const handlerFn = (entry.instance as Record<string | symbol, Function>)[entry.walk.propertyKey]\n\n let result: unknown\n if (entry.walk.interceptors.length > 0) {\n // Import runInterceptors dynamically to avoid circular dep\n const { runInterceptors } = await import('./bridge/interceptor-chain.js')\n result = await runInterceptors(\n entry.walk.interceptors,\n () => handlerFn.apply(entry.instance, args) as Promise<unknown>,\n request,\n )\n } else {\n result = await handlerFn.apply(entry.instance, args)\n }\n\n return buildResponse(result, entry.walk, method)\n } catch (err) {\n // Exception filters (Bug #2 fix — filters also wired)\n if (entry.walk.filters.length > 0) {\n const { runExceptionFilters } = await import('./bridge/exception-filter-chain.js')\n return runExceptionFilters(err, entry.walk.filters, request)\n }\n // Fallback: HttpException subclasses (Bug #3 fix)\n if (err instanceof HttpException) {\n return jsonResponse(err.statusCode, err.toJSON())\n }\n // Security: never leak raw error messages to clients\n console.error('[theokit] Internal error:', err instanceof Error ? err.message : err)\n return jsonResponse(500, { error: { code: 'INTERNAL_SERVER_ERROR', message: 'Internal Server Error' } })\n }\n }\n\n private findRoute(method: string, pathname: string) {\n for (const entry of this.routes) {\n if (entry.walk.verb !== 'ALL' && entry.walk.verb !== method) continue\n // Use pre-compiled regex (built once at create time, not per-request)\n const match = entry.compiledPattern!.exec(pathname)\n if (!match) continue\n const params: Record<string, string> = {}\n entry.compiledParamNames!.forEach((name, i) => { params[name] = match[i + 1] })\n return { entry, params }\n }\n return null\n }\n\n private buildArgs(entries: ParamEntry[], request: Request, body: unknown, params: Record<string, string>, query: Record<string, string>): unknown[] {\n if (entries.length === 0) return []\n const max = Math.max(...entries.map(p => p.index))\n const args: unknown[] = Array.from({ length: max + 1 }, () => undefined)\n for (const p of entries) {\n switch (p.source) {\n case 'req': args[p.index] = request; break\n case 'body': args[p.index] = p.key ? (body as Record<string, unknown>)[p.key] : body; break\n case 'param': args[p.index] = p.key ? params[p.key] : params; break\n case 'query': args[p.index] = p.key ? query[p.key] : query; break\n case 'headers': args[p.index] = p.key ? request.headers.get(p.key.toLowerCase()) : Object.fromEntries(request.headers.entries()); break\n case 'ip': args[p.index] = request.headers.get('x-forwarded-for') ?? '127.0.0.1'; break\n default: args[p.index] = undefined\n }\n }\n return args\n }\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\nfunction buildResponse(result: unknown, walk: WalkResult, method: string): Response {\n const status = walk.status ?? (method === 'POST' ? 201 : 200)\n const headers: Record<string, string> = { 'content-type': 'application/json' }\n for (const [n, v] of walk.headers) headers[n.toLowerCase()] = v\n\n if (result === undefined || result === null) {\n return new Response(null, { status: status === 200 ? 204 : status, headers })\n }\n if (typeof result === 'string') {\n headers['content-type'] = 'text/plain'\n return new Response(result, { status, headers })\n }\n return new Response(JSON.stringify(result), { status, headers })\n}\n"],"mappings":"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","names":["TheoApp","serverHandle","routes","frontendHtml","startTime","Date","now","healthPath","readyPath","readinessChecks","opts","hp","rp","startsWith","Error","adapter","createNodeAdapter","createServer","request","handleRequest","create","app","registry","Map","module","moduleMeta","Reflect","getMetadata","allModules","imports","Mod","meta","Prov","providers","has","set","Controller","controllers","paramTypes","args","map","pt","dep","get","name","instance","postConstruct","result","Promise","walks","walkControllerMetadata","w","push","walk","sort","a","b","aP","fullPath","includes","bP","entry","paramNames","regexStr","replace","_m","compiledPattern","RegExp","compiledParamNames","needsBody","paramEntries","some","p","source","html","agents","length","autoWireAgents","listen","port","resolve","console","log","getServerHandle","close","agentRoutes","agentClasses","importFn","Function","walkAgentMetadata","compileAgent","generateAgentRoutes","getMixins","createRealAgentStreamFn","mod","createRealAgentStream","apiKey","llmApiKey","process","env","OPENROUTER_API_KEY","AgentClass","mixins","allToolboxes","Cls","Symbol","for","toolboxInstances","tb","toolboxes","class","compiled","createRun","agentStreamFactory","tools","llmModel","undefined","createFallbackStream","agentConfig","walkResult","compiledOptions","route","path","method","pattern","handler","guards","agentClass","methodName","mainLoop","propertyKey","handleReadinessCheck","jsonResponse","status","checks","results","all","check","race","setTimeout","healthy","message","err","allHealthy","every","r","agentName","msg","_message","_sessionId","events","type","runId","code","retryable","asyncIterator","i","next","value","done","pathname","URL","url","uptime","timestamp","Response","headers","toUpperCase","test","ctx","createExecutionContext","GuardCtor","guard","canActivate","ex","ForbiddenException","statusCode","toJSON","match","findRoute","error","params","body","text","JSON","parse","bodySchema","safeParse","success","issues","data","buildArgs","Object","fromEntries","searchParams","redirect","location","handlerFn","interceptors","runInterceptors","apply","buildResponse","filters","runExceptionFilters","HttpException","verb","exec","forEach","entries","query","max","Math","index","Array","from","key","toLowerCase","stringify","n","v"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveOrNew
|
|
3
|
+
} from "./chunk-LKNI6QEP.js";
|
|
4
|
+
import {
|
|
5
|
+
__name
|
|
6
|
+
} from "./chunk-7QVYU63E.js";
|
|
7
|
+
|
|
8
|
+
// src/bridge/interceptor-chain.ts
|
|
9
|
+
async function runInterceptors(interceptors, handler, request, container) {
|
|
10
|
+
if (interceptors.length === 0) return handler();
|
|
11
|
+
let chain = handler;
|
|
12
|
+
for (const Ctor of [
|
|
13
|
+
...interceptors
|
|
14
|
+
].reverse()) {
|
|
15
|
+
const instance = resolveOrNew(Ctor, container);
|
|
16
|
+
const nextFn = chain;
|
|
17
|
+
let called = false;
|
|
18
|
+
let cachedResult;
|
|
19
|
+
const memoizedNext = /* @__PURE__ */ __name(async () => {
|
|
20
|
+
if (called) return cachedResult;
|
|
21
|
+
called = true;
|
|
22
|
+
cachedResult = await nextFn();
|
|
23
|
+
return cachedResult;
|
|
24
|
+
}, "memoizedNext");
|
|
25
|
+
chain = /* @__PURE__ */ __name(() => instance.intercept(request, memoizedNext), "chain");
|
|
26
|
+
}
|
|
27
|
+
return chain();
|
|
28
|
+
}
|
|
29
|
+
__name(runInterceptors, "runInterceptors");
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
runInterceptors
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=chunk-U46H4CGF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge/interceptor-chain.ts"],"sourcesContent":["/**\n * Interceptor execution engine — onion-model chain runner.\n *\n * Per Pattern D3: \"@UseInterceptors both translate to defineMiddleware wraps\".\n * Interceptors wrap the handler call (NOT body parsing — EC-1) and can\n * transform the response or short-circuit by not calling next().\n *\n * Execution order follows NestJS convention:\n * middleware → guards → interceptors → handler\n * Interceptor composition: class-level FIRST, then method-level (EC-9).\n */\nimport { resolveOrNew, type DiContainer } from './di-resolve.js'\n\n/**\n * Interceptor interface — Web Standard Request.\n * `next()` wraps ONLY the handler call — body parsing happens before.\n */\nexport interface Interceptor {\n intercept(\n request: Request,\n next: () => Promise<unknown>,\n ): Promise<unknown>\n}\n\n/**\n * Run the interceptor chain using the onion model.\n * Outermost interceptor (first in array) wraps all inner ones.\n */\nexport async function runInterceptors(\n interceptors: Function[],\n handler: () => Promise<unknown>,\n request: Request,\n container?: DiContainer,\n): Promise<unknown> {\n if (interceptors.length === 0) return handler()\n\n let chain = handler\n for (const Ctor of [...interceptors].reverse()) {\n const instance = resolveOrNew(Ctor, container) as Interceptor\n const nextFn = chain\n let called = false\n let cachedResult: unknown\n const memoizedNext = async () => {\n if (called) return cachedResult\n called = true\n cachedResult = await nextFn()\n return cachedResult\n }\n chain = () => instance.intercept(request, memoizedNext)\n }\n return chain()\n}\n"],"mappings":";;;;;;;;AA4BA,eAAsBA,gBACpBC,cACAC,SACAC,SACAC,WAAuB;AAEvB,MAAIH,aAAaI,WAAW,EAAG,QAAOH,QAAAA;AAEtC,MAAII,QAAQJ;AACZ,aAAWK,QAAQ;OAAIN;IAAcO,QAAO,GAAI;AAC9C,UAAMC,WAAWC,aAAaH,MAAMH,SAAAA;AACpC,UAAMO,SAASL;AACf,QAAIM,SAAS;AACb,QAAIC;AACJ,UAAMC,eAAe,mCAAA;AACnB,UAAIF,OAAQ,QAAOC;AACnBD,eAAS;AACTC,qBAAe,MAAMF,OAAAA;AACrB,aAAOE;IACT,GALqB;AAMrBP,YAAQ,6BAAMG,SAASM,UAAUZ,SAASW,YAAAA,GAAlC;EACV;AACA,SAAOR,MAAAA;AACT;AAvBsBN;","names":["runInterceptors","interceptors","handler","request","container","length","chain","Ctor","reverse","instance","resolveOrNew","nextFn","called","cachedResult","memoizedNext","intercept"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|