@mtreeai/msapling-cli 2.3.6-beta.24 → 2.3.6-beta.26
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 +323 -152
- 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}`);
|
|
@@ -9051,15 +9088,18 @@ var init_keys = __esm({
|
|
|
9051
9088
|
try {
|
|
9052
9089
|
if (sub === "list" || sub === "status") {
|
|
9053
9090
|
const s = await context.client.getProviderKeys();
|
|
9054
|
-
const
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9091
|
+
const entries = Object.entries(s).filter(
|
|
9092
|
+
([k]) => !["providers", "status"].includes(k)
|
|
9093
|
+
);
|
|
9094
|
+
const configured = entries.filter(([, v]) => v?.has_key).length;
|
|
9095
|
+
context.addMessage("system", `Provider Keys (${configured}/${entries.length} configured):`);
|
|
9096
|
+
for (const [provider, info] of entries) {
|
|
9097
|
+
const tag = info?.has_key ? "\u2713" : " ";
|
|
9098
|
+
const masked = info?.masked ? ` (${info.masked})` : "";
|
|
9099
|
+
context.addMessage("system", ` [${tag}] ${provider}${masked}`);
|
|
9060
9100
|
}
|
|
9061
|
-
if (
|
|
9062
|
-
context.addMessage("system", " (
|
|
9101
|
+
if (entries.length === 0) {
|
|
9102
|
+
context.addMessage("system", " (no providers returned by backend)");
|
|
9063
9103
|
}
|
|
9064
9104
|
return;
|
|
9065
9105
|
}
|
|
@@ -9150,6 +9190,135 @@ var init_memories = __esm({
|
|
|
9150
9190
|
}
|
|
9151
9191
|
});
|
|
9152
9192
|
|
|
9193
|
+
// src/commands/mdrive.ts
|
|
9194
|
+
import { readFile as readFile14, writeFile as writeFile7 } from "fs/promises";
|
|
9195
|
+
import { existsSync as existsSync15 } from "fs";
|
|
9196
|
+
import { basename, resolve as resolve14 } from "path";
|
|
9197
|
+
function formatBytes(b) {
|
|
9198
|
+
if (!b) return "0";
|
|
9199
|
+
if (b < 1024) return `${b}`;
|
|
9200
|
+
if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)}K`;
|
|
9201
|
+
return `${(b / 1024 / 1024).toFixed(1)}M`;
|
|
9202
|
+
}
|
|
9203
|
+
var mdriveCommand;
|
|
9204
|
+
var init_mdrive = __esm({
|
|
9205
|
+
"src/commands/mdrive.ts"() {
|
|
9206
|
+
"use strict";
|
|
9207
|
+
init_esm_shims();
|
|
9208
|
+
mdriveCommand = {
|
|
9209
|
+
name: "mdrive",
|
|
9210
|
+
args: "[ls|cat|put|get|rm|mv|mkdir] [...args]",
|
|
9211
|
+
description: "Browse and manage files on MSapling Drive (your AI-native context storage).",
|
|
9212
|
+
category: "project",
|
|
9213
|
+
handler: async (args2, context) => {
|
|
9214
|
+
const sub = (args2[0] ?? "ls").toLowerCase();
|
|
9215
|
+
const rest = args2.slice(1);
|
|
9216
|
+
try {
|
|
9217
|
+
if (sub === "ls" || sub === "list") {
|
|
9218
|
+
const path2 = rest[0] || ".";
|
|
9219
|
+
const res = await context.client.mdriveList(path2);
|
|
9220
|
+
const entries = res.entries ?? res.files ?? res.items ?? [];
|
|
9221
|
+
context.addMessage("system", `MDrive: ${path2} (${entries.length} entries)`);
|
|
9222
|
+
for (const e of entries) {
|
|
9223
|
+
const type = e.is_dir || e.type === "dir" ? "d" : "-";
|
|
9224
|
+
const size = e.size != null ? formatBytes(e.size).padStart(6) : " -";
|
|
9225
|
+
const name = e.name ?? e.path ?? "?";
|
|
9226
|
+
context.addMessage("system", ` ${type} ${size} ${name}`);
|
|
9227
|
+
}
|
|
9228
|
+
return;
|
|
9229
|
+
}
|
|
9230
|
+
if (sub === "cat" || sub === "read") {
|
|
9231
|
+
const p = rest[0];
|
|
9232
|
+
if (!p) {
|
|
9233
|
+
context.addMessage("system", "Usage: /mdrive cat <path>");
|
|
9234
|
+
return;
|
|
9235
|
+
}
|
|
9236
|
+
const res = await context.client.mdriveRead(p);
|
|
9237
|
+
context.addMessage("system", res.content ?? res.body ?? "(no content)");
|
|
9238
|
+
return;
|
|
9239
|
+
}
|
|
9240
|
+
if (sub === "put" || sub === "upload" || sub === "write") {
|
|
9241
|
+
const local = rest[0];
|
|
9242
|
+
const remote = rest[1] || (local ? basename(local) : "");
|
|
9243
|
+
if (!local || !remote) {
|
|
9244
|
+
context.addMessage("system", "Usage: /mdrive put <local> [<remote>]");
|
|
9245
|
+
return;
|
|
9246
|
+
}
|
|
9247
|
+
const absLocal = resolve14(local);
|
|
9248
|
+
if (!existsSync15(absLocal)) {
|
|
9249
|
+
context.addMessage("error", `Local file not found: ${absLocal}`);
|
|
9250
|
+
return;
|
|
9251
|
+
}
|
|
9252
|
+
const content = await readFile14(absLocal, "utf8");
|
|
9253
|
+
const res = await context.client.mdriveWrite(remote, content);
|
|
9254
|
+
context.addMessage("system", `Uploaded ${absLocal} \u2192 mdrive:${remote} (${formatBytes(content.length)}, hash=${res?.hash?.slice(0, 12) ?? "?"})`);
|
|
9255
|
+
return;
|
|
9256
|
+
}
|
|
9257
|
+
if (sub === "get" || sub === "download" || sub === "pull") {
|
|
9258
|
+
const remote = rest[0];
|
|
9259
|
+
const local = rest[1];
|
|
9260
|
+
if (!remote) {
|
|
9261
|
+
context.addMessage("system", "Usage: /mdrive get <remote> [<local>]");
|
|
9262
|
+
return;
|
|
9263
|
+
}
|
|
9264
|
+
const res = await context.client.mdriveRead(remote);
|
|
9265
|
+
const content = res.content ?? res.body ?? "";
|
|
9266
|
+
if (local) {
|
|
9267
|
+
await writeFile7(resolve14(local), content, "utf8");
|
|
9268
|
+
context.addMessage("system", `Wrote ${resolve14(local)} (${formatBytes(content.length)})`);
|
|
9269
|
+
} else {
|
|
9270
|
+
context.addMessage("system", content);
|
|
9271
|
+
}
|
|
9272
|
+
return;
|
|
9273
|
+
}
|
|
9274
|
+
if (sub === "rm" || sub === "delete" || sub === "del") {
|
|
9275
|
+
const p = rest[0];
|
|
9276
|
+
if (!p) {
|
|
9277
|
+
context.addMessage("system", "Usage: /mdrive rm <path>");
|
|
9278
|
+
return;
|
|
9279
|
+
}
|
|
9280
|
+
await context.client.mdriveDelete(p);
|
|
9281
|
+
context.addMessage("system", `Deleted mdrive:${p}`);
|
|
9282
|
+
return;
|
|
9283
|
+
}
|
|
9284
|
+
if (sub === "mv" || sub === "rename") {
|
|
9285
|
+
const p = rest[0];
|
|
9286
|
+
const newName = rest[1];
|
|
9287
|
+
if (!p || !newName) {
|
|
9288
|
+
context.addMessage("system", "Usage: /mdrive mv <path> <new-name>");
|
|
9289
|
+
return;
|
|
9290
|
+
}
|
|
9291
|
+
await context.client.mdriveRename(p, newName);
|
|
9292
|
+
context.addMessage("system", `Renamed mdrive:${p} \u2192 ${newName}`);
|
|
9293
|
+
return;
|
|
9294
|
+
}
|
|
9295
|
+
if (sub === "mkdir") {
|
|
9296
|
+
const p = rest[0];
|
|
9297
|
+
if (!p) {
|
|
9298
|
+
context.addMessage("system", "Usage: /mdrive mkdir <path>");
|
|
9299
|
+
return;
|
|
9300
|
+
}
|
|
9301
|
+
await context.client.mdriveMkdir(p);
|
|
9302
|
+
context.addMessage("system", `Created mdrive:${p}/`);
|
|
9303
|
+
return;
|
|
9304
|
+
}
|
|
9305
|
+
context.addMessage("error", `Unknown /mdrive subcommand '${sub}'. Try: ls, cat, put, get, rm, mv, mkdir.`);
|
|
9306
|
+
} catch (e) {
|
|
9307
|
+
const msg = String(e?.message ?? e);
|
|
9308
|
+
if (msg.includes("Invalid or revoked API key") || msg.includes("401")) {
|
|
9309
|
+
context.addMessage(
|
|
9310
|
+
"error",
|
|
9311
|
+
'MDrive requires a paid account + MDrive API key. Generate one at https://msapling.com/settings \u2192 API Keys \u2192 "Create MDrive Key", then run /keys add mdrive <key>.'
|
|
9312
|
+
);
|
|
9313
|
+
} else {
|
|
9314
|
+
context.addMessage("error", `MDrive: ${msg}`);
|
|
9315
|
+
}
|
|
9316
|
+
}
|
|
9317
|
+
}
|
|
9318
|
+
};
|
|
9319
|
+
}
|
|
9320
|
+
});
|
|
9321
|
+
|
|
9153
9322
|
// src/commands/clear.ts
|
|
9154
9323
|
var clearCommand;
|
|
9155
9324
|
var init_clear = __esm({
|
|
@@ -9175,13 +9344,13 @@ var init_clear = __esm({
|
|
|
9175
9344
|
// src/commands/mode.ts
|
|
9176
9345
|
import { homedir as homedir10 } from "os";
|
|
9177
9346
|
import { join as join17 } from "path";
|
|
9178
|
-
import { existsSync as
|
|
9179
|
-
import { readFile as
|
|
9347
|
+
import { existsSync as existsSync16 } from "fs";
|
|
9348
|
+
import { readFile as readFile15, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
|
|
9180
9349
|
async function persistApprovalMode(mode, ttlMs) {
|
|
9181
9350
|
try {
|
|
9182
9351
|
let existing = {};
|
|
9183
|
-
if (
|
|
9184
|
-
const text = await
|
|
9352
|
+
if (existsSync16(SETTINGS_PATH)) {
|
|
9353
|
+
const text = await readFile15(SETTINGS_PATH, "utf8");
|
|
9185
9354
|
if (text.trim()) {
|
|
9186
9355
|
existing = JSON.parse(text);
|
|
9187
9356
|
}
|
|
@@ -9193,10 +9362,10 @@ async function persistApprovalMode(mode, ttlMs) {
|
|
|
9193
9362
|
};
|
|
9194
9363
|
existing.approvalMode = entry;
|
|
9195
9364
|
const settingsDir = join17(homedir10(), ".msapling");
|
|
9196
|
-
if (!
|
|
9365
|
+
if (!existsSync16(settingsDir)) {
|
|
9197
9366
|
await mkdir7(settingsDir, { recursive: true });
|
|
9198
9367
|
}
|
|
9199
|
-
await
|
|
9368
|
+
await writeFile8(SETTINGS_PATH, JSON.stringify(existing, null, 2), "utf8");
|
|
9200
9369
|
} catch {
|
|
9201
9370
|
}
|
|
9202
9371
|
}
|
|
@@ -9581,8 +9750,8 @@ var init_compact = __esm({
|
|
|
9581
9750
|
|
|
9582
9751
|
// src/commands/init.ts
|
|
9583
9752
|
import { join as join18 } from "path";
|
|
9584
|
-
import { existsSync as
|
|
9585
|
-
import { writeFile as
|
|
9753
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9754
|
+
import { writeFile as writeFile9 } from "fs/promises";
|
|
9586
9755
|
var initCommand;
|
|
9587
9756
|
var init_init = __esm({
|
|
9588
9757
|
"src/commands/init.ts"() {
|
|
@@ -9596,7 +9765,7 @@ var init_init = __esm({
|
|
|
9596
9765
|
try {
|
|
9597
9766
|
const cwd = process.cwd();
|
|
9598
9767
|
const path2 = join18(cwd, "MSAPLING.md");
|
|
9599
|
-
if (
|
|
9768
|
+
if (existsSync17(path2)) {
|
|
9600
9769
|
context.addMessage("error", "MSAPLING.md already exists in current directory.");
|
|
9601
9770
|
return;
|
|
9602
9771
|
}
|
|
@@ -9611,7 +9780,7 @@ var init_init = __esm({
|
|
|
9611
9780
|
## Guidelines
|
|
9612
9781
|
- Follow existing code style.
|
|
9613
9782
|
`;
|
|
9614
|
-
await
|
|
9783
|
+
await writeFile9(path2, content, "utf8");
|
|
9615
9784
|
context.addMessage("system", `Created MSAPLING.md at ${path2}`);
|
|
9616
9785
|
} catch (e) {
|
|
9617
9786
|
context.addMessage("error", `Failed to initialize project: ${e.message}`);
|
|
@@ -9622,8 +9791,8 @@ var init_init = __esm({
|
|
|
9622
9791
|
});
|
|
9623
9792
|
|
|
9624
9793
|
// src/commands/review.ts
|
|
9625
|
-
import { existsSync as
|
|
9626
|
-
import { readFile as
|
|
9794
|
+
import { existsSync as existsSync18 } from "fs";
|
|
9795
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
9627
9796
|
var reviewCommand;
|
|
9628
9797
|
var init_review = __esm({
|
|
9629
9798
|
"src/commands/review.ts"() {
|
|
@@ -9642,8 +9811,8 @@ var init_review = __esm({
|
|
|
9642
9811
|
}
|
|
9643
9812
|
let content = "";
|
|
9644
9813
|
try {
|
|
9645
|
-
if (
|
|
9646
|
-
content = await
|
|
9814
|
+
if (existsSync18(target)) {
|
|
9815
|
+
content = await readFile16(target, "utf8");
|
|
9647
9816
|
} else {
|
|
9648
9817
|
content = `Review target: ${target}`;
|
|
9649
9818
|
}
|
|
@@ -9736,15 +9905,15 @@ var init_swarm = __esm({
|
|
|
9736
9905
|
|
|
9737
9906
|
// src/commands/recipe.ts
|
|
9738
9907
|
import { parse as parseYaml } from "yaml";
|
|
9739
|
-
import { existsSync as
|
|
9740
|
-
import { readFile as
|
|
9908
|
+
import { existsSync as existsSync19 } from "fs";
|
|
9909
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
9741
9910
|
import { join as join19 } from "path";
|
|
9742
9911
|
function findRecipe(name, cwd) {
|
|
9743
9912
|
for (const dir of RECIPE_DIRS) {
|
|
9744
9913
|
for (const suffix of NAME_SUFFIXES) {
|
|
9745
9914
|
for (const ext of FILE_EXTS) {
|
|
9746
9915
|
const p = join19(cwd, dir, `${name}${suffix}${ext}`);
|
|
9747
|
-
if (
|
|
9916
|
+
if (existsSync19(p)) return p;
|
|
9748
9917
|
}
|
|
9749
9918
|
}
|
|
9750
9919
|
}
|
|
@@ -9803,7 +9972,7 @@ var init_recipe = __esm({
|
|
|
9803
9972
|
let text;
|
|
9804
9973
|
let recipe;
|
|
9805
9974
|
try {
|
|
9806
|
-
text = await
|
|
9975
|
+
text = await readFile17(path2, "utf8");
|
|
9807
9976
|
recipe = parseYaml(text);
|
|
9808
9977
|
} catch (e) {
|
|
9809
9978
|
context.addMessage("error", `Failed to load ${path2}: ${e.message}`);
|
|
@@ -9857,13 +10026,13 @@ ${rendered}` : rendered;
|
|
|
9857
10026
|
});
|
|
9858
10027
|
|
|
9859
10028
|
// src/commands/skill.ts
|
|
9860
|
-
import { existsSync as
|
|
9861
|
-
import { readFile as
|
|
9862
|
-
import { join as join20, resolve as
|
|
10029
|
+
import { existsSync as existsSync20, readdirSync as readdirSync2, statSync as statSync5 } from "fs";
|
|
10030
|
+
import { readFile as readFile18 } from "fs/promises";
|
|
10031
|
+
import { join as join20, resolve as resolve15 } from "path";
|
|
9863
10032
|
function findSkillsRoot(cwd) {
|
|
9864
10033
|
for (const candidate of SKILLS_DIRS) {
|
|
9865
|
-
const full =
|
|
9866
|
-
if (
|
|
10034
|
+
const full = resolve15(cwd, candidate);
|
|
10035
|
+
if (existsSync20(full) && statSync5(full).isDirectory()) return full;
|
|
9867
10036
|
}
|
|
9868
10037
|
return null;
|
|
9869
10038
|
}
|
|
@@ -9957,7 +10126,7 @@ var init_skill = __esm({
|
|
|
9957
10126
|
}
|
|
9958
10127
|
let body;
|
|
9959
10128
|
try {
|
|
9960
|
-
body = await
|
|
10129
|
+
body = await readFile18(skill.path, "utf8");
|
|
9961
10130
|
} catch (e) {
|
|
9962
10131
|
context.addMessage("error", `Failed to load skill ${skill.path}: ${e.message}`);
|
|
9963
10132
|
return;
|
|
@@ -10353,21 +10522,21 @@ var init_theme = __esm({
|
|
|
10353
10522
|
// src/commands/theme.ts
|
|
10354
10523
|
import { join as join22 } from "path";
|
|
10355
10524
|
import { homedir as homedir12 } from "os";
|
|
10356
|
-
import { existsSync as
|
|
10357
|
-
import { readFile as
|
|
10525
|
+
import { existsSync as existsSync21 } from "fs";
|
|
10526
|
+
import { readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
|
|
10358
10527
|
async function persistTheme(storage, themeName) {
|
|
10359
10528
|
const settingsPath = join22(homedir12(), ".msapling", "settings.json");
|
|
10360
10529
|
let existing = {};
|
|
10361
10530
|
try {
|
|
10362
|
-
if (
|
|
10363
|
-
const text = await
|
|
10531
|
+
if (existsSync21(settingsPath)) {
|
|
10532
|
+
const text = await readFile19(settingsPath, "utf8");
|
|
10364
10533
|
if (text.trim()) existing = JSON.parse(text);
|
|
10365
10534
|
}
|
|
10366
10535
|
} catch {
|
|
10367
10536
|
}
|
|
10368
10537
|
existing["theme"] = themeName;
|
|
10369
10538
|
ensureConfigDir(join22(homedir12(), ".msapling"));
|
|
10370
|
-
await
|
|
10539
|
+
await writeFile10(settingsPath, JSON.stringify(existing, null, 2), "utf8");
|
|
10371
10540
|
}
|
|
10372
10541
|
var VALID_THEMES, themeCommand;
|
|
10373
10542
|
var init_theme2 = __esm({
|
|
@@ -10438,7 +10607,7 @@ var init_version = __esm({
|
|
|
10438
10607
|
description: "Show version information for CLI and core packages",
|
|
10439
10608
|
category: "debug",
|
|
10440
10609
|
handler: async (_args, context) => {
|
|
10441
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
10610
|
+
const cliVersion = true ? "2.3.6-beta.26" : "(dev)";
|
|
10442
10611
|
const coreVersion = true ? "2.3.2" : "(dev)";
|
|
10443
10612
|
const runtime = process.version;
|
|
10444
10613
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -10447,7 +10616,7 @@ var init_version = __esm({
|
|
|
10447
10616
|
context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
|
|
10448
10617
|
context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
|
|
10449
10618
|
try {
|
|
10450
|
-
const ts = "2026-05-
|
|
10619
|
+
const ts = "2026-05-28T23:01:36.725Z";
|
|
10451
10620
|
if (ts && ts !== "__BUILD_TIMESTAMP__") {
|
|
10452
10621
|
context.addMessage("system", row2("Build Timestamp", ts));
|
|
10453
10622
|
}
|
|
@@ -10461,14 +10630,14 @@ var init_version = __esm({
|
|
|
10461
10630
|
|
|
10462
10631
|
// src/commands/feedback.ts
|
|
10463
10632
|
import { join as join23 } from "path";
|
|
10464
|
-
import { existsSync as
|
|
10465
|
-
import { readFile as
|
|
10633
|
+
import { existsSync as existsSync22 } from "fs";
|
|
10634
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
10466
10635
|
async function readCliVersion() {
|
|
10467
10636
|
try {
|
|
10468
10637
|
const baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
10469
10638
|
const pkgPath = join23(baseDir, "..", "..", "package.json");
|
|
10470
|
-
if (!
|
|
10471
|
-
const text = await
|
|
10639
|
+
if (!existsSync22(pkgPath)) return "unknown";
|
|
10640
|
+
const text = await readFile20(pkgPath, "utf8");
|
|
10472
10641
|
const json = JSON.parse(text);
|
|
10473
10642
|
return json.version ?? "unknown";
|
|
10474
10643
|
} catch {
|
|
@@ -10510,7 +10679,7 @@ var init_feedback = __esm({
|
|
|
10510
10679
|
// src/commands/export.ts
|
|
10511
10680
|
import { homedir as homedir13 } from "os";
|
|
10512
10681
|
import { join as join24 } from "path";
|
|
10513
|
-
import { writeFile as
|
|
10682
|
+
import { writeFile as writeFile11, mkdir as mkdir8 } from "fs/promises";
|
|
10514
10683
|
function formatTimestamp(date) {
|
|
10515
10684
|
return date.toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
10516
10685
|
}
|
|
@@ -10576,7 +10745,7 @@ var init_export = __esm({
|
|
|
10576
10745
|
try {
|
|
10577
10746
|
const dir = join24(outputPath, "..");
|
|
10578
10747
|
await mkdir8(dir, { recursive: true });
|
|
10579
|
-
await
|
|
10748
|
+
await writeFile11(outputPath, content, "utf8");
|
|
10580
10749
|
context.addMessage("system", `Exported to: ${outputPath}`);
|
|
10581
10750
|
} catch (e) {
|
|
10582
10751
|
context.addMessage("error", `Failed to export: ${e.message}`);
|
|
@@ -10771,15 +10940,15 @@ var init_plan = __esm({
|
|
|
10771
10940
|
// src/commands/note.ts
|
|
10772
10941
|
import { homedir as homedir14 } from "os";
|
|
10773
10942
|
import { join as join25 } from "path";
|
|
10774
|
-
import { existsSync as
|
|
10775
|
-
import { readFile as
|
|
10943
|
+
import { existsSync as existsSync23 } from "fs";
|
|
10944
|
+
import { readFile as readFile21, writeFile as writeFile12 } from "fs/promises";
|
|
10776
10945
|
function getNotesFilePath() {
|
|
10777
10946
|
return join25(homedir14(), ".msapling", "notes.json");
|
|
10778
10947
|
}
|
|
10779
10948
|
async function readNotes(filePath = getNotesFilePath()) {
|
|
10780
10949
|
try {
|
|
10781
|
-
if (!
|
|
10782
|
-
const raw = await
|
|
10950
|
+
if (!existsSync23(filePath)) return [];
|
|
10951
|
+
const raw = await readFile21(filePath, "utf8");
|
|
10783
10952
|
const parsed = JSON.parse(raw);
|
|
10784
10953
|
if (!Array.isArray(parsed)) return [];
|
|
10785
10954
|
return parsed;
|
|
@@ -10790,7 +10959,7 @@ async function readNotes(filePath = getNotesFilePath()) {
|
|
|
10790
10959
|
async function writeNotes(notes, filePath = getNotesFilePath()) {
|
|
10791
10960
|
const dir = join25(homedir14(), ".msapling");
|
|
10792
10961
|
ensureConfigDir(dir);
|
|
10793
|
-
await
|
|
10962
|
+
await writeFile12(filePath, JSON.stringify(notes, null, 2), "utf8");
|
|
10794
10963
|
}
|
|
10795
10964
|
function formatTimestamp2(iso) {
|
|
10796
10965
|
const d = new Date(iso);
|
|
@@ -10935,8 +11104,8 @@ var init_todo = __esm({
|
|
|
10935
11104
|
|
|
10936
11105
|
// src/commands/outputStyle.ts
|
|
10937
11106
|
import { homedir as homedir15 } from "os";
|
|
10938
|
-
import { join as join26, basename, extname as extname3 } from "path";
|
|
10939
|
-
import { existsSync as
|
|
11107
|
+
import { join as join26, basename as basename2, extname as extname3 } from "path";
|
|
11108
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
10940
11109
|
function stylesDir() {
|
|
10941
11110
|
return join26(homedir15(), ".msapling", "output-styles");
|
|
10942
11111
|
}
|
|
@@ -10962,7 +11131,7 @@ function parseStyleFile(text) {
|
|
|
10962
11131
|
}
|
|
10963
11132
|
function listUserStyles() {
|
|
10964
11133
|
const dir = stylesDir();
|
|
10965
|
-
if (!
|
|
11134
|
+
if (!existsSync24(dir)) return [];
|
|
10966
11135
|
const out = [];
|
|
10967
11136
|
for (const entry of readdirSync3(dir)) {
|
|
10968
11137
|
if (extname3(entry).toLowerCase() !== ".md") continue;
|
|
@@ -10971,7 +11140,7 @@ function listUserStyles() {
|
|
|
10971
11140
|
const text = readFileSync(full, "utf8");
|
|
10972
11141
|
const { description, body } = parseStyleFile(text);
|
|
10973
11142
|
out.push({
|
|
10974
|
-
name:
|
|
11143
|
+
name: basename2(entry, ".md"),
|
|
10975
11144
|
description,
|
|
10976
11145
|
body,
|
|
10977
11146
|
source: "user",
|
|
@@ -10994,7 +11163,7 @@ function findStyle(name) {
|
|
|
10994
11163
|
function getActiveStyleName() {
|
|
10995
11164
|
try {
|
|
10996
11165
|
const f = activeFile();
|
|
10997
|
-
if (!
|
|
11166
|
+
if (!existsSync24(f)) return "default";
|
|
10998
11167
|
return readFileSync(f, "utf8").trim() || "default";
|
|
10999
11168
|
} catch {
|
|
11000
11169
|
return "default";
|
|
@@ -11002,7 +11171,7 @@ function getActiveStyleName() {
|
|
|
11002
11171
|
}
|
|
11003
11172
|
function setActiveStyleName(name) {
|
|
11004
11173
|
const dir = stylesDir();
|
|
11005
|
-
if (!
|
|
11174
|
+
if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
|
|
11006
11175
|
writeFileSync2(activeFile(), `${name}
|
|
11007
11176
|
`, "utf8");
|
|
11008
11177
|
}
|
|
@@ -11015,7 +11184,7 @@ function createUserStyle(name, description, body) {
|
|
|
11015
11184
|
throw new Error(`Invalid style name "${name}" \u2014 use letters, digits, _ and - only.`);
|
|
11016
11185
|
}
|
|
11017
11186
|
const dir = stylesDir();
|
|
11018
|
-
if (!
|
|
11187
|
+
if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
|
|
11019
11188
|
const target = join26(dir, `${name}.md`);
|
|
11020
11189
|
const frontmatter = `---
|
|
11021
11190
|
description: ${description.replace(/\n/g, " ")}
|
|
@@ -11190,6 +11359,7 @@ var init_commands = __esm({
|
|
|
11190
11359
|
init_ollama();
|
|
11191
11360
|
init_keys();
|
|
11192
11361
|
init_memories();
|
|
11362
|
+
init_mdrive();
|
|
11193
11363
|
init_clear();
|
|
11194
11364
|
init_mode();
|
|
11195
11365
|
init_model();
|
|
@@ -11229,6 +11399,7 @@ var init_commands = __esm({
|
|
|
11229
11399
|
ollamaCommand,
|
|
11230
11400
|
keysCommand,
|
|
11231
11401
|
memoriesCommand,
|
|
11402
|
+
mdriveCommand,
|
|
11232
11403
|
clearCommand,
|
|
11233
11404
|
modeCommand,
|
|
11234
11405
|
modelCommand,
|
|
@@ -11325,16 +11496,16 @@ var exec_exports = {};
|
|
|
11325
11496
|
__export(exec_exports, {
|
|
11326
11497
|
runExec: () => runExec
|
|
11327
11498
|
});
|
|
11328
|
-
import { existsSync as
|
|
11329
|
-
import { readFile as
|
|
11499
|
+
import { existsSync as existsSync26 } from "fs";
|
|
11500
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
11330
11501
|
import { homedir as homedir16 } from "os";
|
|
11331
11502
|
import { join as join27 } from "path";
|
|
11332
11503
|
async function loadPersistedSettings() {
|
|
11333
11504
|
const out = { mode: "default", theme: null };
|
|
11334
11505
|
try {
|
|
11335
11506
|
const p = join27(homedir16(), ".msapling", "settings.json");
|
|
11336
|
-
if (!
|
|
11337
|
-
const raw = JSON.parse(await
|
|
11507
|
+
if (!existsSync26(p)) return out;
|
|
11508
|
+
const raw = JSON.parse(await readFile23(p, "utf8"));
|
|
11338
11509
|
const parsed = parseApprovalMode(raw, Date.now());
|
|
11339
11510
|
if (parsed.kind === "ok") out.mode = parsed.mode;
|
|
11340
11511
|
const themeRaw = raw?.theme;
|
|
@@ -11584,13 +11755,13 @@ async function openBrowser(url) {
|
|
|
11584
11755
|
cmd = "xdg-open";
|
|
11585
11756
|
args2 = [url];
|
|
11586
11757
|
}
|
|
11587
|
-
return new Promise((
|
|
11758
|
+
return new Promise((resolve19) => {
|
|
11588
11759
|
try {
|
|
11589
11760
|
const child = spawn10(cmd, args2, { stdio: "ignore", detached: true });
|
|
11590
11761
|
child.unref();
|
|
11591
11762
|
} catch {
|
|
11592
11763
|
}
|
|
11593
|
-
|
|
11764
|
+
resolve19();
|
|
11594
11765
|
});
|
|
11595
11766
|
}
|
|
11596
11767
|
var init_open_browser = __esm({
|
|
@@ -11680,7 +11851,7 @@ var init_checkout = __esm({
|
|
|
11680
11851
|
// src/commands/billing/sub.ts
|
|
11681
11852
|
import * as readline from "readline";
|
|
11682
11853
|
function prompt(rl, question) {
|
|
11683
|
-
return new Promise((
|
|
11854
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11684
11855
|
}
|
|
11685
11856
|
async function runSub(argv) {
|
|
11686
11857
|
const subCmd = argv[0] ?? "";
|
|
@@ -11809,11 +11980,11 @@ var init_sub = __esm({
|
|
|
11809
11980
|
// src/commands/billing/topup.ts
|
|
11810
11981
|
import * as readline2 from "readline";
|
|
11811
11982
|
function prompt2(rl, question) {
|
|
11812
|
-
return new Promise((
|
|
11983
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11813
11984
|
}
|
|
11814
11985
|
function promptDefault(rl, question, defaultVal) {
|
|
11815
11986
|
return new Promise(
|
|
11816
|
-
(
|
|
11987
|
+
(resolve19) => rl.question(`${question} [${defaultVal}]: `, (ans) => resolve19(ans.trim() || defaultVal))
|
|
11817
11988
|
);
|
|
11818
11989
|
}
|
|
11819
11990
|
async function runTopup(argv) {
|
|
@@ -11954,7 +12125,7 @@ var init_redeem = __esm({
|
|
|
11954
12125
|
// src/commands/billing/gift.ts
|
|
11955
12126
|
import * as readline3 from "readline";
|
|
11956
12127
|
function prompt3(rl, question) {
|
|
11957
|
-
return new Promise((
|
|
12128
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11958
12129
|
}
|
|
11959
12130
|
async function runGift(argv) {
|
|
11960
12131
|
const subCmd = argv[0] ?? "";
|
|
@@ -12211,7 +12382,7 @@ __export(doctor_exports, {
|
|
|
12211
12382
|
});
|
|
12212
12383
|
import { homedir as homedir17, platform as platform3 } from "os";
|
|
12213
12384
|
import { join as join28 } from "path";
|
|
12214
|
-
import { existsSync as
|
|
12385
|
+
import { existsSync as existsSync27, statSync as statSync6, accessSync } from "fs";
|
|
12215
12386
|
import { readdir as readdir3 } from "fs/promises";
|
|
12216
12387
|
import { exec } from "child_process";
|
|
12217
12388
|
import { promisify } from "util";
|
|
@@ -12235,7 +12406,7 @@ async function checkNodeVersion() {
|
|
|
12235
12406
|
}
|
|
12236
12407
|
async function checkConfigDir() {
|
|
12237
12408
|
const configDir = join28(homedir17(), ".msapling");
|
|
12238
|
-
if (!
|
|
12409
|
+
if (!existsSync27(configDir)) {
|
|
12239
12410
|
return {
|
|
12240
12411
|
name: "Config directory",
|
|
12241
12412
|
status: "WARN",
|
|
@@ -12301,7 +12472,7 @@ async function checkPathConflicts() {
|
|
|
12301
12472
|
const paths = pathEnv.split(platform3() === "win32" ? ";" : ":");
|
|
12302
12473
|
const conflicts = [];
|
|
12303
12474
|
for (const dir of paths) {
|
|
12304
|
-
if (!dir || !
|
|
12475
|
+
if (!dir || !existsSync27(dir)) continue;
|
|
12305
12476
|
try {
|
|
12306
12477
|
const files = await readdir3(dir);
|
|
12307
12478
|
for (const file of files) {
|
|
@@ -13723,16 +13894,16 @@ var init_registry_merger = __esm({
|
|
|
13723
13894
|
// ../core/src/mcp/local_tools.ts
|
|
13724
13895
|
import { spawn as spawn11 } from "child_process";
|
|
13725
13896
|
import { readdir as readdir4, stat as stat4, realpath as realpath2 } from "fs/promises";
|
|
13726
|
-
import { resolve as
|
|
13897
|
+
import { resolve as resolve17 } from "path";
|
|
13727
13898
|
function asResult(text, isError = false) {
|
|
13728
13899
|
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
13729
13900
|
}
|
|
13730
13901
|
async function runCommand(command, cwd) {
|
|
13731
|
-
return new Promise((
|
|
13902
|
+
return new Promise((resolve19) => {
|
|
13732
13903
|
let p;
|
|
13733
13904
|
const timeout = setTimeout(() => {
|
|
13734
13905
|
if (p) p.kill();
|
|
13735
|
-
|
|
13906
|
+
resolve19({ stdout: "", stderr: "Command timed out after 30s", exit_code: -1 });
|
|
13736
13907
|
}, 3e4);
|
|
13737
13908
|
try {
|
|
13738
13909
|
p = spawn11("sh", ["-c", command], {
|
|
@@ -13750,15 +13921,15 @@ async function runCommand(command, cwd) {
|
|
|
13750
13921
|
});
|
|
13751
13922
|
p.on("error", (e) => {
|
|
13752
13923
|
clearTimeout(timeout);
|
|
13753
|
-
|
|
13924
|
+
resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exit_code: -1 });
|
|
13754
13925
|
});
|
|
13755
13926
|
p.on("exit", (code) => {
|
|
13756
13927
|
clearTimeout(timeout);
|
|
13757
|
-
|
|
13928
|
+
resolve19({ stdout, stderr, exit_code: code });
|
|
13758
13929
|
});
|
|
13759
13930
|
} catch (e) {
|
|
13760
13931
|
clearTimeout(timeout);
|
|
13761
|
-
|
|
13932
|
+
resolve19({
|
|
13762
13933
|
stdout: "",
|
|
13763
13934
|
stderr: e?.message ?? "Failed to spawn process",
|
|
13764
13935
|
exit_code: -1
|
|
@@ -13825,7 +13996,7 @@ async function callLocalTool(name, args2, projectRoot) {
|
|
|
13825
13996
|
const command = String(args2.command ?? "");
|
|
13826
13997
|
let cwd = projectRoot;
|
|
13827
13998
|
if (args2.cwd) {
|
|
13828
|
-
cwd =
|
|
13999
|
+
cwd = resolve17(projectRoot, String(args2.cwd));
|
|
13829
14000
|
try {
|
|
13830
14001
|
const resolvedCwd = await realpath2(cwd);
|
|
13831
14002
|
const resolvedRoot = await realpath2(projectRoot);
|
|
@@ -13862,7 +14033,7 @@ ${res.stderr}`
|
|
|
13862
14033
|
return asResult("path is required", true);
|
|
13863
14034
|
}
|
|
13864
14035
|
try {
|
|
13865
|
-
const resolvedPath = await realpath2(
|
|
14036
|
+
const resolvedPath = await realpath2(resolve17(projectRoot, pathArg));
|
|
13866
14037
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13867
14038
|
if (!resolvedPath.startsWith(resolvedRoot)) {
|
|
13868
14039
|
return asResult("Error: path attempts to escape project root", true);
|
|
@@ -13881,7 +14052,7 @@ ${res.stderr}`
|
|
|
13881
14052
|
}
|
|
13882
14053
|
case "local_glob": {
|
|
13883
14054
|
const pattern = String(args2.pattern ?? "");
|
|
13884
|
-
let cwd = args2.cwd ?
|
|
14055
|
+
let cwd = args2.cwd ? resolve17(projectRoot, String(args2.cwd)) : projectRoot;
|
|
13885
14056
|
if (!pattern) {
|
|
13886
14057
|
return asResult("pattern is required", true);
|
|
13887
14058
|
}
|
|
@@ -13910,7 +14081,7 @@ ${res.stderr}`
|
|
|
13910
14081
|
}
|
|
13911
14082
|
if (path2) {
|
|
13912
14083
|
try {
|
|
13913
|
-
const resolvedPath = await realpath2(
|
|
14084
|
+
const resolvedPath = await realpath2(resolve17(projectRoot, path2));
|
|
13914
14085
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13915
14086
|
if (!resolvedPath.startsWith(resolvedRoot)) {
|
|
13916
14087
|
return asResult("Error: path attempts to escape project root", true);
|
|
@@ -13930,7 +14101,7 @@ ${res.stderr}`
|
|
|
13930
14101
|
return asResult("cwd is required", true);
|
|
13931
14102
|
}
|
|
13932
14103
|
try {
|
|
13933
|
-
const resolvedCwd = await realpath2(
|
|
14104
|
+
const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
|
|
13934
14105
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13935
14106
|
if (!resolvedCwd.startsWith(resolvedRoot)) {
|
|
13936
14107
|
return asResult("Error: cwd attempts to escape project root", true);
|
|
@@ -13956,7 +14127,7 @@ ${status.porcelain || "(clean)"}`
|
|
|
13956
14127
|
return asResult("cwd is required", true);
|
|
13957
14128
|
}
|
|
13958
14129
|
try {
|
|
13959
|
-
const resolvedCwd = await realpath2(
|
|
14130
|
+
const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
|
|
13960
14131
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13961
14132
|
if (!resolvedCwd.startsWith(resolvedRoot)) {
|
|
13962
14133
|
return asResult("Error: cwd attempts to escape project root", true);
|
|
@@ -14072,7 +14243,7 @@ __export(server_exports, {
|
|
|
14072
14243
|
runStdioWithRegistry: () => runStdioWithRegistry
|
|
14073
14244
|
});
|
|
14074
14245
|
import { readdirSync as readdirSync4, readFileSync as readFileSync2, statSync as statSync7 } from "fs";
|
|
14075
|
-
import { join as join29, relative as relative14, resolve as
|
|
14246
|
+
import { join as join29, relative as relative14, resolve as resolve18 } from "path";
|
|
14076
14247
|
function asResult2(text, isError = false) {
|
|
14077
14248
|
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
14078
14249
|
}
|
|
@@ -14430,13 +14601,13 @@ var init_server = __esm({
|
|
|
14430
14601
|
if (inflight === 0) {
|
|
14431
14602
|
return [];
|
|
14432
14603
|
}
|
|
14433
|
-
const forcedResponses = await new Promise((
|
|
14434
|
-
this._drainResolve = () =>
|
|
14604
|
+
const forcedResponses = await new Promise((resolve19) => {
|
|
14605
|
+
this._drainResolve = () => resolve19([]);
|
|
14435
14606
|
setTimeout(() => {
|
|
14436
14607
|
this._drainResolve = null;
|
|
14437
14608
|
const remaining = Array.from(this._inflightCalls.values());
|
|
14438
14609
|
if (remaining.length === 0) {
|
|
14439
|
-
|
|
14610
|
+
resolve19([]);
|
|
14440
14611
|
return;
|
|
14441
14612
|
}
|
|
14442
14613
|
process.stderr.write(
|
|
@@ -14452,7 +14623,7 @@ var init_server = __esm({
|
|
|
14452
14623
|
}
|
|
14453
14624
|
}));
|
|
14454
14625
|
this._inflightCalls.clear();
|
|
14455
|
-
|
|
14626
|
+
resolve19(errorResponses);
|
|
14456
14627
|
}, DRAIN_TIMEOUT_MS);
|
|
14457
14628
|
});
|
|
14458
14629
|
return forcedResponses;
|
|
@@ -14730,7 +14901,7 @@ ${r.response ?? ""}`;
|
|
|
14730
14901
|
return asResult2(JSON.stringify(result));
|
|
14731
14902
|
}
|
|
14732
14903
|
case "msapling_project_context": {
|
|
14733
|
-
const root =
|
|
14904
|
+
const root = resolve18(String(args2.path ?? "."));
|
|
14734
14905
|
const maxFiles = Number.isFinite(args2.max_files) ? Number(args2.max_files) : 30;
|
|
14735
14906
|
const maxKB = Number.isFinite(args2.max_file_size_kb) ? Number(args2.max_file_size_kb) : 50;
|
|
14736
14907
|
const files = buildFileTree(root, maxFiles);
|
|
@@ -14858,7 +15029,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
14858
15029
|
var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
14859
15030
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
14860
15031
|
"\u25CF MSapling CLI v",
|
|
14861
|
-
"2.3.6-beta.
|
|
15032
|
+
"2.3.6-beta.26"
|
|
14862
15033
|
] }),
|
|
14863
15034
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
14864
15035
|
] });
|
|
@@ -15352,9 +15523,9 @@ ${prompt4}` : prompt4;
|
|
|
15352
15523
|
if (proc.stderr) proc.stderr.on("data", (chunk) => {
|
|
15353
15524
|
stderr += chunk.toString();
|
|
15354
15525
|
});
|
|
15355
|
-
await new Promise((
|
|
15526
|
+
await new Promise((resolve19, reject) => {
|
|
15356
15527
|
proc.on("close", (code) => {
|
|
15357
|
-
if (code === 0 || code === null)
|
|
15528
|
+
if (code === 0 || code === null) resolve19();
|
|
15358
15529
|
else reject(new Error(`Process exited with code ${code}`));
|
|
15359
15530
|
});
|
|
15360
15531
|
proc.on("error", reject);
|
|
@@ -15381,10 +15552,10 @@ ${prompt4}` : prompt4;
|
|
|
15381
15552
|
for (const mention of fileMentions) {
|
|
15382
15553
|
const filePath = mention.slice(1);
|
|
15383
15554
|
try {
|
|
15384
|
-
const { existsSync:
|
|
15385
|
-
const { readFile:
|
|
15386
|
-
if (
|
|
15387
|
-
const content = await
|
|
15555
|
+
const { existsSync: existsSync28 } = await import("fs");
|
|
15556
|
+
const { readFile: readFile24 } = await import("fs/promises");
|
|
15557
|
+
if (existsSync28(filePath)) {
|
|
15558
|
+
const content = await readFile24(filePath, "utf8");
|
|
15388
15559
|
const MAX_LEN = 32768;
|
|
15389
15560
|
const truncated = content.length > MAX_LEN ? content.slice(0, MAX_LEN) + "\n...[TRUNCATED]" : content;
|
|
15390
15561
|
finalCmd += `
|
|
@@ -15436,8 +15607,8 @@ ${finalCmd}`;
|
|
|
15436
15607
|
init_esm_shims();
|
|
15437
15608
|
init_src3();
|
|
15438
15609
|
init_parseApprovalMode();
|
|
15439
|
-
import { readFile as
|
|
15440
|
-
import { existsSync as
|
|
15610
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
15611
|
+
import { existsSync as existsSync25 } from "fs";
|
|
15441
15612
|
async function initSession(ctx) {
|
|
15442
15613
|
try {
|
|
15443
15614
|
const { settings } = await loadSettings(
|
|
@@ -15454,8 +15625,8 @@ async function initSession(ctx) {
|
|
|
15454
15625
|
const { homedir: homedir18 } = await import("os");
|
|
15455
15626
|
const { join: join31 } = await import("path");
|
|
15456
15627
|
const userSettingsPath = join31(homedir18(), ".msapling", "settings.json");
|
|
15457
|
-
if (
|
|
15458
|
-
const userText = await
|
|
15628
|
+
if (existsSync25(userSettingsPath)) {
|
|
15629
|
+
const userText = await readFile22(userSettingsPath, "utf8");
|
|
15459
15630
|
let parsed;
|
|
15460
15631
|
try {
|
|
15461
15632
|
parsed = JSON.parse(userText);
|
|
@@ -15555,8 +15726,8 @@ var App = ({ compact: compact2 = false }) => {
|
|
|
15555
15726
|
const storage = useRef(new StorageManager()).current;
|
|
15556
15727
|
const client = useRef(new MSaplingClient()).current;
|
|
15557
15728
|
const requestApproval = useCallback((request) => {
|
|
15558
|
-
return new Promise((
|
|
15559
|
-
setPendingApproval({ request, resolve:
|
|
15729
|
+
return new Promise((resolve19) => {
|
|
15730
|
+
setPendingApproval({ request, resolve: resolve19 });
|
|
15560
15731
|
});
|
|
15561
15732
|
}, []);
|
|
15562
15733
|
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.26",
|
|
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",
|