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