@sandagent/daemon 0.9.7 → 0.9.8

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/bundle.mjs CHANGED
@@ -42940,7 +42940,7 @@ var require_verify_stream = __commonJS({
42940
42940
  function isObject(thing) {
42941
42941
  return Object.prototype.toString.call(thing) === "[object Object]";
42942
42942
  }
42943
- function safeJsonParse(thing) {
42943
+ function safeJsonParse2(thing) {
42944
42944
  if (isObject(thing))
42945
42945
  return thing;
42946
42946
  try {
@@ -42951,7 +42951,7 @@ var require_verify_stream = __commonJS({
42951
42951
  }
42952
42952
  function headerFromJWS(jwsSig) {
42953
42953
  var encodedHeader = jwsSig.split(".", 1)[0];
42954
- return safeJsonParse(Buffer4.from(encodedHeader, "base64").toString("binary"));
42954
+ return safeJsonParse2(Buffer4.from(encodedHeader, "base64").toString("binary"));
42955
42955
  }
42956
42956
  function securedInputFromJWS(jwsSig) {
42957
42957
  return jwsSig.split(".", 2).join(".");
@@ -74906,7 +74906,7 @@ var require_encodings = __commonJS({
74906
74906
  });
74907
74907
  return out;
74908
74908
  }
74909
- function formEncoder(sep6) {
74909
+ function formEncoder(sep7) {
74910
74910
  return (key, value2, options2) => {
74911
74911
  let out = "";
74912
74912
  const pairs = options2?.explode ? explode(key, value2) : [[key, value2]];
@@ -74917,7 +74917,7 @@ var require_encodings = __commonJS({
74917
74917
  return options2?.charEncoding === "percent" ? encodeURIComponent(v2) : v2;
74918
74918
  };
74919
74919
  const encodeValue = (v2) => encodeString(serializeValue(v2));
74920
- const encodedSep = encodeString(sep6);
74920
+ const encodedSep = encodeString(sep7);
74921
74921
  pairs.forEach(([pk, pv]) => {
74922
74922
  let tmp = "";
74923
74923
  let encValue = null;
@@ -164391,10 +164391,10 @@ var require_resolve_block_map = __commonJS({
164391
164391
  let offset = bm.offset;
164392
164392
  let commentEnd = null;
164393
164393
  for (const collItem of bm.items) {
164394
- const { start, key, sep: sep6, value: value2 } = collItem;
164394
+ const { start, key, sep: sep7, value: value2 } = collItem;
164395
164395
  const keyProps = resolveProps.resolveProps(start, {
164396
164396
  indicator: "explicit-key-ind",
164397
- next: key ?? sep6?.[0],
164397
+ next: key ?? sep7?.[0],
164398
164398
  offset,
164399
164399
  onError: onError2,
164400
164400
  parentIndent: bm.indent,
@@ -164408,7 +164408,7 @@ var require_resolve_block_map = __commonJS({
164408
164408
  else if ("indent" in key && key.indent !== bm.indent)
164409
164409
  onError2(offset, "BAD_INDENT", startColMsg);
164410
164410
  }
164411
- if (!keyProps.anchor && !keyProps.tag && !sep6) {
164411
+ if (!keyProps.anchor && !keyProps.tag && !sep7) {
164412
164412
  commentEnd = keyProps.end;
164413
164413
  if (keyProps.comment) {
164414
164414
  if (map3.comment)
@@ -164432,7 +164432,7 @@ var require_resolve_block_map = __commonJS({
164432
164432
  ctx.atKey = false;
164433
164433
  if (utilMapIncludes.mapIncludes(ctx, map3.items, keyNode))
164434
164434
  onError2(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
164435
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
164435
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
164436
164436
  indicator: "map-value-ind",
164437
164437
  next: value2,
164438
164438
  offset: keyNode.range[2],
@@ -164448,7 +164448,7 @@ var require_resolve_block_map = __commonJS({
164448
164448
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
164449
164449
  onError2(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
164450
164450
  }
164451
- const valueNode = value2 ? composeNode(ctx, value2, valueProps, onError2) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError2);
164451
+ const valueNode = value2 ? composeNode(ctx, value2, valueProps, onError2) : composeEmptyNode(ctx, offset, sep7, null, valueProps, onError2);
164452
164452
  if (ctx.schema.compat)
164453
164453
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value2, onError2);
164454
164454
  offset = valueNode.range[2];
@@ -164539,7 +164539,7 @@ var require_resolve_end = __commonJS({
164539
164539
  let comment = "";
164540
164540
  if (end) {
164541
164541
  let hasSpace = false;
164542
- let sep6 = "";
164542
+ let sep7 = "";
164543
164543
  for (const token of end) {
164544
164544
  const { source, type } = token;
164545
164545
  switch (type) {
@@ -164553,13 +164553,13 @@ var require_resolve_end = __commonJS({
164553
164553
  if (!comment)
164554
164554
  comment = cb;
164555
164555
  else
164556
- comment += sep6 + cb;
164557
- sep6 = "";
164556
+ comment += sep7 + cb;
164557
+ sep7 = "";
164558
164558
  break;
164559
164559
  }
164560
164560
  case "newline":
164561
164561
  if (comment)
164562
- sep6 += source;
164562
+ sep7 += source;
164563
164563
  hasSpace = true;
164564
164564
  break;
164565
164565
  default:
@@ -164602,18 +164602,18 @@ var require_resolve_flow_collection = __commonJS({
164602
164602
  let offset = fc.offset + fc.start.source.length;
164603
164603
  for (let i2 = 0; i2 < fc.items.length; ++i2) {
164604
164604
  const collItem = fc.items[i2];
164605
- const { start, key, sep: sep6, value: value2 } = collItem;
164605
+ const { start, key, sep: sep7, value: value2 } = collItem;
164606
164606
  const props = resolveProps.resolveProps(start, {
164607
164607
  flow: fcName,
164608
164608
  indicator: "explicit-key-ind",
164609
- next: key ?? sep6?.[0],
164609
+ next: key ?? sep7?.[0],
164610
164610
  offset,
164611
164611
  onError: onError2,
164612
164612
  parentIndent: fc.indent,
164613
164613
  startOnNewline: false
164614
164614
  });
164615
164615
  if (!props.found) {
164616
- if (!props.anchor && !props.tag && !sep6 && !value2) {
164616
+ if (!props.anchor && !props.tag && !sep7 && !value2) {
164617
164617
  if (i2 === 0 && props.comma)
164618
164618
  onError2(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
164619
164619
  else if (i2 < fc.items.length - 1)
@@ -164667,8 +164667,8 @@ var require_resolve_flow_collection = __commonJS({
164667
164667
  }
164668
164668
  }
164669
164669
  }
164670
- if (!isMap && !sep6 && !props.found) {
164671
- const valueNode = value2 ? composeNode(ctx, value2, props, onError2) : composeEmptyNode(ctx, props.end, sep6, null, props, onError2);
164670
+ if (!isMap && !sep7 && !props.found) {
164671
+ const valueNode = value2 ? composeNode(ctx, value2, props, onError2) : composeEmptyNode(ctx, props.end, sep7, null, props, onError2);
164672
164672
  coll.items.push(valueNode);
164673
164673
  offset = valueNode.range[2];
164674
164674
  if (isBlock(value2))
@@ -164680,7 +164680,7 @@ var require_resolve_flow_collection = __commonJS({
164680
164680
  if (isBlock(key))
164681
164681
  onError2(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
164682
164682
  ctx.atKey = false;
164683
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
164683
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
164684
164684
  flow: fcName,
164685
164685
  indicator: "map-value-ind",
164686
164686
  next: value2,
@@ -164691,8 +164691,8 @@ var require_resolve_flow_collection = __commonJS({
164691
164691
  });
164692
164692
  if (valueProps.found) {
164693
164693
  if (!isMap && !props.found && ctx.options.strict) {
164694
- if (sep6)
164695
- for (const st2 of sep6) {
164694
+ if (sep7)
164695
+ for (const st2 of sep7) {
164696
164696
  if (st2 === valueProps.found)
164697
164697
  break;
164698
164698
  if (st2.type === "newline") {
@@ -164709,7 +164709,7 @@ var require_resolve_flow_collection = __commonJS({
164709
164709
  else
164710
164710
  onError2(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
164711
164711
  }
164712
- const valueNode = value2 ? composeNode(ctx, value2, valueProps, onError2) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError2) : null;
164712
+ const valueNode = value2 ? composeNode(ctx, value2, valueProps, onError2) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep7, null, valueProps, onError2) : null;
164713
164713
  if (valueNode) {
164714
164714
  if (isBlock(value2))
164715
164715
  onError2(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -164889,7 +164889,7 @@ var require_resolve_block_scalar = __commonJS({
164889
164889
  chompStart = i2 + 1;
164890
164890
  }
164891
164891
  let value2 = "";
164892
- let sep6 = "";
164892
+ let sep7 = "";
164893
164893
  let prevMoreIndented = false;
164894
164894
  for (let i2 = 0; i2 < contentStart; ++i2)
164895
164895
  value2 += lines[i2][0].slice(trimIndent) + "\n";
@@ -164906,24 +164906,24 @@ var require_resolve_block_scalar = __commonJS({
164906
164906
  indent = "";
164907
164907
  }
164908
164908
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
164909
- value2 += sep6 + indent.slice(trimIndent) + content;
164910
- sep6 = "\n";
164909
+ value2 += sep7 + indent.slice(trimIndent) + content;
164910
+ sep7 = "\n";
164911
164911
  } else if (indent.length > trimIndent || content[0] === " ") {
164912
- if (sep6 === " ")
164913
- sep6 = "\n";
164914
- else if (!prevMoreIndented && sep6 === "\n")
164915
- sep6 = "\n\n";
164916
- value2 += sep6 + indent.slice(trimIndent) + content;
164917
- sep6 = "\n";
164912
+ if (sep7 === " ")
164913
+ sep7 = "\n";
164914
+ else if (!prevMoreIndented && sep7 === "\n")
164915
+ sep7 = "\n\n";
164916
+ value2 += sep7 + indent.slice(trimIndent) + content;
164917
+ sep7 = "\n";
164918
164918
  prevMoreIndented = true;
164919
164919
  } else if (content === "") {
164920
- if (sep6 === "\n")
164920
+ if (sep7 === "\n")
164921
164921
  value2 += "\n";
164922
164922
  else
164923
- sep6 = "\n";
164923
+ sep7 = "\n";
164924
164924
  } else {
164925
- value2 += sep6 + content;
164926
- sep6 = " ";
164925
+ value2 += sep7 + content;
164926
+ sep7 = " ";
164927
164927
  prevMoreIndented = false;
164928
164928
  }
164929
164929
  }
@@ -165105,25 +165105,25 @@ var require_resolve_flow_scalar = __commonJS({
165105
165105
  if (!match2)
165106
165106
  return source;
165107
165107
  let res = match2[1];
165108
- let sep6 = " ";
165108
+ let sep7 = " ";
165109
165109
  let pos = first.lastIndex;
165110
165110
  line.lastIndex = pos;
165111
165111
  while (match2 = line.exec(source)) {
165112
165112
  if (match2[1] === "") {
165113
- if (sep6 === "\n")
165114
- res += sep6;
165113
+ if (sep7 === "\n")
165114
+ res += sep7;
165115
165115
  else
165116
- sep6 = "\n";
165116
+ sep7 = "\n";
165117
165117
  } else {
165118
- res += sep6 + match2[1];
165119
- sep6 = " ";
165118
+ res += sep7 + match2[1];
165119
+ sep7 = " ";
165120
165120
  }
165121
165121
  pos = line.lastIndex;
165122
165122
  }
165123
165123
  const last = /[ \t]*(.*)/sy;
165124
165124
  last.lastIndex = pos;
165125
165125
  match2 = last.exec(source);
165126
- return res + sep6 + (match2?.[1] ?? "");
165126
+ return res + sep7 + (match2?.[1] ?? "");
165127
165127
  }
165128
165128
  function doubleQuotedValue(source, onError2) {
165129
165129
  let res = "";
@@ -165925,14 +165925,14 @@ var require_cst_stringify = __commonJS({
165925
165925
  }
165926
165926
  }
165927
165927
  }
165928
- function stringifyItem({ start, key, sep: sep6, value: value2 }) {
165928
+ function stringifyItem({ start, key, sep: sep7, value: value2 }) {
165929
165929
  let res = "";
165930
165930
  for (const st2 of start)
165931
165931
  res += st2.source;
165932
165932
  if (key)
165933
165933
  res += stringifyToken(key);
165934
- if (sep6)
165935
- for (const st2 of sep6)
165934
+ if (sep7)
165935
+ for (const st2 of sep7)
165936
165936
  res += st2.source;
165937
165937
  if (value2)
165938
165938
  res += stringifyToken(value2);
@@ -167082,18 +167082,18 @@ var require_parser2 = __commonJS({
167082
167082
  if (this.type === "map-value-ind") {
167083
167083
  const prev = getPrevProps(this.peek(2));
167084
167084
  const start = getFirstKeyStartProps(prev);
167085
- let sep6;
167085
+ let sep7;
167086
167086
  if (scalar.end) {
167087
- sep6 = scalar.end;
167088
- sep6.push(this.sourceToken);
167087
+ sep7 = scalar.end;
167088
+ sep7.push(this.sourceToken);
167089
167089
  delete scalar.end;
167090
167090
  } else
167091
- sep6 = [this.sourceToken];
167091
+ sep7 = [this.sourceToken];
167092
167092
  const map3 = {
167093
167093
  type: "block-map",
167094
167094
  offset: scalar.offset,
167095
167095
  indent: scalar.indent,
167096
- items: [{ start, key: scalar, sep: sep6 }]
167096
+ items: [{ start, key: scalar, sep: sep7 }]
167097
167097
  };
167098
167098
  this.onKeyLine = true;
167099
167099
  this.stack[this.stack.length - 1] = map3;
@@ -167246,15 +167246,15 @@ var require_parser2 = __commonJS({
167246
167246
  } else if (isFlowToken(it2.key) && !includesToken(it2.sep, "newline")) {
167247
167247
  const start2 = getFirstKeyStartProps(it2.start);
167248
167248
  const key = it2.key;
167249
- const sep6 = it2.sep;
167250
- sep6.push(this.sourceToken);
167249
+ const sep7 = it2.sep;
167250
+ sep7.push(this.sourceToken);
167251
167251
  delete it2.key;
167252
167252
  delete it2.sep;
167253
167253
  this.stack.push({
167254
167254
  type: "block-map",
167255
167255
  offset: this.offset,
167256
167256
  indent: this.indent,
167257
- items: [{ start: start2, key, sep: sep6 }]
167257
+ items: [{ start: start2, key, sep: sep7 }]
167258
167258
  });
167259
167259
  } else if (start.length > 0) {
167260
167260
  it2.sep = it2.sep.concat(start, this.sourceToken);
@@ -167448,13 +167448,13 @@ var require_parser2 = __commonJS({
167448
167448
  const prev = getPrevProps(parent);
167449
167449
  const start = getFirstKeyStartProps(prev);
167450
167450
  fixFlowSeqItems(fc);
167451
- const sep6 = fc.end.splice(1, fc.end.length);
167452
- sep6.push(this.sourceToken);
167451
+ const sep7 = fc.end.splice(1, fc.end.length);
167452
+ sep7.push(this.sourceToken);
167453
167453
  const map3 = {
167454
167454
  type: "block-map",
167455
167455
  offset: fc.offset,
167456
167456
  indent: fc.indent,
167457
- items: [{ start, key: fc, sep: sep6 }]
167457
+ items: [{ start, key: fc, sep: sep7 }]
167458
167458
  };
167459
167459
  this.onKeyLine = true;
167460
167460
  this.stack[this.stack.length - 1] = map3;
@@ -206476,12 +206476,13 @@ function resolveVolumeRoot(state, volume) {
206476
206476
  }
206477
206477
  function resolveUnderRoot(root2, raw) {
206478
206478
  if (!raw.trim()) throw new AppError(400, "empty path");
206479
+ const normalizedRoot = path.resolve(root2);
206479
206480
  const normalized = path.normalize(raw);
206480
- if (path.isAbsolute(normalized) && !normalized.startsWith(root2)) {
206481
+ if (path.isAbsolute(normalized) && !normalized.startsWith(normalizedRoot + path.sep) && normalized !== normalizedRoot) {
206481
206482
  throw new AppError(400, `invalid path: ${raw}`);
206482
206483
  }
206483
- const resolved = path.resolve(root2, normalized.replace(/^\/+/, ""));
206484
- if (!resolved.startsWith(root2)) {
206484
+ const resolved = path.resolve(normalizedRoot, normalized.replace(/^\/+/, ""));
206485
+ if (resolved !== normalizedRoot && !resolved.startsWith(normalizedRoot + path.sep)) {
206485
206486
  throw new AppError(400, `path traversal rejected: ${raw}`);
206486
206487
  }
206487
206488
  return resolved;
@@ -206514,7 +206515,9 @@ async function fsList(state, q2) {
206514
206515
  name: e2.name,
206515
206516
  path: fullPath,
206516
206517
  is_dir: e2.isDirectory(),
206517
- size: stat6?.isFile() ? stat6.size : 0
206518
+ size: stat6?.isFile() ? stat6.size : 0,
206519
+ created_at: stat6?.birthtime?.toISOString() ?? null,
206520
+ modified_at: stat6?.mtime?.toISOString() ?? null
206518
206521
  };
206519
206522
  })
206520
206523
  );
@@ -233003,7 +233006,7 @@ function wrapRegisteredTools(registeredTools, runner) {
233003
233006
  // ../../node_modules/.pnpm/@mariozechner+pi-coding-agent@0.61.0_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/prompt-templates.js
233004
233007
  import { existsSync as existsSync10, readdirSync as readdirSync5, readFileSync as readFileSync7, statSync as statSync5 } from "fs";
233005
233008
  import { homedir as homedir5 } from "os";
233006
- import { basename as basename5, isAbsolute as isAbsolute3, join as join15, resolve as resolve5, sep } from "path";
233009
+ import { basename as basename5, isAbsolute as isAbsolute3, join as join15, resolve as resolve5, sep as sep2 } from "path";
233007
233010
  function parseCommandArgs(argsString) {
233008
233011
  const args = [];
233009
233012
  let current = "";
@@ -233146,7 +233149,7 @@ function loadPromptTemplates(options2 = {}) {
233146
233149
  if (target === normalizedRoot) {
233147
233150
  return true;
233148
233151
  }
233149
- const prefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;
233152
+ const prefix = normalizedRoot.endsWith(sep2) ? normalizedRoot : `${normalizedRoot}${sep2}`;
233150
233153
  return target.startsWith(prefix);
233151
233154
  };
233152
233155
  const getSourceInfo = (resolvedPath) => {
@@ -233223,12 +233226,12 @@ var BUILTIN_SLASH_COMMANDS = [
233223
233226
  var import_ignore = __toESM(require_ignore(), 1);
233224
233227
  import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync, statSync as statSync6 } from "fs";
233225
233228
  import { homedir as homedir6 } from "os";
233226
- import { basename as basename6, dirname as dirname7, isAbsolute as isAbsolute4, join as join16, relative, resolve as resolve6, sep as sep2 } from "path";
233229
+ import { basename as basename6, dirname as dirname7, isAbsolute as isAbsolute4, join as join16, relative, resolve as resolve6, sep as sep3 } from "path";
233227
233230
  var MAX_NAME_LENGTH = 64;
233228
233231
  var MAX_DESCRIPTION_LENGTH = 1024;
233229
233232
  var IGNORE_FILE_NAMES = [".gitignore", ".ignore", ".fdignore"];
233230
233233
  function toPosixPath(p) {
233231
- return p.split(sep2).join("/");
233234
+ return p.split(sep3).join("/");
233232
233235
  }
233233
233236
  function prefixIgnorePattern(line, prefix) {
233234
233237
  const trimmed = line.trim();
@@ -233501,7 +233504,7 @@ function loadSkills(options2 = {}) {
233501
233504
  if (target === normalizedRoot) {
233502
233505
  return true;
233503
233506
  }
233504
- const prefix = normalizedRoot.endsWith(sep2) ? normalizedRoot : `${normalizedRoot}${sep2}`;
233507
+ const prefix = normalizedRoot.endsWith(sep3) ? normalizedRoot : `${normalizedRoot}${sep3}`;
233505
233508
  return target.startsWith(prefix);
233506
233509
  };
233507
233510
  const getSource = (resolvedPath) => {
@@ -245360,7 +245363,7 @@ import { spawn as spawn8, spawnSync as spawnSync6 } from "node:child_process";
245360
245363
  import { createHash } from "node:crypto";
245361
245364
  import { existsSync as existsSync18, mkdirSync as mkdirSync7, readdirSync as readdirSync9, readFileSync as readFileSync13, rmSync as rmSync2, statSync as statSync9, writeFileSync as writeFileSync8 } from "node:fs";
245362
245365
  import { homedir as homedir8, tmpdir as tmpdir4 } from "node:os";
245363
- import { basename as basename8, dirname as dirname12, join as join22, relative as relative2, resolve as resolve9, sep as sep4 } from "node:path";
245366
+ import { basename as basename8, dirname as dirname12, join as join22, relative as relative2, resolve as resolve9, sep as sep5 } from "node:path";
245364
245367
 
245365
245368
  // ../../node_modules/.pnpm/balanced-match@4.0.4/node_modules/balanced-match/dist/esm/index.js
245366
245369
  var balanced = (a, b, str3) => {
@@ -246424,8 +246427,8 @@ var path14 = {
246424
246427
  win32: { sep: "\\" },
246425
246428
  posix: { sep: "/" }
246426
246429
  };
246427
- var sep3 = defaultPlatform === "win32" ? path14.win32.sep : path14.posix.sep;
246428
- minimatch.sep = sep3;
246430
+ var sep4 = defaultPlatform === "win32" ? path14.win32.sep : path14.posix.sep;
246431
+ minimatch.sep = sep4;
246429
246432
  var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
246430
246433
  minimatch.GLOBSTAR = GLOBSTAR;
246431
246434
  var qmark2 = "[^/]";
@@ -247335,7 +247338,7 @@ var FILE_PATTERNS = {
247335
247338
  };
247336
247339
  var IGNORE_FILE_NAMES2 = [".gitignore", ".ignore", ".fdignore"];
247337
247340
  function toPosixPath3(p) {
247338
- return p.split(sep4).join("/");
247341
+ return p.split(sep5).join("/");
247339
247342
  }
247340
247343
  function getHomeDir() {
247341
247344
  return process.env.HOME || homedir8();
@@ -248873,7 +248876,7 @@ var DefaultPackageManager = class {
248873
248876
  // ../../node_modules/.pnpm/@mariozechner+pi-coding-agent@0.61.0_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/resource-loader.js
248874
248877
  import { existsSync as existsSync19, readdirSync as readdirSync10, readFileSync as readFileSync14, statSync as statSync10 } from "node:fs";
248875
248878
  import { homedir as homedir9 } from "node:os";
248876
- import { join as join23, resolve as resolve10, sep as sep5 } from "node:path";
248879
+ import { join as join23, resolve as resolve10, sep as sep6 } from "node:path";
248877
248880
  function resolvePromptInput(input, description) {
248878
248881
  if (!input) {
248879
248882
  return void 0;
@@ -249227,7 +249230,7 @@ var DefaultResourceLoader = class {
249227
249230
  if (this.pathMetadata.has(normalizedResourcePath) || this.pathMetadata.has(resourcePath)) {
249228
249231
  continue;
249229
249232
  }
249230
- const match2 = normalized.find((entry) => normalizedResourcePath === entry.path || normalizedResourcePath.startsWith(`${entry.path}${sep5}`));
249233
+ const match2 = normalized.find((entry) => normalizedResourcePath === entry.path || normalizedResourcePath.startsWith(`${entry.path}${sep6}`));
249231
249234
  if (match2) {
249232
249235
  this.pathMetadata.set(normalizedResourcePath, match2.metadata);
249233
249236
  }
@@ -249446,7 +249449,7 @@ var DefaultResourceLoader = class {
249446
249449
  if (target === normalizedRoot) {
249447
249450
  return true;
249448
249451
  }
249449
- const prefix = normalizedRoot.endsWith(sep5) ? normalizedRoot : `${normalizedRoot}${sep5}`;
249452
+ const prefix = normalizedRoot.endsWith(sep6) ? normalizedRoot : `${normalizedRoot}${sep6}`;
249450
249453
  return target.startsWith(prefix);
249451
249454
  }
249452
249455
  detectExtensionConflicts(extensions2) {
@@ -250381,8 +250384,8 @@ var ConfigSelectorHeader = class {
250381
250384
  }
250382
250385
  render(width) {
250383
250386
  const title = theme.bold("Resource Configuration");
250384
- const sep6 = theme.fg("muted", " \xB7 ");
250385
- const hint = rawKeyHint("space", "toggle") + sep6 + rawKeyHint("esc", "close");
250387
+ const sep7 = theme.fg("muted", " \xB7 ");
250388
+ const hint = rawKeyHint("space", "toggle") + sep7 + rawKeyHint("esc", "close");
250386
250389
  const hintWidth = visibleWidth(hint);
250387
250390
  const titleWidth = visibleWidth(title);
250388
250391
  const spacing = Math.max(1, width - titleWidth - hintWidth);
@@ -251415,8 +251418,8 @@ var SessionSelectorHeader = class {
251415
251418
  hintLine2 = "";
251416
251419
  } else {
251417
251420
  const pathState = this.showPath ? "(on)" : "(off)";
251418
- const sep6 = theme.fg("muted", " \xB7 ");
251419
- const hint1 = keyHint("tui.input.tab", "scope") + sep6 + theme.fg("muted", 're:<pattern> regex \xB7 "phrase" exact');
251421
+ const sep7 = theme.fg("muted", " \xB7 ");
251422
+ const hint1 = keyHint("tui.input.tab", "scope") + sep7 + theme.fg("muted", 're:<pattern> regex \xB7 "phrase" exact');
251420
251423
  const hint2Parts = [
251421
251424
  keyHint("app.session.toggleSort", "sort"),
251422
251425
  keyHint("app.session.toggleNamedFilter", "named"),
@@ -251426,7 +251429,7 @@ var SessionSelectorHeader = class {
251426
251429
  if (this.showRenameHint) {
251427
251430
  hint2Parts.push(keyHint("app.session.rename", "rename"));
251428
251431
  }
251429
- const hint2 = hint2Parts.join(sep6);
251432
+ const hint2 = hint2Parts.join(sep7);
251430
251433
  hintLine1 = truncateToWidth(hint1, width, "\u2026");
251431
251434
  hintLine2 = truncateToWidth(hint2, width, "\u2026");
251432
251435
  }
@@ -262472,47 +262475,93 @@ function createDaemon(config) {
262472
262475
  volumesRoot: `${config.root}/volumes`
262473
262476
  };
262474
262477
  return http3.createServer(async (req, res) => {
262475
- const method = req.method ?? "GET";
262476
- const url = new URL2(
262477
- req.url ?? "/",
262478
- `http://${req.headers.host ?? "localhost"}`
262479
- );
262480
- const pathname = url.pathname;
262481
- if (method === "POST" && pathname === "/api/coding/run") {
262482
- const body2 = JSON.parse(await readBody(req) || "{}");
262483
- return sandagentRun(body2, res, env2);
262484
- }
262485
- if (method === "POST" && pathname === "/api/fs/upload") {
262486
- try {
262478
+ try {
262479
+ const method = req.method ?? "GET";
262480
+ const url = new URL2(
262481
+ req.url ?? "/",
262482
+ `http://${req.headers.host ?? "localhost"}`
262483
+ );
262484
+ const pathname = url.pathname;
262485
+ if (method === "POST" && pathname === "/api/coding/run") {
262486
+ const body2 = safeJsonParse(await readBody(req));
262487
+ return sandagentRun(
262488
+ body2,
262489
+ res,
262490
+ env2
262491
+ );
262492
+ }
262493
+ if (method === "POST" && pathname === "/api/fs/upload") {
262494
+ try {
262495
+ const ct2 = req.headers["content-type"] ?? "";
262496
+ if (!ct2.includes("multipart/form-data")) {
262497
+ res.writeHead(400, { "Content-Type": "application/json" });
262498
+ res.end(
262499
+ JSON.stringify(fail("content-type must be multipart/form-data"))
262500
+ );
262501
+ return;
262502
+ }
262503
+ const raw = await readBodyRaw(req);
262504
+ const parts = parseMultipart(ct2, raw);
262505
+ const result2 = await fsUpload(state, parts);
262506
+ res.writeHead(200, { "Content-Type": "application/json" });
262507
+ res.end(JSON.stringify(result2));
262508
+ } catch (err) {
262509
+ const status2 = err instanceof AppError ? err.status : 500;
262510
+ const msg = err instanceof Error ? err.message : String(err);
262511
+ res.writeHead(status2, { "Content-Type": "application/json" });
262512
+ res.end(JSON.stringify(fail(msg)));
262513
+ }
262514
+ return;
262515
+ }
262516
+ let params;
262517
+ if (method === "GET") {
262518
+ params = Object.fromEntries(url.searchParams);
262519
+ } else {
262487
262520
  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"))
262521
+ if (ct2.includes("multipart/form-data") || ct2.includes("application/x-www-form-urlencoded")) {
262522
+ sendJson(
262523
+ res,
262524
+ 400,
262525
+ fail(
262526
+ `Endpoint ${pathname} expects JSON body (content-type: application/json)`
262527
+ )
262492
262528
  );
262493
262529
  return;
262494
262530
  }
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)));
262531
+ params = safeJsonParse(await readBody(req));
262532
+ }
262533
+ const result = await router.handle(method, pathname, params);
262534
+ const status = result?.status ?? 404;
262535
+ const body = result?.body ?? fail(`not found: ${method} ${pathname}`);
262536
+ sendJson(res, status, body);
262537
+ } catch (err) {
262538
+ if (!res.headersSent) {
262539
+ if (err instanceof AppError) {
262540
+ sendJson(res, err.status, fail(err.message));
262541
+ } else {
262542
+ console.error("Unhandled request error:", err);
262543
+ const msg = err instanceof Error ? err.message : String(err);
262544
+ sendJson(res, 500, fail(`Internal server error: ${msg}`));
262545
+ }
262546
+ } else {
262547
+ console.error("Unhandled request error (headers already sent):", err);
262505
262548
  }
262506
- return;
262507
262549
  }
262508
- const params = method === "GET" ? Object.fromEntries(url.searchParams) : JSON.parse(await readBody(req) || "{}");
262509
- const result = await router.handle(method, pathname, params);
262510
- const status = result?.status ?? 404;
262511
- const body = result?.body ?? fail(`not found: ${method} ${pathname}`);
262512
- res.writeHead(status, { "Content-Type": "application/json" });
262513
- res.end(JSON.stringify(body));
262514
262550
  });
262515
262551
  }
262552
+ function sendJson(res, status, body) {
262553
+ res.writeHead(status, { "Content-Type": "application/json" });
262554
+ res.end(JSON.stringify(body));
262555
+ }
262556
+ function safeJsonParse(text) {
262557
+ const trimmed = (text || "").trim();
262558
+ if (!trimmed) return {};
262559
+ try {
262560
+ return JSON.parse(trimmed);
262561
+ } catch {
262562
+ throw new AppError(400, `Invalid JSON body: ${trimmed.slice(0, 120)}`);
262563
+ }
262564
+ }
262516
262565
  function readBody(req) {
262517
262566
  return new Promise((resolve14, reject) => {
262518
262567
  const chunks = [];
@@ -262534,6 +262583,12 @@ function readBodyRaw(req) {
262534
262583
  var host = process.env.SANDAGENT_DAEMON_HOST ?? "0.0.0.0";
262535
262584
  var port = Number(process.env.SANDAGENT_DAEMON_PORT ?? "3080");
262536
262585
  var root = process.env.SANDAGENT_ROOT ?? "/agent";
262586
+ process.on("uncaughtException", (err) => {
262587
+ console.error("Uncaught exception (ignored, server continues):", err);
262588
+ });
262589
+ process.on("unhandledRejection", (reason) => {
262590
+ console.error("Unhandled rejection (ignored, server continues):", reason);
262591
+ });
262537
262592
  async function main2() {
262538
262593
  await ensureDir(root);
262539
262594
  const server = createDaemon({ host, port, root });