@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.
- package/dist/index.js +304 -144
- 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((
|
|
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((
|
|
1378
|
-
proc.on("exit", (code) =>
|
|
1379
|
-
proc.on("error", () =>
|
|
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
|
|
1491
|
-
if (
|
|
1492
|
-
|
|
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((
|
|
1508
|
-
this.pendingRequests.set(id,
|
|
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((
|
|
1641
|
-
proc.on("exit", () =>
|
|
1642
|
-
proc.on("error", () =>
|
|
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((
|
|
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", () =>
|
|
1729
|
-
p.on("exit", (code) =>
|
|
1765
|
+
p.on("error", () => resolve19(null));
|
|
1766
|
+
p.on("exit", (code) => resolve19(code));
|
|
1730
1767
|
} catch {
|
|
1731
|
-
|
|
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((
|
|
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
|
-
|
|
1789
|
+
resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exitCode: -1 });
|
|
1753
1790
|
});
|
|
1754
1791
|
p.on("exit", (code) => {
|
|
1755
|
-
|
|
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
|
-
(
|
|
3044
|
+
(resolve19) => setTimeout(() => resolve19("timeout"), timeoutMs)
|
|
3008
3045
|
);
|
|
3009
3046
|
const processPromise = (async () => {
|
|
3010
|
-
const exitCode2 = await new Promise((
|
|
3011
|
-
proc.on("exit", (code) =>
|
|
3012
|
-
proc.on("error", () =>
|
|
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:
|
|
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
|
|
3773
|
-
await
|
|
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:
|
|
4035
|
+
const { readFile: readFile24, writeFile: writeFile13, mkdir: mkdir9 } = await import("fs/promises");
|
|
3999
4036
|
const { homedir: homedir18 } = await import("os");
|
|
4000
|
-
const existingContent = await
|
|
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
|
|
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((
|
|
4382
|
+
await new Promise((resolve19, reject) => {
|
|
4346
4383
|
try {
|
|
4347
4384
|
const proc = spawn6("powershell", ["-Command", psCommand]);
|
|
4348
|
-
proc.on("exit", () =>
|
|
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((
|
|
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
|
-
|
|
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((
|
|
5343
|
-
release2 =
|
|
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 =
|
|
5984
|
-
function
|
|
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 =
|
|
6001
|
-
function
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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", () =>
|
|
7983
|
-
stdout.on("error", () =>
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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((
|
|
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((
|
|
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
|
|
9179
|
-
import { readFile as
|
|
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 (
|
|
9184
|
-
const text = await
|
|
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 (!
|
|
9354
|
+
if (!existsSync16(settingsDir)) {
|
|
9197
9355
|
await mkdir7(settingsDir, { recursive: true });
|
|
9198
9356
|
}
|
|
9199
|
-
await
|
|
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
|
|
9585
|
-
import { writeFile as
|
|
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 (
|
|
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
|
|
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
|
|
9626
|
-
import { readFile as
|
|
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 (
|
|
9646
|
-
content = await
|
|
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
|
|
9740
|
-
import { readFile as
|
|
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 (
|
|
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
|
|
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
|
|
9861
|
-
import { readFile as
|
|
9862
|
-
import { join as join20, resolve as
|
|
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 =
|
|
9866
|
-
if (
|
|
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
|
|
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
|
|
10357
|
-
import { readFile as
|
|
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 (
|
|
10363
|
-
const text = await
|
|
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
|
|
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.
|
|
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:
|
|
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
|
|
10465
|
-
import { readFile as
|
|
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 (!
|
|
10471
|
-
const text = await
|
|
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
|
|
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
|
|
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
|
|
10775
|
-
import { readFile as
|
|
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 (!
|
|
10782
|
-
const raw = await
|
|
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
|
|
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
|
|
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 (!
|
|
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:
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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
|
|
11329
|
-
import { readFile as
|
|
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 (!
|
|
11337
|
-
const raw = JSON.parse(await
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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((
|
|
11972
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11813
11973
|
}
|
|
11814
11974
|
function promptDefault(rl, question, defaultVal) {
|
|
11815
11975
|
return new Promise(
|
|
11816
|
-
(
|
|
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((
|
|
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
|
|
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 (!
|
|
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 || !
|
|
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
|
|
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((
|
|
13891
|
+
return new Promise((resolve19) => {
|
|
13732
13892
|
let p;
|
|
13733
13893
|
const timeout = setTimeout(() => {
|
|
13734
13894
|
if (p) p.kill();
|
|
13735
|
-
|
|
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
|
-
|
|
13913
|
+
resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exit_code: -1 });
|
|
13754
13914
|
});
|
|
13755
13915
|
p.on("exit", (code) => {
|
|
13756
13916
|
clearTimeout(timeout);
|
|
13757
|
-
|
|
13917
|
+
resolve19({ stdout, stderr, exit_code: code });
|
|
13758
13918
|
});
|
|
13759
13919
|
} catch (e) {
|
|
13760
13920
|
clearTimeout(timeout);
|
|
13761
|
-
|
|
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 =
|
|
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(
|
|
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 ?
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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((
|
|
14434
|
-
this._drainResolve = () =>
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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((
|
|
15515
|
+
await new Promise((resolve19, reject) => {
|
|
15356
15516
|
proc.on("close", (code) => {
|
|
15357
|
-
if (code === 0 || code === null)
|
|
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:
|
|
15385
|
-
const { readFile:
|
|
15386
|
-
if (
|
|
15387
|
-
const content = await
|
|
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
|
|
15440
|
-
import { existsSync as
|
|
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 (
|
|
15458
|
-
const userText = await
|
|
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((
|
|
15559
|
-
setPendingApproval({ request, resolve:
|
|
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.
|
|
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",
|