@standardagents/builder 0.11.0-next.ab7e1ea → 0.11.0-next.af971ae

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.
@@ -1,3 +1,4 @@
1
+ import '@standardagents/spec';
1
2
  import { z } from 'zod';
2
3
 
3
4
  // ../../node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.mjs
@@ -77,8 +78,6 @@ function getParamRegexp(segment) {
77
78
  const regex = segment.replace(/:(\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\./g, "\\.");
78
79
  return /* @__PURE__ */ new RegExp(`^${regex}$`);
79
80
  }
80
-
81
- // src/router/index.ts
82
81
  function defineController(controller) {
83
82
  return controller;
84
83
  }
@@ -145,8 +144,8 @@ var agents_get_default = defineController(async ({ agents, agentNames, prompts,
145
144
  side_a_stop_on_response: definition.sideA?.stopOnResponse !== void 0 ? definition.sideA.stopOnResponse : true,
146
145
  side_a_stop_tool: definition.sideA?.stopTool || null,
147
146
  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,
147
+ side_a_max_steps: definition.sideA?.maxSteps || null,
148
+ side_a_end_session_tool: definition.sideA?.endSessionTool || null,
150
149
  side_a_manual_stop_condition: definition.sideA?.manualStopCondition || false,
151
150
  // Side B configuration (if dual_ai)
152
151
  side_b_label: definition.sideB?.label || null,
@@ -155,16 +154,14 @@ var agents_get_default = defineController(async ({ agents, agentNames, prompts,
155
154
  side_b_stop_on_response: definition.sideB?.stopOnResponse !== void 0 ? definition.sideB.stopOnResponse : true,
156
155
  side_b_stop_tool: definition.sideB?.stopTool || null,
157
156
  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,
157
+ side_b_max_steps: definition.sideB?.maxSteps || null,
158
+ side_b_end_session_tool: definition.sideB?.endSessionTool || null,
160
159
  side_b_manual_stop_condition: definition.sideB?.manualStopCondition || false,
161
160
  // Session configuration
162
161
  max_session_turns: definition.maxSessionTurns || null,
163
162
  // Tool exposure
164
163
  expose_as_tool: definition.exposeAsTool || false,
165
164
  tool_description: definition.toolDescription || null,
166
- // Tags
167
- tags: definition.tags || [],
168
165
  created_at: Math.floor(Date.now() / 1e3)
169
166
  };
170
167
  } catch (error) {
@@ -733,10 +730,7 @@ var prompts_get_default = defineController(async ({ prompts, promptNames, models
733
730
  include_past_tools: definition.includePastTools || false,
734
731
  parallel_tool_calls: definition.parallelToolCalls || false,
735
732
  tool_choice: definition.toolChoice || "auto",
736
- before_tool: definition.beforeTool || null,
737
- after_tool: definition.afterTool || null,
738
733
  tools,
739
- prompts: definition.handoffAgents || [],
740
734
  reasoning: definition.reasoning || null,
741
735
  created_at: Math.floor(Date.now() / 1e3)
742
736
  };
@@ -1200,8 +1194,8 @@ var name_get_default = defineController(async ({ params, agents, prompts, prompt
1200
1194
  side_a_stop_on_response: definition.sideA?.stopOnResponse !== void 0 ? definition.sideA.stopOnResponse : true,
1201
1195
  side_a_stop_tool: definition.sideA?.stopTool || null,
1202
1196
  side_a_stop_tool_response_property: definition.sideA?.stopToolResponseProperty || null,
1203
- side_a_max_turns: definition.sideA?.maxTurns || null,
1204
- side_a_end_conversation_tool: definition.sideA?.endConversationTool || null,
1197
+ side_a_max_steps: definition.sideA?.maxSteps || null,
1198
+ side_a_end_session_tool: definition.sideA?.endSessionTool || null,
1205
1199
  side_a_manual_stop_condition: definition.sideA?.manualStopCondition || false,
1206
1200
  // Side B configuration (if dual_ai)
1207
1201
  side_b_label: definition.sideB?.label || null,
@@ -1210,16 +1204,14 @@ var name_get_default = defineController(async ({ params, agents, prompts, prompt
1210
1204
  side_b_stop_on_response: definition.sideB?.stopOnResponse !== void 0 ? definition.sideB.stopOnResponse : true,
1211
1205
  side_b_stop_tool: definition.sideB?.stopTool || null,
1212
1206
  side_b_stop_tool_response_property: definition.sideB?.stopToolResponseProperty || null,
1213
- side_b_max_turns: definition.sideB?.maxTurns || null,
1214
- side_b_end_conversation_tool: definition.sideB?.endConversationTool || null,
1207
+ side_b_max_steps: definition.sideB?.maxSteps || null,
1208
+ side_b_end_session_tool: definition.sideB?.endSessionTool || null,
1215
1209
  side_b_manual_stop_condition: definition.sideB?.manualStopCondition || false,
1216
1210
  // Session configuration
1217
1211
  max_session_turns: definition.maxSessionTurns || null,
1218
1212
  // Tool exposure
1219
1213
  expose_as_tool: definition.exposeAsTool || false,
1220
1214
  tool_description: definition.toolDescription || null,
1221
- // Tags
1222
- tags: definition.tags || [],
1223
1215
  created_at: Math.floor(Date.now() / 1e3)
1224
1216
  };
1225
1217
  return Response.json({ agent });
@@ -1332,10 +1324,7 @@ var name_get_default2 = defineController(async ({ params, prompts, models, model
1332
1324
  include_past_tools: definition.includePastTools || false,
1333
1325
  parallel_tool_calls: definition.parallelToolCalls || false,
1334
1326
  tool_choice: definition.toolChoice || "auto",
1335
- before_tool: definition.beforeTool || null,
1336
- after_tool: definition.afterTool || null,
1337
1327
  tools,
1338
- prompts: definition.handoffAgents || [],
1339
1328
  reasoning: definition.reasoning || null,
1340
1329
  created_at: Math.floor(Date.now() / 1e3)
1341
1330
  };
@@ -2176,6 +2165,47 @@ var logs_get_default = defineController(async ({ req, params, env }) => {
2176
2165
  }
2177
2166
  });
2178
2167
 
2168
+ // src/api/threads/[id]/messages.get.ts
2169
+ var messages_get_default = defineController(async ({ req, params, env }) => {
2170
+ const url = new URL(req.url);
2171
+ const threadId = params.id;
2172
+ if (!threadId) {
2173
+ return Response.json({ error: "Thread ID required" }, { status: 400 });
2174
+ }
2175
+ try {
2176
+ const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2177
+ const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2178
+ const thread = await agentBuilder.getThread(threadId);
2179
+ if (!thread) {
2180
+ return Response.json(
2181
+ { error: `Thread not found: ${threadId}` },
2182
+ { status: 404 }
2183
+ );
2184
+ }
2185
+ const limit = parseInt(url.searchParams.get("limit") || "100", 10);
2186
+ const offset = parseInt(url.searchParams.get("offset") || "0", 10);
2187
+ const order = url.searchParams.get("order") === "asc" ? "ASC" : "DESC";
2188
+ const includeSilent = url.searchParams.get("includeSilent") === "true";
2189
+ const maxDepth = parseInt(url.searchParams.get("depth") || "0", 10);
2190
+ const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2191
+ const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2192
+ const result = await stub.getMessages(
2193
+ limit,
2194
+ offset,
2195
+ order,
2196
+ includeSilent,
2197
+ maxDepth
2198
+ );
2199
+ return Response.json(result);
2200
+ } catch (error) {
2201
+ console.error(`Error fetching messages for thread ${threadId}:`, error);
2202
+ return Response.json(
2203
+ { error: error.message || "Failed to fetch messages" },
2204
+ { status: 500 }
2205
+ );
2206
+ }
2207
+ });
2208
+
2179
2209
  // src/api/threads/[id]/messages.post.ts
2180
2210
  function needsProcessing(base64Data, mimeType) {
2181
2211
  const binarySize = Math.ceil(base64Data.length * 3 / 4);
@@ -2288,47 +2318,6 @@ var messages_post_default = defineController(async ({ req, params, env }) => {
2288
2318
  }
2289
2319
  });
2290
2320
 
2291
- // src/api/threads/[id]/messages.get.ts
2292
- var messages_get_default = defineController(async ({ req, params, env }) => {
2293
- const url = new URL(req.url);
2294
- const threadId = params.id;
2295
- if (!threadId) {
2296
- return Response.json({ error: "Thread ID required" }, { status: 400 });
2297
- }
2298
- try {
2299
- const agentBuilderId = env.AGENT_BUILDER.idFromName("singleton");
2300
- const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
2301
- const thread = await agentBuilder.getThread(threadId);
2302
- if (!thread) {
2303
- return Response.json(
2304
- { error: `Thread not found: ${threadId}` },
2305
- { status: 404 }
2306
- );
2307
- }
2308
- const limit = parseInt(url.searchParams.get("limit") || "100", 10);
2309
- const offset = parseInt(url.searchParams.get("offset") || "0", 10);
2310
- const order = url.searchParams.get("order") === "asc" ? "ASC" : "DESC";
2311
- const includeSilent = url.searchParams.get("includeSilent") === "true";
2312
- const maxDepth = parseInt(url.searchParams.get("depth") || "0", 10);
2313
- const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2314
- const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2315
- const result = await stub.getMessages(
2316
- limit,
2317
- offset,
2318
- order,
2319
- includeSilent,
2320
- maxDepth
2321
- );
2322
- return Response.json(result);
2323
- } catch (error) {
2324
- console.error(`Error fetching messages for thread ${threadId}:`, error);
2325
- return Response.json(
2326
- { error: error.message || "Failed to fetch messages" },
2327
- { status: 500 }
2328
- );
2329
- }
2330
- });
2331
-
2332
2321
  // src/api/threads/[id]/rpc.post.ts
2333
2322
  var rpc_post_default = defineController(async ({ req, params, env }) => {
2334
2323
  const threadId = params.id;
@@ -2420,6 +2409,7 @@ var stream_default = defineController(async ({ req, params, env }) => {
2420
2409
  });
2421
2410
 
2422
2411
  // src/api/threads/[id]/fs/[...path].ts
2412
+ var CHUNK_SIZE = 1.75 * 1024 * 1024;
2423
2413
  function toAttachmentRef(file) {
2424
2414
  const metadata = file.metadata;
2425
2415
  const width = file.width ?? metadata?.width;
@@ -2449,11 +2439,30 @@ var path_default = defineController(async ({ req, params, env }) => {
2449
2439
  try {
2450
2440
  const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
2451
2441
  const stub = env.AGENT_BUILDER_THREAD.get(durableId);
2442
+ const uploadMatch = path.match(/^(.+)\/upload\/(start|complete|chunk\/(\d+))$/);
2443
+ if (uploadMatch) {
2444
+ const filePath = uploadMatch[1];
2445
+ const action = uploadMatch[2];
2446
+ const chunkIndex = uploadMatch[3] ? parseInt(uploadMatch[3], 10) : void 0;
2447
+ if (action === "start" && req.method === "POST") {
2448
+ return handleChunkedUploadStart(stub, filePath, req);
2449
+ }
2450
+ if (action === "complete" && req.method === "POST") {
2451
+ return handleChunkedUploadComplete(stub, filePath, req);
2452
+ }
2453
+ if (action.startsWith("chunk/") && req.method === "PUT" && chunkIndex !== void 0) {
2454
+ return handleChunkedUploadChunk(stub, filePath, chunkIndex, req);
2455
+ }
2456
+ return Response.json(
2457
+ { error: `Invalid upload action: ${action} with method ${req.method}` },
2458
+ { status: 400 }
2459
+ );
2460
+ }
2452
2461
  switch (req.method) {
2453
2462
  case "GET":
2454
2463
  return handleGet(stub, path, url);
2455
- case "PUT":
2456
- return handlePut(stub, path, req);
2464
+ case "POST":
2465
+ return handlePost(stub, path, req);
2457
2466
  case "DELETE":
2458
2467
  return handleDelete(stub, path);
2459
2468
  default:
@@ -2520,6 +2529,9 @@ async function handleGet(stub, path, url) {
2520
2529
  if (acceptHeader === "json") {
2521
2530
  return Response.json({ file });
2522
2531
  }
2532
+ if (file.isChunked && file.chunkCount) {
2533
+ return streamChunkedFile(stub, path, file);
2534
+ }
2523
2535
  const result = await stub.readFile(path);
2524
2536
  if (!result.success) {
2525
2537
  return Response.json({ error: result.error }, { status: 404 });
@@ -2537,7 +2549,40 @@ async function handleGet(stub, path, url) {
2537
2549
  }
2538
2550
  });
2539
2551
  }
2540
- async function handlePut(stub, path, req) {
2552
+ function streamChunkedFile(stub, path, file) {
2553
+ const { readable, writable } = new TransformStream();
2554
+ const writer = writable.getWriter();
2555
+ (async () => {
2556
+ try {
2557
+ for (let i = 0; i < file.chunkCount; i++) {
2558
+ const result = await stub.readFileChunk(path, i);
2559
+ if (!result.success) {
2560
+ console.error(`Failed to read chunk ${i}:`, result.error);
2561
+ break;
2562
+ }
2563
+ const binary = atob(result.data);
2564
+ const bytes = new Uint8Array(binary.length);
2565
+ for (let j = 0; j < binary.length; j++) {
2566
+ bytes[j] = binary.charCodeAt(j);
2567
+ }
2568
+ await writer.write(bytes);
2569
+ }
2570
+ } catch (error) {
2571
+ console.error("Error streaming chunked file:", error);
2572
+ } finally {
2573
+ await writer.close();
2574
+ }
2575
+ })();
2576
+ return new Response(readable, {
2577
+ headers: {
2578
+ "Content-Type": file.mimeType,
2579
+ "Content-Length": String(file.size),
2580
+ "Content-Disposition": `inline; filename="${file.name}"`
2581
+ // Note: We set Content-Length, but also use chunked transfer internally
2582
+ }
2583
+ });
2584
+ }
2585
+ async function handlePost(stub, path, req) {
2541
2586
  const contentType = req.headers.get("Content-Type") || "";
2542
2587
  if (contentType.includes("application/json")) {
2543
2588
  const body = await req.json();
@@ -2571,8 +2616,12 @@ async function handlePut(stub, path, req) {
2571
2616
  }
2572
2617
  return Response.json({ error: "Invalid request body" }, { status: 400 });
2573
2618
  }
2574
- const data = await req.arrayBuffer();
2575
2619
  const mimeType = contentType.split(";")[0].trim() || "application/octet-stream";
2620
+ const contentLength = parseInt(req.headers.get("Content-Length") || "0", 10);
2621
+ if (contentLength > CHUNK_SIZE && req.body) {
2622
+ return handleStreamingUpload(stub, path, mimeType, contentLength, req);
2623
+ }
2624
+ const data = await req.arrayBuffer();
2576
2625
  const bytes = new Uint8Array(data);
2577
2626
  let binary = "";
2578
2627
  for (let i = 0; i < bytes.length; i++) {
@@ -2585,6 +2634,64 @@ async function handlePut(stub, path, req) {
2585
2634
  }
2586
2635
  return Response.json(toAttachmentRef(result.file), { status: 201 });
2587
2636
  }
2637
+ async function handleStreamingUpload(stub, path, mimeType, totalSize, req) {
2638
+ const startResult = await stub.startChunkedUpload(path, totalSize, mimeType, {});
2639
+ if (!startResult.success) {
2640
+ return Response.json({ error: startResult.error }, { status: 400 });
2641
+ }
2642
+ const reader = req.body.getReader();
2643
+ let chunkIndex = 0;
2644
+ let buffer = new Uint8Array(0);
2645
+ try {
2646
+ while (true) {
2647
+ const { done, value } = await reader.read();
2648
+ if (value) {
2649
+ const newBuffer = new Uint8Array(buffer.length + value.length);
2650
+ newBuffer.set(buffer);
2651
+ newBuffer.set(value, buffer.length);
2652
+ buffer = newBuffer;
2653
+ while (buffer.length >= CHUNK_SIZE) {
2654
+ const chunk = buffer.slice(0, CHUNK_SIZE);
2655
+ const base64 = arrayBufferToBase64(chunk);
2656
+ const chunkResult = await stub.writeFileChunk(path, chunkIndex, base64);
2657
+ if (!chunkResult.success) {
2658
+ return Response.json({ error: chunkResult.error }, { status: 400 });
2659
+ }
2660
+ chunkIndex++;
2661
+ buffer = buffer.slice(CHUNK_SIZE);
2662
+ }
2663
+ }
2664
+ if (done) {
2665
+ if (buffer.length > 0) {
2666
+ const base64 = arrayBufferToBase64(buffer);
2667
+ const chunkResult = await stub.writeFileChunk(path, chunkIndex, base64);
2668
+ if (!chunkResult.success) {
2669
+ return Response.json({ error: chunkResult.error }, { status: 400 });
2670
+ }
2671
+ chunkIndex++;
2672
+ }
2673
+ break;
2674
+ }
2675
+ }
2676
+ const completeResult = await stub.completeChunkedUpload(path, chunkIndex, {});
2677
+ if (!completeResult.success) {
2678
+ return Response.json({ error: completeResult.error }, { status: 400 });
2679
+ }
2680
+ return Response.json(toAttachmentRef(completeResult.file), { status: 201 });
2681
+ } catch (error) {
2682
+ console.error("Streaming upload failed:", error);
2683
+ return Response.json({ error: error.message || "Upload failed" }, { status: 500 });
2684
+ }
2685
+ }
2686
+ function arrayBufferToBase64(bytes) {
2687
+ const BATCH_SIZE = 32768;
2688
+ let binary = "";
2689
+ for (let i = 0; i < bytes.length; i += BATCH_SIZE) {
2690
+ const slice = bytes.subarray(i, Math.min(i + BATCH_SIZE, bytes.length));
2691
+ binary += String.fromCharCode.apply(null, slice);
2692
+ }
2693
+ return btoa(binary);
2694
+ }
2588
2695
  async function handleDelete(stub, path) {
2589
2696
  const statResult = await stub.statFile(path);
2590
2697
  if (!statResult.success) {
@@ -2604,6 +2711,61 @@ async function handleDelete(stub, path) {
2604
2711
  }
2605
2712
  return new Response(null, { status: 204 });
2606
2713
  }
2714
+ async function handleChunkedUploadStart(stub, filePath, req) {
2715
+ const body = await req.json();
2716
+ if (!body.totalSize || !body.mimeType) {
2717
+ return Response.json(
2718
+ { error: "totalSize and mimeType are required" },
2719
+ { status: 400 }
2720
+ );
2721
+ }
2722
+ const result = await stub.startChunkedUpload(filePath, body.totalSize, body.mimeType, {
2723
+ metadata: body.metadata,
2724
+ width: body.width,
2725
+ height: body.height
2726
+ });
2727
+ if (!result.success) {
2728
+ return Response.json({ error: result.error }, { status: 400 });
2729
+ }
2730
+ return Response.json({
2731
+ chunkSize: result.chunkSize,
2732
+ expectedChunks: result.expectedChunks,
2733
+ path: filePath
2734
+ });
2735
+ }
2736
+ async function handleChunkedUploadChunk(stub, filePath, chunkIndex, req) {
2737
+ const data = await req.arrayBuffer();
2738
+ const bytes = new Uint8Array(data);
2739
+ let binary = "";
2740
+ for (let i = 0; i < bytes.length; i++) {
2741
+ binary += String.fromCharCode(bytes[i]);
2742
+ }
2743
+ const base64 = btoa(binary);
2744
+ const result = await stub.writeFileChunk(filePath, chunkIndex, base64);
2745
+ if (!result.success) {
2746
+ return Response.json({ error: result.error }, { status: 400 });
2747
+ }
2748
+ return Response.json({
2749
+ chunkIndex,
2750
+ received: data.byteLength
2751
+ });
2752
+ }
2753
+ async function handleChunkedUploadComplete(stub, filePath, req) {
2754
+ const body = await req.json();
2755
+ if (typeof body.expectedChunks !== "number") {
2756
+ return Response.json(
2757
+ { error: "expectedChunks is required" },
2758
+ { status: 400 }
2759
+ );
2760
+ }
2761
+ const result = await stub.completeChunkedUpload(filePath, body.expectedChunks, {
2762
+ thumbnail: body.thumbnail
2763
+ });
2764
+ if (!result.success) {
2765
+ return Response.json({ error: result.error }, { status: 400 });
2766
+ }
2767
+ return Response.json(toAttachmentRef(result.file), { status: 201 });
2768
+ }
2607
2769
 
2608
2770
  // src/api/threads/[id]/logs/[logId].get.ts
2609
2771
  var logId_get_default = defineController(async ({ req, params, env }) => {
@@ -2767,11 +2929,13 @@ var routeHandlers = {
2767
2929
  "GET:/threads/:id/cost": cost_get_default,
2768
2930
  "GET:/threads/:id/fs": fs_default,
2769
2931
  "GET:/threads/:id/logs": logs_get_default,
2770
- "POST:/threads/:id/messages": messages_post_default,
2771
2932
  "GET:/threads/:id/messages": messages_get_default,
2933
+ "POST:/threads/:id/messages": messages_post_default,
2772
2934
  "POST:/threads/:id/rpc": rpc_post_default,
2773
2935
  "POST:/threads/:id/stop": stop_post_default,
2774
2936
  "GET:/threads/:id/stream": stream_default,
2937
+ "DELETE:/threads/:id/fs/**": path_default,
2938
+ "POST:/threads/:id/fs/**": path_default,
2775
2939
  "GET:/threads/:id/fs/**": path_default,
2776
2940
  "GET:/threads/:id/logs/:logId": logId_get_default,
2777
2941
  "DELETE:/threads/:id/messages/:messageId": messageId_delete_default,