@standardagents/builder 0.8.1

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.
@@ -0,0 +1,2333 @@
1
+ import { z } from 'zod';
2
+
3
+ // ../../node_modules/.pnpm/rou3@0.7.9/node_modules/rou3/dist/index.mjs
4
+ var NullProtoObj = /* @__PURE__ */ (() => {
5
+ const e = function() {
6
+ };
7
+ return e.prototype = /* @__PURE__ */ Object.create(null), Object.freeze(e.prototype), e;
8
+ })();
9
+ function splitPath(path) {
10
+ const [_, ...s] = path.split("/");
11
+ return s[s.length - 1] === "" ? s.slice(0, -1) : s;
12
+ }
13
+ function addRoute(ctx, method = "", path, data) {
14
+ method = method.toUpperCase();
15
+ if (path.charCodeAt(0) !== 47) path = `/${path}`;
16
+ const segments = splitPath(path);
17
+ let node = ctx.root;
18
+ let _unnamedParamIndex = 0;
19
+ const paramsMap = [];
20
+ const paramsRegexp = [];
21
+ for (let i = 0; i < segments.length; i++) {
22
+ const segment = segments[i];
23
+ if (segment.startsWith("**")) {
24
+ if (!node.wildcard) node.wildcard = { key: "**" };
25
+ node = node.wildcard;
26
+ paramsMap.push([
27
+ -i,
28
+ segment.split(":")[1] || "_",
29
+ segment.length === 2
30
+ ]);
31
+ break;
32
+ }
33
+ if (segment === "*" || segment.includes(":")) {
34
+ if (!node.param) node.param = { key: "*" };
35
+ node = node.param;
36
+ if (segment === "*") paramsMap.push([
37
+ i,
38
+ `_${_unnamedParamIndex++}`,
39
+ true
40
+ ]);
41
+ else if (segment.includes(":", 1)) {
42
+ const regexp = getParamRegexp(segment);
43
+ paramsRegexp[i] = regexp;
44
+ node.hasRegexParam = true;
45
+ paramsMap.push([
46
+ i,
47
+ regexp,
48
+ false
49
+ ]);
50
+ } else paramsMap.push([
51
+ i,
52
+ segment.slice(1),
53
+ false
54
+ ]);
55
+ continue;
56
+ }
57
+ const child = node.static?.[segment];
58
+ if (child) node = child;
59
+ else {
60
+ const staticNode = { key: segment };
61
+ if (!node.static) node.static = new NullProtoObj();
62
+ node.static[segment] = staticNode;
63
+ node = staticNode;
64
+ }
65
+ }
66
+ const hasParams = paramsMap.length > 0;
67
+ if (!node.methods) node.methods = new NullProtoObj();
68
+ node.methods[method] ??= [];
69
+ node.methods[method].push({
70
+ data: data || null,
71
+ paramsRegexp,
72
+ paramsMap: hasParams ? paramsMap : void 0
73
+ });
74
+ if (!hasParams) ctx.static[path] = node;
75
+ }
76
+ function getParamRegexp(segment) {
77
+ const regex = segment.replace(/:(\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\./g, "\\.");
78
+ return /* @__PURE__ */ new RegExp(`^${regex}$`);
79
+ }
80
+
81
+ // src/router/index.ts
82
+ function defineController(controller) {
83
+ return controller;
84
+ }
85
+
86
+ // src/api/index.post.ts
87
+ var index_post_default = defineController(() => {
88
+ const stream = new ReadableStream({
89
+ start(controller) {
90
+ const text = "hello world";
91
+ let index = 0;
92
+ const next = () => {
93
+ if (index < text.length) {
94
+ controller.enqueue(new TextEncoder().encode(text[index]));
95
+ index++;
96
+ setTimeout(next, 100);
97
+ } else {
98
+ controller.close();
99
+ }
100
+ };
101
+ next();
102
+ }
103
+ });
104
+ return new Response(stream);
105
+ });
106
+
107
+ // src/api/agents.get.ts
108
+ var agents_get_default = defineController(async ({ agents, agentNames, prompts, promptNames }) => {
109
+ if (!agents || !agentNames) {
110
+ return Response.json({ agents: [] });
111
+ }
112
+ const promptMap = {};
113
+ if (prompts && promptNames) {
114
+ await Promise.all(
115
+ promptNames.map(async (name) => {
116
+ try {
117
+ const loader = prompts[name];
118
+ if (loader) {
119
+ promptMap[name] = await loader();
120
+ }
121
+ } catch (error) {
122
+ }
123
+ })
124
+ );
125
+ }
126
+ const agentList = await Promise.all(
127
+ agentNames.map(async (name) => {
128
+ try {
129
+ const loader = agents[name];
130
+ if (!loader) {
131
+ return null;
132
+ }
133
+ const definition = await loader();
134
+ const sideAPrompt = promptMap[definition.sideA?.prompt];
135
+ const sideBPrompt = definition.sideB ? promptMap[definition.sideB?.prompt] : null;
136
+ return {
137
+ id: definition.name,
138
+ name: definition.name,
139
+ title: definition.title,
140
+ type: definition.type || "ai_human",
141
+ // Side A configuration
142
+ side_a_label: definition.sideA?.label || null,
143
+ side_a_agent_prompt: definition.sideA?.prompt,
144
+ side_a_agent_prompt_name: sideAPrompt?.name || definition.sideA?.prompt,
145
+ side_a_stop_on_response: definition.sideA?.stopOnResponse !== void 0 ? definition.sideA.stopOnResponse : true,
146
+ side_a_stop_tool: definition.sideA?.stopTool || null,
147
+ side_a_stop_tool_response_property: definition.sideA?.stopToolResponseProperty || null,
148
+ side_a_max_turns: definition.sideA?.maxTurns || null,
149
+ side_a_end_conversation_tool: definition.sideA?.endConversationTool || null,
150
+ side_a_manual_stop_condition: definition.sideA?.manualStopCondition || false,
151
+ // Side B configuration (if dual_ai)
152
+ side_b_label: definition.sideB?.label || null,
153
+ side_b_agent_prompt: definition.sideB?.prompt || null,
154
+ side_b_agent_prompt_name: sideBPrompt?.name || definition.sideB?.prompt || null,
155
+ side_b_stop_on_response: definition.sideB?.stopOnResponse !== void 0 ? definition.sideB.stopOnResponse : true,
156
+ side_b_stop_tool: definition.sideB?.stopTool || null,
157
+ side_b_stop_tool_response_property: definition.sideB?.stopToolResponseProperty || null,
158
+ side_b_max_turns: definition.sideB?.maxTurns || null,
159
+ side_b_end_conversation_tool: definition.sideB?.endConversationTool || null,
160
+ side_b_manual_stop_condition: definition.sideB?.manualStopCondition || false,
161
+ // Session configuration
162
+ max_session_turns: definition.maxSessionTurns || null,
163
+ // Tool exposure
164
+ expose_as_tool: definition.exposeAsTool || false,
165
+ tool_description: definition.toolDescription || null,
166
+ // Tags
167
+ tags: definition.tags || [],
168
+ created_at: Math.floor(Date.now() / 1e3)
169
+ };
170
+ } catch (error) {
171
+ console.error(`Error loading agent ${name}:`, error);
172
+ return null;
173
+ }
174
+ })
175
+ );
176
+ const validAgents = agentList.filter(Boolean);
177
+ return Response.json({ agents: validAgents });
178
+ });
179
+
180
+ // src/utils/auth.ts
181
+ function generateSecureToken(length = 32) {
182
+ const array = new Uint8Array(length);
183
+ crypto.getRandomValues(array);
184
+ return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
185
+ }
186
+ function generateUserToken() {
187
+ return `agtuser_${generateSecureToken(32)}`;
188
+ }
189
+ function generateApiKey() {
190
+ return `agtbldr_${generateSecureToken(32)}`;
191
+ }
192
+ async function hashPassword(password) {
193
+ const encoder = new TextEncoder();
194
+ const data = encoder.encode(password);
195
+ const salt = crypto.getRandomValues(new Uint8Array(16));
196
+ const keyMaterial = await crypto.subtle.importKey(
197
+ "raw",
198
+ data,
199
+ { name: "PBKDF2" },
200
+ false,
201
+ ["deriveBits"]
202
+ );
203
+ const derivedBits = await crypto.subtle.deriveBits(
204
+ {
205
+ name: "PBKDF2",
206
+ salt,
207
+ iterations: 1e5,
208
+ hash: "SHA-256"
209
+ },
210
+ keyMaterial,
211
+ 256
212
+ );
213
+ const hashArray = new Uint8Array(derivedBits);
214
+ const combined = new Uint8Array(salt.length + hashArray.length);
215
+ combined.set(salt);
216
+ combined.set(hashArray, salt.length);
217
+ return bufferToBase64(combined);
218
+ }
219
+ async function verifyPassword(password, hash) {
220
+ try {
221
+ const combined = base64ToBuffer(hash);
222
+ const salt = combined.slice(0, 16);
223
+ const storedHash = combined.slice(16);
224
+ const encoder = new TextEncoder();
225
+ const data = encoder.encode(password);
226
+ const keyMaterial = await crypto.subtle.importKey(
227
+ "raw",
228
+ data,
229
+ { name: "PBKDF2" },
230
+ false,
231
+ ["deriveBits"]
232
+ );
233
+ const derivedBits = await crypto.subtle.deriveBits(
234
+ {
235
+ name: "PBKDF2",
236
+ salt,
237
+ iterations: 1e5,
238
+ hash: "SHA-256"
239
+ },
240
+ keyMaterial,
241
+ 256
242
+ );
243
+ const derivedHash = new Uint8Array(derivedBits);
244
+ if (derivedHash.length !== storedHash.length) {
245
+ return false;
246
+ }
247
+ let matches = true;
248
+ for (let i = 0; i < derivedHash.length; i++) {
249
+ if (derivedHash[i] !== storedHash[i]) {
250
+ matches = false;
251
+ }
252
+ }
253
+ return matches;
254
+ } catch (error) {
255
+ console.error("Error verifying password:", error);
256
+ return false;
257
+ }
258
+ }
259
+ async function hashToken(token) {
260
+ const encoder = new TextEncoder();
261
+ const data = encoder.encode(token);
262
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
263
+ const hashArray = new Uint8Array(hashBuffer);
264
+ return Array.from(hashArray, (byte) => byte.toString(16).padStart(2, "0")).join("");
265
+ }
266
+ function getLastChars(str, count = 5) {
267
+ return str.slice(-count);
268
+ }
269
+ function getTokenPrefix(token) {
270
+ const match = token.match(/^([^_]+_)/);
271
+ return match ? match[1] : "";
272
+ }
273
+ function isValidUserToken(token) {
274
+ return token.startsWith("agtuser_") && token.length > 10;
275
+ }
276
+ function isValidApiKey(key) {
277
+ return key.startsWith("agtbldr_") && key.length > 10;
278
+ }
279
+ async function signToken(payload, encryptionKey) {
280
+ const encoder = new TextEncoder();
281
+ const keyData = encoder.encode(encryptionKey);
282
+ const cryptoKey = await crypto.subtle.importKey(
283
+ "raw",
284
+ keyData,
285
+ { name: "HMAC", hash: "SHA-256" },
286
+ false,
287
+ ["sign"]
288
+ );
289
+ const payloadData = encoder.encode(payload);
290
+ const signature = await crypto.subtle.sign("HMAC", cryptoKey, payloadData);
291
+ const payloadB64 = bufferToBase64(new Uint8Array(payloadData));
292
+ const signatureB64 = bufferToBase64(new Uint8Array(signature));
293
+ return `${payloadB64}.${signatureB64}`;
294
+ }
295
+ async function verifySignedToken(signedToken, encryptionKey) {
296
+ try {
297
+ const parts = signedToken.split(".");
298
+ if (parts.length !== 2) {
299
+ return null;
300
+ }
301
+ const [payloadB64, signatureB64] = parts;
302
+ const encoder = new TextEncoder();
303
+ const keyData = encoder.encode(encryptionKey);
304
+ const cryptoKey = await crypto.subtle.importKey(
305
+ "raw",
306
+ keyData,
307
+ { name: "HMAC", hash: "SHA-256" },
308
+ false,
309
+ ["verify"]
310
+ );
311
+ const payloadData = base64ToBuffer(payloadB64);
312
+ const signature = base64ToBuffer(signatureB64);
313
+ const isValid = await crypto.subtle.verify("HMAC", cryptoKey, signature, payloadData);
314
+ if (!isValid) {
315
+ return null;
316
+ }
317
+ const decoder = new TextDecoder();
318
+ return decoder.decode(payloadData);
319
+ } catch (error) {
320
+ console.error("Error verifying signed token:", error);
321
+ return null;
322
+ }
323
+ }
324
+ async function generateSuperAdminToken(encryptionKey) {
325
+ const timestamp = Date.now();
326
+ const nonce = generateSecureToken(16);
327
+ const payload = `super_admin:${timestamp}:${nonce}`;
328
+ return await signToken(payload, encryptionKey);
329
+ }
330
+ async function verifySuperAdminToken(token, encryptionKey) {
331
+ const payload = await verifySignedToken(token, encryptionKey);
332
+ if (!payload) {
333
+ return false;
334
+ }
335
+ const parts = payload.split(":");
336
+ if (parts.length !== 3 || parts[0] !== "super_admin") {
337
+ return false;
338
+ }
339
+ const timestamp = parseInt(parts[1], 10);
340
+ const age = Date.now() - timestamp;
341
+ const maxAge = 30 * 24 * 60 * 60 * 1e3;
342
+ if (age > maxAge) {
343
+ return false;
344
+ }
345
+ return true;
346
+ }
347
+ function bufferToBase64(buffer) {
348
+ let binary = "";
349
+ for (let i = 0; i < buffer.byteLength; i++) {
350
+ binary += String.fromCharCode(buffer[i]);
351
+ }
352
+ return btoa(binary);
353
+ }
354
+ function base64ToBuffer(base64) {
355
+ const binary = atob(base64);
356
+ const bytes = new Uint8Array(binary.length);
357
+ for (let i = 0; i < binary.length; i++) {
358
+ bytes[i] = binary.charCodeAt(i);
359
+ }
360
+ return bytes;
361
+ }
362
+
363
+ // src/middleware/auth.ts
364
+ function extractBearerToken(request) {
365
+ const authHeader = request.headers.get("Authorization");
366
+ if (authHeader && authHeader.startsWith("Bearer ")) {
367
+ return authHeader.substring(7);
368
+ }
369
+ const isWebSocket = request.headers.get("upgrade")?.toLowerCase() === "websocket";
370
+ if (isWebSocket) {
371
+ try {
372
+ const url = new URL(request.url);
373
+ const token = url.searchParams.get("token");
374
+ if (token) {
375
+ return token;
376
+ }
377
+ } catch (err) {
378
+ }
379
+ }
380
+ return null;
381
+ }
382
+ function getAgentBuilder(env) {
383
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
384
+ return env.AGENT_BUILDER.get(agentBuilderId);
385
+ }
386
+ async function authenticate(request, env) {
387
+ const token = extractBearerToken(request);
388
+ if (!token) {
389
+ return null;
390
+ }
391
+ if (env.SUPER_ADMIN_PASSWORD && env.ENCRYPTION_KEY) {
392
+ if (token.includes(".")) {
393
+ const isValidSuperAdmin = await verifySuperAdminToken(
394
+ token,
395
+ env.ENCRYPTION_KEY
396
+ );
397
+ if (isValidSuperAdmin) {
398
+ return {
399
+ user: {
400
+ id: "super_admin",
401
+ username: "admin",
402
+ role: "admin"
403
+ },
404
+ authType: "super_admin"
405
+ };
406
+ }
407
+ }
408
+ }
409
+ if (isValidUserToken(token)) {
410
+ const tokenHash = await hashToken(token);
411
+ const agentBuilder = getAgentBuilder(env);
412
+ const session = await agentBuilder.validateSession(tokenHash);
413
+ if (session) {
414
+ const user = await agentBuilder.getUserById(session.user_id);
415
+ if (user) {
416
+ return {
417
+ user: {
418
+ id: user.id,
419
+ username: user.username,
420
+ role: user.role
421
+ },
422
+ authType: "session"
423
+ };
424
+ }
425
+ }
426
+ }
427
+ if (isValidApiKey(token)) {
428
+ const keyHash = await hashToken(token);
429
+ const agentBuilder = getAgentBuilder(env);
430
+ const apiKey = await agentBuilder.validateApiKey(keyHash);
431
+ if (apiKey) {
432
+ const user = await agentBuilder.getUserById(apiKey.user_id);
433
+ if (user) {
434
+ return {
435
+ user: {
436
+ id: user.id,
437
+ username: user.username,
438
+ role: user.role
439
+ },
440
+ authType: "api_key"
441
+ };
442
+ }
443
+ }
444
+ }
445
+ return null;
446
+ }
447
+ async function requireAuth(request, env) {
448
+ const authContext = await authenticate(request, env);
449
+ if (!authContext) {
450
+ return new Response(JSON.stringify({ error: "Unauthorized" }), {
451
+ status: 401,
452
+ headers: { "Content-Type": "application/json" }
453
+ });
454
+ }
455
+ return authContext;
456
+ }
457
+ async function requireAdmin(request, env) {
458
+ const result = await requireAuth(request, env);
459
+ if (result instanceof Response) {
460
+ return result;
461
+ }
462
+ if (result.user.role !== "admin") {
463
+ return new Response(
464
+ JSON.stringify({ error: "Forbidden: Admin access required" }),
465
+ {
466
+ status: 403,
467
+ headers: { "Content-Type": "application/json" }
468
+ }
469
+ );
470
+ }
471
+ return result;
472
+ }
473
+
474
+ // src/api/api-keys/index.get.ts
475
+ var index_get_default = defineController(async ({ req, env }) => {
476
+ try {
477
+ const authResult = await requireAuth(req, env);
478
+ if (authResult instanceof Response) {
479
+ return authResult;
480
+ }
481
+ if (authResult.authType === "super_admin") {
482
+ return Response.json({ keys: [], message: "Super admin has no API keys. Create a user account to manage API keys." });
483
+ }
484
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
485
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
486
+ const keys = await agentBuilder.listApiKeys(authResult.user.id);
487
+ return Response.json({ keys });
488
+ } catch (error) {
489
+ console.error("List API keys error:", error);
490
+ return Response.json(
491
+ { error: error.message || "Failed to list API keys" },
492
+ { status: 500 }
493
+ );
494
+ }
495
+ });
496
+
497
+ // src/api/api-keys/index.post.ts
498
+ var index_post_default2 = defineController(async ({ req, env }) => {
499
+ try {
500
+ const authResult = await requireAuth(req, env);
501
+ if (authResult instanceof Response) {
502
+ return authResult;
503
+ }
504
+ if (authResult.authType === "super_admin") {
505
+ return Response.json(
506
+ { error: "Super admin cannot create API keys. Please create a user account first." },
507
+ { status: 400 }
508
+ );
509
+ }
510
+ const body = await req.json();
511
+ const { name } = body;
512
+ if (!name || typeof name !== "string") {
513
+ return Response.json(
514
+ { error: "Name is required" },
515
+ { status: 400 }
516
+ );
517
+ }
518
+ if (name.length < 1 || name.length > 100) {
519
+ return Response.json(
520
+ { error: "Name must be between 1 and 100 characters" },
521
+ { status: 400 }
522
+ );
523
+ }
524
+ const apiKey = generateApiKey();
525
+ const keyHash = await hashToken(apiKey);
526
+ const keyPrefix = getTokenPrefix(apiKey);
527
+ const lastFive = getLastChars(apiKey, 5);
528
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
529
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
530
+ const id = await agentBuilder.createApiKey({
531
+ name,
532
+ key_hash: keyHash,
533
+ key_prefix: keyPrefix,
534
+ last_five: lastFive,
535
+ user_id: authResult.user.id
536
+ });
537
+ const now = Math.floor(Date.now() / 1e3);
538
+ return Response.json({
539
+ key: apiKey,
540
+ // Only returned once on creation
541
+ id,
542
+ name,
543
+ key_prefix: keyPrefix,
544
+ last_five: lastFive,
545
+ created_at: now
546
+ }, { status: 201 });
547
+ } catch (error) {
548
+ console.error("Create API key error:", error);
549
+ return Response.json(
550
+ { error: error.message || "Failed to create API key" },
551
+ { status: 500 }
552
+ );
553
+ }
554
+ });
555
+
556
+ // src/api/config.get.ts
557
+ var config_get_default = defineController(async ({ config }) => {
558
+ return Response.json(config);
559
+ });
560
+
561
+ // src/api/diagnostics.get.ts
562
+ var diagnostics_get_default = defineController(async ({ tools, prompts, promptNames, agents, agentNames }) => {
563
+ const warnings = [];
564
+ const toolNameSources = /* @__PURE__ */ new Map();
565
+ if (tools) {
566
+ const toolNames = Object.keys(tools);
567
+ for (const name of toolNames) {
568
+ const sources = toolNameSources.get(name) || /* @__PURE__ */ new Set();
569
+ sources.add("native tool");
570
+ toolNameSources.set(name, sources);
571
+ }
572
+ }
573
+ if (prompts && promptNames) {
574
+ for (const name of promptNames) {
575
+ const sources = toolNameSources.get(name) || /* @__PURE__ */ new Set();
576
+ sources.add("prompt");
577
+ toolNameSources.set(name, sources);
578
+ }
579
+ }
580
+ if (agents && agentNames) {
581
+ for (const name of agentNames) {
582
+ try {
583
+ const loader = agents[name];
584
+ if (loader) {
585
+ const definition = await loader();
586
+ if (definition.exposeAsTool) {
587
+ const sources = toolNameSources.get(name) || /* @__PURE__ */ new Set();
588
+ sources.add("agent");
589
+ toolNameSources.set(name, sources);
590
+ }
591
+ }
592
+ } catch {
593
+ }
594
+ }
595
+ }
596
+ for (const [name, sources] of toolNameSources) {
597
+ if (sources.size > 1) {
598
+ warnings.push({
599
+ type: "duplicate_tool_name",
600
+ message: `Duplicate tool name "${name}" detected`,
601
+ details: {
602
+ name,
603
+ sources: [...sources]
604
+ }
605
+ });
606
+ }
607
+ }
608
+ return Response.json({ warnings });
609
+ });
610
+
611
+ // src/api/events.get.ts
612
+ var events_get_default = defineController(async ({ req, env }) => {
613
+ if (req.headers.get("upgrade")?.toLowerCase() !== "websocket") {
614
+ return Response.json(
615
+ { error: "This endpoint requires a WebSocket connection" },
616
+ { status: 400 }
617
+ );
618
+ }
619
+ try {
620
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
621
+ const stub = env.AGENT_BUILDER.get(agentBuilderId);
622
+ return await stub.fetch(req);
623
+ } catch (error) {
624
+ console.error("Error establishing events WebSocket:", error);
625
+ return Response.json(
626
+ { error: error.message || "Failed to establish WebSocket connection" },
627
+ { status: 500 }
628
+ );
629
+ }
630
+ });
631
+
632
+ // src/api/models.get.ts
633
+ var models_get_default = defineController(async ({ models, modelNames }) => {
634
+ if (!models || !modelNames) {
635
+ return Response.json({ models: [] });
636
+ }
637
+ const modelList = await Promise.all(
638
+ modelNames.map(async (name) => {
639
+ try {
640
+ const loader = models[name];
641
+ if (!loader) {
642
+ return null;
643
+ }
644
+ const definition = await loader();
645
+ const fallbackObjects = (definition.fallbacks || []).map(
646
+ (fallbackName, index) => ({
647
+ id: fallbackName,
648
+ name: fallbackName,
649
+ order: index
650
+ })
651
+ );
652
+ return {
653
+ id: definition.name,
654
+ name: definition.name,
655
+ provider: definition.provider,
656
+ model: definition.model,
657
+ input_price: definition.inputPrice,
658
+ output_price: definition.outputPrice,
659
+ cached_price: definition.cachedPrice,
660
+ included_providers: definition.includedProviders,
661
+ fallbacks: fallbackObjects,
662
+ created_at: Math.floor(Date.now() / 1e3)
663
+ // Not persisted, use current time
664
+ };
665
+ } catch (error) {
666
+ console.error(`Error loading model ${name}:`, error);
667
+ return null;
668
+ }
669
+ })
670
+ );
671
+ const validModels = modelList.filter(Boolean);
672
+ return Response.json({ models: validModels });
673
+ });
674
+
675
+ // src/api/new-test.get.ts
676
+ var new_test_get_default = defineController(async ({ req, params, env }) => {
677
+ return { message: "Modified new test API route", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
678
+ });
679
+ function toJSONSchema(schema) {
680
+ if (!schema) return null;
681
+ if (schema && typeof schema === "object" && ("~standard" in schema || "_def" in schema)) {
682
+ return z.toJSONSchema(schema);
683
+ }
684
+ return schema;
685
+ }
686
+ function normalizePromptContent(prompt) {
687
+ if (!prompt) return "";
688
+ if (Array.isArray(prompt)) {
689
+ return JSON.stringify(prompt);
690
+ }
691
+ return prompt;
692
+ }
693
+ var prompts_get_default = defineController(async ({ prompts, promptNames, models, modelNames }) => {
694
+ if (!prompts || !promptNames) {
695
+ return Response.json({ prompts: [] });
696
+ }
697
+ const modelMap = {};
698
+ if (models && modelNames) {
699
+ await Promise.all(
700
+ modelNames.map(async (name) => {
701
+ try {
702
+ const loader = models[name];
703
+ if (loader) {
704
+ modelMap[name] = await loader();
705
+ }
706
+ } catch (error) {
707
+ }
708
+ })
709
+ );
710
+ }
711
+ const promptList = await Promise.all(
712
+ promptNames.map(async (name) => {
713
+ try {
714
+ const loader = prompts[name];
715
+ if (!loader) {
716
+ return null;
717
+ }
718
+ const definition = await loader();
719
+ const modelDef = modelMap[definition.model];
720
+ const tools = (definition.tools || []).map(
721
+ (tool) => typeof tool === "string" ? tool : tool.name
722
+ );
723
+ return {
724
+ id: definition.name,
725
+ name: definition.name,
726
+ tool_description: definition.toolDescription,
727
+ prompt: normalizePromptContent(definition.prompt),
728
+ required_schema: toJSONSchema(definition.requiredSchema),
729
+ model_id: definition.model,
730
+ model_name: modelDef?.name || definition.model,
731
+ model_provider: modelDef?.provider || "unknown",
732
+ include_chat: definition.includeChat || false,
733
+ include_past_tools: definition.includePastTools || false,
734
+ parallel_tool_calls: definition.parallelToolCalls || false,
735
+ tool_choice: definition.toolChoice || "auto",
736
+ before_tool: definition.beforeTool || null,
737
+ after_tool: definition.afterTool || null,
738
+ tools,
739
+ prompts: definition.handoffAgents || [],
740
+ reasoning: definition.reasoning || null,
741
+ created_at: Math.floor(Date.now() / 1e3)
742
+ };
743
+ } catch (error) {
744
+ console.error(`Error loading prompt ${name}:`, error);
745
+ return null;
746
+ }
747
+ })
748
+ );
749
+ const validPrompts = promptList.filter(Boolean);
750
+ return Response.json({ prompts: validPrompts });
751
+ });
752
+
753
+ // src/api/providers.get.ts
754
+ var SUPPORTED_PROVIDERS = [
755
+ {
756
+ name: "openai",
757
+ sdk: "openai",
758
+ label: "OpenAI",
759
+ envKey: "OPENAI_API_KEY"
760
+ },
761
+ {
762
+ name: "openrouter",
763
+ sdk: "openrouter",
764
+ label: "OpenRouter",
765
+ envKey: "OPENROUTER_API_KEY"
766
+ }
767
+ ];
768
+ var providers_get_default = defineController(async ({ env }) => {
769
+ const providers = SUPPORTED_PROVIDERS.map((provider) => ({
770
+ name: provider.name,
771
+ sdk: provider.sdk,
772
+ label: provider.label,
773
+ hasApiKey: Boolean(env[provider.envKey])
774
+ }));
775
+ return Response.json({ providers });
776
+ });
777
+
778
+ // src/api/threads/index.post.ts
779
+ var index_post_default3 = defineController(async ({ req, env }) => {
780
+ let body;
781
+ try {
782
+ body = await req.json();
783
+ } catch (error) {
784
+ return Response.json(
785
+ { error: "Invalid JSON in request body" },
786
+ { status: 400 }
787
+ );
788
+ }
789
+ const { agent_id, user_id, initial_messages, data, tags } = body;
790
+ if (!agent_id) {
791
+ return Response.json(
792
+ { error: "Missing required field: agent_id" },
793
+ { status: 400 }
794
+ );
795
+ }
796
+ if (initial_messages !== void 0 && initial_messages !== null) {
797
+ if (!Array.isArray(initial_messages)) {
798
+ return Response.json(
799
+ { error: "initial_messages must be an array" },
800
+ { status: 400 }
801
+ );
802
+ }
803
+ }
804
+ if (tags !== void 0 && tags !== null) {
805
+ if (!Array.isArray(tags)) {
806
+ return Response.json(
807
+ { error: "tags must be an array of strings" },
808
+ { status: 400 }
809
+ );
810
+ }
811
+ if (!tags.every((tag) => typeof tag === "string")) {
812
+ return Response.json(
813
+ { error: "All tags must be strings" },
814
+ { status: 400 }
815
+ );
816
+ }
817
+ }
818
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
819
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
820
+ try {
821
+ await agentBuilder.loadAgent(agent_id);
822
+ } catch (error) {
823
+ return Response.json(
824
+ { error: `Agent not found: ${agent_id}` },
825
+ { status: 404 }
826
+ );
827
+ }
828
+ try {
829
+ const thread = await agentBuilder.createThread({
830
+ agent_name: agent_id,
831
+ user_id,
832
+ tags
833
+ });
834
+ return Response.json({
835
+ threadId: thread.id,
836
+ agent_id: thread.agent_name,
837
+ message: "Thread created successfully"
838
+ });
839
+ } catch (error) {
840
+ console.error(`Error creating thread:`, error);
841
+ return Response.json(
842
+ {
843
+ error: error.message || "Failed to create thread"
844
+ },
845
+ { status: 500 }
846
+ );
847
+ }
848
+ });
849
+
850
+ // src/api/threads/index.ts
851
+ var threads_default = defineController(async ({ req, env }) => {
852
+ if (req.method !== "GET") {
853
+ return new Response("Method Not Allowed", { status: 405 });
854
+ }
855
+ try {
856
+ const url = new URL(req.url);
857
+ const limit = parseInt(url.searchParams.get("limit") || "50", 10);
858
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
859
+ const agentName = url.searchParams.get("agent_id");
860
+ const userId = url.searchParams.get("user_id");
861
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
862
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
863
+ const result = await agentBuilder.listThreads({
864
+ agent_name: agentName || void 0,
865
+ user_id: userId || void 0,
866
+ limit,
867
+ offset
868
+ });
869
+ const threads = await Promise.all(
870
+ result.threads.map(async (thread) => {
871
+ let agentDetails = null;
872
+ try {
873
+ const agentDef = await agentBuilder.loadAgent(thread.agent_name);
874
+ agentDetails = {
875
+ title: agentDef.title,
876
+ type: agentDef.type || "ai_human"
877
+ };
878
+ } catch {
879
+ agentDetails = { title: thread.agent_name, type: "unknown" };
880
+ }
881
+ return {
882
+ id: thread.id,
883
+ agent_id: thread.agent_name,
884
+ user_id: thread.user_id,
885
+ tags: thread.tags || [],
886
+ created_at: thread.created_at,
887
+ agent: agentDetails
888
+ };
889
+ })
890
+ );
891
+ return Response.json({
892
+ threads,
893
+ total: result.total,
894
+ hasMore: offset + threads.length < result.total
895
+ });
896
+ } catch (error) {
897
+ console.error("Error fetching threads:", error);
898
+ return Response.json(
899
+ { error: error.message || "Failed to fetch threads" },
900
+ { status: 500 }
901
+ );
902
+ }
903
+ });
904
+ function toJSONSchema2(schema) {
905
+ if (!schema) return null;
906
+ try {
907
+ if (schema && typeof schema === "object" && ("~standard" in schema || schema._def)) {
908
+ return z.toJSONSchema(schema);
909
+ }
910
+ return schema;
911
+ } catch {
912
+ return null;
913
+ }
914
+ }
915
+ var tools_get_default = defineController(async ({ url, tools, prompts, promptNames, agents, agentNames, models, modelNames }) => {
916
+ const type = url.searchParams.get("type");
917
+ const includeSchema = url.searchParams.get("schema") === "true";
918
+ const modelMap = {};
919
+ if (models && modelNames) {
920
+ await Promise.all(
921
+ modelNames.map(async (name) => {
922
+ try {
923
+ const loader = models[name];
924
+ if (loader) {
925
+ modelMap[name] = await loader();
926
+ }
927
+ } catch (error) {
928
+ }
929
+ })
930
+ );
931
+ }
932
+ if (type === "prompts") {
933
+ if (!prompts || !promptNames) {
934
+ return Response.json({});
935
+ }
936
+ const result2 = {};
937
+ await Promise.all(
938
+ promptNames.map(async (name) => {
939
+ try {
940
+ const loader = prompts[name];
941
+ if (!loader) return;
942
+ const definition = await loader();
943
+ const modelDef = modelMap[definition.model];
944
+ result2[name] = {
945
+ description: definition.toolDescription || "",
946
+ schema: includeSchema && definition.requiredSchema ? toJSONSchema2(definition.requiredSchema) : null,
947
+ hasError: false,
948
+ type: "prompt",
949
+ model: modelDef?.name || definition.model
950
+ };
951
+ } catch (error) {
952
+ console.error(`Error loading prompt ${name}:`, error);
953
+ }
954
+ })
955
+ );
956
+ return Response.json(result2);
957
+ }
958
+ if (type === "agents") {
959
+ if (!agents || !agentNames) {
960
+ return Response.json({});
961
+ }
962
+ const result2 = {};
963
+ await Promise.all(
964
+ agentNames.map(async (name) => {
965
+ try {
966
+ const loader = agents[name];
967
+ if (!loader) return;
968
+ const definition = await loader();
969
+ if (!definition.exposeAsTool) return;
970
+ result2[name] = {
971
+ description: definition.toolDescription || definition.title || "",
972
+ schema: null,
973
+ // Agents don't have schemas
974
+ hasError: false,
975
+ type: "agent"
976
+ };
977
+ } catch (error) {
978
+ console.error(`Error loading agent ${name}:`, error);
979
+ }
980
+ })
981
+ );
982
+ return Response.json(result2);
983
+ }
984
+ const result = {};
985
+ if (tools) {
986
+ const toolNames = Object.keys(tools);
987
+ await Promise.all(
988
+ toolNames.map(async (name) => {
989
+ try {
990
+ const loader = tools[name];
991
+ if (!loader) return;
992
+ const toolResult = await loader();
993
+ if (Array.isArray(toolResult) && typeof toolResult[0] === "string" && toolResult[0].includes("error")) {
994
+ result[name] = {
995
+ description: "",
996
+ schema: null,
997
+ hasError: true,
998
+ error: toolResult[0],
999
+ type: "tool"
1000
+ };
1001
+ return;
1002
+ }
1003
+ const [description, schema] = toolResult;
1004
+ result[name] = {
1005
+ description: description || "",
1006
+ schema: includeSchema && schema ? toJSONSchema2(schema) : null,
1007
+ hasError: false,
1008
+ type: "tool"
1009
+ };
1010
+ } catch (error) {
1011
+ console.error(`Error loading tool ${name}:`, error);
1012
+ result[name] = {
1013
+ description: "",
1014
+ schema: null,
1015
+ hasError: true,
1016
+ error: `Error loading tool: ${error}`,
1017
+ type: "tool"
1018
+ };
1019
+ }
1020
+ })
1021
+ );
1022
+ }
1023
+ if (prompts && promptNames) {
1024
+ await Promise.all(
1025
+ promptNames.map(async (name) => {
1026
+ try {
1027
+ const loader = prompts[name];
1028
+ if (!loader) return;
1029
+ const definition = await loader();
1030
+ const modelDef = modelMap[definition.model];
1031
+ result[name] = {
1032
+ description: definition.toolDescription || "",
1033
+ schema: includeSchema && definition.requiredSchema ? toJSONSchema2(definition.requiredSchema) : null,
1034
+ hasError: false,
1035
+ type: "prompt",
1036
+ model: modelDef?.name || definition.model
1037
+ };
1038
+ } catch (error) {
1039
+ console.error(`Error loading prompt ${name}:`, error);
1040
+ }
1041
+ })
1042
+ );
1043
+ }
1044
+ return Response.json(result);
1045
+ });
1046
+
1047
+ // src/api/users/index.get.ts
1048
+ var index_get_default2 = defineController(async ({ req, env }) => {
1049
+ try {
1050
+ const authResult = await requireAdmin(req, env);
1051
+ if (authResult instanceof Response) {
1052
+ return authResult;
1053
+ }
1054
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1055
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1056
+ const users = await agentBuilder.listUsers();
1057
+ return Response.json({ users });
1058
+ } catch (error) {
1059
+ console.error("List users error:", error);
1060
+ return Response.json(
1061
+ { error: error.message || "Failed to list users" },
1062
+ { status: 500 }
1063
+ );
1064
+ }
1065
+ });
1066
+
1067
+ // src/api/users/index.post.ts
1068
+ var index_post_default4 = defineController(async ({ req, env }) => {
1069
+ try {
1070
+ const authResult = await requireAdmin(req, env);
1071
+ if (authResult instanceof Response) {
1072
+ return authResult;
1073
+ }
1074
+ const body = await req.json();
1075
+ const { username, password, role = "admin" } = body;
1076
+ if (!username || !password) {
1077
+ return Response.json(
1078
+ { error: "Username and password are required" },
1079
+ { status: 400 }
1080
+ );
1081
+ }
1082
+ if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
1083
+ return Response.json(
1084
+ { error: "Username can only contain letters, numbers, underscores, and hyphens" },
1085
+ { status: 400 }
1086
+ );
1087
+ }
1088
+ if (username.length < 3 || username.length > 50) {
1089
+ return Response.json(
1090
+ { error: "Username must be between 3 and 50 characters" },
1091
+ { status: 400 }
1092
+ );
1093
+ }
1094
+ if (password.length < 8) {
1095
+ return Response.json(
1096
+ { error: "Password must be at least 8 characters" },
1097
+ { status: 400 }
1098
+ );
1099
+ }
1100
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1101
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1102
+ const existingUser = await agentBuilder.getUserByUsername(username);
1103
+ if (existingUser) {
1104
+ return Response.json(
1105
+ { error: "Username already exists" },
1106
+ { status: 400 }
1107
+ );
1108
+ }
1109
+ const password_hash = await hashPassword(password);
1110
+ const user = await agentBuilder.createUser({
1111
+ username,
1112
+ password_hash,
1113
+ role
1114
+ });
1115
+ return Response.json({
1116
+ user: {
1117
+ id: user.id,
1118
+ username: user.username,
1119
+ role: user.role,
1120
+ created_at: user.created_at,
1121
+ updated_at: user.updated_at
1122
+ }
1123
+ }, { status: 201 });
1124
+ } catch (error) {
1125
+ console.error("Create user error:", error);
1126
+ return Response.json(
1127
+ { error: error.message || "Failed to create user" },
1128
+ { status: 500 }
1129
+ );
1130
+ }
1131
+ });
1132
+
1133
+ // src/api/agents/[name].get.ts
1134
+ var name_get_default = defineController(async ({ params, agents, prompts, promptNames }) => {
1135
+ const { name } = params;
1136
+ if (!agents || !agents[name]) {
1137
+ return Response.json({ error: "Agent not found" }, { status: 404 });
1138
+ }
1139
+ try {
1140
+ const promptMap = {};
1141
+ if (prompts && promptNames) {
1142
+ await Promise.all(
1143
+ promptNames.map(async (promptName) => {
1144
+ try {
1145
+ const loader2 = prompts[promptName];
1146
+ if (loader2) {
1147
+ promptMap[promptName] = await loader2();
1148
+ }
1149
+ } catch (error) {
1150
+ }
1151
+ })
1152
+ );
1153
+ }
1154
+ const loader = agents[name];
1155
+ const definition = await loader();
1156
+ const sideAPrompt = promptMap[definition.sideA?.prompt];
1157
+ const sideBPrompt = definition.sideB ? promptMap[definition.sideB?.prompt] : null;
1158
+ const agent = {
1159
+ id: definition.name,
1160
+ name: definition.name,
1161
+ // title is deprecated - include for backward compatibility but prefer name
1162
+ title: definition.title || definition.name,
1163
+ type: definition.type || "ai_human",
1164
+ // Side A configuration
1165
+ side_a_label: definition.sideA?.label || null,
1166
+ side_a_agent_prompt: definition.sideA?.prompt,
1167
+ side_a_agent_prompt_name: sideAPrompt?.name || definition.sideA?.prompt,
1168
+ side_a_stop_on_response: definition.sideA?.stopOnResponse !== void 0 ? definition.sideA.stopOnResponse : true,
1169
+ side_a_stop_tool: definition.sideA?.stopTool || null,
1170
+ side_a_stop_tool_response_property: definition.sideA?.stopToolResponseProperty || null,
1171
+ side_a_max_turns: definition.sideA?.maxTurns || null,
1172
+ side_a_end_conversation_tool: definition.sideA?.endConversationTool || null,
1173
+ side_a_manual_stop_condition: definition.sideA?.manualStopCondition || false,
1174
+ // Side B configuration (if dual_ai)
1175
+ side_b_label: definition.sideB?.label || null,
1176
+ side_b_agent_prompt: definition.sideB?.prompt || null,
1177
+ side_b_agent_prompt_name: sideBPrompt?.name || definition.sideB?.prompt || null,
1178
+ side_b_stop_on_response: definition.sideB?.stopOnResponse !== void 0 ? definition.sideB.stopOnResponse : true,
1179
+ side_b_stop_tool: definition.sideB?.stopTool || null,
1180
+ side_b_stop_tool_response_property: definition.sideB?.stopToolResponseProperty || null,
1181
+ side_b_max_turns: definition.sideB?.maxTurns || null,
1182
+ side_b_end_conversation_tool: definition.sideB?.endConversationTool || null,
1183
+ side_b_manual_stop_condition: definition.sideB?.manualStopCondition || false,
1184
+ // Session configuration
1185
+ max_session_turns: definition.maxSessionTurns || null,
1186
+ // Tool exposure
1187
+ expose_as_tool: definition.exposeAsTool || false,
1188
+ tool_description: definition.toolDescription || null,
1189
+ // Tags
1190
+ tags: definition.tags || [],
1191
+ created_at: Math.floor(Date.now() / 1e3)
1192
+ };
1193
+ return Response.json({ agent });
1194
+ } catch (error) {
1195
+ console.error(`Error loading agent ${name}:`, error);
1196
+ return Response.json(
1197
+ { error: `Error loading agent: ${error}` },
1198
+ { status: 500 }
1199
+ );
1200
+ }
1201
+ });
1202
+
1203
+ // src/api/api-keys/[id].delete.ts
1204
+ var id_delete_default = defineController(async ({ req, env, params }) => {
1205
+ try {
1206
+ const authResult = await requireAuth(req, env);
1207
+ if (authResult instanceof Response) {
1208
+ return authResult;
1209
+ }
1210
+ if (authResult.authType === "super_admin") {
1211
+ return Response.json(
1212
+ { error: "Super admin has no API keys to delete." },
1213
+ { status: 400 }
1214
+ );
1215
+ }
1216
+ const keyId = params.id;
1217
+ if (!keyId) {
1218
+ return Response.json(
1219
+ { error: "API key ID is required" },
1220
+ { status: 400 }
1221
+ );
1222
+ }
1223
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1224
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1225
+ await agentBuilder.deleteApiKey(keyId, authResult.user.id);
1226
+ return Response.json({ success: true });
1227
+ } catch (error) {
1228
+ console.error("Delete API key error:", error);
1229
+ return Response.json(
1230
+ { error: error.message || "Failed to delete API key" },
1231
+ { status: 500 }
1232
+ );
1233
+ }
1234
+ });
1235
+ function toJSONSchema3(schema) {
1236
+ if (!schema) return null;
1237
+ if (schema && typeof schema === "object" && ("~standard" in schema || "_def" in schema)) {
1238
+ return z.toJSONSchema(schema);
1239
+ }
1240
+ return schema;
1241
+ }
1242
+ function normalizePromptContent2(prompt) {
1243
+ if (!prompt) return "";
1244
+ if (Array.isArray(prompt)) {
1245
+ return JSON.stringify(prompt);
1246
+ }
1247
+ return prompt;
1248
+ }
1249
+ var name_get_default2 = defineController(async ({ params, prompts, models, modelNames }) => {
1250
+ const { name } = params;
1251
+ if (!prompts || !prompts[name]) {
1252
+ return Response.json({ error: "Prompt not found" }, { status: 404 });
1253
+ }
1254
+ try {
1255
+ const modelMap = {};
1256
+ if (models && modelNames) {
1257
+ await Promise.all(
1258
+ modelNames.map(async (modelName) => {
1259
+ try {
1260
+ const loader2 = models[modelName];
1261
+ if (loader2) {
1262
+ modelMap[modelName] = await loader2();
1263
+ }
1264
+ } catch (error) {
1265
+ }
1266
+ })
1267
+ );
1268
+ }
1269
+ const loader = prompts[name];
1270
+ const definition = await loader();
1271
+ const modelDef = modelMap[definition.model];
1272
+ const tools = (definition.tools || []).map((tool) => {
1273
+ if (typeof tool === "string") {
1274
+ return {
1275
+ name: tool,
1276
+ include_text_response: true,
1277
+ include_tool_calls: true,
1278
+ include_errors: true,
1279
+ init_user_message_property: null
1280
+ };
1281
+ }
1282
+ return {
1283
+ name: tool.name,
1284
+ include_text_response: tool.includeTextResponse !== void 0 ? tool.includeTextResponse : true,
1285
+ include_tool_calls: tool.includeToolCalls !== void 0 ? tool.includeToolCalls : true,
1286
+ include_errors: tool.includeErrors !== void 0 ? tool.includeErrors : true,
1287
+ init_user_message_property: tool.initUserMessageProperty || null
1288
+ };
1289
+ });
1290
+ const prompt = {
1291
+ id: definition.name,
1292
+ name: definition.name,
1293
+ tool_description: definition.toolDescription,
1294
+ prompt: normalizePromptContent2(definition.prompt),
1295
+ required_schema: toJSONSchema3(definition.requiredSchema),
1296
+ model_id: definition.model,
1297
+ model_name: modelDef?.name || definition.model,
1298
+ model_provider: modelDef?.provider || "unknown",
1299
+ include_chat: definition.includeChat || false,
1300
+ include_past_tools: definition.includePastTools || false,
1301
+ parallel_tool_calls: definition.parallelToolCalls || false,
1302
+ tool_choice: definition.toolChoice || "auto",
1303
+ before_tool: definition.beforeTool || null,
1304
+ after_tool: definition.afterTool || null,
1305
+ tools,
1306
+ prompts: definition.handoffAgents || [],
1307
+ reasoning: definition.reasoning || null,
1308
+ created_at: Math.floor(Date.now() / 1e3)
1309
+ };
1310
+ return Response.json({ prompt });
1311
+ } catch (error) {
1312
+ console.error(`Error loading prompt ${name}:`, error);
1313
+ return Response.json(
1314
+ { error: `Error loading prompt: ${error}` },
1315
+ { status: 500 }
1316
+ );
1317
+ }
1318
+ });
1319
+
1320
+ // src/api/threads/[id].delete.ts
1321
+ var id_delete_default2 = defineController(async ({ req, env, params }) => {
1322
+ const threadId = params.id;
1323
+ if (!threadId) {
1324
+ return Response.json({ error: "Missing thread ID" }, { status: 400 });
1325
+ }
1326
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1327
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1328
+ const thread = await agentBuilder.getThread(threadId);
1329
+ if (!thread) {
1330
+ return Response.json(
1331
+ { error: `Thread not found: ${threadId}` },
1332
+ { status: 404 }
1333
+ );
1334
+ }
1335
+ try {
1336
+ await agentBuilder.deleteThread(threadId);
1337
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
1338
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
1339
+ await stub.deleteThread();
1340
+ return Response.json({
1341
+ success: true,
1342
+ threadId,
1343
+ message: "Thread deleted successfully"
1344
+ });
1345
+ } catch (error) {
1346
+ console.error(`Error deleting thread ${threadId}:`, error);
1347
+ return Response.json(
1348
+ {
1349
+ error: error.message || "Failed to delete thread",
1350
+ threadId
1351
+ },
1352
+ { status: 500 }
1353
+ );
1354
+ }
1355
+ });
1356
+
1357
+ // src/api/threads/[id].patch.ts
1358
+ var id_patch_default = defineController(async ({ req, env, params }) => {
1359
+ if (req.method !== "PATCH") {
1360
+ return new Response("Method Not Allowed", { status: 405 });
1361
+ }
1362
+ const threadId = params?.id;
1363
+ if (!threadId) {
1364
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
1365
+ }
1366
+ try {
1367
+ const body = await req.json();
1368
+ const { tags, agent_id } = body;
1369
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1370
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1371
+ const existingThread = await agentBuilder.getThread(threadId);
1372
+ if (!existingThread) {
1373
+ return Response.json(
1374
+ { error: `Thread not found: ${threadId}` },
1375
+ { status: 404 }
1376
+ );
1377
+ }
1378
+ const updates = {};
1379
+ if (tags !== void 0) {
1380
+ if (!Array.isArray(tags)) {
1381
+ return Response.json(
1382
+ { error: "tags must be an array of strings" },
1383
+ { status: 400 }
1384
+ );
1385
+ }
1386
+ if (!tags.every((tag) => typeof tag === "string")) {
1387
+ return Response.json(
1388
+ { error: "All tags must be strings" },
1389
+ { status: 400 }
1390
+ );
1391
+ }
1392
+ updates.tags = tags;
1393
+ }
1394
+ if (agent_id !== void 0) {
1395
+ if (typeof agent_id !== "string") {
1396
+ return Response.json(
1397
+ { error: "agent_id must be a string" },
1398
+ { status: 400 }
1399
+ );
1400
+ }
1401
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
1402
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
1403
+ try {
1404
+ const agentDef = await stub.loadAgent(agent_id);
1405
+ if (!agentDef) {
1406
+ return Response.json(
1407
+ { error: `Agent not found: ${agent_id}` },
1408
+ { status: 404 }
1409
+ );
1410
+ }
1411
+ if (agentDef.type !== "ai_human") {
1412
+ return Response.json(
1413
+ { error: "Only ai_human agents can be assigned to threads" },
1414
+ { status: 400 }
1415
+ );
1416
+ }
1417
+ } catch (e) {
1418
+ return Response.json(
1419
+ { error: `Agent not found: ${agent_id}` },
1420
+ { status: 404 }
1421
+ );
1422
+ }
1423
+ updates.agent_name = agent_id;
1424
+ }
1425
+ if (Object.keys(updates).length === 0) {
1426
+ return Response.json(
1427
+ { error: "No valid fields to update" },
1428
+ { status: 400 }
1429
+ );
1430
+ }
1431
+ const updatedThread = await agentBuilder.updateThread(threadId, updates);
1432
+ return Response.json({
1433
+ id: updatedThread.id,
1434
+ agent_id: updatedThread.agent_name,
1435
+ // Map agent_name back to agent_id for API compat
1436
+ user_id: updatedThread.user_id,
1437
+ tags: updatedThread.tags || [],
1438
+ created_at: updatedThread.created_at
1439
+ });
1440
+ } catch (error) {
1441
+ console.error("Error updating thread:", error);
1442
+ return Response.json(
1443
+ { error: error.message || "Failed to update thread" },
1444
+ { status: 500 }
1445
+ );
1446
+ }
1447
+ });
1448
+
1449
+ // src/api/threads/[id].ts
1450
+ var id_default = defineController(async ({ req, params, env }) => {
1451
+ const threadId = params.id;
1452
+ if (!threadId) {
1453
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
1454
+ }
1455
+ try {
1456
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
1457
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
1458
+ const doData = await stub.getThreadMeta(threadId);
1459
+ if (!doData) {
1460
+ return Response.json(
1461
+ { error: `Thread not found: ${threadId}` },
1462
+ { status: 404 }
1463
+ );
1464
+ }
1465
+ return Response.json(doData);
1466
+ } catch (error) {
1467
+ console.error(`Error fetching thread ${threadId}:`, error);
1468
+ return Response.json(
1469
+ { error: error.message || "Failed to fetch thread" },
1470
+ { status: 500 }
1471
+ );
1472
+ }
1473
+ });
1474
+ function toJSONSchema4(schema) {
1475
+ if (!schema) return null;
1476
+ try {
1477
+ if (schema && typeof schema === "object" && ("~standard" in schema || schema._def)) {
1478
+ return z.toJSONSchema(schema);
1479
+ }
1480
+ return schema;
1481
+ } catch {
1482
+ return null;
1483
+ }
1484
+ }
1485
+ var name_get_default3 = defineController(async ({ params, tools }) => {
1486
+ const { name } = params;
1487
+ if (!tools || !tools[name]) {
1488
+ return Response.json({ error: "Tool not found" }, { status: 404 });
1489
+ }
1490
+ try {
1491
+ const loader = tools[name];
1492
+ const toolResult = await loader();
1493
+ if (Array.isArray(toolResult) && typeof toolResult[0] === "string" && toolResult[0].includes("error")) {
1494
+ return Response.json({
1495
+ name,
1496
+ description: "",
1497
+ schema: null,
1498
+ hasError: true,
1499
+ error: toolResult[0]
1500
+ });
1501
+ }
1502
+ const [description, schema] = toolResult;
1503
+ return Response.json({
1504
+ name,
1505
+ description: description || "",
1506
+ schema: toJSONSchema4(schema),
1507
+ hasError: false
1508
+ });
1509
+ } catch (error) {
1510
+ console.error(`Error loading tool ${name}:`, error);
1511
+ return Response.json({
1512
+ name,
1513
+ description: "",
1514
+ schema: null,
1515
+ hasError: true,
1516
+ error: `Error loading tool: ${error}`
1517
+ });
1518
+ }
1519
+ });
1520
+
1521
+ // src/api/users/[id].delete.ts
1522
+ var id_delete_default3 = defineController(async ({ req, env, params }) => {
1523
+ try {
1524
+ const authResult = await requireAdmin(req, env);
1525
+ if (authResult instanceof Response) {
1526
+ return authResult;
1527
+ }
1528
+ const { id } = params;
1529
+ if (!id) {
1530
+ return Response.json({ error: "User ID is required" }, { status: 400 });
1531
+ }
1532
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1533
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1534
+ const user = await agentBuilder.getUserById(id);
1535
+ if (!user) {
1536
+ return Response.json({ error: "User not found" }, { status: 404 });
1537
+ }
1538
+ await agentBuilder.deleteUser(id);
1539
+ return Response.json({ success: true });
1540
+ } catch (error) {
1541
+ console.error("Delete user error:", error);
1542
+ return Response.json(
1543
+ { error: error.message || "Failed to delete user" },
1544
+ { status: 500 }
1545
+ );
1546
+ }
1547
+ });
1548
+
1549
+ // src/api/users/[id].put.ts
1550
+ var id_put_default = defineController(async ({ req, env, params }) => {
1551
+ try {
1552
+ const authResult = await requireAdmin(req, env);
1553
+ if (authResult instanceof Response) {
1554
+ return authResult;
1555
+ }
1556
+ const { id } = params;
1557
+ if (!id) {
1558
+ return Response.json({ error: "User ID is required" }, { status: 400 });
1559
+ }
1560
+ const body = await req.json();
1561
+ const { username, password, role } = body;
1562
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1563
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1564
+ const existingUser = await agentBuilder.getUserById(id);
1565
+ if (!existingUser) {
1566
+ return Response.json({ error: "User not found" }, { status: 404 });
1567
+ }
1568
+ if (username && username !== existingUser.username) {
1569
+ const userWithUsername = await agentBuilder.getUserByUsername(username);
1570
+ if (userWithUsername && userWithUsername.id !== id) {
1571
+ return Response.json(
1572
+ { error: "Username already taken" },
1573
+ { status: 409 }
1574
+ );
1575
+ }
1576
+ }
1577
+ const updateParams = {};
1578
+ if (username) {
1579
+ updateParams.username = username;
1580
+ }
1581
+ if (password) {
1582
+ updateParams.password_hash = await hashPassword(password);
1583
+ }
1584
+ if (role) {
1585
+ updateParams.role = role;
1586
+ }
1587
+ const updatedUser = await agentBuilder.updateUser(id, updateParams);
1588
+ return Response.json({
1589
+ user: {
1590
+ id: updatedUser.id,
1591
+ username: updatedUser.username,
1592
+ role: updatedUser.role,
1593
+ created_at: updatedUser.created_at,
1594
+ updated_at: updatedUser.updated_at
1595
+ }
1596
+ });
1597
+ } catch (error) {
1598
+ console.error("Update user error:", error);
1599
+ return Response.json(
1600
+ { error: error.message || "Failed to update user" },
1601
+ { status: 500 }
1602
+ );
1603
+ }
1604
+ });
1605
+
1606
+ // src/api/auth/config.get.ts
1607
+ var config_get_default2 = defineController(async ({ env }) => {
1608
+ const githubConfigured = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET);
1609
+ const googleConfigured = !!(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET);
1610
+ return {
1611
+ github: githubConfigured,
1612
+ google: googleConfigured
1613
+ };
1614
+ });
1615
+
1616
+ // src/api/auth/login.post.ts
1617
+ var login_post_default = defineController(async ({ req, env }) => {
1618
+ try {
1619
+ const body = await req.json();
1620
+ const { username, password } = body;
1621
+ if (!password) {
1622
+ return Response.json(
1623
+ { error: "Password is required" },
1624
+ { status: 400 }
1625
+ );
1626
+ }
1627
+ if (env.SUPER_ADMIN_PASSWORD && password === env.SUPER_ADMIN_PASSWORD) {
1628
+ if (!env.ENCRYPTION_KEY) {
1629
+ return Response.json(
1630
+ { error: "Server misconfigured: ENCRYPTION_KEY required for super admin" },
1631
+ { status: 500 }
1632
+ );
1633
+ }
1634
+ const token2 = await generateSuperAdminToken(env.ENCRYPTION_KEY);
1635
+ return Response.json({
1636
+ token: token2,
1637
+ user: {
1638
+ id: "super_admin",
1639
+ username: "admin",
1640
+ role: "admin"
1641
+ }
1642
+ });
1643
+ }
1644
+ if (!username) {
1645
+ return Response.json(
1646
+ { error: "Username is required" },
1647
+ { status: 400 }
1648
+ );
1649
+ }
1650
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1651
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1652
+ const user = await agentBuilder.getUserByUsername(username);
1653
+ if (!user) {
1654
+ return Response.json(
1655
+ { error: "Invalid username or password" },
1656
+ { status: 401 }
1657
+ );
1658
+ }
1659
+ const isValid = await verifyPassword(password, user.password_hash);
1660
+ if (!isValid) {
1661
+ return Response.json(
1662
+ { error: "Invalid username or password" },
1663
+ { status: 401 }
1664
+ );
1665
+ }
1666
+ const token = generateUserToken();
1667
+ const tokenHash = await hashToken(token);
1668
+ const expiresAt = Math.floor(Date.now() / 1e3) + 30 * 24 * 60 * 60;
1669
+ await agentBuilder.createSession({
1670
+ user_id: user.id,
1671
+ token_hash: tokenHash,
1672
+ expires_at: expiresAt
1673
+ });
1674
+ return Response.json({
1675
+ token,
1676
+ user: {
1677
+ id: user.id,
1678
+ username: user.username,
1679
+ role: user.role
1680
+ }
1681
+ });
1682
+ } catch (error) {
1683
+ console.error("Login error:", error);
1684
+ return Response.json(
1685
+ { error: error.message || "Login failed" },
1686
+ { status: 500 }
1687
+ );
1688
+ }
1689
+ });
1690
+
1691
+ // src/api/auth/logout.post.ts
1692
+ var logout_post_default = defineController(async ({ req, env }) => {
1693
+ try {
1694
+ const authHeader = req.headers.get("Authorization");
1695
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
1696
+ return Response.json({ error: "Unauthorized" }, { status: 401 });
1697
+ }
1698
+ const token = authHeader.substring(7);
1699
+ if (token.includes(".")) {
1700
+ return Response.json({ success: true });
1701
+ }
1702
+ if (isValidUserToken(token)) {
1703
+ const tokenHash = await hashToken(token);
1704
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1705
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1706
+ await agentBuilder.deleteSession(tokenHash);
1707
+ }
1708
+ return Response.json({ success: true });
1709
+ } catch (error) {
1710
+ console.error("Logout error:", error);
1711
+ return Response.json(
1712
+ { error: error.message || "Logout failed" },
1713
+ { status: 500 }
1714
+ );
1715
+ }
1716
+ });
1717
+
1718
+ // src/api/auth/me.get.ts
1719
+ var me_get_default = defineController(async ({ req, env }) => {
1720
+ try {
1721
+ const authContext = await authenticate(req, env);
1722
+ if (!authContext) {
1723
+ return Response.json({ error: "Unauthorized" }, { status: 401 });
1724
+ }
1725
+ return Response.json({
1726
+ user: authContext.user,
1727
+ authType: authContext.authType
1728
+ });
1729
+ } catch (error) {
1730
+ console.error("Auth check error:", error);
1731
+ return Response.json(
1732
+ { error: error.message || "Authentication check failed" },
1733
+ { status: 500 }
1734
+ );
1735
+ }
1736
+ });
1737
+
1738
+ // src/api/models/available.post.ts
1739
+ var PROVIDER_CONFIGS = {
1740
+ openai: {
1741
+ sdk: "openai",
1742
+ modelsEndpoint: "https://api.openai.com/v1/models",
1743
+ envKey: "OPENAI_API_KEY",
1744
+ headers: (apiKey) => ({
1745
+ Authorization: `Bearer ${apiKey}`
1746
+ }),
1747
+ parseResponse: (data) => {
1748
+ const chatModelPrefixes = [
1749
+ "gpt-4",
1750
+ "gpt-3.5",
1751
+ "o1",
1752
+ "o3",
1753
+ "chatgpt"
1754
+ ];
1755
+ return data.data.filter((model) => {
1756
+ const id = model.id.toLowerCase();
1757
+ return chatModelPrefixes.some((prefix) => id.startsWith(prefix));
1758
+ }).map((model) => ({
1759
+ value: model.id,
1760
+ label: model.id,
1761
+ description: `Owned by ${model.owned_by}`,
1762
+ iconId: "openai"
1763
+ })).sort((a, b) => a.label.localeCompare(b.label));
1764
+ }
1765
+ },
1766
+ openrouter: {
1767
+ sdk: "openrouter",
1768
+ modelsEndpoint: "https://openrouter.ai/api/v1/models",
1769
+ envKey: "OPENROUTER_API_KEY",
1770
+ headers: () => ({}),
1771
+ // OpenRouter models endpoint doesn't require auth
1772
+ parseResponse: (data) => {
1773
+ return data.data.map((model) => ({
1774
+ value: model.id,
1775
+ label: model.name || model.id,
1776
+ description: model.description?.slice(0, 150) + (model.description?.length > 150 ? "..." : "") || "",
1777
+ slug: model.canonical_slug || model.id,
1778
+ iconId: model.id.split("/")[0]
1779
+ // e.g., "anthropic" from "anthropic/claude-3"
1780
+ })).sort((a, b) => a.label.localeCompare(b.label));
1781
+ }
1782
+ }
1783
+ };
1784
+ var available_post_default = defineController(async ({ req, env }) => {
1785
+ const body = await req.json().catch(() => ({}));
1786
+ const { provider } = body;
1787
+ if (!provider) {
1788
+ return Response.json({ error: "Provider is required" }, { status: 400 });
1789
+ }
1790
+ const config = PROVIDER_CONFIGS[provider];
1791
+ if (!config) {
1792
+ return Response.json(
1793
+ { error: `Unknown provider: ${provider}. Supported: ${Object.keys(PROVIDER_CONFIGS).join(", ")}` },
1794
+ { status: 400 }
1795
+ );
1796
+ }
1797
+ const apiKey = env[config.envKey];
1798
+ if (!apiKey && config.sdk !== "openrouter") {
1799
+ return Response.json(
1800
+ { error: `API key not configured for ${provider}. Set ${config.envKey} environment variable.` },
1801
+ { status: 401 }
1802
+ );
1803
+ }
1804
+ try {
1805
+ const response = await fetch(config.modelsEndpoint, {
1806
+ method: "GET",
1807
+ headers: {
1808
+ "Content-Type": "application/json",
1809
+ ...config.headers(apiKey || "")
1810
+ }
1811
+ });
1812
+ if (!response.ok) {
1813
+ const errorText = await response.text();
1814
+ console.error(`Failed to fetch models from ${provider}:`, errorText);
1815
+ return Response.json(
1816
+ { error: `Failed to fetch models from ${provider}: ${response.statusText}` },
1817
+ { status: response.status }
1818
+ );
1819
+ }
1820
+ const data = await response.json();
1821
+ const models = config.parseResponse(data);
1822
+ return Response.json({ models });
1823
+ } catch (error) {
1824
+ console.error(`Error fetching models from ${provider}:`, error);
1825
+ return Response.json(
1826
+ { error: `Failed to fetch models: ${error.message}` },
1827
+ { status: 500 }
1828
+ );
1829
+ }
1830
+ });
1831
+
1832
+ // src/api/models/endpoints.post.ts
1833
+ var endpoints_post_default = defineController(async ({ req, env }) => {
1834
+ const body = await req.json().catch(() => ({}));
1835
+ const { provider, modelSlug } = body;
1836
+ if (!provider || !modelSlug) {
1837
+ return Response.json(
1838
+ { error: "Provider and modelSlug are required" },
1839
+ { status: 400 }
1840
+ );
1841
+ }
1842
+ if (provider !== "openrouter") {
1843
+ return Response.json(
1844
+ { error: "Endpoints are only available for OpenRouter provider" },
1845
+ { status: 400 }
1846
+ );
1847
+ }
1848
+ const slashIndex = modelSlug.indexOf("/");
1849
+ if (slashIndex === -1) {
1850
+ return Response.json(
1851
+ { error: `Invalid model slug format: ${modelSlug}. Expected format: author/model-name` },
1852
+ { status: 400 }
1853
+ );
1854
+ }
1855
+ const author = modelSlug.substring(0, slashIndex);
1856
+ const slug = modelSlug.substring(slashIndex + 1);
1857
+ try {
1858
+ const response = await fetch(`https://openrouter.ai/api/v1/models/${author}/${slug}/endpoints`, {
1859
+ method: "GET",
1860
+ headers: {
1861
+ "Content-Type": "application/json"
1862
+ }
1863
+ });
1864
+ if (!response.ok) {
1865
+ if (response.status === 404) {
1866
+ return Response.json(
1867
+ { error: `Model not found: ${modelSlug}` },
1868
+ { status: 404 }
1869
+ );
1870
+ }
1871
+ const errorText = await response.text();
1872
+ console.error(`Failed to fetch endpoints from OpenRouter:`, errorText);
1873
+ return Response.json(
1874
+ { error: `Failed to fetch endpoints: ${response.statusText}` },
1875
+ { status: response.status }
1876
+ );
1877
+ }
1878
+ const data = await response.json();
1879
+ const endpoints = parseOpenRouterEndpoints(data);
1880
+ return Response.json({ endpoints });
1881
+ } catch (error) {
1882
+ console.error(`Error fetching endpoints for ${modelSlug}:`, error);
1883
+ return Response.json(
1884
+ { error: `Failed to fetch endpoints: ${error.message}` },
1885
+ { status: 500 }
1886
+ );
1887
+ }
1888
+ });
1889
+ function parseOpenRouterEndpoints(data) {
1890
+ const model = data.data || data;
1891
+ const endpointsArray = model.endpoints || [];
1892
+ if (!Array.isArray(endpointsArray) || endpointsArray.length === 0) {
1893
+ return [];
1894
+ }
1895
+ return endpointsArray.map((endpoint) => ({
1896
+ // Use 'tag' as the ID since it's the provider identifier used for routing
1897
+ id: endpoint.tag || endpoint.provider_name || endpoint.name,
1898
+ name: endpoint.name || endpoint.provider_name || endpoint.tag,
1899
+ pricing: {
1900
+ // Pricing values come as strings, convert to numbers
1901
+ prompt: parseFloat(endpoint.pricing?.prompt) || 0,
1902
+ completion: parseFloat(endpoint.pricing?.completion) || 0
1903
+ },
1904
+ quantization: endpoint.quantization,
1905
+ maxPromptTokens: endpoint.max_prompt_tokens || endpoint.context_length,
1906
+ maxCompletionTokens: endpoint.max_completion_tokens
1907
+ }));
1908
+ }
1909
+
1910
+ // src/api/threads/[id]/cost.get.ts
1911
+ var cost_get_default = defineController(async ({ req, params, env }) => {
1912
+ const threadId = params.id;
1913
+ if (!threadId) {
1914
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
1915
+ }
1916
+ try {
1917
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1918
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1919
+ const thread = await agentBuilder.getThread(threadId);
1920
+ if (!thread) {
1921
+ return Response.json(
1922
+ { error: `Thread not found: ${threadId}` },
1923
+ { status: 404 }
1924
+ );
1925
+ }
1926
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
1927
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
1928
+ const logsResult = await stub.getLogs(1e4, 0, "ASC");
1929
+ const logs = logsResult.logs || [];
1930
+ let totalCost = 0;
1931
+ const modelCosts = {};
1932
+ const uniqueMessages = /* @__PURE__ */ new Set();
1933
+ for (const log of logs) {
1934
+ const cost = log.cost_total;
1935
+ if (cost !== null && cost !== void 0 && !isNaN(cost)) {
1936
+ totalCost += cost;
1937
+ if (log.message_id) {
1938
+ uniqueMessages.add(log.message_id);
1939
+ }
1940
+ const modelKey = log.model_name || log.model || "unknown";
1941
+ if (!modelCosts[modelKey]) {
1942
+ modelCosts[modelKey] = {
1943
+ totalCost: 0,
1944
+ count: 0
1945
+ };
1946
+ }
1947
+ modelCosts[modelKey].totalCost += cost;
1948
+ modelCosts[modelKey].count += 1;
1949
+ }
1950
+ }
1951
+ const messageCount = uniqueMessages.size;
1952
+ const avgCostPerMessage = messageCount > 0 ? totalCost / messageCount : 0;
1953
+ const avgCostPerMessageByModel = {};
1954
+ for (const [modelName, data] of Object.entries(modelCosts)) {
1955
+ avgCostPerMessageByModel[modelName] = {
1956
+ avgCost: data.count > 0 ? data.totalCost / data.count : 0,
1957
+ messageCount: data.count
1958
+ };
1959
+ }
1960
+ const modelBreakdown = Object.entries(modelCosts).map(([modelName, data]) => ({
1961
+ modelName,
1962
+ totalCost: data.totalCost,
1963
+ requestCount: data.count,
1964
+ avgCostPerRequest: data.count > 0 ? data.totalCost / data.count : 0
1965
+ }));
1966
+ return Response.json({
1967
+ totalCost,
1968
+ messageCount,
1969
+ avgCostPerMessage,
1970
+ modelBreakdown,
1971
+ avgCostPerMessageByModel
1972
+ });
1973
+ } catch (error) {
1974
+ console.error(`Error calculating cost for thread ${threadId}:`, error);
1975
+ return Response.json(
1976
+ { error: error.message || "Failed to calculate costs" },
1977
+ { status: 500 }
1978
+ );
1979
+ }
1980
+ });
1981
+
1982
+ // src/api/threads/[id]/logs.get.ts
1983
+ var logs_get_default = defineController(async ({ req, params, env }) => {
1984
+ const url = new URL(req.url);
1985
+ const threadId = params.id;
1986
+ if (!threadId) {
1987
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
1988
+ }
1989
+ try {
1990
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
1991
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
1992
+ const thread = await agentBuilder.getThread(threadId);
1993
+ if (!thread) {
1994
+ return Response.json(
1995
+ { error: `Thread not found: ${threadId}` },
1996
+ { status: 404 }
1997
+ );
1998
+ }
1999
+ const limit = parseInt(url.searchParams.get("limit") || "100", 10);
2000
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
2001
+ const order = url.searchParams.get("order") === "desc" ? "DESC" : "ASC";
2002
+ if (req.headers.get("upgrade")?.toLowerCase() === "websocket") {
2003
+ const durableId2 = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2004
+ const stub2 = env.AGENT_BUILDER_THREAD.get(durableId2);
2005
+ return await stub2.fetch(req);
2006
+ }
2007
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2008
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2009
+ const result = await stub.getLogs(limit, offset, order);
2010
+ return Response.json(result);
2011
+ } catch (error) {
2012
+ console.error(`Error fetching logs for thread ${threadId}:`, error);
2013
+ return Response.json(
2014
+ { error: error.message || "Failed to fetch logs" },
2015
+ { status: 500 }
2016
+ );
2017
+ }
2018
+ });
2019
+
2020
+ // src/api/threads/[id]/message.post.ts
2021
+ var message_post_default = defineController(async ({ req, params, env }) => {
2022
+ const threadId = params.id;
2023
+ if (!threadId) {
2024
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2025
+ }
2026
+ try {
2027
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2028
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2029
+ const thread = await agentBuilder.getThread(threadId);
2030
+ if (!thread) {
2031
+ return Response.json(
2032
+ { error: `Thread not found: ${threadId}` },
2033
+ { status: 404 }
2034
+ );
2035
+ }
2036
+ const body = await req.json();
2037
+ const { content, role } = body;
2038
+ if (!content || typeof content !== "string") {
2039
+ return Response.json(
2040
+ { error: "Message content is required" },
2041
+ { status: 400 }
2042
+ );
2043
+ }
2044
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2045
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2046
+ return await stub.sendMessage(threadId, content, role);
2047
+ } catch (error) {
2048
+ console.error(`Error sending message to thread ${threadId}:`, error);
2049
+ return Response.json(
2050
+ { error: error.message || "Failed to send message" },
2051
+ { status: 500 }
2052
+ );
2053
+ }
2054
+ });
2055
+
2056
+ // src/api/threads/[id]/messages.get.ts
2057
+ var messages_get_default = defineController(async ({ req, params, env }) => {
2058
+ const url = new URL(req.url);
2059
+ const threadId = params.id;
2060
+ if (!threadId) {
2061
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2062
+ }
2063
+ try {
2064
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2065
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2066
+ const thread = await agentBuilder.getThread(threadId);
2067
+ if (!thread) {
2068
+ return Response.json(
2069
+ { error: `Thread not found: ${threadId}` },
2070
+ { status: 404 }
2071
+ );
2072
+ }
2073
+ const limit = parseInt(url.searchParams.get("limit") || "100", 10);
2074
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
2075
+ const order = url.searchParams.get("order") === "asc" ? "ASC" : "DESC";
2076
+ const includeSilent = url.searchParams.get("includeSilent") === "true";
2077
+ const maxDepth = parseInt(url.searchParams.get("depth") || "0", 10);
2078
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2079
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2080
+ const result = await stub.getMessages(
2081
+ limit,
2082
+ offset,
2083
+ order,
2084
+ includeSilent,
2085
+ maxDepth
2086
+ );
2087
+ return Response.json(result);
2088
+ } catch (error) {
2089
+ console.error(`Error fetching messages for thread ${threadId}:`, error);
2090
+ return Response.json(
2091
+ { error: error.message || "Failed to fetch messages" },
2092
+ { status: 500 }
2093
+ );
2094
+ }
2095
+ });
2096
+
2097
+ // src/api/threads/[id]/rpc.post.ts
2098
+ var rpc_post_default = defineController(async ({ req, params, env }) => {
2099
+ const threadId = params.id;
2100
+ if (!threadId) {
2101
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2102
+ }
2103
+ const body = await req.json();
2104
+ const { method, args = [] } = body;
2105
+ if (!method) {
2106
+ return Response.json({ error: "Method required" }, { status: 400 });
2107
+ }
2108
+ try {
2109
+ const id = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2110
+ const thread = env.AGENT_BUILDER_THREAD.get(id);
2111
+ const result = await thread[method](...args);
2112
+ if (result instanceof Response) {
2113
+ return result;
2114
+ }
2115
+ return Response.json(result);
2116
+ } catch (error) {
2117
+ console.error(`RPC call to ${method} failed:`, error);
2118
+ return Response.json(
2119
+ { error: error.message || "RPC call failed" },
2120
+ { status: 500 }
2121
+ );
2122
+ }
2123
+ });
2124
+
2125
+ // src/api/threads/[id]/stop.post.ts
2126
+ var stop_post_default = defineController(async ({ params, env }) => {
2127
+ const threadId = params.id;
2128
+ if (!threadId) {
2129
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2130
+ }
2131
+ try {
2132
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2133
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2134
+ const thread = await agentBuilder.getThread(threadId);
2135
+ if (!thread) {
2136
+ return Response.json(
2137
+ { error: `Thread not found: ${threadId}` },
2138
+ { status: 404 }
2139
+ );
2140
+ }
2141
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2142
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2143
+ return await stub.stop();
2144
+ } catch (error) {
2145
+ console.error(`Error stopping thread ${threadId}:`, error);
2146
+ return Response.json(
2147
+ { error: error.message || "Failed to stop thread" },
2148
+ { status: 500 }
2149
+ );
2150
+ }
2151
+ });
2152
+
2153
+ // src/api/threads/[id]/stream.ts
2154
+ var stream_default = defineController(async ({ req, params, env }) => {
2155
+ const threadId = params.id;
2156
+ if (!threadId) {
2157
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2158
+ }
2159
+ if (req.headers.get("upgrade")?.toLowerCase() !== "websocket") {
2160
+ return Response.json(
2161
+ { error: "This endpoint only supports WebSocket connections" },
2162
+ { status: 400 }
2163
+ );
2164
+ }
2165
+ try {
2166
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2167
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2168
+ const thread = await agentBuilder.getThread(threadId);
2169
+ if (!thread) {
2170
+ return Response.json(
2171
+ { error: `Thread not found: ${threadId}` },
2172
+ { status: 404 }
2173
+ );
2174
+ }
2175
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2176
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2177
+ return await stub.fetch(req);
2178
+ } catch (error) {
2179
+ console.error(`Error handling message stream for thread ${threadId}:`, error);
2180
+ return Response.json(
2181
+ { error: error.message || "Failed to establish message stream" },
2182
+ { status: 500 }
2183
+ );
2184
+ }
2185
+ });
2186
+
2187
+ // src/api/threads/[id]/logs/[logId].get.ts
2188
+ var logId_get_default = defineController(async ({ req, params, env }) => {
2189
+ const threadId = params.id;
2190
+ const logId = params.logId;
2191
+ if (!threadId) {
2192
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2193
+ }
2194
+ if (!logId) {
2195
+ return Response.json({ error: "Log ID required" }, { status: 400 });
2196
+ }
2197
+ try {
2198
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2199
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2200
+ const thread = await agentBuilder.getThread(threadId);
2201
+ if (!thread) {
2202
+ return Response.json(
2203
+ { error: `Thread not found: ${threadId}` },
2204
+ { status: 404 }
2205
+ );
2206
+ }
2207
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2208
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2209
+ const logDetails = await stub.getLogDetails(logId);
2210
+ return Response.json(logDetails);
2211
+ } catch (error) {
2212
+ console.error(`Error fetching log details for ${logId}:`, error);
2213
+ if (error.message?.includes("not found")) {
2214
+ return Response.json(
2215
+ { error: error.message },
2216
+ { status: 404 }
2217
+ );
2218
+ }
2219
+ return Response.json(
2220
+ { error: error.message || "Failed to fetch log details" },
2221
+ { status: 500 }
2222
+ );
2223
+ }
2224
+ });
2225
+
2226
+ // src/api/threads/[id]/messages/[messageId].delete.ts
2227
+ var messageId_delete_default = defineController(async ({ req, params, env }) => {
2228
+ const threadId = params.id;
2229
+ const messageId = params.messageId;
2230
+ if (!threadId) {
2231
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2232
+ }
2233
+ if (!messageId) {
2234
+ return Response.json({ error: "Message ID required" }, { status: 400 });
2235
+ }
2236
+ try {
2237
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2238
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2239
+ const thread = await agentBuilder.getThread(threadId);
2240
+ if (!thread) {
2241
+ return Response.json(
2242
+ { error: `Thread not found: ${threadId}` },
2243
+ { status: 404 }
2244
+ );
2245
+ }
2246
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2247
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2248
+ const result = await stub.deleteMessage(messageId);
2249
+ if (!result.success) {
2250
+ return Response.json(
2251
+ { error: result.error || "Failed to delete message" },
2252
+ { status: 404 }
2253
+ );
2254
+ }
2255
+ return Response.json({ success: true });
2256
+ } catch (error) {
2257
+ console.error(`Error deleting message ${messageId} from thread ${threadId}:`, error);
2258
+ return Response.json(
2259
+ { error: error.message || "Failed to delete message" },
2260
+ { status: 500 }
2261
+ );
2262
+ }
2263
+ });
2264
+
2265
+ // src/built-in-routes.ts
2266
+ var routeHandlers = {
2267
+ "POST:/": index_post_default,
2268
+ "GET:/agents": agents_get_default,
2269
+ "GET:/api-keys": index_get_default,
2270
+ "POST:/api-keys": index_post_default2,
2271
+ "GET:/config": config_get_default,
2272
+ "GET:/diagnostics": diagnostics_get_default,
2273
+ "GET:/events": events_get_default,
2274
+ "GET:/models": models_get_default,
2275
+ "GET:/new-test": new_test_get_default,
2276
+ "GET:/prompts": prompts_get_default,
2277
+ "GET:/providers": providers_get_default,
2278
+ "POST:/threads": index_post_default3,
2279
+ "GET:/threads": threads_default,
2280
+ "GET:/tools": tools_get_default,
2281
+ "GET:/users": index_get_default2,
2282
+ "POST:/users": index_post_default4,
2283
+ "GET:/agents/:name": name_get_default,
2284
+ "DELETE:/api-keys/:id": id_delete_default,
2285
+ "GET:/prompts/:name": name_get_default2,
2286
+ "DELETE:/threads/:id": id_delete_default2,
2287
+ "PATCH:/threads/:id": id_patch_default,
2288
+ "GET:/threads/:id": id_default,
2289
+ "GET:/tools/:name": name_get_default3,
2290
+ "DELETE:/users/:id": id_delete_default3,
2291
+ "PUT:/users/:id": id_put_default,
2292
+ "GET:/auth/config": config_get_default2,
2293
+ "POST:/auth/login": login_post_default,
2294
+ "POST:/auth/logout": logout_post_default,
2295
+ "GET:/auth/me": me_get_default,
2296
+ "POST:/models/available": available_post_default,
2297
+ "POST:/models/endpoints": endpoints_post_default,
2298
+ "GET:/threads/:id/cost": cost_get_default,
2299
+ "GET:/threads/:id/logs": logs_get_default,
2300
+ "POST:/threads/:id/message": message_post_default,
2301
+ "GET:/threads/:id/messages": messages_get_default,
2302
+ "POST:/threads/:id/rpc": rpc_post_default,
2303
+ "POST:/threads/:id/stop": stop_post_default,
2304
+ "GET:/threads/:id/stream": stream_default,
2305
+ "GET:/threads/:id/logs/:logId": logId_get_default,
2306
+ "DELETE:/threads/:id/messages/:messageId": messageId_delete_default
2307
+ };
2308
+ function registerBuiltInRoutes(router, runtimeData) {
2309
+ for (const [key, handler] of Object.entries(routeHandlers)) {
2310
+ const [method, ...routeParts] = key.split(":");
2311
+ const route = routeParts.join(":");
2312
+ const apiRoute = `/api${route}`;
2313
+ const wrappedHandler = async (context) => {
2314
+ const enhancedContext = {
2315
+ ...context,
2316
+ ...runtimeData?.config && { config: runtimeData.config },
2317
+ ...runtimeData?.tools && { tools: runtimeData.tools },
2318
+ ...runtimeData?.models && { models: runtimeData.models },
2319
+ ...runtimeData?.modelNames && { modelNames: runtimeData.modelNames },
2320
+ ...runtimeData?.prompts && { prompts: runtimeData.prompts },
2321
+ ...runtimeData?.promptNames && { promptNames: runtimeData.promptNames },
2322
+ ...runtimeData?.agents && { agents: runtimeData.agents },
2323
+ ...runtimeData?.agentNames && { agentNames: runtimeData.agentNames }
2324
+ };
2325
+ return handler(enhancedContext);
2326
+ };
2327
+ addRoute(router, method, apiRoute, async () => wrappedHandler);
2328
+ }
2329
+ }
2330
+
2331
+ export { registerBuiltInRoutes };
2332
+ //# sourceMappingURL=built-in-routes.js.map
2333
+ //# sourceMappingURL=built-in-routes.js.map