@sandagent/daemon 0.9.4 → 0.9.5

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
@@ -206419,6 +206419,42 @@ var require_lib4 = __commonJS({
206419
206419
  import * as http3 from "node:http";
206420
206420
  import { URL as URL2 } from "node:url";
206421
206421
 
206422
+ // src/multipart.ts
206423
+ function parseMultipart(contentType, body) {
206424
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206425
+ if (!match2) throw new Error("missing multipart boundary");
206426
+ const boundary = match2[1] ?? match2[2];
206427
+ const delimiter2 = Buffer.from(`--${boundary}`);
206428
+ const fields = {};
206429
+ const files = [];
206430
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206431
+ while (start < body.length) {
206432
+ const end = body.indexOf(delimiter2, start);
206433
+ if (end === -1) break;
206434
+ const part = body.subarray(start, end);
206435
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206436
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206437
+ if (headerEnd === -1) {
206438
+ start = end + delimiter2.length;
206439
+ continue;
206440
+ }
206441
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206442
+ let data = part.subarray(headerEnd + 4);
206443
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206444
+ data = data.subarray(0, data.length - 2);
206445
+ }
206446
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206447
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206448
+ if (filenameMatch && nameMatch) {
206449
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206450
+ } else if (nameMatch) {
206451
+ fields[nameMatch[1]] = data.toString("utf-8");
206452
+ }
206453
+ start = end + delimiter2.length;
206454
+ }
206455
+ return { fields, files };
206456
+ }
206457
+
206422
206458
  // src/routes/fs.ts
206423
206459
  import * as fs2 from "node:fs/promises";
206424
206460
  import * as path2 from "node:path";
@@ -206596,6 +206632,26 @@ async function fsCopy(state, body) {
206596
206632
  await fs2.copyFile(from, to);
206597
206633
  return ok({ path: to });
206598
206634
  }
206635
+ async function fsUpload(state, parts) {
206636
+ const volume = parts.fields.volume;
206637
+ const targetDir = parts.fields.path ?? ".";
206638
+ const createDirs = parts.fields.create_dirs !== "false";
206639
+ const root2 = resolveVolumeRoot(state, volume);
206640
+ const dir = resolveUnderRoot(root2, targetDir);
206641
+ if (createDirs) await ensureDir(dir);
206642
+ const results = [];
206643
+ for (const file of parts.files) {
206644
+ const target = resolveUnderRoot(root2, path2.join(targetDir, file.filename));
206645
+ await fs2.writeFile(target, file.data);
206646
+ results.push({
206647
+ fieldname: "file",
206648
+ filename: file.filename,
206649
+ path: target,
206650
+ size: file.data.length
206651
+ });
206652
+ }
206653
+ return ok({ files: results });
206654
+ }
206599
206655
 
206600
206656
  // src/routes/git.ts
206601
206657
  import { execFile } from "node:child_process";
@@ -262410,6 +262466,10 @@ async function sandagentRun(req, res, env2) {
262410
262466
  function createDaemon(config) {
262411
262467
  const router = new DaemonRouter({ root: config.root });
262412
262468
  const env2 = process.env;
262469
+ const state = {
262470
+ root: config.root,
262471
+ volumesRoot: `${config.root}/volumes`
262472
+ };
262413
262473
  return http3.createServer(async (req, res) => {
262414
262474
  const method = req.method ?? "GET";
262415
262475
  const url = new URL2(
@@ -262421,6 +262481,29 @@ function createDaemon(config) {
262421
262481
  const body2 = JSON.parse(await readBody(req) || "{}");
262422
262482
  return sandagentRun(body2, res, env2);
262423
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
+ }
262424
262507
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : JSON.parse(await readBody(req) || "{}");
262425
262508
  const result = await router.handle(method, pathname, params);
262426
262509
  const status = result?.status ?? 404;
@@ -262437,6 +262520,14 @@ function readBody(req) {
262437
262520
  req.on("error", reject);
262438
262521
  });
262439
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
+ }
262440
262531
 
262441
262532
  // src/cli.ts
262442
262533
  var host = process.env.SANDAGENT_DAEMON_HOST ?? "0.0.0.0";
package/dist/index.js CHANGED
@@ -206591,6 +206591,26 @@ async function fsCopy(state, body) {
206591
206591
  await fs2.copyFile(from, to);
206592
206592
  return ok({ path: to });
206593
206593
  }
206594
+ async function fsUpload(state, parts) {
206595
+ const volume = parts.fields.volume;
206596
+ const targetDir = parts.fields.path ?? ".";
206597
+ const createDirs = parts.fields.create_dirs !== "false";
206598
+ const root = resolveVolumeRoot(state, volume);
206599
+ const dir = resolveUnderRoot(root, targetDir);
206600
+ if (createDirs) await ensureDir(dir);
206601
+ const results = [];
206602
+ for (const file of parts.files) {
206603
+ const target = resolveUnderRoot(root, path2.join(targetDir, file.filename));
206604
+ await fs2.writeFile(target, file.data);
206605
+ results.push({
206606
+ fieldname: "file",
206607
+ filename: file.filename,
206608
+ path: target,
206609
+ size: file.data.length
206610
+ });
206611
+ }
206612
+ return ok({ files: results });
206613
+ }
206594
206614
 
206595
206615
  // src/routes/git.ts
206596
206616
  import { execFile } from "node:child_process";
@@ -206764,6 +206784,42 @@ var DaemonRouter = class {
206764
206784
  import * as http3 from "node:http";
206765
206785
  import { URL as URL2 } from "node:url";
206766
206786
 
206787
+ // src/multipart.ts
206788
+ function parseMultipart(contentType, body) {
206789
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206790
+ if (!match2) throw new Error("missing multipart boundary");
206791
+ const boundary = match2[1] ?? match2[2];
206792
+ const delimiter2 = Buffer.from(`--${boundary}`);
206793
+ const fields = {};
206794
+ const files = [];
206795
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206796
+ while (start < body.length) {
206797
+ const end = body.indexOf(delimiter2, start);
206798
+ if (end === -1) break;
206799
+ const part = body.subarray(start, end);
206800
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206801
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206802
+ if (headerEnd === -1) {
206803
+ start = end + delimiter2.length;
206804
+ continue;
206805
+ }
206806
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206807
+ let data = part.subarray(headerEnd + 4);
206808
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206809
+ data = data.subarray(0, data.length - 2);
206810
+ }
206811
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206812
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206813
+ if (filenameMatch && nameMatch) {
206814
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206815
+ } else if (nameMatch) {
206816
+ fields[nameMatch[1]] = data.toString("utf-8");
206817
+ }
206818
+ start = end + delimiter2.length;
206819
+ }
206820
+ return { fields, files };
206821
+ }
206822
+
206767
206823
  // ../../packages/runner-claude/dist/ai-sdk-stream.js
206768
206824
  import { appendFileSync, existsSync, unlinkSync } from "node:fs";
206769
206825
  import { join as join3 } from "node:path";
@@ -262409,6 +262465,10 @@ async function sandagentRun(req, res, env2) {
262409
262465
  function createDaemon(config) {
262410
262466
  const router = new DaemonRouter({ root: config.root });
262411
262467
  const env2 = process.env;
262468
+ const state = {
262469
+ root: config.root,
262470
+ volumesRoot: `${config.root}/volumes`
262471
+ };
262412
262472
  return http3.createServer(async (req, res) => {
262413
262473
  const method = req.method ?? "GET";
262414
262474
  const url = new URL2(
@@ -262420,6 +262480,29 @@ function createDaemon(config) {
262420
262480
  const body2 = JSON.parse(await readBody(req) || "{}");
262421
262481
  return sandagentRun(body2, res, env2);
262422
262482
  }
262483
+ if (method === "POST" && pathname === "/api/fs/upload") {
262484
+ try {
262485
+ const ct2 = req.headers["content-type"] ?? "";
262486
+ if (!ct2.includes("multipart/form-data")) {
262487
+ res.writeHead(400, { "Content-Type": "application/json" });
262488
+ res.end(
262489
+ JSON.stringify(fail("content-type must be multipart/form-data"))
262490
+ );
262491
+ return;
262492
+ }
262493
+ const raw = await readBodyRaw(req);
262494
+ const parts = parseMultipart(ct2, raw);
262495
+ const result2 = await fsUpload(state, parts);
262496
+ res.writeHead(200, { "Content-Type": "application/json" });
262497
+ res.end(JSON.stringify(result2));
262498
+ } catch (err) {
262499
+ const status2 = err instanceof AppError ? err.status : 500;
262500
+ const msg = err instanceof Error ? err.message : String(err);
262501
+ res.writeHead(status2, { "Content-Type": "application/json" });
262502
+ res.end(JSON.stringify(fail(msg)));
262503
+ }
262504
+ return;
262505
+ }
262423
262506
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : JSON.parse(await readBody(req) || "{}");
262424
262507
  const result = await router.handle(method, pathname, params);
262425
262508
  const status = result?.status ?? 404;
@@ -262436,6 +262519,14 @@ function readBody(req) {
262436
262519
  req.on("error", reject);
262437
262520
  });
262438
262521
  }
262522
+ function readBodyRaw(req) {
262523
+ return new Promise((resolve14, reject) => {
262524
+ const chunks = [];
262525
+ req.on("data", (c) => chunks.push(c));
262526
+ req.on("end", () => resolve14(Buffer.concat(chunks)));
262527
+ req.on("error", reject);
262528
+ });
262529
+ }
262439
262530
  export {
262440
262531
  DaemonRouter,
262441
262532
  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
@@ -206414,6 +206414,42 @@ var require_lib4 = __commonJS({
206414
206414
  }
206415
206415
  });
206416
206416
 
206417
+ // src/multipart.ts
206418
+ function parseMultipart(contentType, body) {
206419
+ const match2 = contentType.match(/boundary=(?:"([^"]+)"|([^\s;]+))/);
206420
+ if (!match2) throw new Error("missing multipart boundary");
206421
+ const boundary = match2[1] ?? match2[2];
206422
+ const delimiter2 = Buffer.from(`--${boundary}`);
206423
+ const fields = {};
206424
+ const files = [];
206425
+ let start = body.indexOf(delimiter2) + delimiter2.length;
206426
+ while (start < body.length) {
206427
+ const end = body.indexOf(delimiter2, start);
206428
+ if (end === -1) break;
206429
+ const part = body.subarray(start, end);
206430
+ const partStart = part[0] === 13 && part[1] === 10 ? 2 : 0;
206431
+ const headerEnd = part.indexOf("\r\n\r\n", partStart);
206432
+ if (headerEnd === -1) {
206433
+ start = end + delimiter2.length;
206434
+ continue;
206435
+ }
206436
+ const headerStr = part.subarray(partStart, headerEnd).toString("utf-8");
206437
+ let data = part.subarray(headerEnd + 4);
206438
+ if (data.length >= 2 && data[data.length - 2] === 13 && data[data.length - 1] === 10) {
206439
+ data = data.subarray(0, data.length - 2);
206440
+ }
206441
+ const nameMatch = headerStr.match(/name="([^"]+)"/);
206442
+ const filenameMatch = headerStr.match(/filename="([^"]+)"/);
206443
+ if (filenameMatch && nameMatch) {
206444
+ files.push({ filename: filenameMatch[1], data: Buffer.from(data) });
206445
+ } else if (nameMatch) {
206446
+ fields[nameMatch[1]] = data.toString("utf-8");
206447
+ }
206448
+ start = end + delimiter2.length;
206449
+ }
206450
+ return { fields, files };
206451
+ }
206452
+
206417
206453
  // src/routes/fs.ts
206418
206454
  import * as fs2 from "node:fs/promises";
206419
206455
  import * as path2 from "node:path";
@@ -206591,6 +206627,26 @@ async function fsCopy(state, body) {
206591
206627
  await fs2.copyFile(from, to);
206592
206628
  return ok({ path: to });
206593
206629
  }
206630
+ async function fsUpload(state, parts) {
206631
+ const volume = parts.fields.volume;
206632
+ const targetDir = parts.fields.path ?? ".";
206633
+ const createDirs = parts.fields.create_dirs !== "false";
206634
+ const root = resolveVolumeRoot(state, volume);
206635
+ const dir = resolveUnderRoot(root, targetDir);
206636
+ if (createDirs) await ensureDir(dir);
206637
+ const results = [];
206638
+ for (const file of parts.files) {
206639
+ const target = resolveUnderRoot(root, path2.join(targetDir, file.filename));
206640
+ await fs2.writeFile(target, file.data);
206641
+ results.push({
206642
+ fieldname: "file",
206643
+ filename: file.filename,
206644
+ path: target,
206645
+ size: file.data.length
206646
+ });
206647
+ }
206648
+ return ok({ files: results });
206649
+ }
206594
206650
 
206595
206651
  // src/routes/git.ts
206596
206652
  import { execFile } from "node:child_process";
@@ -262415,6 +262471,10 @@ function createNextHandler(opts) {
262415
262471
  const router = new DaemonRouter({ root: opts.root });
262416
262472
  const env2 = process.env;
262417
262473
  const prefix = opts.prefix ?? "/api/daemon";
262474
+ const state = {
262475
+ root: opts.root,
262476
+ volumesRoot: `${opts.root}/volumes`
262477
+ };
262418
262478
  return async (req) => {
262419
262479
  const url = new URL(req.url);
262420
262480
  const pathname = url.pathname.startsWith(prefix) ? url.pathname.slice(prefix.length) || "/" : url.pathname;
@@ -262423,6 +262483,25 @@ function createNextHandler(opts) {
262423
262483
  const body = await req.json().catch(() => ({}));
262424
262484
  return codingRunStream(body, env2);
262425
262485
  }
262486
+ if (method === "POST" && pathname === "/api/fs/upload") {
262487
+ try {
262488
+ const ct2 = req.headers.get("content-type") ?? "";
262489
+ if (!ct2.includes("multipart/form-data")) {
262490
+ return Response.json(
262491
+ fail("content-type must be multipart/form-data"),
262492
+ { status: 400 }
262493
+ );
262494
+ }
262495
+ const raw = Buffer.from(await req.arrayBuffer());
262496
+ const parts = parseMultipart(ct2, raw);
262497
+ const result2 = await fsUpload(state, parts);
262498
+ return Response.json(result2);
262499
+ } catch (err) {
262500
+ const status = err instanceof AppError ? err.status : 500;
262501
+ const msg = err instanceof Error ? err.message : String(err);
262502
+ return Response.json(fail(msg), { status });
262503
+ }
262504
+ }
262426
262505
  const params = method === "GET" ? Object.fromEntries(url.searchParams) : await req.json().catch(() => ({}));
262427
262506
  const result = await router.handle(method, pathname, params);
262428
262507
  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.5",
4
4
  "description": "SandAgent Daemon - Unified API gateway for sandbox services (file, git, volumes)",
5
5
  "type": "module",
6
6
  "bin": {