@sandagent/daemon 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -325,6 +325,55 @@ Response: `application/x-ndjson` chunked stream — each line is an AI SDK UI me
325
325
  | POST | `/api/fs/remove` | `{"path":"tmp","recursive":true}` |
326
326
  | POST | `/api/fs/move` | `{"from":"a.txt","to":"b.txt"}` |
327
327
  | POST | `/api/fs/copy` | `{"from":"a.txt","to":"b.txt"}` |
328
+ | POST | `/api/fs/upload` | `multipart/form-data` — see below |
329
+
330
+ #### `POST /api/fs/upload`
331
+
332
+ Upload one or more files via `multipart/form-data`.
333
+
334
+ Form fields:
335
+
336
+ | Field | Type | Required | Description |
337
+ |-------|------|----------|-------------|
338
+ | `path` | string | No | Target directory (default: `.`) |
339
+ | `volume` | string | No | Volume name for multi-tenant isolation |
340
+ | `create_dirs` | string | No | Create parent dirs (default: `"true"`) |
341
+ | `file` | file | Yes | One or more files to upload |
342
+
343
+ Example:
344
+
345
+ ```bash
346
+ # Upload a single file
347
+ curl -X POST http://localhost:3080/api/fs/upload \
348
+ -F "path=uploads" \
349
+ -F "file=@local-file.txt"
350
+
351
+ # Upload multiple files
352
+ curl -X POST http://localhost:3080/api/fs/upload \
353
+ -F "path=data" \
354
+ -F "file=@report.csv" \
355
+ -F "file=@image.png"
356
+
357
+ # Upload to a specific volume
358
+ curl -X POST http://localhost:3080/api/fs/upload \
359
+ -F "path=docs" \
360
+ -F "volume=vol-001" \
361
+ -F "file=@readme.md"
362
+ ```
363
+
364
+ Response:
365
+
366
+ ```json
367
+ {
368
+ "ok": true,
369
+ "data": {
370
+ "files": [
371
+ { "fieldname": "file", "filename": "report.csv", "path": "/workspace/data/report.csv", "size": 1234 }
372
+ ]
373
+ },
374
+ "error": null
375
+ }
376
+ ```
328
377
 
329
378
  All fs endpoints accept optional `volume` for multi-tenant isolation.
330
379
 
package/dist/bundle.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __banner_cjsRequire } from "module"; const require = __banner_cjsRequire(import.meta.url);
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -206419,6 +206420,42 @@ var require_lib4 = __commonJS({
206419
206420
  import * as http3 from "node:http";
206420
206421
  import { URL as URL2 } from "node:url";
206421
206422
 
206423
+ // src/multipart.ts
206424
+ function parseMultipart(contentType, body) {
206425
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206426
+ if (!match2) throw new Error("missing multipart boundary");
206427
+ const boundary = match2[1] ?? match2[2];
206428
+ const delimiter2 = Buffer.from(`--${boundary}`);
206429
+ const fields = {};
206430
+ const files = [];
206431
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206432
+ while (start < body.length) {
206433
+ const end = body.indexOf(delimiter2, start);
206434
+ if (end === -1) break;
206435
+ const part = body.subarray(start, end);
206436
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206437
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206438
+ if (headerEnd === -1) {
206439
+ start = end + delimiter2.length;
206440
+ continue;
206441
+ }
206442
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206443
+ let data = part.subarray(headerEnd + 4);
206444
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206445
+ data = data.subarray(0, data.length - 2);
206446
+ }
206447
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206448
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206449
+ if (filenameMatch && nameMatch) {
206450
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206451
+ } else if (nameMatch) {
206452
+ fields[nameMatch[1]] = data.toString("utf-8");
206453
+ }
206454
+ start = end + delimiter2.length;
206455
+ }
206456
+ return { fields, files };
206457
+ }
206458
+
206422
206459
  // src/routes/fs.ts
206423
206460
  import * as fs2 from "node:fs/promises";
206424
206461
  import * as path2 from "node:path";
@@ -206596,6 +206633,26 @@ async function fsCopy(state, body) {
206596
206633
  await fs2.copyFile(from, to);
206597
206634
  return ok({ path: to });
206598
206635
  }
206636
+ async function fsUpload(state, parts) {
206637
+ const volume = parts.fields.volume;
206638
+ const targetDir = parts.fields.path ?? ".";
206639
+ const createDirs = parts.fields.create_dirs !== "false";
206640
+ const root2 = resolveVolumeRoot(state, volume);
206641
+ const dir = resolveUnderRoot(root2, targetDir);
206642
+ if (createDirs) await ensureDir(dir);
206643
+ const results = [];
206644
+ for (const file of parts.files) {
206645
+ const target = resolveUnderRoot(root2, path2.join(targetDir, file.filename));
206646
+ await fs2.writeFile(target, file.data);
206647
+ results.push({
206648
+ fieldname: "file",
206649
+ filename: file.filename,
206650
+ path: target,
206651
+ size: file.data.length
206652
+ });
206653
+ }
206654
+ return ok({ files: results });
206655
+ }
206599
206656
 
206600
206657
  // src/routes/git.ts
206601
206658
  import { execFile } from "node:child_process";
@@ -262410,6 +262467,10 @@ async function sandagentRun(req, res, env2) {
262410
262467
  function createDaemon(config) {
262411
262468
  const router = new DaemonRouter({ root: config.root });
262412
262469
  const env2 = process.env;
262470
+ const state = {
262471
+ root: config.root,
262472
+ volumesRoot: `${config.root}/volumes`
262473
+ };
262413
262474
  return http3.createServer(async (req, res) => {
262414
262475
  const method = req.method ?? "GET";
262415
262476
  const url = new URL2(
@@ -262421,6 +262482,29 @@ function createDaemon(config) {
262421
262482
  const body2 = JSON.parse(await readBody(req) || "{}");
262422
262483
  return sandagentRun(body2, res, env2);
262423
262484
  }
262485
+ if (method === "POST" && pathname === "/api/fs/upload") {
262486
+ try {
262487
+ const ct2 = req.headers["content-type"] ?? "";
262488
+ if (!ct2.includes("multipart/form-data")) {
262489
+ res.writeHead(400, { "Content-Type": "application/json" });
262490
+ res.end(
262491
+ JSON.stringify(fail("content-type must be multipart/form-data"))
262492
+ );
262493
+ return;
262494
+ }
262495
+ const raw = await readBodyRaw(req);
262496
+ const parts = parseMultipart(ct2, raw);
262497
+ const result2 = await fsUpload(state, parts);
262498
+ res.writeHead(200, { "Content-Type": "application/json" });
262499
+ res.end(JSON.stringify(result2));
262500
+ } catch (err) {
262501
+ const status2 = err instanceof AppError ? err.status : 500;
262502
+ const msg = err instanceof Error ? err.message : String(err);
262503
+ res.writeHead(status2, { "Content-Type": "application/json" });
262504
+ res.end(JSON.stringify(fail(msg)));
262505
+ }
262506
+ return;
262507
+ }
262424
262508
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : JSON.parse(await readBody(req) || "{}");
262425
262509
  const result = await router.handle(method, pathname, params);
262426
262510
  const status = result?.status ?? 404;
@@ -262437,14 +262521,21 @@ function readBody(req) {
262437
262521
  req.on("error", reject);
262438
262522
  });
262439
262523
  }
262524
+ function readBodyRaw(req) {
262525
+ return new Promise((resolve14, reject) => {
262526
+ const chunks = [];
262527
+ req.on("data", (c) => chunks.push(c));
262528
+ req.on("end", () => resolve14(Buffer.concat(chunks)));
262529
+ req.on("error", reject);
262530
+ });
262531
+ }
262440
262532
 
262441
262533
  // src/cli.ts
262442
262534
  var host = process.env.SANDAGENT_DAEMON_HOST ?? "0.0.0.0";
262443
262535
  var port = Number(process.env.SANDAGENT_DAEMON_PORT ?? "3080");
262444
- var root = process.env.SANDAGENT_ROOT ?? "/workspace";
262536
+ var root = process.env.SANDAGENT_ROOT ?? "/agent";
262445
262537
  async function main2() {
262446
262538
  await ensureDir(root);
262447
- await ensureDir(`${root}/volumes`);
262448
262539
  const server = createDaemon({ host, port, root });
262449
262540
  server.listen(port, host, () => {
262450
262541
  console.log(`sandagent-daemon listening on http://${host}:${port}`);
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createRequire as __banner_cjsRequire } from "module"; const require = __banner_cjsRequire(import.meta.url);
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -206591,6 +206592,26 @@ async function fsCopy(state, body) {
206591
206592
  await fs2.copyFile(from, to);
206592
206593
  return ok({ path: to });
206593
206594
  }
206595
+ async function fsUpload(state, parts) {
206596
+ const volume = parts.fields.volume;
206597
+ const targetDir = parts.fields.path ?? ".";
206598
+ const createDirs = parts.fields.create_dirs !== "false";
206599
+ const root = resolveVolumeRoot(state, volume);
206600
+ const dir = resolveUnderRoot(root, targetDir);
206601
+ if (createDirs) await ensureDir(dir);
206602
+ const results = [];
206603
+ for (const file of parts.files) {
206604
+ const target = resolveUnderRoot(root, path2.join(targetDir, file.filename));
206605
+ await fs2.writeFile(target, file.data);
206606
+ results.push({
206607
+ fieldname: "file",
206608
+ filename: file.filename,
206609
+ path: target,
206610
+ size: file.data.length
206611
+ });
206612
+ }
206613
+ return ok({ files: results });
206614
+ }
206594
206615
 
206595
206616
  // src/routes/git.ts
206596
206617
  import { execFile } from "node:child_process";
@@ -206764,6 +206785,42 @@ var DaemonRouter = class {
206764
206785
  import * as http3 from "node:http";
206765
206786
  import { URL as URL2 } from "node:url";
206766
206787
 
206788
+ // src/multipart.ts
206789
+ function parseMultipart(contentType, body) {
206790
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206791
+ if (!match2) throw new Error("missing multipart boundary");
206792
+ const boundary = match2[1] ?? match2[2];
206793
+ const delimiter2 = Buffer.from(`--${boundary}`);
206794
+ const fields = {};
206795
+ const files = [];
206796
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206797
+ while (start < body.length) {
206798
+ const end = body.indexOf(delimiter2, start);
206799
+ if (end === -1) break;
206800
+ const part = body.subarray(start, end);
206801
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206802
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206803
+ if (headerEnd === -1) {
206804
+ start = end + delimiter2.length;
206805
+ continue;
206806
+ }
206807
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206808
+ let data = part.subarray(headerEnd + 4);
206809
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206810
+ data = data.subarray(0, data.length - 2);
206811
+ }
206812
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206813
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206814
+ if (filenameMatch && nameMatch) {
206815
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206816
+ } else if (nameMatch) {
206817
+ fields[nameMatch[1]] = data.toString("utf-8");
206818
+ }
206819
+ start = end + delimiter2.length;
206820
+ }
206821
+ return { fields, files };
206822
+ }
206823
+
206767
206824
  // ../../packages/runner-claude/dist/ai-sdk-stream.js
206768
206825
  import { appendFileSync, existsSync, unlinkSync } from "node:fs";
206769
206826
  import { join as join3 } from "node:path";
@@ -262409,6 +262466,10 @@ async function sandagentRun(req, res, env2) {
262409
262466
  function createDaemon(config) {
262410
262467
  const router = new DaemonRouter({ root: config.root });
262411
262468
  const env2 = process.env;
262469
+ const state = {
262470
+ root: config.root,
262471
+ volumesRoot: `${config.root}/volumes`
262472
+ };
262412
262473
  return http3.createServer(async (req, res) => {
262413
262474
  const method = req.method ?? "GET";
262414
262475
  const url = new URL2(
@@ -262420,6 +262481,29 @@ function createDaemon(config) {
262420
262481
  const body2 = JSON.parse(await readBody(req) || "{}");
262421
262482
  return sandagentRun(body2, res, env2);
262422
262483
  }
262484
+ if (method === "POST" && pathname === "/api/fs/upload") {
262485
+ try {
262486
+ const ct2 = req.headers["content-type"] ?? "";
262487
+ if (!ct2.includes("multipart/form-data")) {
262488
+ res.writeHead(400, { "Content-Type": "application/json" });
262489
+ res.end(
262490
+ JSON.stringify(fail("content-type must be multipart/form-data"))
262491
+ );
262492
+ return;
262493
+ }
262494
+ const raw = await readBodyRaw(req);
262495
+ const parts = parseMultipart(ct2, raw);
262496
+ const result2 = await fsUpload(state, parts);
262497
+ res.writeHead(200, { "Content-Type": "application/json" });
262498
+ res.end(JSON.stringify(result2));
262499
+ } catch (err) {
262500
+ const status2 = err instanceof AppError ? err.status : 500;
262501
+ const msg = err instanceof Error ? err.message : String(err);
262502
+ res.writeHead(status2, { "Content-Type": "application/json" });
262503
+ res.end(JSON.stringify(fail(msg)));
262504
+ }
262505
+ return;
262506
+ }
262423
262507
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : JSON.parse(await readBody(req) || "{}");
262424
262508
  const result = await router.handle(method, pathname, params);
262425
262509
  const status = result?.status ?? 404;
@@ -262436,6 +262520,14 @@ function readBody(req) {
262436
262520
  req.on("error", reject);
262437
262521
  });
262438
262522
  }
262523
+ function readBodyRaw(req) {
262524
+ return new Promise((resolve14, reject) => {
262525
+ const chunks = [];
262526
+ req.on("data", (c) => chunks.push(c));
262527
+ req.on("end", () => resolve14(Buffer.concat(chunks)));
262528
+ req.on("error", reject);
262529
+ });
262530
+ }
262439
262531
  export {
262440
262532
  DaemonRouter,
262441
262533
  createDaemon
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Minimal multipart/form-data parser — zero external dependencies.
3
+ * Parses raw body buffer using the boundary from Content-Type header.
4
+ */
5
+ export interface ParsedMultipart {
6
+ fields: Record<string, string>;
7
+ files: Array<{
8
+ filename: string;
9
+ data: Buffer;
10
+ }>;
11
+ }
12
+ export declare function parseMultipart(contentType: string, body: Buffer): ParsedMultipart;
13
+ //# sourceMappingURL=multipart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../src/multipart.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,eAAe,CAiDjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,IAKzD,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CA6B/C"}
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,IASzD,KAAK,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAkD/C"}
package/dist/nextjs.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createRequire as __banner_cjsRequire } from "module"; const require = __banner_cjsRequire(import.meta.url);
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -206414,6 +206415,42 @@ var require_lib4 = __commonJS({
206414
206415
  }
206415
206416
  });
206416
206417
 
206418
+ // src/multipart.ts
206419
+ function parseMultipart(contentType, body) {
206420
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206421
+ if (!match2) throw new Error("missing multipart boundary");
206422
+ const boundary = match2[1] ?? match2[2];
206423
+ const delimiter2 = Buffer.from(`--${boundary}`);
206424
+ const fields = {};
206425
+ const files = [];
206426
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206427
+ while (start < body.length) {
206428
+ const end = body.indexOf(delimiter2, start);
206429
+ if (end === -1) break;
206430
+ const part = body.subarray(start, end);
206431
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206432
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206433
+ if (headerEnd === -1) {
206434
+ start = end + delimiter2.length;
206435
+ continue;
206436
+ }
206437
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206438
+ let data = part.subarray(headerEnd + 4);
206439
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206440
+ data = data.subarray(0, data.length - 2);
206441
+ }
206442
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206443
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206444
+ if (filenameMatch && nameMatch) {
206445
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206446
+ } else if (nameMatch) {
206447
+ fields[nameMatch[1]] = data.toString("utf-8");
206448
+ }
206449
+ start = end + delimiter2.length;
206450
+ }
206451
+ return { fields, files };
206452
+ }
206453
+
206417
206454
  // src/routes/fs.ts
206418
206455
  import * as fs2 from "node:fs/promises";
206419
206456
  import * as path2 from "node:path";
@@ -206591,6 +206628,26 @@ async function fsCopy(state, body) {
206591
206628
  await fs2.copyFile(from, to);
206592
206629
  return ok({ path: to });
206593
206630
  }
206631
+ async function fsUpload(state, parts) {
206632
+ const volume = parts.fields.volume;
206633
+ const targetDir = parts.fields.path ?? ".";
206634
+ const createDirs = parts.fields.create_dirs !== "false";
206635
+ const root = resolveVolumeRoot(state, volume);
206636
+ const dir = resolveUnderRoot(root, targetDir);
206637
+ if (createDirs) await ensureDir(dir);
206638
+ const results = [];
206639
+ for (const file of parts.files) {
206640
+ const target = resolveUnderRoot(root, path2.join(targetDir, file.filename));
206641
+ await fs2.writeFile(target, file.data);
206642
+ results.push({
206643
+ fieldname: "file",
206644
+ filename: file.filename,
206645
+ path: target,
206646
+ size: file.data.length
206647
+ });
206648
+ }
206649
+ return ok({ files: results });
206650
+ }
206594
206651
 
206595
206652
  // src/routes/git.ts
206596
206653
  import { execFile } from "node:child_process";
@@ -262415,6 +262472,10 @@ function createNextHandler(opts) {
262415
262472
  const router = new DaemonRouter({ root: opts.root });
262416
262473
  const env2 = process.env;
262417
262474
  const prefix = opts.prefix ?? "/api/daemon";
262475
+ const state = {
262476
+ root: opts.root,
262477
+ volumesRoot: `${opts.root}/volumes`
262478
+ };
262418
262479
  return async (req) => {
262419
262480
  const url = new URL(req.url);
262420
262481
  const pathname = url.pathname.startsWith(prefix) ? url.pathname.slice(prefix.length) || "/" : url.pathname;
@@ -262423,6 +262484,25 @@ function createNextHandler(opts) {
262423
262484
  const body = await req.json().catch(() => ({}));
262424
262485
  return codingRunStream(body, env2);
262425
262486
  }
262487
+ if (method === "POST" && pathname === "/api/fs/upload") {
262488
+ try {
262489
+ const ct2 = req.headers.get("content-type") ?? "";
262490
+ if (!ct2.includes("multipart/form-data")) {
262491
+ return Response.json(
262492
+ fail("content-type must be multipart/form-data"),
262493
+ { status: 400 }
262494
+ );
262495
+ }
262496
+ const raw = Buffer.from(await req.arrayBuffer());
262497
+ const parts = parseMultipart(ct2, raw);
262498
+ const result2 = await fsUpload(state, parts);
262499
+ return Response.json(result2);
262500
+ } catch (err) {
262501
+ const status = err instanceof AppError ? err.status : 500;
262502
+ const msg = err instanceof Error ? err.message : String(err);
262503
+ return Response.json(fail(msg), { status });
262504
+ }
262505
+ }
262426
262506
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : await req.json().catch(() => ({}));
262427
262507
  const result = await router.handle(method, pathname, params);
262428
262508
  if (!result) {
@@ -79,5 +79,27 @@ export declare function fsMove(state: AppState, body: MoveCopyBody): Promise<imp
79
79
  export declare function fsCopy(state: AppState, body: MoveCopyBody): Promise<import("../utils.js").ApiEnvelope<{
80
80
  path: string;
81
81
  }>>;
82
+ export interface UploadedFile {
83
+ fieldname: string;
84
+ filename: string;
85
+ path: string;
86
+ size: number;
87
+ }
88
+ export interface UploadResult {
89
+ files: UploadedFile[];
90
+ }
91
+ /**
92
+ * Handle multipart/form-data file upload.
93
+ * Expects form field "path" for target directory and one or more "file" parts.
94
+ */
95
+ export declare function fsUpload(state: AppState, parts: {
96
+ fields: Record<string, string>;
97
+ files: Array<{
98
+ filename: string;
99
+ data: Buffer;
100
+ }>;
101
+ }): Promise<import("../utils.js").ApiEnvelope<{
102
+ files: UploadedFile[];
103
+ }>>;
82
104
  export {};
83
105
  //# sourceMappingURL=fs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/routes/fs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAU5C,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAID,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;;;MAkBzD;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;IAKzD;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;;IASzD;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;IAQ3D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;UAMhD,MAAM;UACN,MAAM;YACJ,OAAO;UACT,MAAM;MA4Bf;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;;IAQ7D;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;IAQ9D;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;IAK7D;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU;;IAU/D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;;IAS/D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;;IAS/D"}
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/routes/fs.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAU5C,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAID,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;;;MAkBzD;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;IAKzD;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;;IASzD;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;;;IAQ3D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS;UAMhD,MAAM;UACN,MAAM;YACJ,OAAO;UACT,MAAM;MA4Bf;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;;IAQ7D;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;IAQ9D;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS;;IAK7D;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU;;IAU/D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;;IAS/D;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;;IAS/D;AAID,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE;IACL,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;;IAuBF"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAMlC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC,MAAM,CA8B9D"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAQlC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC,MAAM,CA2D9D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandagent/daemon",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "SandAgent Daemon - Unified API gateway for sandbox services (file, git, volumes)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,8 +42,9 @@
42
42
  },
43
43
  "scripts": {
44
44
  "build": "pnpm clean && tsc --emitDeclarationOnly && pnpm bundle",
45
- "bundle": "esbuild src/index.ts src/nextjs.ts --bundle --platform=node --format=esm --outdir=dist && esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=dist/bundle.mjs",
46
- "dev": "tsc --watch",
45
+ "bundle": "node scripts/build.mjs",
46
+ "dev": "pnpm build && node dist/bundle.mjs",
47
+ "dev:watch": "tsc --watch",
47
48
  "clean": "rm -rf dist",
48
49
  "typecheck": "tsc --noEmit",
49
50
  "lint": "echo 'no lint configured'",