@joeyshi12/casper 0.8.6 → 0.8.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.
Files changed (68) hide show
  1. package/dist/mcp.js +1 -1
  2. package/dist/server.js +174 -133
  3. package/dist/web/assets/{abnfDiagram-N423BO3Z-i4fdRJCJ.js → abnfDiagram-N423BO3Z-dD8GuEng.js} +1 -1
  4. package/dist/web/assets/{arc-CNTtovdQ.js → arc-BrT5U_LP.js} +1 -1
  5. package/dist/web/assets/{architectureDiagram-T3A2C74G-DduZE2nZ.js → architectureDiagram-T3A2C74G-Bk6pq1Xm.js} +1 -1
  6. package/dist/web/assets/{blockDiagram-VBNYF7ZC-ByAhziEP.js → blockDiagram-VBNYF7ZC-nMmkAmal.js} +1 -1
  7. package/dist/web/assets/{c4Diagram-5PPSVZJV-yrt3tSEp.js → c4Diagram-5PPSVZJV-ByqsIevu.js} +1 -1
  8. package/dist/web/assets/channel-DKLeFBN9.js +1 -0
  9. package/dist/web/assets/{chunk-2GRJ4B5K-CSdeo0L0.js → chunk-2GRJ4B5K-Dk5J1dTv.js} +1 -1
  10. package/dist/web/assets/{chunk-2Q5K7J3B-D4G9X5EX.js → chunk-2Q5K7J3B-D-ucNMTq.js} +1 -1
  11. package/dist/web/assets/{chunk-5RXB4S5H-B_OWWGvR.js → chunk-5RXB4S5H-Ca3yO8vV.js} +1 -1
  12. package/dist/web/assets/{chunk-5VM5RSS4-B7cnRpAw.js → chunk-5VM5RSS4-Bu0AKdlE.js} +1 -1
  13. package/dist/web/assets/{chunk-6Q2QTUOP-Qy2FKYGg.js → chunk-6Q2QTUOP-C0g01XOe.js} +1 -1
  14. package/dist/web/assets/{chunk-GF5L2VYU-BnhYHDi7.js → chunk-GF5L2VYU-B-h7MnmL.js} +1 -1
  15. package/dist/web/assets/{chunk-JWPE2WC7-DbeWy5Y-.js → chunk-JWPE2WC7-BgEwGAlP.js} +1 -1
  16. package/dist/web/assets/{chunk-KBJHAD2P-DZsGP_P8.js → chunk-KBJHAD2P-NrU17DU3.js} +1 -1
  17. package/dist/web/assets/{chunk-RYQCIY6F-LB_aFtph.js → chunk-RYQCIY6F-BqzMscSM.js} +1 -1
  18. package/dist/web/assets/{chunk-XXDRQBXY-CLWgiD5b.js → chunk-XXDRQBXY-DuAhRVgm.js} +1 -1
  19. package/dist/web/assets/classDiagram-JCYQIIEL-D8ek01K6.js +1 -0
  20. package/dist/web/assets/classDiagram-v2-OCEON4UE-D8ek01K6.js +1 -0
  21. package/dist/web/assets/{cose-bilkent-JH36ORCC-g-7BsXo5.js → cose-bilkent-JH36ORCC-BrGerPmF.js} +1 -1
  22. package/dist/web/assets/{cynefin-VYW2F7L2-BOGFr3Us.js → cynefin-VYW2F7L2-wgLYEWNl.js} +1 -1
  23. package/dist/web/assets/{cynefinDiagram-MW4NZA55-CxyNa-7x.js → cynefinDiagram-MW4NZA55-VK-IHzZm.js} +1 -1
  24. package/dist/web/assets/{dagre-VZM6K2ZE-DfjbiFpB.js → dagre-VZM6K2ZE-DNNj1LbS.js} +1 -1
  25. package/dist/web/assets/{diagram-7IWD3JNH-CeiPmTYy.js → diagram-7IWD3JNH-CXXXIjt0.js} +1 -1
  26. package/dist/web/assets/{diagram-B4RE2ZJO-DJVn3KKP.js → diagram-B4RE2ZJO-COXtMeEv.js} +1 -1
  27. package/dist/web/assets/{diagram-LBJQPF4R-COyh9pF4.js → diagram-LBJQPF4R-vKGeSxFy.js} +1 -1
  28. package/dist/web/assets/{diagram-Q27KOJAE-QKsIhxbP.js → diagram-Q27KOJAE-C4Lsm9DM.js} +1 -1
  29. package/dist/web/assets/{diagram-UB23O5K3-B_gx39Gp.js → diagram-UB23O5K3-e_pZTiEr.js} +1 -1
  30. package/dist/web/assets/{ebnfDiagram-BXEA7PRR-Bpdn9ysk.js → ebnfDiagram-BXEA7PRR-bAwMS4kZ.js} +1 -1
  31. package/dist/web/assets/{erDiagram-JOGREHBK-BnQtyQgW.js → erDiagram-JOGREHBK-zT-mXzlN.js} +1 -1
  32. package/dist/web/assets/{flowDiagram-UKHOOZJN-DZTP5Enz.js → flowDiagram-UKHOOZJN-BJZREKw8.js} +1 -1
  33. package/dist/web/assets/{ganttDiagram-PKOTCBZU-CieyMFHt.js → ganttDiagram-PKOTCBZU-MsCI5Oop.js} +1 -1
  34. package/dist/web/assets/{gitGraphDiagram-DS77QQ5N-DrRXUZVu.js → gitGraphDiagram-DS77QQ5N-CrTLzDOq.js} +1 -1
  35. package/dist/web/assets/{index-BOwn2Ixs.js → index-1jKtQqrL.js} +65 -64
  36. package/dist/web/assets/index-DvasuQ2p.css +1 -0
  37. package/dist/web/assets/{infoDiagram-6WML65LV-CYJG2_PK.js → infoDiagram-6WML65LV-CZF-68Rp.js} +1 -1
  38. package/dist/web/assets/{ishikawaDiagram-WSZJBQD7-Bddz1oRs.js → ishikawaDiagram-WSZJBQD7-0r_z2Yor.js} +1 -1
  39. package/dist/web/assets/{journeyDiagram-NVQOT4AX-CzcRW94Q.js → journeyDiagram-NVQOT4AX-U8Bc6JlF.js} +1 -1
  40. package/dist/web/assets/{kanban-definition-27J2QSJJ-CPUQK_3h.js → kanban-definition-27J2QSJJ-BrJ15Haw.js} +1 -1
  41. package/dist/web/assets/{linear-D9L46R2G.js → linear-Vi7chwnv.js} +1 -1
  42. package/dist/web/assets/{mermaid.core-CfPzZfnE.js → mermaid.core-cpP24Vzz.js} +5 -5
  43. package/dist/web/assets/{mindmap-definition-FAOFIHXS-BwAV9mj2.js → mindmap-definition-FAOFIHXS-9-3-DDeb.js} +1 -1
  44. package/dist/web/assets/{pegDiagram-VL7TDLO6-Dr3kP1zj.js → pegDiagram-VL7TDLO6-Bl_cAnPS.js} +1 -1
  45. package/dist/web/assets/{pieDiagram-7S7Q4E2Y-DUs-kVVq.js → pieDiagram-7S7Q4E2Y-Bz29FvF6.js} +1 -1
  46. package/dist/web/assets/{quadrantDiagram-CIZ2JOQS-oj0dwtC1.js → quadrantDiagram-CIZ2JOQS-BXSpkyEn.js} +1 -1
  47. package/dist/web/assets/{railroadDiagram-AXF67PYL-BRh-D40Z.js → railroadDiagram-AXF67PYL-DZqWxSoF.js} +1 -1
  48. package/dist/web/assets/{requirementDiagram-LRYGKXZP-D-dYL6Gd.js → requirementDiagram-LRYGKXZP-CWEdHghn.js} +1 -1
  49. package/dist/web/assets/{sankeyDiagram-W5VNT64P-CmUWmT7X.js → sankeyDiagram-W5VNT64P-BGbJYr4X.js} +1 -1
  50. package/dist/web/assets/{sequenceDiagram-SI44F4Z6-iu1LfaIM.js → sequenceDiagram-SI44F4Z6-p_wF9iET.js} +1 -1
  51. package/dist/web/assets/{sizeCapture-X5ZJPWSS-5ZLmVlhi.js → sizeCapture-X5ZJPWSS-w3BcIn6X.js} +1 -1
  52. package/dist/web/assets/{stateDiagram-OKZ733FA-Cn1wvg1w.js → stateDiagram-OKZ733FA-Bz6FXoF6.js} +1 -1
  53. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-DVcj7931.js +1 -0
  54. package/dist/web/assets/{swimlanes-SLNWSIFB-_0o7Xy3Y.js → swimlanes-SLNWSIFB-B5rAwYj-.js} +2 -2
  55. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-Dv2xZebs.js +8 -0
  56. package/dist/web/assets/{timeline-definition-Z64GVDOM-DVcHO53x.js → timeline-definition-Z64GVDOM-gsS6Mn-_.js} +1 -1
  57. package/dist/web/assets/{vennDiagram-T6HMQDX7-CTGvSXQY.js → vennDiagram-T6HMQDX7-DLYvB8dm.js} +1 -1
  58. package/dist/web/assets/{wardleyDiagram-T6FBY63Y-yB2tMkwc.js → wardleyDiagram-T6FBY63Y-DM2Cz5Yx.js} +1 -1
  59. package/dist/web/assets/{xychartDiagram-ELKLHX3M-Cj_PZuOR.js → xychartDiagram-ELKLHX3M-CuA0hj28.js} +1 -1
  60. package/dist/web/index.html +2 -2
  61. package/dist/web/sw.js +1 -1
  62. package/package.json +1 -1
  63. package/dist/web/assets/channel-B58CT03a.js +0 -1
  64. package/dist/web/assets/classDiagram-JCYQIIEL-DxP2ZBOt.js +0 -1
  65. package/dist/web/assets/classDiagram-v2-OCEON4UE-DxP2ZBOt.js +0 -1
  66. package/dist/web/assets/index-iMxQdvho.css +0 -1
  67. package/dist/web/assets/stateDiagram-v2-UEYNNEHI-pgkNY837.js +0 -1
  68. package/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CauQgrWG.js +0 -8
package/dist/server.js CHANGED
@@ -319,12 +319,10 @@ var init_config = __esm({
319
319
  */
320
320
  defaultAgent: setting("DEFAULT_AGENT", "defaultAgent", "casper"),
321
321
  /**
322
- * Filesystem root that file-serving endpoints (/api/fs/dirs, /api/fs/image)
323
- * are confined to. Requests resolving outside this root are rejected.
324
- * Defaults to the filesystem root (/), so file browsing spans everything the
325
- * server process can read. Set CASPER_FILE_ROOT to a narrower path (e.g. the
326
- * user's home directory) to stop authenticated users from reading system
327
- * files such as /etc or SSH keys.
322
+ * Filesystem root the file endpoints (/api/fs/dirs, /api/fs/image) are confined to; anything
323
+ * resolving outside it is rejected. Defaults to /, so browsing spans everything the process
324
+ * can read - set a narrower path to keep authenticated users out of system files such as /etc
325
+ * or SSH keys.
328
326
  */
329
327
  fileRoot: path5.resolve(setting("CASPER_FILE_ROOT", "fileRoot", "/")),
330
328
  /** Directory where kiro-cli persists its own session files. */
@@ -723,24 +721,66 @@ var init_dist = __esm({
723
721
  }
724
722
  });
725
723
 
726
- // server/src/util/paths.ts
724
+ // server/src/session/workspaces.ts
725
+ import crypto3 from "node:crypto";
727
726
  import fs7 from "node:fs";
728
- import fsp from "node:fs/promises";
729
727
  import path8 from "node:path";
728
+ function workspacesRoot() {
729
+ return path8.join(config.casperDataDir, "workspaces");
730
+ }
731
+ function workspaceDir(workspaceId) {
732
+ return path8.join(workspacesRoot(), workspaceId);
733
+ }
734
+ function createWorkspace() {
735
+ const id = crypto3.randomUUID();
736
+ const dir = workspaceDir(id);
737
+ fs7.mkdirSync(dir, { recursive: true, mode: 448 });
738
+ return { id, dir };
739
+ }
740
+ var init_workspaces = __esm({
741
+ "server/src/session/workspaces.ts"() {
742
+ "use strict";
743
+ init_config();
744
+ }
745
+ });
746
+
747
+ // server/src/session/titles.ts
748
+ function titleFromPrompt(content) {
749
+ const text2 = content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
750
+ const words = stripAttachmentsLine(text2).replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim();
751
+ if (!words) return "";
752
+ if (words.length <= MAX_TITLE) return words.replace(/[.,;:!?]+$/, "");
753
+ const cut = words.slice(0, MAX_TITLE);
754
+ const lastSpace = cut.lastIndexOf(" ");
755
+ return `${(lastSpace > MAX_TITLE / 2 ? cut.slice(0, lastSpace) : cut).replace(/[.,;:!?]+$/, "")}\u2026`;
756
+ }
757
+ var MAX_TITLE;
758
+ var init_titles = __esm({
759
+ "server/src/session/titles.ts"() {
760
+ "use strict";
761
+ init_dist();
762
+ MAX_TITLE = 60;
763
+ }
764
+ });
765
+
766
+ // server/src/util/paths.ts
767
+ import fs8 from "node:fs";
768
+ import fsp from "node:fs/promises";
769
+ import path9 from "node:path";
730
770
  function isWithinRoot(root, target) {
731
- const resolved = path8.resolve(target);
732
- if (root === path8.sep) return true;
733
- return resolved === root || resolved.startsWith(root + path8.sep);
771
+ const resolved = path9.resolve(target);
772
+ if (root === path9.sep) return true;
773
+ return resolved === root || resolved.startsWith(root + path9.sep);
734
774
  }
735
775
  function confineToRoot(root, input) {
736
- const resolved = path8.resolve(root, input);
776
+ const resolved = path9.resolve(root, input);
737
777
  return isWithinRoot(root, resolved) ? resolved : null;
738
778
  }
739
779
  function resolveRealRoot(root) {
740
780
  if (realRootCache && realRootCache.root === root) return realRootCache.real;
741
781
  let real;
742
782
  try {
743
- real = fs7.realpathSync(root);
783
+ real = fs8.realpathSync(root);
744
784
  } catch {
745
785
  real = root;
746
786
  }
@@ -1221,8 +1261,8 @@ var init_TurnState = __esm({
1221
1261
  });
1222
1262
 
1223
1263
  // server/src/session/kiroFiles.ts
1224
- import fs8 from "node:fs/promises";
1225
- import path9 from "node:path";
1264
+ import fs9 from "node:fs/promises";
1265
+ import path10 from "node:path";
1226
1266
  function isContentBlock(v) {
1227
1267
  return isRecord(v) && typeof v.kind === "string";
1228
1268
  }
@@ -1274,7 +1314,7 @@ function summarize(j) {
1274
1314
  async function listPersistedSessions(log) {
1275
1315
  let files;
1276
1316
  try {
1277
- files = await fs8.readdir(config.kiroSessionsDir);
1317
+ files = await fs9.readdir(config.kiroSessionsDir);
1278
1318
  } catch {
1279
1319
  return [];
1280
1320
  }
@@ -1283,7 +1323,7 @@ async function listPersistedSessions(log) {
1283
1323
  await Promise.all(
1284
1324
  jsonFiles.map(async (f) => {
1285
1325
  try {
1286
- const raw = await fs8.readFile(path9.join(config.kiroSessionsDir, f), "utf8");
1326
+ const raw = await fs9.readFile(path10.join(config.kiroSessionsDir, f), "utf8");
1287
1327
  summaries.push(summarize(JSON.parse(raw)));
1288
1328
  } catch (err) {
1289
1329
  log.debug({ err, f }, "kiroFiles: skipping unreadable session file");
@@ -1296,18 +1336,18 @@ async function listPersistedSessions(log) {
1296
1336
  async function deletePersistedSession(sessionId) {
1297
1337
  if (!isValidSessionId(sessionId)) return;
1298
1338
  const targets = [
1299
- path9.join(config.kiroSessionsDir, `${sessionId}.json`),
1300
- path9.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
1301
- path9.join(config.kiroSessionsDir, `${sessionId}.history`),
1302
- path9.join(config.kiroSessionsDir, sessionId)
1339
+ path10.join(config.kiroSessionsDir, `${sessionId}.json`),
1340
+ path10.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
1341
+ path10.join(config.kiroSessionsDir, `${sessionId}.history`),
1342
+ path10.join(config.kiroSessionsDir, sessionId)
1303
1343
  ];
1304
- await Promise.all(targets.map((f) => fs8.rm(f, { recursive: true, force: true })));
1344
+ await Promise.all(targets.map((f) => fs9.rm(f, { recursive: true, force: true })));
1305
1345
  }
1306
1346
  async function readPersistedSession(sessionId) {
1307
1347
  if (!isValidSessionId(sessionId)) return null;
1308
1348
  try {
1309
- const raw = await fs8.readFile(
1310
- path9.join(config.kiroSessionsDir, `${sessionId}.json`),
1349
+ const raw = await fs9.readFile(
1350
+ path10.join(config.kiroSessionsDir, `${sessionId}.json`),
1311
1351
  "utf8"
1312
1352
  );
1313
1353
  return summarize(JSON.parse(raw));
@@ -1319,8 +1359,8 @@ async function hydrateTranscript(sessionId) {
1319
1359
  if (!isValidSessionId(sessionId)) return [];
1320
1360
  let raw;
1321
1361
  try {
1322
- raw = await fs8.readFile(
1323
- path9.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
1362
+ raw = await fs9.readFile(
1363
+ path10.join(config.kiroSessionsDir, `${sessionId}.jsonl`),
1324
1364
  "utf8"
1325
1365
  );
1326
1366
  } catch {
@@ -1435,17 +1475,17 @@ var init_sessionStore = __esm({
1435
1475
  });
1436
1476
 
1437
1477
  // server/src/session/SessionManager.ts
1438
- import fs9 from "node:fs";
1439
- import path10 from "node:path";
1478
+ import fs10 from "node:fs";
1479
+ import path11 from "node:path";
1440
1480
  function resolveCwd(input) {
1441
1481
  const raw = input?.trim();
1442
- const abs = raw ? path10.resolve(config.defaultCwd, raw) : config.defaultCwd;
1482
+ const abs = raw ? path11.resolve(config.defaultCwd, raw) : config.defaultCwd;
1443
1483
  if (!isWithinRoot(config.fileRoot, abs)) {
1444
1484
  throw new Error(`Working directory is outside the allowed root: ${abs}`);
1445
1485
  }
1446
1486
  let stat;
1447
1487
  try {
1448
- stat = fs9.statSync(abs);
1488
+ stat = fs10.statSync(abs);
1449
1489
  } catch {
1450
1490
  stat = void 0;
1451
1491
  }
@@ -1453,7 +1493,7 @@ function resolveCwd(input) {
1453
1493
  throw new Error(`Working directory path is a file, not a directory: ${abs}`);
1454
1494
  }
1455
1495
  if (!stat) {
1456
- fs9.mkdirSync(abs, { recursive: true });
1496
+ fs10.mkdirSync(abs, { recursive: true });
1457
1497
  }
1458
1498
  return abs;
1459
1499
  }
@@ -1485,6 +1525,8 @@ var init_SessionManager = __esm({
1485
1525
  "use strict";
1486
1526
  init_dist();
1487
1527
  init_config();
1528
+ init_workspaces();
1529
+ init_titles();
1488
1530
  init_paths2();
1489
1531
  init_KiroProcess();
1490
1532
  init_EventStore();
@@ -1551,17 +1593,10 @@ var init_SessionManager = __esm({
1551
1593
  if (s) s.title = title.trim() || s.title;
1552
1594
  }
1553
1595
  /**
1554
- * Re-point a session at a different working directory. A session's cwd is
1555
- * fixed at creation, so this is needed when the original folder was moved or
1556
- * deleted (the workspace endpoints and the kiro process are scoped to it).
1557
- *
1558
- * The target is validated and created exactly like a new session's cwd, so a
1559
- * folder is only created on this explicit action - never silently on resume.
1560
- * Any live kiro process was spawned with the old cwd, so it's disposed here;
1561
- * the next turn respawns in the new directory with the transcript intact
1562
- * (kiro reloads the session from its own file).
1563
- *
1564
- * Returns the resolved absolute path.
1596
+ * Re-point a session at a different working directory, for when the original was moved
1597
+ * or deleted. Validates and creates the target exactly like a new session's cwd, so a
1598
+ * folder is only created on this explicit action. Any live process was spawned with the
1599
+ * old cwd, so it is disposed and the next turn respawns in the new one, transcript intact.
1565
1600
  */
1566
1601
  async setSessionCwd(sessionId, input) {
1567
1602
  const resolved = resolveCwd(input);
@@ -1709,7 +1744,7 @@ var init_SessionManager = __esm({
1709
1744
  // -------------------------------------------------------------------------
1710
1745
  /** Create a new session. Spawns immediately so we get a real kiro sessionId. */
1711
1746
  async createSession(opts) {
1712
- const cwd = resolveCwd(opts.cwd);
1747
+ const cwd = opts.freshWorkspace ? createWorkspace().dir : resolveCwd(opts.cwd);
1713
1748
  const tempId = `pending-${Date.now()}-${Math.floor(this.sessions.size)}`;
1714
1749
  const store = new EventStore(tempId);
1715
1750
  const s = new Session(tempId, store, cwd);
@@ -1723,7 +1758,7 @@ var init_SessionManager = __esm({
1723
1758
  this.evict(s.sessionId);
1724
1759
  throw err;
1725
1760
  }
1726
- const folder = path10.basename(s.cwd);
1761
+ const folder = opts.freshWorkspace ? "" : path11.basename(s.cwd);
1727
1762
  if (folder) {
1728
1763
  this.store.setTitle(s.sessionId, folder);
1729
1764
  s.title = folder;
@@ -1740,6 +1775,13 @@ var init_SessionManager = __esm({
1740
1775
  s.running = true;
1741
1776
  s.lastActivity = Date.now();
1742
1777
  s.record({ kind: "turn_started", prompt: content });
1778
+ if (!this.store.getTitle(s.sessionId)) {
1779
+ const title = titleFromPrompt(content);
1780
+ if (title) {
1781
+ this.store.setTitle(s.sessionId, title);
1782
+ s.title = title;
1783
+ }
1784
+ }
1743
1785
  proc.prompt({ sessionId: s.sessionId, prompt: content }).then((res) => s.record({ kind: "turn_ended", stopReason: res.stopReason })).catch((err) => {
1744
1786
  this.log.error({ err, sessionId: s.sessionId }, "prompt turn failed");
1745
1787
  const tail = proc.stderrTail();
@@ -1873,12 +1915,10 @@ ${tail}` : err.message;
1873
1915
  };
1874
1916
  }
1875
1917
  /**
1876
- * The cursor a reconnecting client should start from. Normally the store
1877
- * head, but while a turn is in flight the prompt/response are not yet in
1878
- * kiro's persisted jsonl (kiro writes a turn only when it completes), so the
1879
- * hydrated transcript is missing them. Rewind to just before the in-flight
1880
- * turn_started so the WS replays the whole in-flight turn. Guarded against
1881
- * duplication in case kiro ever persists the prompt at turn start.
1918
+ * The cursor a reconnecting client should start from. Normally the store head, but kiro writes
1919
+ * a turn to its jsonl only once the turn completes, so a hydrated transcript is missing one in
1920
+ * flight. Rewind to just before its turn_started and let the WS replay the whole turn. Guarded
1921
+ * against duplication in case kiro ever persists the prompt at turn start.
1882
1922
  */
1883
1923
  replayHead(s, transcript) {
1884
1924
  const head = s.store.head();
@@ -1983,13 +2023,13 @@ var init_rateLimit = __esm({
1983
2023
  });
1984
2024
 
1985
2025
  // server/src/routes/auth.ts
1986
- import crypto3 from "node:crypto";
2026
+ import crypto4 from "node:crypto";
1987
2027
  import fastifyCookie from "@fastify/cookie";
1988
2028
  function secretMatches(supplied, expected) {
1989
2029
  if (typeof supplied !== "string") return false;
1990
- const a = crypto3.createHash("sha256").update(supplied).digest();
1991
- const b = crypto3.createHash("sha256").update(expected).digest();
1992
- return crypto3.timingSafeEqual(a, b);
2030
+ const a = crypto4.createHash("sha256").update(supplied).digest();
2031
+ const b = crypto4.createHash("sha256").update(expected).digest();
2032
+ return crypto4.timingSafeEqual(a, b);
1993
2033
  }
1994
2034
  function extractToken(req) {
1995
2035
  const auth = req.headers["authorization"];
@@ -2193,9 +2233,9 @@ var init_agents2 = __esm({
2193
2233
  });
2194
2234
 
2195
2235
  // server/src/routes/fs.ts
2196
- import fs10 from "node:fs/promises";
2236
+ import fs11 from "node:fs/promises";
2197
2237
  import { createReadStream } from "node:fs";
2198
- import path11 from "node:path";
2238
+ import path12 from "node:path";
2199
2239
  function confinedPath(input) {
2200
2240
  return confineToRoot(config.fileRoot, input) ?? confineToRoot(config.casperDataDir, input);
2201
2241
  }
@@ -2206,10 +2246,10 @@ function registerFsRoutes(app) {
2206
2246
  const input = (req.query.path ?? "").trim();
2207
2247
  const base = config.defaultCwd;
2208
2248
  const endsWithSep = input.endsWith("/");
2209
- const resolved = input ? path11.resolve(base, input) : base;
2210
- const dir = endsWithSep || !input ? resolved : path11.dirname(resolved);
2211
- const prefix = endsWithSep || !input ? "" : path11.basename(resolved);
2212
- const targetKind = await fs10.stat(resolved).then((s) => s.isDirectory() ? "directory" : "file").catch(() => "missing");
2249
+ const resolved = input ? path12.resolve(base, input) : base;
2250
+ const dir = endsWithSep || !input ? resolved : path12.dirname(resolved);
2251
+ const prefix = endsWithSep || !input ? "" : path12.basename(resolved);
2252
+ const targetKind = await fs11.stat(resolved).then((s) => s.isDirectory() ? "directory" : "file").catch(() => "missing");
2213
2253
  if (confinedPath(dir) === null) {
2214
2254
  reply.code(403);
2215
2255
  return { error: "Path outside allowed root" };
@@ -2220,23 +2260,23 @@ function registerFsRoutes(app) {
2220
2260
  }
2221
2261
  let entries = [];
2222
2262
  try {
2223
- const dirents = await fs10.readdir(realDir, { withFileTypes: true });
2263
+ const dirents = await fs11.readdir(realDir, { withFileTypes: true });
2224
2264
  const candidates = dirents.filter((d) => !d.name.startsWith("."));
2225
2265
  const checks2 = await Promise.all(
2226
2266
  candidates.map(async (d) => {
2227
2267
  if (d.isDirectory()) return d.name;
2228
2268
  if (!d.isSymbolicLink()) return null;
2229
- const full = path11.join(realDir, d.name);
2269
+ const full = path12.join(realDir, d.name);
2230
2270
  const real = await realConfineToRoot(config.fileRoot, full);
2231
2271
  if (!real) return null;
2232
2272
  try {
2233
- return (await fs10.stat(real)).isDirectory() ? d.name : null;
2273
+ return (await fs11.stat(real)).isDirectory() ? d.name : null;
2234
2274
  } catch {
2235
2275
  return null;
2236
2276
  }
2237
2277
  })
2238
2278
  );
2239
- entries = checks2.filter((name) => name !== null).filter((name) => name.toLowerCase().startsWith(prefix.toLowerCase())).sort((a, b) => a.localeCompare(b)).slice(0, 20).map((name) => path11.join(dir, name));
2279
+ entries = checks2.filter((name) => name !== null).filter((name) => name.toLowerCase().startsWith(prefix.toLowerCase())).sort((a, b) => a.localeCompare(b)).slice(0, 20).map((name) => path12.join(dir, name));
2240
2280
  } catch {
2241
2281
  entries = [];
2242
2282
  }
@@ -2251,7 +2291,7 @@ function registerFsRoutes(app) {
2251
2291
  reply.code(400);
2252
2292
  return { error: "path parameter is required" };
2253
2293
  }
2254
- if (!path11.isAbsolute(filePath)) {
2294
+ if (!path12.isAbsolute(filePath)) {
2255
2295
  reply.code(400);
2256
2296
  return { error: "path must be absolute" };
2257
2297
  }
@@ -2260,7 +2300,7 @@ function registerFsRoutes(app) {
2260
2300
  reply.code(403);
2261
2301
  return { error: "Path outside allowed root" };
2262
2302
  }
2263
- const ext = path11.extname(resolved).toLowerCase();
2303
+ const ext = path12.extname(resolved).toLowerCase();
2264
2304
  const mime = IMAGE_MIMES[ext];
2265
2305
  if (!mime) {
2266
2306
  reply.code(400);
@@ -2273,7 +2313,7 @@ function registerFsRoutes(app) {
2273
2313
  }
2274
2314
  let stat;
2275
2315
  try {
2276
- stat = await fs10.stat(real);
2316
+ stat = await fs11.stat(real);
2277
2317
  } catch {
2278
2318
  reply.code(404);
2279
2319
  return { error: "File not found" };
@@ -2332,7 +2372,8 @@ function registerSessionRoutes(app, manager) {
2332
2372
  return await manager.createSession({
2333
2373
  cwd: body.cwd,
2334
2374
  agentId: body.agentId,
2335
- modelId: body.modelId
2375
+ modelId: body.modelId,
2376
+ freshWorkspace: body.freshWorkspace
2336
2377
  });
2337
2378
  } catch (err) {
2338
2379
  reply.code(400);
@@ -2429,7 +2470,7 @@ var init_sessions = __esm({
2429
2470
  });
2430
2471
 
2431
2472
  // server/src/util/filekind.ts
2432
- import path12 from "node:path";
2473
+ import path13 from "node:path";
2433
2474
  function mimeForExt(ext) {
2434
2475
  return MIME_MAP[ext.toLowerCase()] ?? "application/octet-stream";
2435
2476
  }
@@ -2449,7 +2490,7 @@ function looksBinary(buf) {
2449
2490
  return control / buf.length > 0.3;
2450
2491
  }
2451
2492
  function classifyKind(name) {
2452
- const ext = path12.extname(name).toLowerCase();
2493
+ const ext = path13.extname(name).toLowerCase();
2453
2494
  if (ext in IMAGE_EXTS2) return "image";
2454
2495
  if (TEXT_EXTS.has(ext)) return "text";
2455
2496
  return "binary";
@@ -2559,9 +2600,9 @@ var init_filekind = __esm({
2559
2600
  });
2560
2601
 
2561
2602
  // server/src/routes/workspace.ts
2562
- import fs11 from "node:fs/promises";
2603
+ import fs12 from "node:fs/promises";
2563
2604
  import { createReadStream as createReadStream2 } from "node:fs";
2564
- import path13 from "node:path";
2605
+ import path14 from "node:path";
2565
2606
  function tooLargeForPreview(size, maxBytes) {
2566
2607
  return {
2567
2608
  error: `File too large for preview (${(size / 1024 / 1024).toFixed(1)} MB, max ${maxBytes / 1024 / 1024} MB)`
@@ -2606,7 +2647,7 @@ function registerWorkspaceRoutes(app, manager) {
2606
2647
  }
2607
2648
  const workspaceMissing = async () => {
2608
2649
  try {
2609
- return !(await fs11.stat(cwd)).isDirectory();
2650
+ return !(await fs12.stat(cwd)).isDirectory();
2610
2651
  } catch {
2611
2652
  return true;
2612
2653
  }
@@ -2621,7 +2662,7 @@ function registerWorkspaceRoutes(app, manager) {
2621
2662
  }
2622
2663
  let dirents;
2623
2664
  try {
2624
- dirents = await fs11.readdir(realTarget, { withFileTypes: true, encoding: "utf8" });
2665
+ dirents = await fs12.readdir(realTarget, { withFileTypes: true, encoding: "utf8" });
2625
2666
  } catch {
2626
2667
  return notFound();
2627
2668
  }
@@ -2629,14 +2670,14 @@ function registerWorkspaceRoutes(app, manager) {
2629
2670
  for (const d of dirents) {
2630
2671
  const name = d.name;
2631
2672
  const entryRelative = relative ? `${relative}/${name}` : name;
2632
- const entryAbsolute = path13.join(realTarget, name);
2673
+ const entryAbsolute = path14.join(realTarget, name);
2633
2674
  let kind = d.isDirectory() ? "directory" : d.isFile() ? "file" : null;
2634
2675
  let statTarget = entryAbsolute;
2635
2676
  if (kind === null && d.isSymbolicLink()) {
2636
2677
  const real = await realConfineToRoot(config.fileRoot, entryAbsolute);
2637
2678
  if (!real) continue;
2638
2679
  try {
2639
- const st = await fs11.stat(real);
2680
+ const st = await fs12.stat(real);
2640
2681
  kind = st.isDirectory() ? "directory" : st.isFile() ? "file" : null;
2641
2682
  statTarget = real;
2642
2683
  } catch {
@@ -2648,7 +2689,7 @@ function registerWorkspaceRoutes(app, manager) {
2648
2689
  entries.push({ name, path: entryRelative, type: "directory" });
2649
2690
  } else {
2650
2691
  try {
2651
- const stat = await fs11.stat(statTarget);
2692
+ const stat = await fs12.stat(statTarget);
2652
2693
  entries.push({
2653
2694
  name,
2654
2695
  path: entryRelative,
@@ -2695,7 +2736,7 @@ function registerWorkspaceRoutes(app, manager) {
2695
2736
  }
2696
2737
  let stat;
2697
2738
  try {
2698
- stat = await fs11.stat(realTarget);
2739
+ stat = await fs12.stat(realTarget);
2699
2740
  } catch {
2700
2741
  reply.code(404);
2701
2742
  return { error: "File not found" };
@@ -2708,8 +2749,8 @@ function registerWorkspaceRoutes(app, manager) {
2708
2749
  reply.code(413);
2709
2750
  return { error: `File too large (${(stat.size / 1024 / 1024).toFixed(1)} MB, max 100 MB)` };
2710
2751
  }
2711
- const ext = path13.extname(realTarget);
2712
- const filename = path13.basename(realTarget);
2752
+ const ext = path14.extname(realTarget);
2753
+ const filename = path14.basename(realTarget);
2713
2754
  const asciiName = filename.replace(/[^\w.\-]/g, "_");
2714
2755
  reply.header("Content-Type", mimeForExt(ext));
2715
2756
  reply.header(
@@ -2747,7 +2788,7 @@ function registerWorkspaceRoutes(app, manager) {
2747
2788
  }
2748
2789
  let stat;
2749
2790
  try {
2750
- stat = await fs11.stat(realTarget);
2791
+ stat = await fs12.stat(realTarget);
2751
2792
  } catch {
2752
2793
  reply.code(404);
2753
2794
  return { error: "File not found" };
@@ -2756,7 +2797,7 @@ function registerWorkspaceRoutes(app, manager) {
2756
2797
  reply.code(400);
2757
2798
  return { error: "Path is not a file" };
2758
2799
  }
2759
- const ext = path13.extname(realTarget).toLowerCase();
2800
+ const ext = path14.extname(realTarget).toLowerCase();
2760
2801
  const mime = mimeForExt(ext);
2761
2802
  const isImage = mime.startsWith("image/");
2762
2803
  const isPdf = mime === "application/pdf";
@@ -2801,7 +2842,7 @@ function registerWorkspaceRoutes(app, manager) {
2801
2842
  if (kind === "binary") {
2802
2843
  let fh;
2803
2844
  try {
2804
- fh = await fs11.open(realTarget, "r");
2845
+ fh = await fs12.open(realTarget, "r");
2805
2846
  const buf = Buffer.alloc(Math.min(HEXDUMP_BYTES, stat.size));
2806
2847
  const { bytesRead } = await fh.read(buf, 0, buf.length, 0);
2807
2848
  const head = buf.subarray(0, bytesRead);
@@ -2851,36 +2892,36 @@ var init_workspace = __esm({
2851
2892
 
2852
2893
  // server/src/routes/uploads.ts
2853
2894
  import { createReadStream as createReadStream3, createWriteStream } from "node:fs";
2854
- import fs12 from "node:fs/promises";
2855
- import path14 from "node:path";
2856
- import crypto4 from "node:crypto";
2895
+ import fs13 from "node:fs/promises";
2896
+ import path15 from "node:path";
2897
+ import crypto5 from "node:crypto";
2857
2898
  import { execFile as execFile3 } from "node:child_process";
2858
2899
  import { pipeline } from "node:stream/promises";
2859
2900
  function uploadDirFor(sessionId) {
2860
- return path14.join(config.casperDataDir, "sessions", sessionId, "uploads");
2901
+ return path15.join(config.casperDataDir, "sessions", sessionId, "uploads");
2861
2902
  }
2862
2903
  function sanitizeName(raw) {
2863
- const base = path14.basename(raw).replace(/[^\w.\- ]/g, "_").trim();
2904
+ const base = path15.basename(raw).replace(/[^\w.\- ]/g, "_").trim();
2864
2905
  if (!base || base === "." || base === "..") return `upload-${Date.now()}`;
2865
2906
  return base.replace(/^\.+/, "") || `upload-${Date.now()}`;
2866
2907
  }
2867
2908
  async function uniquePath(dir, name) {
2868
- const ext = path14.extname(name);
2909
+ const ext = path15.extname(name);
2869
2910
  const stem = name.slice(0, name.length - ext.length);
2870
2911
  let candidate = name;
2871
2912
  let n = 1;
2872
2913
  while (true) {
2873
2914
  try {
2874
- await fs12.access(path14.join(dir, candidate));
2915
+ await fs13.access(path15.join(dir, candidate));
2875
2916
  candidate = `${stem} (${n++})${ext}`;
2876
2917
  } catch {
2877
- return path14.join(dir, candidate);
2918
+ return path15.join(dir, candidate);
2878
2919
  }
2879
2920
  }
2880
2921
  }
2881
2922
  function sha256File(absPath) {
2882
2923
  return new Promise((resolve, reject) => {
2883
- const hash = crypto4.createHash("sha256");
2924
+ const hash = crypto5.createHash("sha256");
2884
2925
  createReadStream3(absPath).on("data", (d) => hash.update(d)).on("end", () => resolve(hash.digest("hex"))).on("error", reject);
2885
2926
  });
2886
2927
  }
@@ -2894,7 +2935,7 @@ function fileType(absPath) {
2894
2935
  async function sampleStrings(absPath, limit = 40) {
2895
2936
  let fh;
2896
2937
  try {
2897
- fh = await fs12.open(absPath, "r");
2938
+ fh = await fs13.open(absPath, "r");
2898
2939
  const buf = Buffer.alloc(STRINGS_SCAN_BYTES);
2899
2940
  const { bytesRead } = await fh.read(buf, 0, STRINGS_SCAN_BYTES, 0);
2900
2941
  const out = [];
@@ -2932,7 +2973,7 @@ function registerUploadRoutes(app, manager) {
2932
2973
  return { error: "Invalid session id" };
2933
2974
  }
2934
2975
  const uploadDir = uploadDirFor(req.params.id);
2935
- await fs12.mkdir(uploadDir, { recursive: true, mode: 448 });
2976
+ await fs13.mkdir(uploadDir, { recursive: true, mode: 448 });
2936
2977
  const results = [];
2937
2978
  const parts = req.files();
2938
2979
  for await (const part of parts) {
@@ -2946,17 +2987,17 @@ function registerUploadRoutes(app, manager) {
2946
2987
  return { error: `Failed to store ${name}` };
2947
2988
  }
2948
2989
  if (part.file.truncated) {
2949
- await fs12.rm(dest, { force: true });
2990
+ await fs13.rm(dest, { force: true });
2950
2991
  reply.code(413);
2951
2992
  return {
2952
2993
  error: `${name} exceeds the max upload size (${Math.round(config.maxUploadBytes / 1024 / 1024)} MB)`
2953
2994
  };
2954
2995
  }
2955
- const stat = await fs12.stat(dest);
2956
- const ext = path14.extname(dest);
2996
+ const stat = await fs13.stat(dest);
2997
+ const ext = path15.extname(dest);
2957
2998
  const kind = classifyKind(dest);
2958
2999
  const uploaded = {
2959
- name: path14.basename(dest),
3000
+ name: path15.basename(dest),
2960
3001
  // Absolute, because the file sits outside the session's workspace: a
2961
3002
  // relative path would resolve against the wrong root for both the agent
2962
3003
  // and the image endpoint.
@@ -3103,7 +3144,7 @@ var init_dispatch = __esm({
3103
3144
  });
3104
3145
 
3105
3146
  // server/src/ws/dirWatchers.ts
3106
- import fs13 from "node:fs";
3147
+ import fs14 from "node:fs";
3107
3148
  function diffWatchSet(current, next) {
3108
3149
  const have = new Set(current);
3109
3150
  const want = new Set(next.slice(0, MAX_WATCHES));
@@ -3127,7 +3168,7 @@ function createDirWatchers(opts) {
3127
3168
  const target = await opts.resolve(relative);
3128
3169
  if (!target || closed) return;
3129
3170
  try {
3130
- const watcher = fs13.watch(target, { persistent: false }, () => {
3171
+ const watcher = fs14.watch(target, { persistent: false }, () => {
3131
3172
  const existing = timers.get(relative);
3132
3173
  if (existing) clearTimeout(existing);
3133
3174
  timers.set(
@@ -3193,7 +3234,7 @@ function registerWsGateway(app, manager) {
3193
3234
  return null;
3194
3235
  }
3195
3236
  },
3196
- onChange: (path17) => send(socket, { type: "fs_changed", path: path17 })
3237
+ onChange: (path18) => send(socket, { type: "fs_changed", path: path18 })
3197
3238
  });
3198
3239
  let alive = true;
3199
3240
  let ready = false;
@@ -3278,7 +3319,7 @@ var init_gateway = __esm({
3278
3319
  });
3279
3320
 
3280
3321
  // server/src/app.ts
3281
- import fs14 from "node:fs";
3322
+ import fs15 from "node:fs";
3282
3323
  import Fastify from "fastify";
3283
3324
  import cors from "@fastify/cors";
3284
3325
  import websocket from "@fastify/websocket";
@@ -3316,14 +3357,14 @@ async function buildApp() {
3316
3357
  registerWorkspaceRoutes(app, manager);
3317
3358
  registerUploadRoutes(app, manager);
3318
3359
  registerWsGateway(app, manager);
3319
- if (fs14.existsSync(config.webDist)) {
3360
+ if (fs15.existsSync(config.webDist)) {
3320
3361
  await app.register(fastifyStatic, {
3321
3362
  root: config.webDist
3322
3363
  });
3323
3364
  app.setNotFoundHandler((req, reply) => {
3324
- const path17 = req.url.split("?")[0] ?? "";
3325
- const looksLikeAsset = path17.startsWith("/assets/") || /\.[a-zA-Z0-9]+$/.test(path17);
3326
- if (path17.startsWith("/api/") || path17.startsWith("/ws") || looksLikeAsset) {
3365
+ const path18 = req.url.split("?")[0] ?? "";
3366
+ const looksLikeAsset = path18.startsWith("/assets/") || /\.[a-zA-Z0-9]+$/.test(path18);
3367
+ if (path18.startsWith("/api/") || path18.startsWith("/ws") || looksLikeAsset) {
3327
3368
  reply.code(404).send({ error: "Not found" });
3328
3369
  return;
3329
3370
  }
@@ -3397,15 +3438,15 @@ __export(doctor_exports, {
3397
3438
  mcpWiring: () => mcpWiring
3398
3439
  });
3399
3440
  import { execFileSync as execFileSync3 } from "node:child_process";
3400
- import fs15 from "node:fs";
3401
- import path15 from "node:path";
3441
+ import fs16 from "node:fs";
3442
+ import path16 from "node:path";
3402
3443
  function which(bin) {
3403
- if (bin.includes("/")) return fs15.existsSync(bin) ? bin : void 0;
3404
- for (const dir of (process.env.PATH ?? "").split(path15.delimiter)) {
3444
+ if (bin.includes("/")) return fs16.existsSync(bin) ? bin : void 0;
3445
+ for (const dir of (process.env.PATH ?? "").split(path16.delimiter)) {
3405
3446
  if (dir === "") continue;
3406
- const candidate = path15.join(dir, bin);
3447
+ const candidate = path16.join(dir, bin);
3407
3448
  try {
3408
- fs15.accessSync(candidate, fs15.constants.X_OK);
3449
+ fs16.accessSync(candidate, fs16.constants.X_OK);
3409
3450
  return candidate;
3410
3451
  } catch {
3411
3452
  }
@@ -3429,7 +3470,7 @@ function mcpWiring(agentJson, resolve) {
3429
3470
  return { ok: false, detail: `${command || "(no command)"} not found - widgets are unavailable` };
3430
3471
  }
3431
3472
  const script = args.find((a) => a.endsWith(".js"));
3432
- if (script && !fs15.existsSync(script)) {
3473
+ if (script && !fs16.existsSync(script)) {
3433
3474
  return { ok: false, detail: `${script} is gone - delete the agent file and restart to rewrite it` };
3434
3475
  }
3435
3476
  return { ok: true, detail: script ?? `${command} ${args.join(" ")}` };
@@ -3461,7 +3502,7 @@ function checks() {
3461
3502
  const settings = readSettings(config.configFile);
3462
3503
  const hasToken = typeof settings.token === "string" && settings.token !== "";
3463
3504
  out.push(
3464
- fs15.existsSync(config.configFile) ? {
3505
+ fs16.existsSync(config.configFile) ? {
3465
3506
  ok: hasToken,
3466
3507
  name: "settings",
3467
3508
  detail: hasToken ? `${config.configFile} (token set)` : `${config.configFile} exists but has no token - auth is DISABLED`
@@ -3471,8 +3512,8 @@ function checks() {
3471
3512
  detail: `${config.configFile} not found; a token is generated on first run`
3472
3513
  }
3473
3514
  );
3474
- if (fs15.existsSync(config.configFile)) {
3475
- const mode = fs15.statSync(config.configFile).mode & 511;
3515
+ if (fs16.existsSync(config.configFile)) {
3516
+ const mode = fs16.statSync(config.configFile).mode & 511;
3476
3517
  out.push({
3477
3518
  ok: mode === 384,
3478
3519
  name: "settings mode",
@@ -3480,10 +3521,10 @@ function checks() {
3480
3521
  });
3481
3522
  }
3482
3523
  try {
3483
- fs15.mkdirSync(config.casperDataDir, { recursive: true });
3484
- fs15.accessSync(config.casperDataDir, fs15.constants.W_OK);
3485
- const db2 = path15.join(config.casperDataDir, "casper.db");
3486
- const size = fs15.existsSync(db2) ? `, casper.db ${(fs15.statSync(db2).size / 1024).toFixed(0)} KB` : "";
3524
+ fs16.mkdirSync(config.casperDataDir, { recursive: true });
3525
+ fs16.accessSync(config.casperDataDir, fs16.constants.W_OK);
3526
+ const db2 = path16.join(config.casperDataDir, "casper.db");
3527
+ const size = fs16.existsSync(db2) ? `, casper.db ${(fs16.statSync(db2).size / 1024).toFixed(0)} KB` : "";
3487
3528
  out.push({ ok: true, name: "data dir", detail: `${config.casperDataDir} writable${size}` });
3488
3529
  } catch (err) {
3489
3530
  out.push({
@@ -3494,22 +3535,22 @@ function checks() {
3494
3535
  });
3495
3536
  }
3496
3537
  out.push(
3497
- fs15.existsSync(config.webDist) ? { ok: true, name: "web app", detail: config.webDist } : {
3538
+ fs16.existsSync(config.webDist) ? { ok: true, name: "web app", detail: config.webDist } : {
3498
3539
  ok: false,
3499
3540
  fatal: true,
3500
3541
  name: "web app",
3501
3542
  detail: `${config.webDist} not found - the package is incomplete or CASPER_WEB_DIST is wrong`
3502
3543
  }
3503
3544
  );
3504
- const agent = path15.join(config.kiroSessionsDir, "..", "..", "agents", "casper.json");
3505
- const hasAgent = fs15.existsSync(agent);
3545
+ const agent = path16.join(config.kiroSessionsDir, "..", "..", "agents", "casper.json");
3546
+ const hasAgent = fs16.existsSync(agent);
3506
3547
  out.push({
3507
3548
  ok: hasAgent,
3508
3549
  name: "casper agent",
3509
3550
  detail: hasAgent ? agent : `${agent} missing - it is installed on first run`
3510
3551
  });
3511
3552
  if (hasAgent) {
3512
- const wiring = mcpWiring(fs15.readFileSync(agent, "utf8"), which);
3553
+ const wiring = mcpWiring(fs16.readFileSync(agent, "utf8"), which);
3513
3554
  out.push({ ok: wiring.ok, name: "casper mcp", detail: wiring.detail });
3514
3555
  }
3515
3556
  return out;
@@ -3973,14 +4014,14 @@ var init_server2 = __esm({
3973
4014
  "server/src/mcp/server.ts"() {
3974
4015
  "use strict";
3975
4016
  init_protocol();
3976
- VERSION = true ? "0.8.6" : "dev";
4017
+ VERSION = true ? "0.8.8" : "dev";
3977
4018
  }
3978
4019
  });
3979
4020
 
3980
4021
  // server/src/cli/program.ts
3981
- import fs16 from "node:fs";
4022
+ import fs17 from "node:fs";
3982
4023
  import os4 from "node:os";
3983
- import path16 from "node:path";
4024
+ import path17 from "node:path";
3984
4025
 
3985
4026
  // server/node_modules/commander/lib/error.js
3986
4027
  var CommanderError = class extends Error {
@@ -7093,9 +7134,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
7093
7134
  * @param {string} [path]
7094
7135
  * @return {(string|null|Command)}
7095
7136
  */
7096
- executableDir(path17) {
7097
- if (path17 === void 0) return this._executableDir;
7098
- this._executableDir = path17;
7137
+ executableDir(path18) {
7138
+ if (path18 === void 0) return this._executableDir;
7139
+ this._executableDir = path18;
7099
7140
  return this;
7100
7141
  }
7101
7142
  /**
@@ -7353,7 +7394,7 @@ var program = new Command();
7353
7394
  // server/src/cli/program.ts
7354
7395
  init_paths();
7355
7396
  init_settings();
7356
- var VERSION2 = true ? "0.8.6" : "dev";
7397
+ var VERSION2 = true ? "0.8.8" : "dev";
7357
7398
  async function bootstrap() {
7358
7399
  const file = configFilePath();
7359
7400
  const settings = readSettings(file);
@@ -7399,8 +7440,8 @@ async function resetToken(value) {
7399
7440
  updateSettings(file, { token });
7400
7441
  process.stdout.write(`wrote a new token to ${file}
7401
7442
  `);
7402
- const dbFile = path16.join(dataDirPath(), "casper.db");
7403
- if (fs16.existsSync(dbFile)) {
7443
+ const dbFile = path17.join(dataDirPath(), "casper.db");
7444
+ if (fs17.existsSync(dbFile)) {
7404
7445
  const { LoginStore: LoginStore2 } = await Promise.resolve().then(() => (init_logins(), logins_exports));
7405
7446
  new LoginStore2().revokeAll();
7406
7447
  process.stdout.write("revoked all device sessions\n");