@mtreeai/msapling-cli 2.3.6-beta.24 → 2.3.6-beta.25

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 (2) hide show
  1. package/dist/index.js +304 -144
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -266,6 +266,43 @@ var init_src = __esm({
266
266
  body: JSON.stringify(symbol)
267
267
  });
268
268
  }
269
+ // CLI-MDRIVE-COMMANDS-01 (Iter 36): MDrive user-facing file CRUD. Per LAB
270
+ // routers/mdrive_files.py — all paths under /api/mdrive/ (assembled by
271
+ // mdrive_product.py).
272
+ async mdriveList(path2 = ".", limit = 1e3, offset = 0) {
273
+ const qs = new URLSearchParams({ path: path2, limit: String(limit), offset: String(offset) });
274
+ return await this.request(`/api/mdrive/list?${qs.toString()}`);
275
+ }
276
+ async mdriveRead(path2) {
277
+ return await this.request("/api/mdrive/read", {
278
+ method: "POST",
279
+ body: JSON.stringify({ path: path2 })
280
+ });
281
+ }
282
+ async mdriveWrite(path2, content) {
283
+ return await this.request("/api/mdrive/write", {
284
+ method: "POST",
285
+ body: JSON.stringify({ path: path2, content })
286
+ });
287
+ }
288
+ async mdriveDelete(path2) {
289
+ return await this.request("/api/mdrive/delete", {
290
+ method: "POST",
291
+ body: JSON.stringify({ path: path2 })
292
+ });
293
+ }
294
+ async mdriveRename(path2, newName) {
295
+ return await this.request("/api/mdrive/rename", {
296
+ method: "POST",
297
+ body: JSON.stringify({ path: path2, new_name: newName })
298
+ });
299
+ }
300
+ async mdriveMkdir(path2) {
301
+ return await this.request("/api/mdrive/mkdir", {
302
+ method: "POST",
303
+ body: JSON.stringify({ path: path2 })
304
+ });
305
+ }
269
306
  // CLI-OLLAMA-COMMANDS-01 (Iter 35): Ollama BYOK helpers. Per LAB ollama.py
270
307
  // routes are GET/POST/DELETE under /api/ollama. The CLI uses these to wire
271
308
  // up the user's local Ollama instance as a free-tier model provider.
@@ -1295,7 +1332,7 @@ var init_RunCommandTool = __esm({
1295
1332
  this.activeCommands++;
1296
1333
  return;
1297
1334
  }
1298
- return new Promise((resolve18) => this.queue.push(resolve18));
1335
+ return new Promise((resolve19) => this.queue.push(resolve19));
1299
1336
  }
1300
1337
  static releaseLock() {
1301
1338
  if (this.queue.length > 0) {
@@ -1374,9 +1411,9 @@ var init_RunCommandTool = __esm({
1374
1411
  const chunks = { stdout: [], stderr: [] };
1375
1412
  proc.stdout?.on("data", (chunk) => chunks.stdout.push(chunk));
1376
1413
  proc.stderr?.on("data", (chunk) => chunks.stderr.push(chunk));
1377
- const exitCode = await new Promise((resolve18) => {
1378
- proc.on("exit", (code) => resolve18(code ?? 1));
1379
- proc.on("error", () => resolve18(1));
1414
+ const exitCode = await new Promise((resolve19) => {
1415
+ proc.on("exit", (code) => resolve19(code ?? 1));
1416
+ proc.on("error", () => resolve19(1));
1380
1417
  });
1381
1418
  const stdout = Buffer.concat(chunks.stdout).toString("utf-8");
1382
1419
  const stderr = Buffer.concat(chunks.stderr).toString("utf-8");
@@ -1487,9 +1524,9 @@ var init_src2 = __esm({
1487
1524
  const messages = this.parser.parse(value);
1488
1525
  for (const msg of messages) {
1489
1526
  if (msg.id !== void 0 && this.pendingRequests.has(Number(msg.id))) {
1490
- const resolve18 = this.pendingRequests.get(Number(msg.id));
1491
- if (resolve18) {
1492
- resolve18(msg.result || msg.error);
1527
+ const resolve19 = this.pendingRequests.get(Number(msg.id));
1528
+ if (resolve19) {
1529
+ resolve19(msg.result || msg.error);
1493
1530
  this.pendingRequests.delete(Number(msg.id));
1494
1531
  }
1495
1532
  }
@@ -1504,8 +1541,8 @@ var init_src2 = __esm({
1504
1541
  const message = `Content-Length: ${Buffer.byteLength(content, "utf8")}\r
1505
1542
  \r
1506
1543
  ${content}`;
1507
- return new Promise((resolve18) => {
1508
- this.pendingRequests.set(id, resolve18);
1544
+ return new Promise((resolve19) => {
1545
+ this.pendingRequests.set(id, resolve19);
1509
1546
  this.process.stdin.write(message);
1510
1547
  this.process.stdin.flush();
1511
1548
  });
@@ -1637,9 +1674,9 @@ var init_SubShellTool = __esm({
1637
1674
  }
1638
1675
  throw e;
1639
1676
  }
1640
- await new Promise((resolve18) => {
1641
- proc.on("exit", () => resolve18());
1642
- proc.on("error", () => resolve18());
1677
+ await new Promise((resolve19) => {
1678
+ proc.on("exit", () => resolve19());
1679
+ proc.on("error", () => resolve19());
1643
1680
  });
1644
1681
  return { content: `Successfully launched separate window for ${args2.worker_id}` };
1645
1682
  }
@@ -1722,13 +1759,13 @@ async function findRg() {
1722
1759
  const candidates = ["rg", "C:\\Program Files\\ripgrep\\rg.exe"];
1723
1760
  for (const bin of candidates) {
1724
1761
  try {
1725
- const exited = await new Promise((resolve18) => {
1762
+ const exited = await new Promise((resolve19) => {
1726
1763
  try {
1727
1764
  const p = spawn4(bin, ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
1728
- p.on("error", () => resolve18(null));
1729
- p.on("exit", (code) => resolve18(code));
1765
+ p.on("error", () => resolve19(null));
1766
+ p.on("exit", (code) => resolve19(code));
1730
1767
  } catch {
1731
- resolve18(null);
1768
+ resolve19(null);
1732
1769
  }
1733
1770
  });
1734
1771
  if (exited === 0) return bin;
@@ -1738,7 +1775,7 @@ async function findRg() {
1738
1775
  return null;
1739
1776
  }
1740
1777
  function runRg(bin, args2) {
1741
- return new Promise((resolve18) => {
1778
+ return new Promise((resolve19) => {
1742
1779
  const p = spawn4(bin, args2, { stdio: ["ignore", "pipe", "pipe"] });
1743
1780
  let stdout = "";
1744
1781
  let stderr = "";
@@ -1749,10 +1786,10 @@ function runRg(bin, args2) {
1749
1786
  stderr += d.toString("utf8");
1750
1787
  });
1751
1788
  p.on("error", (e) => {
1752
- resolve18({ stdout, stderr: stderr + (e?.message ?? ""), exitCode: -1 });
1789
+ resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exitCode: -1 });
1753
1790
  });
1754
1791
  p.on("exit", (code) => {
1755
- resolve18({ stdout, stderr, exitCode: code });
1792
+ resolve19({ stdout, stderr, exitCode: code });
1756
1793
  });
1757
1794
  });
1758
1795
  }
@@ -3004,12 +3041,12 @@ Command: ${command}`,
3004
3041
  proc.stdout?.on("data", (chunk) => chunks.stdout.push(chunk));
3005
3042
  proc.stderr?.on("data", (chunk) => chunks.stderr.push(chunk));
3006
3043
  const timeoutPromise = new Promise(
3007
- (resolve18) => setTimeout(() => resolve18("timeout"), timeoutMs)
3044
+ (resolve19) => setTimeout(() => resolve19("timeout"), timeoutMs)
3008
3045
  );
3009
3046
  const processPromise = (async () => {
3010
- const exitCode2 = await new Promise((resolve18) => {
3011
- proc.on("exit", (code) => resolve18(code ?? 1));
3012
- proc.on("error", () => resolve18(1));
3047
+ const exitCode2 = await new Promise((resolve19) => {
3048
+ proc.on("exit", (code) => resolve19(code ?? 1));
3049
+ proc.on("error", () => resolve19(1));
3013
3050
  });
3014
3051
  const stdout2 = Buffer.concat(chunks.stdout).toString("utf-8");
3015
3052
  const stderr2 = Buffer.concat(chunks.stderr).toString("utf-8");
@@ -3756,7 +3793,7 @@ async function copyDir(src, dst) {
3756
3793
  }
3757
3794
  async function backupFile(absPath) {
3758
3795
  try {
3759
- const { readFile: readFile23, writeFile: writeFile12, mkdir: mkdir9 } = await import("fs/promises");
3796
+ const { readFile: readFile24, writeFile: writeFile13, mkdir: mkdir9 } = await import("fs/promises");
3760
3797
  const { homedir: homedir18 } = await import("os");
3761
3798
  const { join: join31 } = await import("path");
3762
3799
  const filename = absPath.split(/[\\/]/).pop() ?? "file";
@@ -3769,8 +3806,8 @@ async function backupFile(absPath) {
3769
3806
  `${filename}.backup-${stamp}-${suffix}.bak`
3770
3807
  );
3771
3808
  await mkdir9(join31(homedir18(), ".msapling", "backups"), { recursive: true });
3772
- const content = await readFile23(absPath, "utf8");
3773
- await writeFile12(backupPath, content, "utf8");
3809
+ const content = await readFile24(absPath, "utf8");
3810
+ await writeFile13(backupPath, content, "utf8");
3774
3811
  return backupPath;
3775
3812
  } catch {
3776
3813
  return null;
@@ -3995,15 +4032,15 @@ var init_DeleteFileTool = __esm({
3995
4032
  let backedUpTo = null;
3996
4033
  if (isFile) {
3997
4034
  try {
3998
- const { readFile: readFile23, writeFile: writeFile12, mkdir: mkdir9 } = await import("fs/promises");
4035
+ const { readFile: readFile24, writeFile: writeFile13, mkdir: mkdir9 } = await import("fs/promises");
3999
4036
  const { homedir: homedir18 } = await import("os");
4000
- const existingContent = await readFile23(abs, "utf8");
4037
+ const existingContent = await readFile24(abs, "utf8");
4001
4038
  const filename = abs.split(/[\\/]/).pop() ?? "file";
4002
4039
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4003
4040
  const suffix = randomBytes6(4).toString("hex");
4004
4041
  const backupPath = join11(homedir18(), ".msapling", "backups", `${filename}.backup-${stamp}-${suffix}.bak`);
4005
4042
  await mkdir9(join11(homedir18(), ".msapling", "backups"), { recursive: true });
4006
- await writeFile12(backupPath, existingContent, "utf8");
4043
+ await writeFile13(backupPath, existingContent, "utf8");
4007
4044
  backedUpTo = backupPath;
4008
4045
  } catch {
4009
4046
  }
@@ -4342,10 +4379,10 @@ var init_Voice = __esm({
4342
4379
  `;
4343
4380
  try {
4344
4381
  if (process.platform === "win32") {
4345
- await new Promise((resolve18, reject) => {
4382
+ await new Promise((resolve19, reject) => {
4346
4383
  try {
4347
4384
  const proc = spawn6("powershell", ["-Command", psCommand]);
4348
- proc.on("exit", () => resolve18());
4385
+ proc.on("exit", () => resolve19());
4349
4386
  proc.on("error", reject);
4350
4387
  } catch (e) {
4351
4388
  reject(e);
@@ -4459,7 +4496,7 @@ function matches(entry, ctx) {
4459
4496
  async function runOne(entry, ctx) {
4460
4497
  const timeoutMs = entry.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
4461
4498
  const command = entry.command;
4462
- return new Promise((resolve18) => {
4499
+ return new Promise((resolve19) => {
4463
4500
  const isWindows = process.platform === "win32";
4464
4501
  const child = spawn7(isWindows ? "cmd.exe" : "sh", isWindows ? ["/c", command] : ["-c", command], {
4465
4502
  cwd: ctx.cwd ?? process.cwd(),
@@ -4474,7 +4511,7 @@ async function runOne(entry, ctx) {
4474
4511
  settled = true;
4475
4512
  clearTimeout(killer);
4476
4513
  const blocked = !!entry.blocking && (exitCode === null || exitCode !== 0);
4477
- resolve18({ command, exitCode, stdout, stderr, timedOut, blocked });
4514
+ resolve19({ command, exitCode, stdout, stderr, timedOut, blocked });
4478
4515
  };
4479
4516
  const killer = setTimeout(() => {
4480
4517
  timedOut = true;
@@ -5339,8 +5376,8 @@ var init_Mutex = __esm({
5339
5376
  */
5340
5377
  acquire() {
5341
5378
  let release2;
5342
- const next = new Promise((resolve18) => {
5343
- release2 = resolve18;
5379
+ const next = new Promise((resolve19) => {
5380
+ release2 = resolve19;
5344
5381
  });
5345
5382
  const entry = this._queue.then(() => release2);
5346
5383
  this._queue = this._queue.then(() => next);
@@ -5980,8 +6017,8 @@ var require_graceful_fs = __commonJS({
5980
6017
  fs4.createReadStream = createReadStream;
5981
6018
  fs4.createWriteStream = createWriteStream;
5982
6019
  var fs$readFile = fs4.readFile;
5983
- fs4.readFile = readFile23;
5984
- function readFile23(path2, options, cb) {
6020
+ fs4.readFile = readFile24;
6021
+ function readFile24(path2, options, cb) {
5985
6022
  if (typeof options === "function")
5986
6023
  cb = options, options = null;
5987
6024
  return go$readFile(path2, options, cb);
@@ -5997,8 +6034,8 @@ var require_graceful_fs = __commonJS({
5997
6034
  }
5998
6035
  }
5999
6036
  var fs$writeFile = fs4.writeFile;
6000
- fs4.writeFile = writeFile12;
6001
- function writeFile12(path2, data, options, cb) {
6037
+ fs4.writeFile = writeFile13;
6038
+ function writeFile13(path2, data, options, cb) {
6002
6039
  if (typeof options === "function")
6003
6040
  cb = options, options = null;
6004
6041
  return go$writeFile(path2, data, options, cb);
@@ -7000,12 +7037,12 @@ var require_adapter = __commonJS({
7000
7037
  return newFs;
7001
7038
  }
7002
7039
  function toPromise(method) {
7003
- return (...args2) => new Promise((resolve18, reject) => {
7040
+ return (...args2) => new Promise((resolve19, reject) => {
7004
7041
  args2.push((err, result) => {
7005
7042
  if (err) {
7006
7043
  reject(err);
7007
7044
  } else {
7008
- resolve18(result);
7045
+ resolve19(result);
7009
7046
  }
7010
7047
  });
7011
7048
  method(...args2);
@@ -7933,7 +7970,7 @@ var init_client = __esm({
7933
7970
  if (!this.proc) throw new MCPClientError(`MCP server "${this.name}" not started`);
7934
7971
  const id = this.nextId++;
7935
7972
  const frame = { jsonrpc: "2.0", id, method, params };
7936
- return new Promise((resolve18, reject) => {
7973
+ return new Promise((resolve19, reject) => {
7937
7974
  const timer = setTimeout(() => {
7938
7975
  this.pending.delete(id);
7939
7976
  reject(new MCPClientError(`MCP request ${method} timed out after ${timeoutMs}ms`));
@@ -7941,7 +7978,7 @@ var init_client = __esm({
7941
7978
  this.pending.set(id, {
7942
7979
  resolve: (v) => {
7943
7980
  clearTimeout(timer);
7944
- resolve18(v);
7981
+ resolve19(v);
7945
7982
  },
7946
7983
  reject: (e) => {
7947
7984
  clearTimeout(timer);
@@ -7968,7 +8005,7 @@ var init_client = __esm({
7968
8005
  if (!this.proc?.stdout) return;
7969
8006
  const stdout = this.proc.stdout;
7970
8007
  const decoder = new TextDecoder();
7971
- return new Promise((resolve18) => {
8008
+ return new Promise((resolve19) => {
7972
8009
  stdout.on("data", (chunk) => {
7973
8010
  this.buffer += decoder.decode(chunk, { stream: true });
7974
8011
  let idx;
@@ -7979,8 +8016,8 @@ var init_client = __esm({
7979
8016
  this.handleFrame(line);
7980
8017
  }
7981
8018
  });
7982
- stdout.on("end", () => resolve18());
7983
- stdout.on("error", () => resolve18());
8019
+ stdout.on("end", () => resolve19());
8020
+ stdout.on("error", () => resolve19());
7984
8021
  });
7985
8022
  }
7986
8023
  handleFrame(line) {
@@ -8204,7 +8241,7 @@ function setRawModeGuarded(stdin, mode) {
8204
8241
  }
8205
8242
  }
8206
8243
  async function promptPassword(prompt4) {
8207
- return new Promise((resolve18) => {
8244
+ return new Promise((resolve19) => {
8208
8245
  const stdin = process.stdin;
8209
8246
  const stdout = process.stdout;
8210
8247
  stdout.write(prompt4);
@@ -8217,12 +8254,12 @@ async function promptPassword(prompt4) {
8217
8254
  setRawModeGuarded(stdin, wasRaw);
8218
8255
  stdin.removeListener("data", onData);
8219
8256
  stdout.write("\n");
8220
- resolve18(password);
8257
+ resolve19(password);
8221
8258
  } else if (char === "") {
8222
8259
  setRawModeGuarded(stdin, wasRaw);
8223
8260
  stdin.removeListener("data", onData);
8224
8261
  stdout.write("\n");
8225
- resolve18("");
8262
+ resolve19("");
8226
8263
  } else if (char === "\x7F" || char === "\b") {
8227
8264
  password = password.slice(0, -1);
8228
8265
  } else if (char >= " " && char <= "~") {
@@ -8301,7 +8338,7 @@ async function loginWithGithubDevice(context) {
8301
8338
  const deadline = Date.now() + expires_in * 1e3;
8302
8339
  let githubToken = null;
8303
8340
  while (Date.now() < deadline) {
8304
- await new Promise((resolve18) => setTimeout(resolve18, pollMs));
8341
+ await new Promise((resolve19) => setTimeout(resolve19, pollMs));
8305
8342
  let tokenResp;
8306
8343
  try {
8307
8344
  tokenResp = await fetch(GITHUB_TOKEN_URL, {
@@ -8325,7 +8362,7 @@ async function loginWithGithubDevice(context) {
8325
8362
  if (tokenData.error === "authorization_pending") continue;
8326
8363
  if (tokenData.error === "slow_down") {
8327
8364
  pollMs += 5e3;
8328
- await new Promise((resolve18) => setTimeout(resolve18, 5e3));
8365
+ await new Promise((resolve19) => setTimeout(resolve19, 5e3));
8329
8366
  continue;
8330
8367
  }
8331
8368
  context.addMessage("system", `GitHub auth error: ${tokenData.error_description || tokenData.error}`);
@@ -9150,6 +9187,127 @@ var init_memories = __esm({
9150
9187
  }
9151
9188
  });
9152
9189
 
9190
+ // src/commands/mdrive.ts
9191
+ import { readFile as readFile14, writeFile as writeFile7 } from "fs/promises";
9192
+ import { existsSync as existsSync15 } from "fs";
9193
+ import { basename, resolve as resolve14 } from "path";
9194
+ function formatBytes(b) {
9195
+ if (!b) return "0";
9196
+ if (b < 1024) return `${b}`;
9197
+ if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)}K`;
9198
+ return `${(b / 1024 / 1024).toFixed(1)}M`;
9199
+ }
9200
+ var mdriveCommand;
9201
+ var init_mdrive = __esm({
9202
+ "src/commands/mdrive.ts"() {
9203
+ "use strict";
9204
+ init_esm_shims();
9205
+ mdriveCommand = {
9206
+ name: "mdrive",
9207
+ args: "[ls|cat|put|get|rm|mv|mkdir] [...args]",
9208
+ description: "Browse and manage files on MSapling Drive (your AI-native context storage).",
9209
+ category: "project",
9210
+ handler: async (args2, context) => {
9211
+ const sub = (args2[0] ?? "ls").toLowerCase();
9212
+ const rest = args2.slice(1);
9213
+ try {
9214
+ if (sub === "ls" || sub === "list") {
9215
+ const path2 = rest[0] || ".";
9216
+ const res = await context.client.mdriveList(path2);
9217
+ const entries = res.entries ?? res.files ?? res.items ?? [];
9218
+ context.addMessage("system", `MDrive: ${path2} (${entries.length} entries)`);
9219
+ for (const e of entries) {
9220
+ const type = e.is_dir || e.type === "dir" ? "d" : "-";
9221
+ const size = e.size != null ? formatBytes(e.size).padStart(6) : " -";
9222
+ const name = e.name ?? e.path ?? "?";
9223
+ context.addMessage("system", ` ${type} ${size} ${name}`);
9224
+ }
9225
+ return;
9226
+ }
9227
+ if (sub === "cat" || sub === "read") {
9228
+ const p = rest[0];
9229
+ if (!p) {
9230
+ context.addMessage("system", "Usage: /mdrive cat <path>");
9231
+ return;
9232
+ }
9233
+ const res = await context.client.mdriveRead(p);
9234
+ context.addMessage("system", res.content ?? res.body ?? "(no content)");
9235
+ return;
9236
+ }
9237
+ if (sub === "put" || sub === "upload" || sub === "write") {
9238
+ const local = rest[0];
9239
+ const remote = rest[1] || (local ? basename(local) : "");
9240
+ if (!local || !remote) {
9241
+ context.addMessage("system", "Usage: /mdrive put <local> [<remote>]");
9242
+ return;
9243
+ }
9244
+ const absLocal = resolve14(local);
9245
+ if (!existsSync15(absLocal)) {
9246
+ context.addMessage("error", `Local file not found: ${absLocal}`);
9247
+ return;
9248
+ }
9249
+ const content = await readFile14(absLocal, "utf8");
9250
+ const res = await context.client.mdriveWrite(remote, content);
9251
+ context.addMessage("system", `Uploaded ${absLocal} \u2192 mdrive:${remote} (${formatBytes(content.length)}, hash=${res?.hash?.slice(0, 12) ?? "?"})`);
9252
+ return;
9253
+ }
9254
+ if (sub === "get" || sub === "download" || sub === "pull") {
9255
+ const remote = rest[0];
9256
+ const local = rest[1];
9257
+ if (!remote) {
9258
+ context.addMessage("system", "Usage: /mdrive get <remote> [<local>]");
9259
+ return;
9260
+ }
9261
+ const res = await context.client.mdriveRead(remote);
9262
+ const content = res.content ?? res.body ?? "";
9263
+ if (local) {
9264
+ await writeFile7(resolve14(local), content, "utf8");
9265
+ context.addMessage("system", `Wrote ${resolve14(local)} (${formatBytes(content.length)})`);
9266
+ } else {
9267
+ context.addMessage("system", content);
9268
+ }
9269
+ return;
9270
+ }
9271
+ if (sub === "rm" || sub === "delete" || sub === "del") {
9272
+ const p = rest[0];
9273
+ if (!p) {
9274
+ context.addMessage("system", "Usage: /mdrive rm <path>");
9275
+ return;
9276
+ }
9277
+ await context.client.mdriveDelete(p);
9278
+ context.addMessage("system", `Deleted mdrive:${p}`);
9279
+ return;
9280
+ }
9281
+ if (sub === "mv" || sub === "rename") {
9282
+ const p = rest[0];
9283
+ const newName = rest[1];
9284
+ if (!p || !newName) {
9285
+ context.addMessage("system", "Usage: /mdrive mv <path> <new-name>");
9286
+ return;
9287
+ }
9288
+ await context.client.mdriveRename(p, newName);
9289
+ context.addMessage("system", `Renamed mdrive:${p} \u2192 ${newName}`);
9290
+ return;
9291
+ }
9292
+ if (sub === "mkdir") {
9293
+ const p = rest[0];
9294
+ if (!p) {
9295
+ context.addMessage("system", "Usage: /mdrive mkdir <path>");
9296
+ return;
9297
+ }
9298
+ await context.client.mdriveMkdir(p);
9299
+ context.addMessage("system", `Created mdrive:${p}/`);
9300
+ return;
9301
+ }
9302
+ context.addMessage("error", `Unknown /mdrive subcommand '${sub}'. Try: ls, cat, put, get, rm, mv, mkdir.`);
9303
+ } catch (e) {
9304
+ context.addMessage("error", `MDrive: ${e.message}`);
9305
+ }
9306
+ }
9307
+ };
9308
+ }
9309
+ });
9310
+
9153
9311
  // src/commands/clear.ts
9154
9312
  var clearCommand;
9155
9313
  var init_clear = __esm({
@@ -9175,13 +9333,13 @@ var init_clear = __esm({
9175
9333
  // src/commands/mode.ts
9176
9334
  import { homedir as homedir10 } from "os";
9177
9335
  import { join as join17 } from "path";
9178
- import { existsSync as existsSync15 } from "fs";
9179
- import { readFile as readFile14, writeFile as writeFile7, mkdir as mkdir7 } from "fs/promises";
9336
+ import { existsSync as existsSync16 } from "fs";
9337
+ import { readFile as readFile15, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
9180
9338
  async function persistApprovalMode(mode, ttlMs) {
9181
9339
  try {
9182
9340
  let existing = {};
9183
- if (existsSync15(SETTINGS_PATH)) {
9184
- const text = await readFile14(SETTINGS_PATH, "utf8");
9341
+ if (existsSync16(SETTINGS_PATH)) {
9342
+ const text = await readFile15(SETTINGS_PATH, "utf8");
9185
9343
  if (text.trim()) {
9186
9344
  existing = JSON.parse(text);
9187
9345
  }
@@ -9193,10 +9351,10 @@ async function persistApprovalMode(mode, ttlMs) {
9193
9351
  };
9194
9352
  existing.approvalMode = entry;
9195
9353
  const settingsDir = join17(homedir10(), ".msapling");
9196
- if (!existsSync15(settingsDir)) {
9354
+ if (!existsSync16(settingsDir)) {
9197
9355
  await mkdir7(settingsDir, { recursive: true });
9198
9356
  }
9199
- await writeFile7(SETTINGS_PATH, JSON.stringify(existing, null, 2), "utf8");
9357
+ await writeFile8(SETTINGS_PATH, JSON.stringify(existing, null, 2), "utf8");
9200
9358
  } catch {
9201
9359
  }
9202
9360
  }
@@ -9581,8 +9739,8 @@ var init_compact = __esm({
9581
9739
 
9582
9740
  // src/commands/init.ts
9583
9741
  import { join as join18 } from "path";
9584
- import { existsSync as existsSync16 } from "fs";
9585
- import { writeFile as writeFile8 } from "fs/promises";
9742
+ import { existsSync as existsSync17 } from "fs";
9743
+ import { writeFile as writeFile9 } from "fs/promises";
9586
9744
  var initCommand;
9587
9745
  var init_init = __esm({
9588
9746
  "src/commands/init.ts"() {
@@ -9596,7 +9754,7 @@ var init_init = __esm({
9596
9754
  try {
9597
9755
  const cwd = process.cwd();
9598
9756
  const path2 = join18(cwd, "MSAPLING.md");
9599
- if (existsSync16(path2)) {
9757
+ if (existsSync17(path2)) {
9600
9758
  context.addMessage("error", "MSAPLING.md already exists in current directory.");
9601
9759
  return;
9602
9760
  }
@@ -9611,7 +9769,7 @@ var init_init = __esm({
9611
9769
  ## Guidelines
9612
9770
  - Follow existing code style.
9613
9771
  `;
9614
- await writeFile8(path2, content, "utf8");
9772
+ await writeFile9(path2, content, "utf8");
9615
9773
  context.addMessage("system", `Created MSAPLING.md at ${path2}`);
9616
9774
  } catch (e) {
9617
9775
  context.addMessage("error", `Failed to initialize project: ${e.message}`);
@@ -9622,8 +9780,8 @@ var init_init = __esm({
9622
9780
  });
9623
9781
 
9624
9782
  // src/commands/review.ts
9625
- import { existsSync as existsSync17 } from "fs";
9626
- import { readFile as readFile15 } from "fs/promises";
9783
+ import { existsSync as existsSync18 } from "fs";
9784
+ import { readFile as readFile16 } from "fs/promises";
9627
9785
  var reviewCommand;
9628
9786
  var init_review = __esm({
9629
9787
  "src/commands/review.ts"() {
@@ -9642,8 +9800,8 @@ var init_review = __esm({
9642
9800
  }
9643
9801
  let content = "";
9644
9802
  try {
9645
- if (existsSync17(target)) {
9646
- content = await readFile15(target, "utf8");
9803
+ if (existsSync18(target)) {
9804
+ content = await readFile16(target, "utf8");
9647
9805
  } else {
9648
9806
  content = `Review target: ${target}`;
9649
9807
  }
@@ -9736,15 +9894,15 @@ var init_swarm = __esm({
9736
9894
 
9737
9895
  // src/commands/recipe.ts
9738
9896
  import { parse as parseYaml } from "yaml";
9739
- import { existsSync as existsSync18 } from "fs";
9740
- import { readFile as readFile16 } from "fs/promises";
9897
+ import { existsSync as existsSync19 } from "fs";
9898
+ import { readFile as readFile17 } from "fs/promises";
9741
9899
  import { join as join19 } from "path";
9742
9900
  function findRecipe(name, cwd) {
9743
9901
  for (const dir of RECIPE_DIRS) {
9744
9902
  for (const suffix of NAME_SUFFIXES) {
9745
9903
  for (const ext of FILE_EXTS) {
9746
9904
  const p = join19(cwd, dir, `${name}${suffix}${ext}`);
9747
- if (existsSync18(p)) return p;
9905
+ if (existsSync19(p)) return p;
9748
9906
  }
9749
9907
  }
9750
9908
  }
@@ -9803,7 +9961,7 @@ var init_recipe = __esm({
9803
9961
  let text;
9804
9962
  let recipe;
9805
9963
  try {
9806
- text = await readFile16(path2, "utf8");
9964
+ text = await readFile17(path2, "utf8");
9807
9965
  recipe = parseYaml(text);
9808
9966
  } catch (e) {
9809
9967
  context.addMessage("error", `Failed to load ${path2}: ${e.message}`);
@@ -9857,13 +10015,13 @@ ${rendered}` : rendered;
9857
10015
  });
9858
10016
 
9859
10017
  // src/commands/skill.ts
9860
- import { existsSync as existsSync19, readdirSync as readdirSync2, statSync as statSync5 } from "fs";
9861
- import { readFile as readFile17 } from "fs/promises";
9862
- import { join as join20, resolve as resolve14 } from "path";
10018
+ import { existsSync as existsSync20, readdirSync as readdirSync2, statSync as statSync5 } from "fs";
10019
+ import { readFile as readFile18 } from "fs/promises";
10020
+ import { join as join20, resolve as resolve15 } from "path";
9863
10021
  function findSkillsRoot(cwd) {
9864
10022
  for (const candidate of SKILLS_DIRS) {
9865
- const full = resolve14(cwd, candidate);
9866
- if (existsSync19(full) && statSync5(full).isDirectory()) return full;
10023
+ const full = resolve15(cwd, candidate);
10024
+ if (existsSync20(full) && statSync5(full).isDirectory()) return full;
9867
10025
  }
9868
10026
  return null;
9869
10027
  }
@@ -9957,7 +10115,7 @@ var init_skill = __esm({
9957
10115
  }
9958
10116
  let body;
9959
10117
  try {
9960
- body = await readFile17(skill.path, "utf8");
10118
+ body = await readFile18(skill.path, "utf8");
9961
10119
  } catch (e) {
9962
10120
  context.addMessage("error", `Failed to load skill ${skill.path}: ${e.message}`);
9963
10121
  return;
@@ -10353,21 +10511,21 @@ var init_theme = __esm({
10353
10511
  // src/commands/theme.ts
10354
10512
  import { join as join22 } from "path";
10355
10513
  import { homedir as homedir12 } from "os";
10356
- import { existsSync as existsSync20 } from "fs";
10357
- import { readFile as readFile18, writeFile as writeFile9 } from "fs/promises";
10514
+ import { existsSync as existsSync21 } from "fs";
10515
+ import { readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
10358
10516
  async function persistTheme(storage, themeName) {
10359
10517
  const settingsPath = join22(homedir12(), ".msapling", "settings.json");
10360
10518
  let existing = {};
10361
10519
  try {
10362
- if (existsSync20(settingsPath)) {
10363
- const text = await readFile18(settingsPath, "utf8");
10520
+ if (existsSync21(settingsPath)) {
10521
+ const text = await readFile19(settingsPath, "utf8");
10364
10522
  if (text.trim()) existing = JSON.parse(text);
10365
10523
  }
10366
10524
  } catch {
10367
10525
  }
10368
10526
  existing["theme"] = themeName;
10369
10527
  ensureConfigDir(join22(homedir12(), ".msapling"));
10370
- await writeFile9(settingsPath, JSON.stringify(existing, null, 2), "utf8");
10528
+ await writeFile10(settingsPath, JSON.stringify(existing, null, 2), "utf8");
10371
10529
  }
10372
10530
  var VALID_THEMES, themeCommand;
10373
10531
  var init_theme2 = __esm({
@@ -10438,7 +10596,7 @@ var init_version = __esm({
10438
10596
  description: "Show version information for CLI and core packages",
10439
10597
  category: "debug",
10440
10598
  handler: async (_args, context) => {
10441
- const cliVersion = true ? "2.3.6-beta.24" : "(dev)";
10599
+ const cliVersion = true ? "2.3.6-beta.25" : "(dev)";
10442
10600
  const coreVersion = true ? "2.3.2" : "(dev)";
10443
10601
  const runtime = process.version;
10444
10602
  context.addMessage("system", "MSapling Version Info");
@@ -10447,7 +10605,7 @@ var init_version = __esm({
10447
10605
  context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
10448
10606
  context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
10449
10607
  try {
10450
- const ts = "2026-05-28T19:31:59.228Z";
10608
+ const ts = "2026-05-28T19:45:02.204Z";
10451
10609
  if (ts && ts !== "__BUILD_TIMESTAMP__") {
10452
10610
  context.addMessage("system", row2("Build Timestamp", ts));
10453
10611
  }
@@ -10461,14 +10619,14 @@ var init_version = __esm({
10461
10619
 
10462
10620
  // src/commands/feedback.ts
10463
10621
  import { join as join23 } from "path";
10464
- import { existsSync as existsSync21 } from "fs";
10465
- import { readFile as readFile19 } from "fs/promises";
10622
+ import { existsSync as existsSync22 } from "fs";
10623
+ import { readFile as readFile20 } from "fs/promises";
10466
10624
  async function readCliVersion() {
10467
10625
  try {
10468
10626
  const baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
10469
10627
  const pkgPath = join23(baseDir, "..", "..", "package.json");
10470
- if (!existsSync21(pkgPath)) return "unknown";
10471
- const text = await readFile19(pkgPath, "utf8");
10628
+ if (!existsSync22(pkgPath)) return "unknown";
10629
+ const text = await readFile20(pkgPath, "utf8");
10472
10630
  const json = JSON.parse(text);
10473
10631
  return json.version ?? "unknown";
10474
10632
  } catch {
@@ -10510,7 +10668,7 @@ var init_feedback = __esm({
10510
10668
  // src/commands/export.ts
10511
10669
  import { homedir as homedir13 } from "os";
10512
10670
  import { join as join24 } from "path";
10513
- import { writeFile as writeFile10, mkdir as mkdir8 } from "fs/promises";
10671
+ import { writeFile as writeFile11, mkdir as mkdir8 } from "fs/promises";
10514
10672
  function formatTimestamp(date) {
10515
10673
  return date.toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
10516
10674
  }
@@ -10576,7 +10734,7 @@ var init_export = __esm({
10576
10734
  try {
10577
10735
  const dir = join24(outputPath, "..");
10578
10736
  await mkdir8(dir, { recursive: true });
10579
- await writeFile10(outputPath, content, "utf8");
10737
+ await writeFile11(outputPath, content, "utf8");
10580
10738
  context.addMessage("system", `Exported to: ${outputPath}`);
10581
10739
  } catch (e) {
10582
10740
  context.addMessage("error", `Failed to export: ${e.message}`);
@@ -10771,15 +10929,15 @@ var init_plan = __esm({
10771
10929
  // src/commands/note.ts
10772
10930
  import { homedir as homedir14 } from "os";
10773
10931
  import { join as join25 } from "path";
10774
- import { existsSync as existsSync22 } from "fs";
10775
- import { readFile as readFile20, writeFile as writeFile11 } from "fs/promises";
10932
+ import { existsSync as existsSync23 } from "fs";
10933
+ import { readFile as readFile21, writeFile as writeFile12 } from "fs/promises";
10776
10934
  function getNotesFilePath() {
10777
10935
  return join25(homedir14(), ".msapling", "notes.json");
10778
10936
  }
10779
10937
  async function readNotes(filePath = getNotesFilePath()) {
10780
10938
  try {
10781
- if (!existsSync22(filePath)) return [];
10782
- const raw = await readFile20(filePath, "utf8");
10939
+ if (!existsSync23(filePath)) return [];
10940
+ const raw = await readFile21(filePath, "utf8");
10783
10941
  const parsed = JSON.parse(raw);
10784
10942
  if (!Array.isArray(parsed)) return [];
10785
10943
  return parsed;
@@ -10790,7 +10948,7 @@ async function readNotes(filePath = getNotesFilePath()) {
10790
10948
  async function writeNotes(notes, filePath = getNotesFilePath()) {
10791
10949
  const dir = join25(homedir14(), ".msapling");
10792
10950
  ensureConfigDir(dir);
10793
- await writeFile11(filePath, JSON.stringify(notes, null, 2), "utf8");
10951
+ await writeFile12(filePath, JSON.stringify(notes, null, 2), "utf8");
10794
10952
  }
10795
10953
  function formatTimestamp2(iso) {
10796
10954
  const d = new Date(iso);
@@ -10935,8 +11093,8 @@ var init_todo = __esm({
10935
11093
 
10936
11094
  // src/commands/outputStyle.ts
10937
11095
  import { homedir as homedir15 } from "os";
10938
- import { join as join26, basename, extname as extname3 } from "path";
10939
- import { existsSync as existsSync23, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync, writeFileSync as writeFileSync2 } from "fs";
11096
+ import { join as join26, basename as basename2, extname as extname3 } from "path";
11097
+ import { existsSync as existsSync24, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync, writeFileSync as writeFileSync2 } from "fs";
10940
11098
  function stylesDir() {
10941
11099
  return join26(homedir15(), ".msapling", "output-styles");
10942
11100
  }
@@ -10962,7 +11120,7 @@ function parseStyleFile(text) {
10962
11120
  }
10963
11121
  function listUserStyles() {
10964
11122
  const dir = stylesDir();
10965
- if (!existsSync23(dir)) return [];
11123
+ if (!existsSync24(dir)) return [];
10966
11124
  const out = [];
10967
11125
  for (const entry of readdirSync3(dir)) {
10968
11126
  if (extname3(entry).toLowerCase() !== ".md") continue;
@@ -10971,7 +11129,7 @@ function listUserStyles() {
10971
11129
  const text = readFileSync(full, "utf8");
10972
11130
  const { description, body } = parseStyleFile(text);
10973
11131
  out.push({
10974
- name: basename(entry, ".md"),
11132
+ name: basename2(entry, ".md"),
10975
11133
  description,
10976
11134
  body,
10977
11135
  source: "user",
@@ -10994,7 +11152,7 @@ function findStyle(name) {
10994
11152
  function getActiveStyleName() {
10995
11153
  try {
10996
11154
  const f = activeFile();
10997
- if (!existsSync23(f)) return "default";
11155
+ if (!existsSync24(f)) return "default";
10998
11156
  return readFileSync(f, "utf8").trim() || "default";
10999
11157
  } catch {
11000
11158
  return "default";
@@ -11002,7 +11160,7 @@ function getActiveStyleName() {
11002
11160
  }
11003
11161
  function setActiveStyleName(name) {
11004
11162
  const dir = stylesDir();
11005
- if (!existsSync23(dir)) mkdirSync5(dir, { recursive: true });
11163
+ if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
11006
11164
  writeFileSync2(activeFile(), `${name}
11007
11165
  `, "utf8");
11008
11166
  }
@@ -11015,7 +11173,7 @@ function createUserStyle(name, description, body) {
11015
11173
  throw new Error(`Invalid style name "${name}" \u2014 use letters, digits, _ and - only.`);
11016
11174
  }
11017
11175
  const dir = stylesDir();
11018
- if (!existsSync23(dir)) mkdirSync5(dir, { recursive: true });
11176
+ if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
11019
11177
  const target = join26(dir, `${name}.md`);
11020
11178
  const frontmatter = `---
11021
11179
  description: ${description.replace(/\n/g, " ")}
@@ -11190,6 +11348,7 @@ var init_commands = __esm({
11190
11348
  init_ollama();
11191
11349
  init_keys();
11192
11350
  init_memories();
11351
+ init_mdrive();
11193
11352
  init_clear();
11194
11353
  init_mode();
11195
11354
  init_model();
@@ -11229,6 +11388,7 @@ var init_commands = __esm({
11229
11388
  ollamaCommand,
11230
11389
  keysCommand,
11231
11390
  memoriesCommand,
11391
+ mdriveCommand,
11232
11392
  clearCommand,
11233
11393
  modeCommand,
11234
11394
  modelCommand,
@@ -11325,16 +11485,16 @@ var exec_exports = {};
11325
11485
  __export(exec_exports, {
11326
11486
  runExec: () => runExec
11327
11487
  });
11328
- import { existsSync as existsSync25 } from "fs";
11329
- import { readFile as readFile22 } from "fs/promises";
11488
+ import { existsSync as existsSync26 } from "fs";
11489
+ import { readFile as readFile23 } from "fs/promises";
11330
11490
  import { homedir as homedir16 } from "os";
11331
11491
  import { join as join27 } from "path";
11332
11492
  async function loadPersistedSettings() {
11333
11493
  const out = { mode: "default", theme: null };
11334
11494
  try {
11335
11495
  const p = join27(homedir16(), ".msapling", "settings.json");
11336
- if (!existsSync25(p)) return out;
11337
- const raw = JSON.parse(await readFile22(p, "utf8"));
11496
+ if (!existsSync26(p)) return out;
11497
+ const raw = JSON.parse(await readFile23(p, "utf8"));
11338
11498
  const parsed = parseApprovalMode(raw, Date.now());
11339
11499
  if (parsed.kind === "ok") out.mode = parsed.mode;
11340
11500
  const themeRaw = raw?.theme;
@@ -11584,13 +11744,13 @@ async function openBrowser(url) {
11584
11744
  cmd = "xdg-open";
11585
11745
  args2 = [url];
11586
11746
  }
11587
- return new Promise((resolve18) => {
11747
+ return new Promise((resolve19) => {
11588
11748
  try {
11589
11749
  const child = spawn10(cmd, args2, { stdio: "ignore", detached: true });
11590
11750
  child.unref();
11591
11751
  } catch {
11592
11752
  }
11593
- resolve18();
11753
+ resolve19();
11594
11754
  });
11595
11755
  }
11596
11756
  var init_open_browser = __esm({
@@ -11680,7 +11840,7 @@ var init_checkout = __esm({
11680
11840
  // src/commands/billing/sub.ts
11681
11841
  import * as readline from "readline";
11682
11842
  function prompt(rl, question) {
11683
- return new Promise((resolve18) => rl.question(question, resolve18));
11843
+ return new Promise((resolve19) => rl.question(question, resolve19));
11684
11844
  }
11685
11845
  async function runSub(argv) {
11686
11846
  const subCmd = argv[0] ?? "";
@@ -11809,11 +11969,11 @@ var init_sub = __esm({
11809
11969
  // src/commands/billing/topup.ts
11810
11970
  import * as readline2 from "readline";
11811
11971
  function prompt2(rl, question) {
11812
- return new Promise((resolve18) => rl.question(question, resolve18));
11972
+ return new Promise((resolve19) => rl.question(question, resolve19));
11813
11973
  }
11814
11974
  function promptDefault(rl, question, defaultVal) {
11815
11975
  return new Promise(
11816
- (resolve18) => rl.question(`${question} [${defaultVal}]: `, (ans) => resolve18(ans.trim() || defaultVal))
11976
+ (resolve19) => rl.question(`${question} [${defaultVal}]: `, (ans) => resolve19(ans.trim() || defaultVal))
11817
11977
  );
11818
11978
  }
11819
11979
  async function runTopup(argv) {
@@ -11954,7 +12114,7 @@ var init_redeem = __esm({
11954
12114
  // src/commands/billing/gift.ts
11955
12115
  import * as readline3 from "readline";
11956
12116
  function prompt3(rl, question) {
11957
- return new Promise((resolve18) => rl.question(question, resolve18));
12117
+ return new Promise((resolve19) => rl.question(question, resolve19));
11958
12118
  }
11959
12119
  async function runGift(argv) {
11960
12120
  const subCmd = argv[0] ?? "";
@@ -12211,7 +12371,7 @@ __export(doctor_exports, {
12211
12371
  });
12212
12372
  import { homedir as homedir17, platform as platform3 } from "os";
12213
12373
  import { join as join28 } from "path";
12214
- import { existsSync as existsSync26, statSync as statSync6, accessSync } from "fs";
12374
+ import { existsSync as existsSync27, statSync as statSync6, accessSync } from "fs";
12215
12375
  import { readdir as readdir3 } from "fs/promises";
12216
12376
  import { exec } from "child_process";
12217
12377
  import { promisify } from "util";
@@ -12235,7 +12395,7 @@ async function checkNodeVersion() {
12235
12395
  }
12236
12396
  async function checkConfigDir() {
12237
12397
  const configDir = join28(homedir17(), ".msapling");
12238
- if (!existsSync26(configDir)) {
12398
+ if (!existsSync27(configDir)) {
12239
12399
  return {
12240
12400
  name: "Config directory",
12241
12401
  status: "WARN",
@@ -12301,7 +12461,7 @@ async function checkPathConflicts() {
12301
12461
  const paths = pathEnv.split(platform3() === "win32" ? ";" : ":");
12302
12462
  const conflicts = [];
12303
12463
  for (const dir of paths) {
12304
- if (!dir || !existsSync26(dir)) continue;
12464
+ if (!dir || !existsSync27(dir)) continue;
12305
12465
  try {
12306
12466
  const files = await readdir3(dir);
12307
12467
  for (const file of files) {
@@ -13723,16 +13883,16 @@ var init_registry_merger = __esm({
13723
13883
  // ../core/src/mcp/local_tools.ts
13724
13884
  import { spawn as spawn11 } from "child_process";
13725
13885
  import { readdir as readdir4, stat as stat4, realpath as realpath2 } from "fs/promises";
13726
- import { resolve as resolve16 } from "path";
13886
+ import { resolve as resolve17 } from "path";
13727
13887
  function asResult(text, isError = false) {
13728
13888
  return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
13729
13889
  }
13730
13890
  async function runCommand(command, cwd) {
13731
- return new Promise((resolve18) => {
13891
+ return new Promise((resolve19) => {
13732
13892
  let p;
13733
13893
  const timeout = setTimeout(() => {
13734
13894
  if (p) p.kill();
13735
- resolve18({ stdout: "", stderr: "Command timed out after 30s", exit_code: -1 });
13895
+ resolve19({ stdout: "", stderr: "Command timed out after 30s", exit_code: -1 });
13736
13896
  }, 3e4);
13737
13897
  try {
13738
13898
  p = spawn11("sh", ["-c", command], {
@@ -13750,15 +13910,15 @@ async function runCommand(command, cwd) {
13750
13910
  });
13751
13911
  p.on("error", (e) => {
13752
13912
  clearTimeout(timeout);
13753
- resolve18({ stdout, stderr: stderr + (e?.message ?? ""), exit_code: -1 });
13913
+ resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exit_code: -1 });
13754
13914
  });
13755
13915
  p.on("exit", (code) => {
13756
13916
  clearTimeout(timeout);
13757
- resolve18({ stdout, stderr, exit_code: code });
13917
+ resolve19({ stdout, stderr, exit_code: code });
13758
13918
  });
13759
13919
  } catch (e) {
13760
13920
  clearTimeout(timeout);
13761
- resolve18({
13921
+ resolve19({
13762
13922
  stdout: "",
13763
13923
  stderr: e?.message ?? "Failed to spawn process",
13764
13924
  exit_code: -1
@@ -13825,7 +13985,7 @@ async function callLocalTool(name, args2, projectRoot) {
13825
13985
  const command = String(args2.command ?? "");
13826
13986
  let cwd = projectRoot;
13827
13987
  if (args2.cwd) {
13828
- cwd = resolve16(projectRoot, String(args2.cwd));
13988
+ cwd = resolve17(projectRoot, String(args2.cwd));
13829
13989
  try {
13830
13990
  const resolvedCwd = await realpath2(cwd);
13831
13991
  const resolvedRoot = await realpath2(projectRoot);
@@ -13862,7 +14022,7 @@ ${res.stderr}`
13862
14022
  return asResult("path is required", true);
13863
14023
  }
13864
14024
  try {
13865
- const resolvedPath = await realpath2(resolve16(projectRoot, pathArg));
14025
+ const resolvedPath = await realpath2(resolve17(projectRoot, pathArg));
13866
14026
  const resolvedRoot = await realpath2(projectRoot);
13867
14027
  if (!resolvedPath.startsWith(resolvedRoot)) {
13868
14028
  return asResult("Error: path attempts to escape project root", true);
@@ -13881,7 +14041,7 @@ ${res.stderr}`
13881
14041
  }
13882
14042
  case "local_glob": {
13883
14043
  const pattern = String(args2.pattern ?? "");
13884
- let cwd = args2.cwd ? resolve16(projectRoot, String(args2.cwd)) : projectRoot;
14044
+ let cwd = args2.cwd ? resolve17(projectRoot, String(args2.cwd)) : projectRoot;
13885
14045
  if (!pattern) {
13886
14046
  return asResult("pattern is required", true);
13887
14047
  }
@@ -13910,7 +14070,7 @@ ${res.stderr}`
13910
14070
  }
13911
14071
  if (path2) {
13912
14072
  try {
13913
- const resolvedPath = await realpath2(resolve16(projectRoot, path2));
14073
+ const resolvedPath = await realpath2(resolve17(projectRoot, path2));
13914
14074
  const resolvedRoot = await realpath2(projectRoot);
13915
14075
  if (!resolvedPath.startsWith(resolvedRoot)) {
13916
14076
  return asResult("Error: path attempts to escape project root", true);
@@ -13930,7 +14090,7 @@ ${res.stderr}`
13930
14090
  return asResult("cwd is required", true);
13931
14091
  }
13932
14092
  try {
13933
- const resolvedCwd = await realpath2(resolve16(projectRoot, cwdArg));
14093
+ const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
13934
14094
  const resolvedRoot = await realpath2(projectRoot);
13935
14095
  if (!resolvedCwd.startsWith(resolvedRoot)) {
13936
14096
  return asResult("Error: cwd attempts to escape project root", true);
@@ -13956,7 +14116,7 @@ ${status.porcelain || "(clean)"}`
13956
14116
  return asResult("cwd is required", true);
13957
14117
  }
13958
14118
  try {
13959
- const resolvedCwd = await realpath2(resolve16(projectRoot, cwdArg));
14119
+ const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
13960
14120
  const resolvedRoot = await realpath2(projectRoot);
13961
14121
  if (!resolvedCwd.startsWith(resolvedRoot)) {
13962
14122
  return asResult("Error: cwd attempts to escape project root", true);
@@ -14072,7 +14232,7 @@ __export(server_exports, {
14072
14232
  runStdioWithRegistry: () => runStdioWithRegistry
14073
14233
  });
14074
14234
  import { readdirSync as readdirSync4, readFileSync as readFileSync2, statSync as statSync7 } from "fs";
14075
- import { join as join29, relative as relative14, resolve as resolve17 } from "path";
14235
+ import { join as join29, relative as relative14, resolve as resolve18 } from "path";
14076
14236
  function asResult2(text, isError = false) {
14077
14237
  return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
14078
14238
  }
@@ -14430,13 +14590,13 @@ var init_server = __esm({
14430
14590
  if (inflight === 0) {
14431
14591
  return [];
14432
14592
  }
14433
- const forcedResponses = await new Promise((resolve18) => {
14434
- this._drainResolve = () => resolve18([]);
14593
+ const forcedResponses = await new Promise((resolve19) => {
14594
+ this._drainResolve = () => resolve19([]);
14435
14595
  setTimeout(() => {
14436
14596
  this._drainResolve = null;
14437
14597
  const remaining = Array.from(this._inflightCalls.values());
14438
14598
  if (remaining.length === 0) {
14439
- resolve18([]);
14599
+ resolve19([]);
14440
14600
  return;
14441
14601
  }
14442
14602
  process.stderr.write(
@@ -14452,7 +14612,7 @@ var init_server = __esm({
14452
14612
  }
14453
14613
  }));
14454
14614
  this._inflightCalls.clear();
14455
- resolve18(errorResponses);
14615
+ resolve19(errorResponses);
14456
14616
  }, DRAIN_TIMEOUT_MS);
14457
14617
  });
14458
14618
  return forcedResponses;
@@ -14730,7 +14890,7 @@ ${r.response ?? ""}`;
14730
14890
  return asResult2(JSON.stringify(result));
14731
14891
  }
14732
14892
  case "msapling_project_context": {
14733
- const root = resolve17(String(args2.path ?? "."));
14893
+ const root = resolve18(String(args2.path ?? "."));
14734
14894
  const maxFiles = Number.isFinite(args2.max_files) ? Number(args2.max_files) : 30;
14735
14895
  const maxKB = Number.isFinite(args2.max_file_size_kb) ? Number(args2.max_file_size_kb) : 50;
14736
14896
  const files = buildFileTree(root, maxFiles);
@@ -14858,7 +15018,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
14858
15018
  var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
14859
15019
  /* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
14860
15020
  "\u25CF MSapling CLI v",
14861
- "2.3.6-beta.24"
15021
+ "2.3.6-beta.25"
14862
15022
  ] }),
14863
15023
  /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
14864
15024
  ] });
@@ -15352,9 +15512,9 @@ ${prompt4}` : prompt4;
15352
15512
  if (proc.stderr) proc.stderr.on("data", (chunk) => {
15353
15513
  stderr += chunk.toString();
15354
15514
  });
15355
- await new Promise((resolve18, reject) => {
15515
+ await new Promise((resolve19, reject) => {
15356
15516
  proc.on("close", (code) => {
15357
- if (code === 0 || code === null) resolve18();
15517
+ if (code === 0 || code === null) resolve19();
15358
15518
  else reject(new Error(`Process exited with code ${code}`));
15359
15519
  });
15360
15520
  proc.on("error", reject);
@@ -15381,10 +15541,10 @@ ${prompt4}` : prompt4;
15381
15541
  for (const mention of fileMentions) {
15382
15542
  const filePath = mention.slice(1);
15383
15543
  try {
15384
- const { existsSync: existsSync27 } = await import("fs");
15385
- const { readFile: readFile23 } = await import("fs/promises");
15386
- if (existsSync27(filePath)) {
15387
- const content = await readFile23(filePath, "utf8");
15544
+ const { existsSync: existsSync28 } = await import("fs");
15545
+ const { readFile: readFile24 } = await import("fs/promises");
15546
+ if (existsSync28(filePath)) {
15547
+ const content = await readFile24(filePath, "utf8");
15388
15548
  const MAX_LEN = 32768;
15389
15549
  const truncated = content.length > MAX_LEN ? content.slice(0, MAX_LEN) + "\n...[TRUNCATED]" : content;
15390
15550
  finalCmd += `
@@ -15436,8 +15596,8 @@ ${finalCmd}`;
15436
15596
  init_esm_shims();
15437
15597
  init_src3();
15438
15598
  init_parseApprovalMode();
15439
- import { readFile as readFile21 } from "fs/promises";
15440
- import { existsSync as existsSync24 } from "fs";
15599
+ import { readFile as readFile22 } from "fs/promises";
15600
+ import { existsSync as existsSync25 } from "fs";
15441
15601
  async function initSession(ctx) {
15442
15602
  try {
15443
15603
  const { settings } = await loadSettings(
@@ -15454,8 +15614,8 @@ async function initSession(ctx) {
15454
15614
  const { homedir: homedir18 } = await import("os");
15455
15615
  const { join: join31 } = await import("path");
15456
15616
  const userSettingsPath = join31(homedir18(), ".msapling", "settings.json");
15457
- if (existsSync24(userSettingsPath)) {
15458
- const userText = await readFile21(userSettingsPath, "utf8");
15617
+ if (existsSync25(userSettingsPath)) {
15618
+ const userText = await readFile22(userSettingsPath, "utf8");
15459
15619
  let parsed;
15460
15620
  try {
15461
15621
  parsed = JSON.parse(userText);
@@ -15555,8 +15715,8 @@ var App = ({ compact: compact2 = false }) => {
15555
15715
  const storage = useRef(new StorageManager()).current;
15556
15716
  const client = useRef(new MSaplingClient()).current;
15557
15717
  const requestApproval = useCallback((request) => {
15558
- return new Promise((resolve18) => {
15559
- setPendingApproval({ request, resolve: resolve18 });
15718
+ return new Promise((resolve19) => {
15719
+ setPendingApproval({ request, resolve: resolve19 });
15560
15720
  });
15561
15721
  }, []);
15562
15722
  const agent = useRef(new Agent(client, process.cwd(), requestApproval)).current;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mtreeai/msapling-cli",
3
- "version": "2.3.6-beta.24",
3
+ "version": "2.3.6-beta.25",
4
4
  "description": "MSapling CLI — React/Ink terminal client for the MSapling backend (chat, projects, MDrive, agent tools). Proprietary; redistribution prohibited.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "MSapling Team",