@standardagents/builder 0.9.16 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/built-in-routes.js +306 -4
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/assets/index.css +1 -1
- package/dist/client/index.js +19 -19
- package/dist/client/vendor.js +1 -1
- package/dist/client/vue.js +1 -1
- package/dist/image-processing.d.ts +41 -0
- package/dist/image-processing.js +198 -0
- package/dist/image-processing.js.map +1 -0
- package/dist/index.d.ts +758 -3
- package/dist/index.js +1342 -37
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +16 -2
- package/dist/plugin.js.map +1 -1
- package/package.json +11 -1
package/dist/built-in-routes.js
CHANGED
|
@@ -1979,6 +1979,66 @@ var cost_get_default = defineController(async ({ req, params, env }) => {
|
|
|
1979
1979
|
}
|
|
1980
1980
|
});
|
|
1981
1981
|
|
|
1982
|
+
// src/api/threads/[id]/fs/index.ts
|
|
1983
|
+
var fs_default = defineController(async ({ req, params, env }) => {
|
|
1984
|
+
const threadId = params.id;
|
|
1985
|
+
if (!threadId) {
|
|
1986
|
+
return Response.json({ error: "Thread ID required" }, { status: 400 });
|
|
1987
|
+
}
|
|
1988
|
+
if (req.method !== "GET") {
|
|
1989
|
+
return Response.json(
|
|
1990
|
+
{ error: `Method ${req.method} not allowed` },
|
|
1991
|
+
{ status: 405 }
|
|
1992
|
+
);
|
|
1993
|
+
}
|
|
1994
|
+
const url = new URL(req.url);
|
|
1995
|
+
try {
|
|
1996
|
+
const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
|
|
1997
|
+
const stub = env.AGENT_BUILDER_THREAD.get(durableId);
|
|
1998
|
+
if (url.searchParams.has("stats")) {
|
|
1999
|
+
const result2 = await stub.getFileStats();
|
|
2000
|
+
if (!result2.success) {
|
|
2001
|
+
return Response.json({ error: result2.error }, { status: 500 });
|
|
2002
|
+
}
|
|
2003
|
+
return Response.json(result2.stats);
|
|
2004
|
+
}
|
|
2005
|
+
const grepPattern = url.searchParams.get("grep");
|
|
2006
|
+
if (grepPattern) {
|
|
2007
|
+
const path = url.searchParams.get("path") || void 0;
|
|
2008
|
+
const limit = parseInt(url.searchParams.get("limit") || "100", 10);
|
|
2009
|
+
const result2 = await stub.grepFiles(grepPattern, { path, limit });
|
|
2010
|
+
if (!result2.success) {
|
|
2011
|
+
return Response.json({ error: result2.error }, { status: 500 });
|
|
2012
|
+
}
|
|
2013
|
+
return Response.json({ results: result2.results, pattern: grepPattern });
|
|
2014
|
+
}
|
|
2015
|
+
const findPattern = url.searchParams.get("find");
|
|
2016
|
+
if (findPattern) {
|
|
2017
|
+
const type = url.searchParams.get("type");
|
|
2018
|
+
const limit = parseInt(url.searchParams.get("limit") || "100", 10);
|
|
2019
|
+
const result2 = await stub.findFiles(findPattern, {
|
|
2020
|
+
type: type || "all",
|
|
2021
|
+
limit
|
|
2022
|
+
});
|
|
2023
|
+
if (!result2.success) {
|
|
2024
|
+
return Response.json({ error: result2.error }, { status: 500 });
|
|
2025
|
+
}
|
|
2026
|
+
return Response.json({ files: result2.files, pattern: findPattern });
|
|
2027
|
+
}
|
|
2028
|
+
const result = await stub.readdirFile("/");
|
|
2029
|
+
if (!result.success) {
|
|
2030
|
+
return Response.json({ error: result.error }, { status: 500 });
|
|
2031
|
+
}
|
|
2032
|
+
return Response.json({ files: result.files, path: "/" });
|
|
2033
|
+
} catch (error) {
|
|
2034
|
+
console.error(`Error in fs root API for thread ${threadId}:`, error);
|
|
2035
|
+
return Response.json(
|
|
2036
|
+
{ error: error.message || "File operation failed" },
|
|
2037
|
+
{ status: 500 }
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
});
|
|
2041
|
+
|
|
1982
2042
|
// src/api/threads/[id]/logs.get.ts
|
|
1983
2043
|
var logs_get_default = defineController(async ({ req, params, env }) => {
|
|
1984
2044
|
const url = new URL(req.url);
|
|
@@ -2018,6 +2078,13 @@ var logs_get_default = defineController(async ({ req, params, env }) => {
|
|
|
2018
2078
|
});
|
|
2019
2079
|
|
|
2020
2080
|
// src/api/threads/[id]/message.post.ts
|
|
2081
|
+
var imageProcessingModule = null;
|
|
2082
|
+
async function getImageProcessing() {
|
|
2083
|
+
if (!imageProcessingModule) {
|
|
2084
|
+
imageProcessingModule = await import('@standardagents/builder/image-processing');
|
|
2085
|
+
}
|
|
2086
|
+
return imageProcessingModule;
|
|
2087
|
+
}
|
|
2021
2088
|
var message_post_default = defineController(async ({ req, params, env }) => {
|
|
2022
2089
|
const threadId = params.id;
|
|
2023
2090
|
if (!threadId) {
|
|
@@ -2034,16 +2101,79 @@ var message_post_default = defineController(async ({ req, params, env }) => {
|
|
|
2034
2101
|
);
|
|
2035
2102
|
}
|
|
2036
2103
|
const body = await req.json();
|
|
2037
|
-
const { content, role } = body;
|
|
2038
|
-
|
|
2104
|
+
const { content = "", role, attachments, silent } = body;
|
|
2105
|
+
const hasContent = content && typeof content === "string" && content.trim().length > 0;
|
|
2106
|
+
const hasAttachments = attachments && Array.isArray(attachments) && attachments.length > 0;
|
|
2107
|
+
if (!hasContent && !hasAttachments) {
|
|
2039
2108
|
return Response.json(
|
|
2040
|
-
{ error: "Message content
|
|
2109
|
+
{ error: "Message content or attachments required" },
|
|
2041
2110
|
{ status: 400 }
|
|
2042
2111
|
);
|
|
2043
2112
|
}
|
|
2044
2113
|
const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
|
|
2045
2114
|
const stub = env.AGENT_BUILDER_THREAD.get(durableId);
|
|
2046
|
-
|
|
2115
|
+
let attachmentRefs;
|
|
2116
|
+
if (attachments && attachments.length > 0) {
|
|
2117
|
+
attachmentRefs = [];
|
|
2118
|
+
for (const attachment of attachments) {
|
|
2119
|
+
const attachmentId = crypto.randomUUID();
|
|
2120
|
+
const timestamp = Date.now();
|
|
2121
|
+
let fileData = attachment.data;
|
|
2122
|
+
let mimeType = attachment.mimeType;
|
|
2123
|
+
let width = attachment.width;
|
|
2124
|
+
let height = attachment.height;
|
|
2125
|
+
const imgProc = await getImageProcessing();
|
|
2126
|
+
if (mimeType.startsWith("image/") && imgProc.needsProcessing(fileData, mimeType)) {
|
|
2127
|
+
try {
|
|
2128
|
+
const buffer = imgProc.base64ToArrayBuffer(fileData);
|
|
2129
|
+
const processed = await imgProc.processImage(buffer, mimeType);
|
|
2130
|
+
fileData = imgProc.arrayBufferToBase64(processed.data);
|
|
2131
|
+
mimeType = processed.mimeType;
|
|
2132
|
+
width = processed.width;
|
|
2133
|
+
height = processed.height;
|
|
2134
|
+
console.log(
|
|
2135
|
+
`[image-processing] Processed ${attachment.name}: ${(buffer.byteLength / 1024 / 1024).toFixed(2)}MB \u2192 ${(processed.data.byteLength / 1024 / 1024).toFixed(2)}MB, ${processed.width}x${processed.height}, ${processed.mimeType}`
|
|
2136
|
+
);
|
|
2137
|
+
} catch (err) {
|
|
2138
|
+
console.error(`[image-processing] Failed to process ${attachment.name}:`, err);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
const ext = mimeType === "image/png" ? "png" : mimeType === "image/jpeg" ? "jpg" : attachment.name.split(".").pop() || "bin";
|
|
2142
|
+
const path = `/attachments/${timestamp}-${attachmentId}.${ext}`;
|
|
2143
|
+
const metadata = {};
|
|
2144
|
+
if (width) metadata.width = width;
|
|
2145
|
+
if (height) metadata.height = height;
|
|
2146
|
+
const base64Size = fileData.length;
|
|
2147
|
+
const binarySize = Math.ceil(base64Size * 3 / 4);
|
|
2148
|
+
console.log(`[writeFile] Storing ${attachment.name}: ${(binarySize / 1024 / 1024).toFixed(2)}MB binary (${(base64Size / 1024 / 1024).toFixed(2)}MB base64) to ${path}`);
|
|
2149
|
+
const result = await stub.writeFile(
|
|
2150
|
+
path,
|
|
2151
|
+
fileData,
|
|
2152
|
+
mimeType,
|
|
2153
|
+
{
|
|
2154
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
|
|
2155
|
+
thumbnail: attachment.thumbnail
|
|
2156
|
+
}
|
|
2157
|
+
);
|
|
2158
|
+
console.log(`[writeFile] Result:`, result.success ? "success" : result.error);
|
|
2159
|
+
if (!result.success) {
|
|
2160
|
+
console.error(`Failed to store attachment ${attachment.name}:`, result.error);
|
|
2161
|
+
continue;
|
|
2162
|
+
}
|
|
2163
|
+
const ref = {
|
|
2164
|
+
id: attachmentId,
|
|
2165
|
+
type: "file",
|
|
2166
|
+
path,
|
|
2167
|
+
name: attachment.name,
|
|
2168
|
+
mimeType
|
|
2169
|
+
};
|
|
2170
|
+
if (width) ref.width = width;
|
|
2171
|
+
if (height) ref.height = height;
|
|
2172
|
+
attachmentRefs.push(ref);
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
const attachmentsJson = attachmentRefs && attachmentRefs.length > 0 ? JSON.stringify(attachmentRefs) : void 0;
|
|
2176
|
+
return await stub.sendMessage(threadId, content, role, attachmentsJson);
|
|
2047
2177
|
} catch (error) {
|
|
2048
2178
|
console.error(`Error sending message to thread ${threadId}:`, error);
|
|
2049
2179
|
return Response.json(
|
|
@@ -2184,6 +2314,176 @@ var stream_default = defineController(async ({ req, params, env }) => {
|
|
|
2184
2314
|
}
|
|
2185
2315
|
});
|
|
2186
2316
|
|
|
2317
|
+
// src/api/threads/[id]/fs/[...path].ts
|
|
2318
|
+
var path_default = defineController(async ({ req, params, env }) => {
|
|
2319
|
+
console.log("[fs] params received:", JSON.stringify(params));
|
|
2320
|
+
const threadId = params.id;
|
|
2321
|
+
const pathParam = params._ || params.path || params["*"] || "";
|
|
2322
|
+
if (!threadId) {
|
|
2323
|
+
return Response.json({ error: "Thread ID required" }, { status: 400 });
|
|
2324
|
+
}
|
|
2325
|
+
console.log("[fs] threadId:", threadId, "pathParam:", pathParam);
|
|
2326
|
+
const path = pathParam ? `/${pathParam}` : "/";
|
|
2327
|
+
const url = new URL(req.url);
|
|
2328
|
+
try {
|
|
2329
|
+
const durableId = env.AGENT_BUILDER_THREAD.idFromName(threadId);
|
|
2330
|
+
const stub = env.AGENT_BUILDER_THREAD.get(durableId);
|
|
2331
|
+
switch (req.method) {
|
|
2332
|
+
case "GET":
|
|
2333
|
+
return handleGet(stub, path, url);
|
|
2334
|
+
case "PUT":
|
|
2335
|
+
return handlePut(stub, path, req);
|
|
2336
|
+
case "DELETE":
|
|
2337
|
+
return handleDelete(stub, path);
|
|
2338
|
+
default:
|
|
2339
|
+
return Response.json(
|
|
2340
|
+
{ error: `Method ${req.method} not allowed` },
|
|
2341
|
+
{ status: 405 }
|
|
2342
|
+
);
|
|
2343
|
+
}
|
|
2344
|
+
} catch (error) {
|
|
2345
|
+
console.error(`Error in fs API for thread ${threadId}:`, error);
|
|
2346
|
+
return Response.json(
|
|
2347
|
+
{ error: error.message || "File operation failed" },
|
|
2348
|
+
{ status: 500 }
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2351
|
+
});
|
|
2352
|
+
async function handleGet(stub, path, url) {
|
|
2353
|
+
if (url.searchParams.has("stats")) {
|
|
2354
|
+
const result2 = await stub.getFileStats();
|
|
2355
|
+
if (!result2.success) {
|
|
2356
|
+
return Response.json({ error: result2.error }, { status: 500 });
|
|
2357
|
+
}
|
|
2358
|
+
return Response.json(result2.stats);
|
|
2359
|
+
}
|
|
2360
|
+
if (url.searchParams.has("thumbnail")) {
|
|
2361
|
+
const result2 = await stub.getFileThumbnail(path);
|
|
2362
|
+
if (!result2.success) {
|
|
2363
|
+
return Response.json({ error: result2.error }, { status: 404 });
|
|
2364
|
+
}
|
|
2365
|
+
const binary2 = atob(result2.data);
|
|
2366
|
+
const bytes2 = new Uint8Array(binary2.length);
|
|
2367
|
+
for (let i = 0; i < binary2.length; i++) {
|
|
2368
|
+
bytes2[i] = binary2.charCodeAt(i);
|
|
2369
|
+
}
|
|
2370
|
+
return new Response(bytes2, {
|
|
2371
|
+
headers: {
|
|
2372
|
+
"Content-Type": "image/jpeg",
|
|
2373
|
+
// Thumbnails are typically JPEG
|
|
2374
|
+
"Cache-Control": "public, max-age=31536000"
|
|
2375
|
+
// Cache for 1 year
|
|
2376
|
+
}
|
|
2377
|
+
});
|
|
2378
|
+
}
|
|
2379
|
+
const statResult = await stub.statFile(path);
|
|
2380
|
+
if (!statResult.success) {
|
|
2381
|
+
return Response.json({ error: "Not found" }, { status: 404 });
|
|
2382
|
+
}
|
|
2383
|
+
const file = statResult.file;
|
|
2384
|
+
if (file.isDirectory) {
|
|
2385
|
+
const result2 = await stub.readdirFile(path);
|
|
2386
|
+
if (!result2.success) {
|
|
2387
|
+
return Response.json({ error: result2.error }, { status: 500 });
|
|
2388
|
+
}
|
|
2389
|
+
return Response.json({ files: result2.files, path });
|
|
2390
|
+
}
|
|
2391
|
+
if (file.storage !== "local") {
|
|
2392
|
+
return Response.json({
|
|
2393
|
+
file,
|
|
2394
|
+
external: true,
|
|
2395
|
+
location: file.location
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
const acceptHeader = url.searchParams.get("format") || "auto";
|
|
2399
|
+
if (acceptHeader === "json") {
|
|
2400
|
+
return Response.json({ file });
|
|
2401
|
+
}
|
|
2402
|
+
const result = await stub.readFile(path);
|
|
2403
|
+
if (!result.success) {
|
|
2404
|
+
return Response.json({ error: result.error }, { status: 404 });
|
|
2405
|
+
}
|
|
2406
|
+
const binary = atob(result.data);
|
|
2407
|
+
const bytes = new Uint8Array(binary.length);
|
|
2408
|
+
for (let i = 0; i < binary.length; i++) {
|
|
2409
|
+
bytes[i] = binary.charCodeAt(i);
|
|
2410
|
+
}
|
|
2411
|
+
return new Response(bytes, {
|
|
2412
|
+
headers: {
|
|
2413
|
+
"Content-Type": file.mimeType,
|
|
2414
|
+
"Content-Length": String(file.size),
|
|
2415
|
+
"Content-Disposition": `inline; filename="${file.name}"`
|
|
2416
|
+
}
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
async function handlePut(stub, path, req) {
|
|
2420
|
+
const contentType = req.headers.get("Content-Type") || "";
|
|
2421
|
+
if (contentType.includes("application/json")) {
|
|
2422
|
+
const body = await req.json();
|
|
2423
|
+
if (body.type === "directory") {
|
|
2424
|
+
const result2 = await stub.mkdirFile(path);
|
|
2425
|
+
if (!result2.success) {
|
|
2426
|
+
return Response.json({ error: result2.error }, { status: 400 });
|
|
2427
|
+
}
|
|
2428
|
+
return Response.json({ directory: result2.directory }, { status: 201 });
|
|
2429
|
+
}
|
|
2430
|
+
if (body.location) {
|
|
2431
|
+
const result2 = await stub.linkFile(path, body.location, {
|
|
2432
|
+
mimeType: body.mimeType,
|
|
2433
|
+
size: body.size,
|
|
2434
|
+
metadata: body.metadata
|
|
2435
|
+
});
|
|
2436
|
+
if (!result2.success) {
|
|
2437
|
+
return Response.json({ error: result2.error }, { status: 400 });
|
|
2438
|
+
}
|
|
2439
|
+
return Response.json({ file: result2.file }, { status: 201 });
|
|
2440
|
+
}
|
|
2441
|
+
if (body.data) {
|
|
2442
|
+
const result2 = await stub.writeFile(path, body.data, body.mimeType || "application/octet-stream", {
|
|
2443
|
+
metadata: body.metadata,
|
|
2444
|
+
thumbnail: body.thumbnail
|
|
2445
|
+
});
|
|
2446
|
+
if (!result2.success) {
|
|
2447
|
+
return Response.json({ error: result2.error }, { status: 400 });
|
|
2448
|
+
}
|
|
2449
|
+
return Response.json({ file: result2.file }, { status: 201 });
|
|
2450
|
+
}
|
|
2451
|
+
return Response.json({ error: "Invalid request body" }, { status: 400 });
|
|
2452
|
+
}
|
|
2453
|
+
const data = await req.arrayBuffer();
|
|
2454
|
+
const mimeType = contentType.split(";")[0].trim() || "application/octet-stream";
|
|
2455
|
+
const bytes = new Uint8Array(data);
|
|
2456
|
+
let binary = "";
|
|
2457
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2458
|
+
binary += String.fromCharCode(bytes[i]);
|
|
2459
|
+
}
|
|
2460
|
+
const base64 = btoa(binary);
|
|
2461
|
+
const result = await stub.writeFile(path, base64, mimeType, {});
|
|
2462
|
+
if (!result.success) {
|
|
2463
|
+
return Response.json({ error: result.error }, { status: 400 });
|
|
2464
|
+
}
|
|
2465
|
+
return Response.json({ file: result.file }, { status: 201 });
|
|
2466
|
+
}
|
|
2467
|
+
async function handleDelete(stub, path) {
|
|
2468
|
+
const statResult = await stub.statFile(path);
|
|
2469
|
+
if (!statResult.success) {
|
|
2470
|
+
return Response.json({ error: "Not found" }, { status: 404 });
|
|
2471
|
+
}
|
|
2472
|
+
const file = statResult.file;
|
|
2473
|
+
if (file.isDirectory) {
|
|
2474
|
+
const result = await stub.rmdirFile(path);
|
|
2475
|
+
if (!result.success) {
|
|
2476
|
+
return Response.json({ error: result.error }, { status: 400 });
|
|
2477
|
+
}
|
|
2478
|
+
} else {
|
|
2479
|
+
const result = await stub.unlinkFile(path);
|
|
2480
|
+
if (!result.success) {
|
|
2481
|
+
return Response.json({ error: result.error }, { status: 400 });
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return new Response(null, { status: 204 });
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2187
2487
|
// src/api/threads/[id]/logs/[logId].get.ts
|
|
2188
2488
|
var logId_get_default = defineController(async ({ req, params, env }) => {
|
|
2189
2489
|
const threadId = params.id;
|
|
@@ -2344,12 +2644,14 @@ var routeHandlers = {
|
|
|
2344
2644
|
"POST:/models/available": available_post_default,
|
|
2345
2645
|
"POST:/models/endpoints": endpoints_post_default,
|
|
2346
2646
|
"GET:/threads/:id/cost": cost_get_default,
|
|
2647
|
+
"GET:/threads/:id/fs": fs_default,
|
|
2347
2648
|
"GET:/threads/:id/logs": logs_get_default,
|
|
2348
2649
|
"POST:/threads/:id/message": message_post_default,
|
|
2349
2650
|
"GET:/threads/:id/messages": messages_get_default,
|
|
2350
2651
|
"POST:/threads/:id/rpc": rpc_post_default,
|
|
2351
2652
|
"POST:/threads/:id/stop": stop_post_default,
|
|
2352
2653
|
"GET:/threads/:id/stream": stream_default,
|
|
2654
|
+
"GET:/threads/:id/fs/**": path_default,
|
|
2353
2655
|
"GET:/threads/:id/logs/:logId": logId_get_default,
|
|
2354
2656
|
"DELETE:/threads/:id/messages/:messageId": messageId_delete_default,
|
|
2355
2657
|
"PATCH:/threads/:id/messages/:messageId": messageId_patch_default
|