@mtreeai/msapling-cli 2.3.6-beta.23 → 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 +678 -144
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -266,6 +266,125 @@ 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
|
+
}
|
|
306
|
+
// CLI-OLLAMA-COMMANDS-01 (Iter 35): Ollama BYOK helpers. Per LAB ollama.py
|
|
307
|
+
// routes are GET/POST/DELETE under /api/ollama. The CLI uses these to wire
|
|
308
|
+
// up the user's local Ollama instance as a free-tier model provider.
|
|
309
|
+
async getOllamaStatus() {
|
|
310
|
+
return await this.request("/api/ollama/status");
|
|
311
|
+
}
|
|
312
|
+
async configureOllama(opts) {
|
|
313
|
+
return await this.request("/api/ollama/configure", {
|
|
314
|
+
method: "POST",
|
|
315
|
+
body: JSON.stringify({
|
|
316
|
+
base_url: opts.baseUrl,
|
|
317
|
+
enabled: opts.enabled,
|
|
318
|
+
action: opts.action,
|
|
319
|
+
model: opts.model
|
|
320
|
+
})
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
async testOllama(baseUrl) {
|
|
324
|
+
return await this.request("/api/ollama/test", {
|
|
325
|
+
method: "POST",
|
|
326
|
+
body: JSON.stringify({ base_url: baseUrl })
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
async deleteOllamaModel(modelName) {
|
|
330
|
+
return await this.request(`/api/ollama/models/${encodeURIComponent(modelName)}`, {
|
|
331
|
+
method: "DELETE"
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
async disableOllama() {
|
|
335
|
+
return await this.request("/api/ollama/disable", { method: "POST" });
|
|
336
|
+
}
|
|
337
|
+
// CLI-KEYS-BYOK-01 (Iter 35): BYOK provider-key management. Per LAB
|
|
338
|
+
// routers/keys.py — /api/keys/{status,save,{provider}}.
|
|
339
|
+
async getProviderKeys() {
|
|
340
|
+
return await this.request("/api/keys/status");
|
|
341
|
+
}
|
|
342
|
+
async saveProviderKey(provider, apiKey) {
|
|
343
|
+
return await this.request("/api/keys/save", {
|
|
344
|
+
method: "POST",
|
|
345
|
+
body: JSON.stringify({ provider, api_key: apiKey })
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
async deleteProviderKey(provider) {
|
|
349
|
+
return await this.request(`/api/keys/${encodeURIComponent(provider)}`, { method: "DELETE" });
|
|
350
|
+
}
|
|
351
|
+
// CLI-CHAT-LIFECYCLE-01 (Iter 35): rename/delete/fork/pin. Per LAB
|
|
352
|
+
// projects.py:404 (PATCH), 879 (DELETE), 534 (POST fork), 726 (PATCH pin).
|
|
353
|
+
async renameChat(chatId, title) {
|
|
354
|
+
return await this.request(`/api/projects/chat/${encodeURIComponent(chatId)}`, {
|
|
355
|
+
method: "PATCH",
|
|
356
|
+
body: JSON.stringify({ title })
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
async deleteChat(chatId) {
|
|
360
|
+
return await this.request(`/api/projects/chat/${encodeURIComponent(chatId)}`, { method: "DELETE" });
|
|
361
|
+
}
|
|
362
|
+
async forkChat(chatId, body) {
|
|
363
|
+
return await this.request(`/api/projects/chat/${encodeURIComponent(chatId)}/fork`, {
|
|
364
|
+
method: "POST",
|
|
365
|
+
body: JSON.stringify(body ?? {})
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
async pinChat(chatId, pinned) {
|
|
369
|
+
return await this.request(`/api/projects/chat/${encodeURIComponent(chatId)}/pin`, {
|
|
370
|
+
method: "PATCH",
|
|
371
|
+
body: JSON.stringify({ pinned })
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
// CLI-MEMORIES-01 (Iter 35): backend-managed memories (vs the local notes
|
|
375
|
+
// /memory currently surfaces). Per LAB memories.py — list / create / delete.
|
|
376
|
+
async listMemories() {
|
|
377
|
+
return await this.request("/api/memories");
|
|
378
|
+
}
|
|
379
|
+
async createMemory(content) {
|
|
380
|
+
return await this.request("/api/memories", {
|
|
381
|
+
method: "POST",
|
|
382
|
+
body: JSON.stringify({ content })
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
async deleteMemory(memoryId) {
|
|
386
|
+
return await this.request(`/api/memories/${encodeURIComponent(memoryId)}`, { method: "DELETE" });
|
|
387
|
+
}
|
|
269
388
|
// CLI-PROJECT-CREATE-01 (Iter 34): create a new project. Per LAB
|
|
270
389
|
// projects.py:239 — POST /api/projects/ with {project_name}.
|
|
271
390
|
async createProject(name) {
|
|
@@ -1213,7 +1332,7 @@ var init_RunCommandTool = __esm({
|
|
|
1213
1332
|
this.activeCommands++;
|
|
1214
1333
|
return;
|
|
1215
1334
|
}
|
|
1216
|
-
return new Promise((
|
|
1335
|
+
return new Promise((resolve19) => this.queue.push(resolve19));
|
|
1217
1336
|
}
|
|
1218
1337
|
static releaseLock() {
|
|
1219
1338
|
if (this.queue.length > 0) {
|
|
@@ -1292,9 +1411,9 @@ var init_RunCommandTool = __esm({
|
|
|
1292
1411
|
const chunks = { stdout: [], stderr: [] };
|
|
1293
1412
|
proc.stdout?.on("data", (chunk) => chunks.stdout.push(chunk));
|
|
1294
1413
|
proc.stderr?.on("data", (chunk) => chunks.stderr.push(chunk));
|
|
1295
|
-
const exitCode = await new Promise((
|
|
1296
|
-
proc.on("exit", (code) =>
|
|
1297
|
-
proc.on("error", () =>
|
|
1414
|
+
const exitCode = await new Promise((resolve19) => {
|
|
1415
|
+
proc.on("exit", (code) => resolve19(code ?? 1));
|
|
1416
|
+
proc.on("error", () => resolve19(1));
|
|
1298
1417
|
});
|
|
1299
1418
|
const stdout = Buffer.concat(chunks.stdout).toString("utf-8");
|
|
1300
1419
|
const stderr = Buffer.concat(chunks.stderr).toString("utf-8");
|
|
@@ -1405,9 +1524,9 @@ var init_src2 = __esm({
|
|
|
1405
1524
|
const messages = this.parser.parse(value);
|
|
1406
1525
|
for (const msg of messages) {
|
|
1407
1526
|
if (msg.id !== void 0 && this.pendingRequests.has(Number(msg.id))) {
|
|
1408
|
-
const
|
|
1409
|
-
if (
|
|
1410
|
-
|
|
1527
|
+
const resolve19 = this.pendingRequests.get(Number(msg.id));
|
|
1528
|
+
if (resolve19) {
|
|
1529
|
+
resolve19(msg.result || msg.error);
|
|
1411
1530
|
this.pendingRequests.delete(Number(msg.id));
|
|
1412
1531
|
}
|
|
1413
1532
|
}
|
|
@@ -1422,8 +1541,8 @@ var init_src2 = __esm({
|
|
|
1422
1541
|
const message = `Content-Length: ${Buffer.byteLength(content, "utf8")}\r
|
|
1423
1542
|
\r
|
|
1424
1543
|
${content}`;
|
|
1425
|
-
return new Promise((
|
|
1426
|
-
this.pendingRequests.set(id,
|
|
1544
|
+
return new Promise((resolve19) => {
|
|
1545
|
+
this.pendingRequests.set(id, resolve19);
|
|
1427
1546
|
this.process.stdin.write(message);
|
|
1428
1547
|
this.process.stdin.flush();
|
|
1429
1548
|
});
|
|
@@ -1555,9 +1674,9 @@ var init_SubShellTool = __esm({
|
|
|
1555
1674
|
}
|
|
1556
1675
|
throw e;
|
|
1557
1676
|
}
|
|
1558
|
-
await new Promise((
|
|
1559
|
-
proc.on("exit", () =>
|
|
1560
|
-
proc.on("error", () =>
|
|
1677
|
+
await new Promise((resolve19) => {
|
|
1678
|
+
proc.on("exit", () => resolve19());
|
|
1679
|
+
proc.on("error", () => resolve19());
|
|
1561
1680
|
});
|
|
1562
1681
|
return { content: `Successfully launched separate window for ${args2.worker_id}` };
|
|
1563
1682
|
}
|
|
@@ -1640,13 +1759,13 @@ async function findRg() {
|
|
|
1640
1759
|
const candidates = ["rg", "C:\\Program Files\\ripgrep\\rg.exe"];
|
|
1641
1760
|
for (const bin of candidates) {
|
|
1642
1761
|
try {
|
|
1643
|
-
const exited = await new Promise((
|
|
1762
|
+
const exited = await new Promise((resolve19) => {
|
|
1644
1763
|
try {
|
|
1645
1764
|
const p = spawn4(bin, ["--version"], { stdio: ["ignore", "pipe", "pipe"] });
|
|
1646
|
-
p.on("error", () =>
|
|
1647
|
-
p.on("exit", (code) =>
|
|
1765
|
+
p.on("error", () => resolve19(null));
|
|
1766
|
+
p.on("exit", (code) => resolve19(code));
|
|
1648
1767
|
} catch {
|
|
1649
|
-
|
|
1768
|
+
resolve19(null);
|
|
1650
1769
|
}
|
|
1651
1770
|
});
|
|
1652
1771
|
if (exited === 0) return bin;
|
|
@@ -1656,7 +1775,7 @@ async function findRg() {
|
|
|
1656
1775
|
return null;
|
|
1657
1776
|
}
|
|
1658
1777
|
function runRg(bin, args2) {
|
|
1659
|
-
return new Promise((
|
|
1778
|
+
return new Promise((resolve19) => {
|
|
1660
1779
|
const p = spawn4(bin, args2, { stdio: ["ignore", "pipe", "pipe"] });
|
|
1661
1780
|
let stdout = "";
|
|
1662
1781
|
let stderr = "";
|
|
@@ -1667,10 +1786,10 @@ function runRg(bin, args2) {
|
|
|
1667
1786
|
stderr += d.toString("utf8");
|
|
1668
1787
|
});
|
|
1669
1788
|
p.on("error", (e) => {
|
|
1670
|
-
|
|
1789
|
+
resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exitCode: -1 });
|
|
1671
1790
|
});
|
|
1672
1791
|
p.on("exit", (code) => {
|
|
1673
|
-
|
|
1792
|
+
resolve19({ stdout, stderr, exitCode: code });
|
|
1674
1793
|
});
|
|
1675
1794
|
});
|
|
1676
1795
|
}
|
|
@@ -2922,12 +3041,12 @@ Command: ${command}`,
|
|
|
2922
3041
|
proc.stdout?.on("data", (chunk) => chunks.stdout.push(chunk));
|
|
2923
3042
|
proc.stderr?.on("data", (chunk) => chunks.stderr.push(chunk));
|
|
2924
3043
|
const timeoutPromise = new Promise(
|
|
2925
|
-
(
|
|
3044
|
+
(resolve19) => setTimeout(() => resolve19("timeout"), timeoutMs)
|
|
2926
3045
|
);
|
|
2927
3046
|
const processPromise = (async () => {
|
|
2928
|
-
const exitCode2 = await new Promise((
|
|
2929
|
-
proc.on("exit", (code) =>
|
|
2930
|
-
proc.on("error", () =>
|
|
3047
|
+
const exitCode2 = await new Promise((resolve19) => {
|
|
3048
|
+
proc.on("exit", (code) => resolve19(code ?? 1));
|
|
3049
|
+
proc.on("error", () => resolve19(1));
|
|
2931
3050
|
});
|
|
2932
3051
|
const stdout2 = Buffer.concat(chunks.stdout).toString("utf-8");
|
|
2933
3052
|
const stderr2 = Buffer.concat(chunks.stderr).toString("utf-8");
|
|
@@ -3674,7 +3793,7 @@ async function copyDir(src, dst) {
|
|
|
3674
3793
|
}
|
|
3675
3794
|
async function backupFile(absPath) {
|
|
3676
3795
|
try {
|
|
3677
|
-
const { readFile:
|
|
3796
|
+
const { readFile: readFile24, writeFile: writeFile13, mkdir: mkdir9 } = await import("fs/promises");
|
|
3678
3797
|
const { homedir: homedir18 } = await import("os");
|
|
3679
3798
|
const { join: join31 } = await import("path");
|
|
3680
3799
|
const filename = absPath.split(/[\\/]/).pop() ?? "file";
|
|
@@ -3687,8 +3806,8 @@ async function backupFile(absPath) {
|
|
|
3687
3806
|
`${filename}.backup-${stamp}-${suffix}.bak`
|
|
3688
3807
|
);
|
|
3689
3808
|
await mkdir9(join31(homedir18(), ".msapling", "backups"), { recursive: true });
|
|
3690
|
-
const content = await
|
|
3691
|
-
await
|
|
3809
|
+
const content = await readFile24(absPath, "utf8");
|
|
3810
|
+
await writeFile13(backupPath, content, "utf8");
|
|
3692
3811
|
return backupPath;
|
|
3693
3812
|
} catch {
|
|
3694
3813
|
return null;
|
|
@@ -3913,15 +4032,15 @@ var init_DeleteFileTool = __esm({
|
|
|
3913
4032
|
let backedUpTo = null;
|
|
3914
4033
|
if (isFile) {
|
|
3915
4034
|
try {
|
|
3916
|
-
const { readFile:
|
|
4035
|
+
const { readFile: readFile24, writeFile: writeFile13, mkdir: mkdir9 } = await import("fs/promises");
|
|
3917
4036
|
const { homedir: homedir18 } = await import("os");
|
|
3918
|
-
const existingContent = await
|
|
4037
|
+
const existingContent = await readFile24(abs, "utf8");
|
|
3919
4038
|
const filename = abs.split(/[\\/]/).pop() ?? "file";
|
|
3920
4039
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3921
4040
|
const suffix = randomBytes6(4).toString("hex");
|
|
3922
4041
|
const backupPath = join11(homedir18(), ".msapling", "backups", `${filename}.backup-${stamp}-${suffix}.bak`);
|
|
3923
4042
|
await mkdir9(join11(homedir18(), ".msapling", "backups"), { recursive: true });
|
|
3924
|
-
await
|
|
4043
|
+
await writeFile13(backupPath, existingContent, "utf8");
|
|
3925
4044
|
backedUpTo = backupPath;
|
|
3926
4045
|
} catch {
|
|
3927
4046
|
}
|
|
@@ -4260,10 +4379,10 @@ var init_Voice = __esm({
|
|
|
4260
4379
|
`;
|
|
4261
4380
|
try {
|
|
4262
4381
|
if (process.platform === "win32") {
|
|
4263
|
-
await new Promise((
|
|
4382
|
+
await new Promise((resolve19, reject) => {
|
|
4264
4383
|
try {
|
|
4265
4384
|
const proc = spawn6("powershell", ["-Command", psCommand]);
|
|
4266
|
-
proc.on("exit", () =>
|
|
4385
|
+
proc.on("exit", () => resolve19());
|
|
4267
4386
|
proc.on("error", reject);
|
|
4268
4387
|
} catch (e) {
|
|
4269
4388
|
reject(e);
|
|
@@ -4377,7 +4496,7 @@ function matches(entry, ctx) {
|
|
|
4377
4496
|
async function runOne(entry, ctx) {
|
|
4378
4497
|
const timeoutMs = entry.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
4379
4498
|
const command = entry.command;
|
|
4380
|
-
return new Promise((
|
|
4499
|
+
return new Promise((resolve19) => {
|
|
4381
4500
|
const isWindows = process.platform === "win32";
|
|
4382
4501
|
const child = spawn7(isWindows ? "cmd.exe" : "sh", isWindows ? ["/c", command] : ["-c", command], {
|
|
4383
4502
|
cwd: ctx.cwd ?? process.cwd(),
|
|
@@ -4392,7 +4511,7 @@ async function runOne(entry, ctx) {
|
|
|
4392
4511
|
settled = true;
|
|
4393
4512
|
clearTimeout(killer);
|
|
4394
4513
|
const blocked = !!entry.blocking && (exitCode === null || exitCode !== 0);
|
|
4395
|
-
|
|
4514
|
+
resolve19({ command, exitCode, stdout, stderr, timedOut, blocked });
|
|
4396
4515
|
};
|
|
4397
4516
|
const killer = setTimeout(() => {
|
|
4398
4517
|
timedOut = true;
|
|
@@ -5257,8 +5376,8 @@ var init_Mutex = __esm({
|
|
|
5257
5376
|
*/
|
|
5258
5377
|
acquire() {
|
|
5259
5378
|
let release2;
|
|
5260
|
-
const next = new Promise((
|
|
5261
|
-
release2 =
|
|
5379
|
+
const next = new Promise((resolve19) => {
|
|
5380
|
+
release2 = resolve19;
|
|
5262
5381
|
});
|
|
5263
5382
|
const entry = this._queue.then(() => release2);
|
|
5264
5383
|
this._queue = this._queue.then(() => next);
|
|
@@ -5898,8 +6017,8 @@ var require_graceful_fs = __commonJS({
|
|
|
5898
6017
|
fs4.createReadStream = createReadStream;
|
|
5899
6018
|
fs4.createWriteStream = createWriteStream;
|
|
5900
6019
|
var fs$readFile = fs4.readFile;
|
|
5901
|
-
fs4.readFile =
|
|
5902
|
-
function
|
|
6020
|
+
fs4.readFile = readFile24;
|
|
6021
|
+
function readFile24(path2, options, cb) {
|
|
5903
6022
|
if (typeof options === "function")
|
|
5904
6023
|
cb = options, options = null;
|
|
5905
6024
|
return go$readFile(path2, options, cb);
|
|
@@ -5915,8 +6034,8 @@ var require_graceful_fs = __commonJS({
|
|
|
5915
6034
|
}
|
|
5916
6035
|
}
|
|
5917
6036
|
var fs$writeFile = fs4.writeFile;
|
|
5918
|
-
fs4.writeFile =
|
|
5919
|
-
function
|
|
6037
|
+
fs4.writeFile = writeFile13;
|
|
6038
|
+
function writeFile13(path2, data, options, cb) {
|
|
5920
6039
|
if (typeof options === "function")
|
|
5921
6040
|
cb = options, options = null;
|
|
5922
6041
|
return go$writeFile(path2, data, options, cb);
|
|
@@ -6918,12 +7037,12 @@ var require_adapter = __commonJS({
|
|
|
6918
7037
|
return newFs;
|
|
6919
7038
|
}
|
|
6920
7039
|
function toPromise(method) {
|
|
6921
|
-
return (...args2) => new Promise((
|
|
7040
|
+
return (...args2) => new Promise((resolve19, reject) => {
|
|
6922
7041
|
args2.push((err, result) => {
|
|
6923
7042
|
if (err) {
|
|
6924
7043
|
reject(err);
|
|
6925
7044
|
} else {
|
|
6926
|
-
|
|
7045
|
+
resolve19(result);
|
|
6927
7046
|
}
|
|
6928
7047
|
});
|
|
6929
7048
|
method(...args2);
|
|
@@ -7851,7 +7970,7 @@ var init_client = __esm({
|
|
|
7851
7970
|
if (!this.proc) throw new MCPClientError(`MCP server "${this.name}" not started`);
|
|
7852
7971
|
const id = this.nextId++;
|
|
7853
7972
|
const frame = { jsonrpc: "2.0", id, method, params };
|
|
7854
|
-
return new Promise((
|
|
7973
|
+
return new Promise((resolve19, reject) => {
|
|
7855
7974
|
const timer = setTimeout(() => {
|
|
7856
7975
|
this.pending.delete(id);
|
|
7857
7976
|
reject(new MCPClientError(`MCP request ${method} timed out after ${timeoutMs}ms`));
|
|
@@ -7859,7 +7978,7 @@ var init_client = __esm({
|
|
|
7859
7978
|
this.pending.set(id, {
|
|
7860
7979
|
resolve: (v) => {
|
|
7861
7980
|
clearTimeout(timer);
|
|
7862
|
-
|
|
7981
|
+
resolve19(v);
|
|
7863
7982
|
},
|
|
7864
7983
|
reject: (e) => {
|
|
7865
7984
|
clearTimeout(timer);
|
|
@@ -7886,7 +8005,7 @@ var init_client = __esm({
|
|
|
7886
8005
|
if (!this.proc?.stdout) return;
|
|
7887
8006
|
const stdout = this.proc.stdout;
|
|
7888
8007
|
const decoder = new TextDecoder();
|
|
7889
|
-
return new Promise((
|
|
8008
|
+
return new Promise((resolve19) => {
|
|
7890
8009
|
stdout.on("data", (chunk) => {
|
|
7891
8010
|
this.buffer += decoder.decode(chunk, { stream: true });
|
|
7892
8011
|
let idx;
|
|
@@ -7897,8 +8016,8 @@ var init_client = __esm({
|
|
|
7897
8016
|
this.handleFrame(line);
|
|
7898
8017
|
}
|
|
7899
8018
|
});
|
|
7900
|
-
stdout.on("end", () =>
|
|
7901
|
-
stdout.on("error", () =>
|
|
8019
|
+
stdout.on("end", () => resolve19());
|
|
8020
|
+
stdout.on("error", () => resolve19());
|
|
7902
8021
|
});
|
|
7903
8022
|
}
|
|
7904
8023
|
handleFrame(line) {
|
|
@@ -8122,7 +8241,7 @@ function setRawModeGuarded(stdin, mode) {
|
|
|
8122
8241
|
}
|
|
8123
8242
|
}
|
|
8124
8243
|
async function promptPassword(prompt4) {
|
|
8125
|
-
return new Promise((
|
|
8244
|
+
return new Promise((resolve19) => {
|
|
8126
8245
|
const stdin = process.stdin;
|
|
8127
8246
|
const stdout = process.stdout;
|
|
8128
8247
|
stdout.write(prompt4);
|
|
@@ -8135,12 +8254,12 @@ async function promptPassword(prompt4) {
|
|
|
8135
8254
|
setRawModeGuarded(stdin, wasRaw);
|
|
8136
8255
|
stdin.removeListener("data", onData);
|
|
8137
8256
|
stdout.write("\n");
|
|
8138
|
-
|
|
8257
|
+
resolve19(password);
|
|
8139
8258
|
} else if (char === "") {
|
|
8140
8259
|
setRawModeGuarded(stdin, wasRaw);
|
|
8141
8260
|
stdin.removeListener("data", onData);
|
|
8142
8261
|
stdout.write("\n");
|
|
8143
|
-
|
|
8262
|
+
resolve19("");
|
|
8144
8263
|
} else if (char === "\x7F" || char === "\b") {
|
|
8145
8264
|
password = password.slice(0, -1);
|
|
8146
8265
|
} else if (char >= " " && char <= "~") {
|
|
@@ -8219,7 +8338,7 @@ async function loginWithGithubDevice(context) {
|
|
|
8219
8338
|
const deadline = Date.now() + expires_in * 1e3;
|
|
8220
8339
|
let githubToken = null;
|
|
8221
8340
|
while (Date.now() < deadline) {
|
|
8222
|
-
await new Promise((
|
|
8341
|
+
await new Promise((resolve19) => setTimeout(resolve19, pollMs));
|
|
8223
8342
|
let tokenResp;
|
|
8224
8343
|
try {
|
|
8225
8344
|
tokenResp = await fetch(GITHUB_TOKEN_URL, {
|
|
@@ -8243,7 +8362,7 @@ async function loginWithGithubDevice(context) {
|
|
|
8243
8362
|
if (tokenData.error === "authorization_pending") continue;
|
|
8244
8363
|
if (tokenData.error === "slow_down") {
|
|
8245
8364
|
pollMs += 5e3;
|
|
8246
|
-
await new Promise((
|
|
8365
|
+
await new Promise((resolve19) => setTimeout(resolve19, 5e3));
|
|
8247
8366
|
continue;
|
|
8248
8367
|
}
|
|
8249
8368
|
context.addMessage("system", `GitHub auth error: ${tokenData.error_description || tokenData.error}`);
|
|
@@ -8656,10 +8775,79 @@ async function createChat(args2, context) {
|
|
|
8656
8775
|
context.addMessage("error", `Failed to create chat: ${e.message}`);
|
|
8657
8776
|
}
|
|
8658
8777
|
}
|
|
8778
|
+
async function resolveChatId(rest, context) {
|
|
8779
|
+
const candidate = rest[0]?.trim();
|
|
8780
|
+
if (candidate && /^[0-9a-fA-F-]{32,}$/.test(candidate)) return candidate;
|
|
8781
|
+
return context.activeChatId ?? null;
|
|
8782
|
+
}
|
|
8783
|
+
async function lifecycleSub(args2, context) {
|
|
8784
|
+
const sub = args2[0]?.toLowerCase();
|
|
8785
|
+
const rest = args2.slice(1);
|
|
8786
|
+
try {
|
|
8787
|
+
if (sub === "rename") {
|
|
8788
|
+
const newTitle = rest.slice(1).join(" ").trim() || rest[0]?.trim();
|
|
8789
|
+
const chatId = await resolveChatId(rest, context);
|
|
8790
|
+
if (!chatId || !newTitle) {
|
|
8791
|
+
context.addMessage("system", "Usage: /chat rename [<chat_id>] <new title>");
|
|
8792
|
+
return;
|
|
8793
|
+
}
|
|
8794
|
+
const r = await context.client.renameChat(chatId, newTitle);
|
|
8795
|
+
context.addMessage("system", `Renamed to "${r.title}"`);
|
|
8796
|
+
return;
|
|
8797
|
+
}
|
|
8798
|
+
if (sub === "delete" || sub === "rm") {
|
|
8799
|
+
const chatId = await resolveChatId(rest, context);
|
|
8800
|
+
if (!chatId) {
|
|
8801
|
+
context.addMessage("system", "Usage: /chat delete [<chat_id>]");
|
|
8802
|
+
return;
|
|
8803
|
+
}
|
|
8804
|
+
await context.client.deleteChat(chatId);
|
|
8805
|
+
context.addMessage("system", `Deleted chat ${chatId}`);
|
|
8806
|
+
if (chatId === context.activeChatId) context.setActiveChatId(null);
|
|
8807
|
+
return;
|
|
8808
|
+
}
|
|
8809
|
+
if (sub === "fork") {
|
|
8810
|
+
const chatId = await resolveChatId(rest, context);
|
|
8811
|
+
if (!chatId) {
|
|
8812
|
+
context.addMessage("system", "Usage: /chat fork [<chat_id>]");
|
|
8813
|
+
return;
|
|
8814
|
+
}
|
|
8815
|
+
const r = await context.client.forkChat(chatId);
|
|
8816
|
+
context.addMessage("system", `Forked \u2192 ${r.chat_id ?? r.title ?? "(ok)"}`);
|
|
8817
|
+
if (r.chat_id) context.setActiveChatId(r.chat_id);
|
|
8818
|
+
return;
|
|
8819
|
+
}
|
|
8820
|
+
if (sub === "pin") {
|
|
8821
|
+
const chatId = await resolveChatId(rest, context);
|
|
8822
|
+
if (!chatId) {
|
|
8823
|
+
context.addMessage("system", "Usage: /chat pin [<chat_id>]");
|
|
8824
|
+
return;
|
|
8825
|
+
}
|
|
8826
|
+
await context.client.pinChat(chatId, true);
|
|
8827
|
+
context.addMessage("system", `Pinned ${chatId}`);
|
|
8828
|
+
return;
|
|
8829
|
+
}
|
|
8830
|
+
if (sub === "unpin") {
|
|
8831
|
+
const chatId = await resolveChatId(rest, context);
|
|
8832
|
+
if (!chatId) {
|
|
8833
|
+
context.addMessage("system", "Usage: /chat unpin [<chat_id>]");
|
|
8834
|
+
return;
|
|
8835
|
+
}
|
|
8836
|
+
await context.client.pinChat(chatId, false);
|
|
8837
|
+
context.addMessage("system", `Unpinned ${chatId}`);
|
|
8838
|
+
return;
|
|
8839
|
+
}
|
|
8840
|
+
} catch (e) {
|
|
8841
|
+
context.addMessage("error", `Chat ${sub}: ${e.message}`);
|
|
8842
|
+
}
|
|
8843
|
+
}
|
|
8659
8844
|
async function listChats(args2, context) {
|
|
8660
8845
|
if (args2[0] === "new" || args2[0] === "create") {
|
|
8661
8846
|
return createChat(args2.slice(1), context);
|
|
8662
8847
|
}
|
|
8848
|
+
if (["rename", "delete", "rm", "fork", "pin", "unpin"].includes(args2[0])) {
|
|
8849
|
+
return lifecycleSub(args2, context);
|
|
8850
|
+
}
|
|
8663
8851
|
const arg = args2.join(" ").trim();
|
|
8664
8852
|
const result = await fetchChatsForCurrentProject(context);
|
|
8665
8853
|
if ("error" in result) {
|
|
@@ -8782,6 +8970,344 @@ var init_broadcast = __esm({
|
|
|
8782
8970
|
}
|
|
8783
8971
|
});
|
|
8784
8972
|
|
|
8973
|
+
// src/commands/ollama.ts
|
|
8974
|
+
function formatSize(bytes) {
|
|
8975
|
+
if (!bytes) return "?";
|
|
8976
|
+
const gb = bytes / 1e9;
|
|
8977
|
+
if (gb >= 1) return `${gb.toFixed(1)} GB`;
|
|
8978
|
+
const mb = bytes / 1e6;
|
|
8979
|
+
return `${mb.toFixed(0)} MB`;
|
|
8980
|
+
}
|
|
8981
|
+
var DEFAULT_BASE_URL, ollamaCommand;
|
|
8982
|
+
var init_ollama = __esm({
|
|
8983
|
+
"src/commands/ollama.ts"() {
|
|
8984
|
+
"use strict";
|
|
8985
|
+
init_esm_shims();
|
|
8986
|
+
DEFAULT_BASE_URL = "http://localhost:11434";
|
|
8987
|
+
ollamaCommand = {
|
|
8988
|
+
name: "ollama",
|
|
8989
|
+
args: "[status|configure|enable|disable|test|models|pull|delete] [...args]",
|
|
8990
|
+
description: "Configure local Ollama integration (BYOK free tier) and manage local models.",
|
|
8991
|
+
category: "config",
|
|
8992
|
+
handler: async (args2, context) => {
|
|
8993
|
+
const sub = (args2[0] ?? "status").toLowerCase();
|
|
8994
|
+
const rest = args2.slice(1);
|
|
8995
|
+
try {
|
|
8996
|
+
if (sub === "status" || sub === "models") {
|
|
8997
|
+
const s = await context.client.getOllamaStatus();
|
|
8998
|
+
context.addMessage("system", "=== Ollama Status ===");
|
|
8999
|
+
context.addMessage("system", ` Enabled: ${s.enabled ? "yes" : "no"}`);
|
|
9000
|
+
context.addMessage("system", ` Base URL: ${s.base_url}`);
|
|
9001
|
+
context.addMessage("system", ` Connected: ${s.connected ? "yes" : "no"}${s.connection_message ? " \u2014 " + s.connection_message : ""}`);
|
|
9002
|
+
if (s.models?.length) {
|
|
9003
|
+
context.addMessage("system", ` Models (${s.models.length}):`);
|
|
9004
|
+
for (const m of s.models) {
|
|
9005
|
+
context.addMessage("system", ` - ${m.id} (${formatSize(m.size)})`);
|
|
9006
|
+
}
|
|
9007
|
+
} else if (s.enabled) {
|
|
9008
|
+
context.addMessage("system", " Models: (none pulled \u2014 try /ollama pull <name>, e.g. llama3.2)");
|
|
9009
|
+
} else {
|
|
9010
|
+
context.addMessage("system", "");
|
|
9011
|
+
context.addMessage("system", " Run '/ollama configure' to enable.");
|
|
9012
|
+
}
|
|
9013
|
+
return;
|
|
9014
|
+
}
|
|
9015
|
+
if (sub === "configure" || sub === "enable") {
|
|
9016
|
+
const url = rest[0] || DEFAULT_BASE_URL;
|
|
9017
|
+
const res = await context.client.configureOllama({ baseUrl: url, enabled: true });
|
|
9018
|
+
context.addMessage("system", `Ollama enabled at ${url}: ${res.message ?? res.status}`);
|
|
9019
|
+
return;
|
|
9020
|
+
}
|
|
9021
|
+
if (sub === "disable") {
|
|
9022
|
+
const res = await context.client.disableOllama();
|
|
9023
|
+
context.addMessage("system", `Ollama disabled: ${res.message ?? res.status}`);
|
|
9024
|
+
return;
|
|
9025
|
+
}
|
|
9026
|
+
if (sub === "test") {
|
|
9027
|
+
const url = rest[0] || DEFAULT_BASE_URL;
|
|
9028
|
+
const res = await context.client.testOllama(url);
|
|
9029
|
+
context.addMessage("system", `Connection to ${url}: ${res.connected ? "OK" : "FAILED"} \u2014 ${res.message}`);
|
|
9030
|
+
if (res.models?.length) {
|
|
9031
|
+
context.addMessage("system", ` Found ${res.models.length} model(s):`);
|
|
9032
|
+
for (const m of res.models.slice(0, 12)) {
|
|
9033
|
+
context.addMessage("system", ` - ${m.id}`);
|
|
9034
|
+
}
|
|
9035
|
+
if (res.models.length > 12) context.addMessage("system", ` \u2026and ${res.models.length - 12} more.`);
|
|
9036
|
+
}
|
|
9037
|
+
return;
|
|
9038
|
+
}
|
|
9039
|
+
if (sub === "pull") {
|
|
9040
|
+
const model = rest[0];
|
|
9041
|
+
if (!model) {
|
|
9042
|
+
context.addMessage("system", "Usage: /ollama pull <model> (e.g. /ollama pull llama3.2)");
|
|
9043
|
+
return;
|
|
9044
|
+
}
|
|
9045
|
+
const status = await context.client.getOllamaStatus();
|
|
9046
|
+
const res = await context.client.configureOllama({
|
|
9047
|
+
baseUrl: status.base_url || DEFAULT_BASE_URL,
|
|
9048
|
+
enabled: status.enabled !== false,
|
|
9049
|
+
action: "pull",
|
|
9050
|
+
model
|
|
9051
|
+
});
|
|
9052
|
+
context.addMessage("system", res.message ?? res.status);
|
|
9053
|
+
return;
|
|
9054
|
+
}
|
|
9055
|
+
if (sub === "delete" || sub === "remove" || sub === "rm") {
|
|
9056
|
+
const model = rest[0];
|
|
9057
|
+
if (!model) {
|
|
9058
|
+
context.addMessage("system", "Usage: /ollama delete <model>");
|
|
9059
|
+
return;
|
|
9060
|
+
}
|
|
9061
|
+
const res = await context.client.deleteOllamaModel(model);
|
|
9062
|
+
context.addMessage("system", res.message ?? res.status);
|
|
9063
|
+
return;
|
|
9064
|
+
}
|
|
9065
|
+
context.addMessage("error", `Unknown /ollama subcommand '${sub}'. Try: status, configure, disable, test, pull, delete.`);
|
|
9066
|
+
} catch (e) {
|
|
9067
|
+
context.addMessage("error", `Ollama: ${e.message}`);
|
|
9068
|
+
}
|
|
9069
|
+
}
|
|
9070
|
+
};
|
|
9071
|
+
}
|
|
9072
|
+
});
|
|
9073
|
+
|
|
9074
|
+
// src/commands/keys.ts
|
|
9075
|
+
var keysCommand;
|
|
9076
|
+
var init_keys = __esm({
|
|
9077
|
+
"src/commands/keys.ts"() {
|
|
9078
|
+
"use strict";
|
|
9079
|
+
init_esm_shims();
|
|
9080
|
+
keysCommand = {
|
|
9081
|
+
name: "keys",
|
|
9082
|
+
args: "[list|add|delete] [...args]",
|
|
9083
|
+
description: "Manage BYOK provider API keys (openai, anthropic, google, openrouter, \u2026).",
|
|
9084
|
+
category: "config",
|
|
9085
|
+
handler: async (args2, context) => {
|
|
9086
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
9087
|
+
const rest = args2.slice(1);
|
|
9088
|
+
try {
|
|
9089
|
+
if (sub === "list" || sub === "status") {
|
|
9090
|
+
const s = await context.client.getProviderKeys();
|
|
9091
|
+
const providers = s.providers ?? [];
|
|
9092
|
+
context.addMessage("system", `Provider Keys (${providers.length}):`);
|
|
9093
|
+
for (const p of providers) {
|
|
9094
|
+
const tag = p.configured ? "\u2713" : " ";
|
|
9095
|
+
const prefix = p.key_prefix ? ` (${p.key_prefix}\u2026)` : "";
|
|
9096
|
+
context.addMessage("system", ` [${tag}] ${p.provider}${prefix}`);
|
|
9097
|
+
}
|
|
9098
|
+
if (providers.length === 0) {
|
|
9099
|
+
context.addMessage("system", " (none \u2014 add via /keys add <provider> <key>)");
|
|
9100
|
+
}
|
|
9101
|
+
return;
|
|
9102
|
+
}
|
|
9103
|
+
if (sub === "add" || sub === "save") {
|
|
9104
|
+
const provider = rest[0];
|
|
9105
|
+
const key = rest.slice(1).join(" ").trim();
|
|
9106
|
+
if (!provider || !key) {
|
|
9107
|
+
context.addMessage("system", "Usage: /keys add <provider> <key> (e.g. /keys add openai sk-...)");
|
|
9108
|
+
return;
|
|
9109
|
+
}
|
|
9110
|
+
const res = await context.client.saveProviderKey(provider, key);
|
|
9111
|
+
context.addMessage("system", `Saved key for ${provider}: ${res.message ?? res.status}`);
|
|
9112
|
+
return;
|
|
9113
|
+
}
|
|
9114
|
+
if (sub === "delete" || sub === "rm" || sub === "remove") {
|
|
9115
|
+
const provider = rest[0];
|
|
9116
|
+
if (!provider) {
|
|
9117
|
+
context.addMessage("system", "Usage: /keys delete <provider>");
|
|
9118
|
+
return;
|
|
9119
|
+
}
|
|
9120
|
+
const res = await context.client.deleteProviderKey(provider);
|
|
9121
|
+
context.addMessage("system", `Removed key for ${provider}: ${res.message ?? res.status}`);
|
|
9122
|
+
return;
|
|
9123
|
+
}
|
|
9124
|
+
context.addMessage("error", `Unknown /keys subcommand '${sub}'. Try: list, add, delete.`);
|
|
9125
|
+
} catch (e) {
|
|
9126
|
+
context.addMessage("error", `Keys: ${e.message}`);
|
|
9127
|
+
}
|
|
9128
|
+
}
|
|
9129
|
+
};
|
|
9130
|
+
}
|
|
9131
|
+
});
|
|
9132
|
+
|
|
9133
|
+
// src/commands/memories.ts
|
|
9134
|
+
var memoriesCommand;
|
|
9135
|
+
var init_memories = __esm({
|
|
9136
|
+
"src/commands/memories.ts"() {
|
|
9137
|
+
"use strict";
|
|
9138
|
+
init_esm_shims();
|
|
9139
|
+
memoriesCommand = {
|
|
9140
|
+
name: "memories",
|
|
9141
|
+
args: "[list|add|delete] [...args]",
|
|
9142
|
+
description: "Manage the user-scoped memory bank (used across all chats).",
|
|
9143
|
+
category: "project",
|
|
9144
|
+
handler: async (args2, context) => {
|
|
9145
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
9146
|
+
const rest = args2.slice(1);
|
|
9147
|
+
try {
|
|
9148
|
+
if (sub === "list" || sub === "show") {
|
|
9149
|
+
const items = await context.client.listMemories();
|
|
9150
|
+
if (!items || items.length === 0) {
|
|
9151
|
+
context.addMessage("system", "No memories yet. Add one via /memories add <text>.");
|
|
9152
|
+
return;
|
|
9153
|
+
}
|
|
9154
|
+
context.addMessage("system", `Memories (${items.length}):`);
|
|
9155
|
+
for (const m of items) {
|
|
9156
|
+
const when = m.created_at ? new Date(m.created_at).toISOString().slice(0, 10) : "";
|
|
9157
|
+
context.addMessage("system", ` ${m.id?.slice(0, 8)} \xB7 ${when} ${m.content}`);
|
|
9158
|
+
}
|
|
9159
|
+
return;
|
|
9160
|
+
}
|
|
9161
|
+
if (sub === "add" || sub === "save") {
|
|
9162
|
+
const content = rest.join(" ").trim();
|
|
9163
|
+
if (!content) {
|
|
9164
|
+
context.addMessage("system", "Usage: /memories add <content>");
|
|
9165
|
+
return;
|
|
9166
|
+
}
|
|
9167
|
+
const m = await context.client.createMemory(content);
|
|
9168
|
+
context.addMessage("system", `Saved (${m.id?.slice(0, 8)}).`);
|
|
9169
|
+
return;
|
|
9170
|
+
}
|
|
9171
|
+
if (sub === "delete" || sub === "rm" || sub === "remove") {
|
|
9172
|
+
const id = rest[0]?.trim();
|
|
9173
|
+
if (!id) {
|
|
9174
|
+
context.addMessage("system", "Usage: /memories delete <id>");
|
|
9175
|
+
return;
|
|
9176
|
+
}
|
|
9177
|
+
await context.client.deleteMemory(id);
|
|
9178
|
+
context.addMessage("system", `Deleted ${id.slice(0, 8)}.`);
|
|
9179
|
+
return;
|
|
9180
|
+
}
|
|
9181
|
+
context.addMessage("error", `Unknown /memories subcommand '${sub}'. Try: list, add, delete.`);
|
|
9182
|
+
} catch (e) {
|
|
9183
|
+
context.addMessage("error", `Memories: ${e.message}`);
|
|
9184
|
+
}
|
|
9185
|
+
}
|
|
9186
|
+
};
|
|
9187
|
+
}
|
|
9188
|
+
});
|
|
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
|
+
|
|
8785
9311
|
// src/commands/clear.ts
|
|
8786
9312
|
var clearCommand;
|
|
8787
9313
|
var init_clear = __esm({
|
|
@@ -8807,13 +9333,13 @@ var init_clear = __esm({
|
|
|
8807
9333
|
// src/commands/mode.ts
|
|
8808
9334
|
import { homedir as homedir10 } from "os";
|
|
8809
9335
|
import { join as join17 } from "path";
|
|
8810
|
-
import { existsSync as
|
|
8811
|
-
import { readFile as
|
|
9336
|
+
import { existsSync as existsSync16 } from "fs";
|
|
9337
|
+
import { readFile as readFile15, writeFile as writeFile8, mkdir as mkdir7 } from "fs/promises";
|
|
8812
9338
|
async function persistApprovalMode(mode, ttlMs) {
|
|
8813
9339
|
try {
|
|
8814
9340
|
let existing = {};
|
|
8815
|
-
if (
|
|
8816
|
-
const text = await
|
|
9341
|
+
if (existsSync16(SETTINGS_PATH)) {
|
|
9342
|
+
const text = await readFile15(SETTINGS_PATH, "utf8");
|
|
8817
9343
|
if (text.trim()) {
|
|
8818
9344
|
existing = JSON.parse(text);
|
|
8819
9345
|
}
|
|
@@ -8825,10 +9351,10 @@ async function persistApprovalMode(mode, ttlMs) {
|
|
|
8825
9351
|
};
|
|
8826
9352
|
existing.approvalMode = entry;
|
|
8827
9353
|
const settingsDir = join17(homedir10(), ".msapling");
|
|
8828
|
-
if (!
|
|
9354
|
+
if (!existsSync16(settingsDir)) {
|
|
8829
9355
|
await mkdir7(settingsDir, { recursive: true });
|
|
8830
9356
|
}
|
|
8831
|
-
await
|
|
9357
|
+
await writeFile8(SETTINGS_PATH, JSON.stringify(existing, null, 2), "utf8");
|
|
8832
9358
|
} catch {
|
|
8833
9359
|
}
|
|
8834
9360
|
}
|
|
@@ -9213,8 +9739,8 @@ var init_compact = __esm({
|
|
|
9213
9739
|
|
|
9214
9740
|
// src/commands/init.ts
|
|
9215
9741
|
import { join as join18 } from "path";
|
|
9216
|
-
import { existsSync as
|
|
9217
|
-
import { writeFile as
|
|
9742
|
+
import { existsSync as existsSync17 } from "fs";
|
|
9743
|
+
import { writeFile as writeFile9 } from "fs/promises";
|
|
9218
9744
|
var initCommand;
|
|
9219
9745
|
var init_init = __esm({
|
|
9220
9746
|
"src/commands/init.ts"() {
|
|
@@ -9228,7 +9754,7 @@ var init_init = __esm({
|
|
|
9228
9754
|
try {
|
|
9229
9755
|
const cwd = process.cwd();
|
|
9230
9756
|
const path2 = join18(cwd, "MSAPLING.md");
|
|
9231
|
-
if (
|
|
9757
|
+
if (existsSync17(path2)) {
|
|
9232
9758
|
context.addMessage("error", "MSAPLING.md already exists in current directory.");
|
|
9233
9759
|
return;
|
|
9234
9760
|
}
|
|
@@ -9243,7 +9769,7 @@ var init_init = __esm({
|
|
|
9243
9769
|
## Guidelines
|
|
9244
9770
|
- Follow existing code style.
|
|
9245
9771
|
`;
|
|
9246
|
-
await
|
|
9772
|
+
await writeFile9(path2, content, "utf8");
|
|
9247
9773
|
context.addMessage("system", `Created MSAPLING.md at ${path2}`);
|
|
9248
9774
|
} catch (e) {
|
|
9249
9775
|
context.addMessage("error", `Failed to initialize project: ${e.message}`);
|
|
@@ -9254,8 +9780,8 @@ var init_init = __esm({
|
|
|
9254
9780
|
});
|
|
9255
9781
|
|
|
9256
9782
|
// src/commands/review.ts
|
|
9257
|
-
import { existsSync as
|
|
9258
|
-
import { readFile as
|
|
9783
|
+
import { existsSync as existsSync18 } from "fs";
|
|
9784
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
9259
9785
|
var reviewCommand;
|
|
9260
9786
|
var init_review = __esm({
|
|
9261
9787
|
"src/commands/review.ts"() {
|
|
@@ -9274,8 +9800,8 @@ var init_review = __esm({
|
|
|
9274
9800
|
}
|
|
9275
9801
|
let content = "";
|
|
9276
9802
|
try {
|
|
9277
|
-
if (
|
|
9278
|
-
content = await
|
|
9803
|
+
if (existsSync18(target)) {
|
|
9804
|
+
content = await readFile16(target, "utf8");
|
|
9279
9805
|
} else {
|
|
9280
9806
|
content = `Review target: ${target}`;
|
|
9281
9807
|
}
|
|
@@ -9368,15 +9894,15 @@ var init_swarm = __esm({
|
|
|
9368
9894
|
|
|
9369
9895
|
// src/commands/recipe.ts
|
|
9370
9896
|
import { parse as parseYaml } from "yaml";
|
|
9371
|
-
import { existsSync as
|
|
9372
|
-
import { readFile as
|
|
9897
|
+
import { existsSync as existsSync19 } from "fs";
|
|
9898
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
9373
9899
|
import { join as join19 } from "path";
|
|
9374
9900
|
function findRecipe(name, cwd) {
|
|
9375
9901
|
for (const dir of RECIPE_DIRS) {
|
|
9376
9902
|
for (const suffix of NAME_SUFFIXES) {
|
|
9377
9903
|
for (const ext of FILE_EXTS) {
|
|
9378
9904
|
const p = join19(cwd, dir, `${name}${suffix}${ext}`);
|
|
9379
|
-
if (
|
|
9905
|
+
if (existsSync19(p)) return p;
|
|
9380
9906
|
}
|
|
9381
9907
|
}
|
|
9382
9908
|
}
|
|
@@ -9435,7 +9961,7 @@ var init_recipe = __esm({
|
|
|
9435
9961
|
let text;
|
|
9436
9962
|
let recipe;
|
|
9437
9963
|
try {
|
|
9438
|
-
text = await
|
|
9964
|
+
text = await readFile17(path2, "utf8");
|
|
9439
9965
|
recipe = parseYaml(text);
|
|
9440
9966
|
} catch (e) {
|
|
9441
9967
|
context.addMessage("error", `Failed to load ${path2}: ${e.message}`);
|
|
@@ -9489,13 +10015,13 @@ ${rendered}` : rendered;
|
|
|
9489
10015
|
});
|
|
9490
10016
|
|
|
9491
10017
|
// src/commands/skill.ts
|
|
9492
|
-
import { existsSync as
|
|
9493
|
-
import { readFile as
|
|
9494
|
-
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";
|
|
9495
10021
|
function findSkillsRoot(cwd) {
|
|
9496
10022
|
for (const candidate of SKILLS_DIRS) {
|
|
9497
|
-
const full =
|
|
9498
|
-
if (
|
|
10023
|
+
const full = resolve15(cwd, candidate);
|
|
10024
|
+
if (existsSync20(full) && statSync5(full).isDirectory()) return full;
|
|
9499
10025
|
}
|
|
9500
10026
|
return null;
|
|
9501
10027
|
}
|
|
@@ -9589,7 +10115,7 @@ var init_skill = __esm({
|
|
|
9589
10115
|
}
|
|
9590
10116
|
let body;
|
|
9591
10117
|
try {
|
|
9592
|
-
body = await
|
|
10118
|
+
body = await readFile18(skill.path, "utf8");
|
|
9593
10119
|
} catch (e) {
|
|
9594
10120
|
context.addMessage("error", `Failed to load skill ${skill.path}: ${e.message}`);
|
|
9595
10121
|
return;
|
|
@@ -9985,21 +10511,21 @@ var init_theme = __esm({
|
|
|
9985
10511
|
// src/commands/theme.ts
|
|
9986
10512
|
import { join as join22 } from "path";
|
|
9987
10513
|
import { homedir as homedir12 } from "os";
|
|
9988
|
-
import { existsSync as
|
|
9989
|
-
import { readFile as
|
|
10514
|
+
import { existsSync as existsSync21 } from "fs";
|
|
10515
|
+
import { readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
|
|
9990
10516
|
async function persistTheme(storage, themeName) {
|
|
9991
10517
|
const settingsPath = join22(homedir12(), ".msapling", "settings.json");
|
|
9992
10518
|
let existing = {};
|
|
9993
10519
|
try {
|
|
9994
|
-
if (
|
|
9995
|
-
const text = await
|
|
10520
|
+
if (existsSync21(settingsPath)) {
|
|
10521
|
+
const text = await readFile19(settingsPath, "utf8");
|
|
9996
10522
|
if (text.trim()) existing = JSON.parse(text);
|
|
9997
10523
|
}
|
|
9998
10524
|
} catch {
|
|
9999
10525
|
}
|
|
10000
10526
|
existing["theme"] = themeName;
|
|
10001
10527
|
ensureConfigDir(join22(homedir12(), ".msapling"));
|
|
10002
|
-
await
|
|
10528
|
+
await writeFile10(settingsPath, JSON.stringify(existing, null, 2), "utf8");
|
|
10003
10529
|
}
|
|
10004
10530
|
var VALID_THEMES, themeCommand;
|
|
10005
10531
|
var init_theme2 = __esm({
|
|
@@ -10070,7 +10596,7 @@ var init_version = __esm({
|
|
|
10070
10596
|
description: "Show version information for CLI and core packages",
|
|
10071
10597
|
category: "debug",
|
|
10072
10598
|
handler: async (_args, context) => {
|
|
10073
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
10599
|
+
const cliVersion = true ? "2.3.6-beta.25" : "(dev)";
|
|
10074
10600
|
const coreVersion = true ? "2.3.2" : "(dev)";
|
|
10075
10601
|
const runtime = process.version;
|
|
10076
10602
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -10079,7 +10605,7 @@ var init_version = __esm({
|
|
|
10079
10605
|
context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
|
|
10080
10606
|
context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
|
|
10081
10607
|
try {
|
|
10082
|
-
const ts = "2026-05-28T19:
|
|
10608
|
+
const ts = "2026-05-28T19:45:02.204Z";
|
|
10083
10609
|
if (ts && ts !== "__BUILD_TIMESTAMP__") {
|
|
10084
10610
|
context.addMessage("system", row2("Build Timestamp", ts));
|
|
10085
10611
|
}
|
|
@@ -10093,14 +10619,14 @@ var init_version = __esm({
|
|
|
10093
10619
|
|
|
10094
10620
|
// src/commands/feedback.ts
|
|
10095
10621
|
import { join as join23 } from "path";
|
|
10096
|
-
import { existsSync as
|
|
10097
|
-
import { readFile as
|
|
10622
|
+
import { existsSync as existsSync22 } from "fs";
|
|
10623
|
+
import { readFile as readFile20 } from "fs/promises";
|
|
10098
10624
|
async function readCliVersion() {
|
|
10099
10625
|
try {
|
|
10100
10626
|
const baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
10101
10627
|
const pkgPath = join23(baseDir, "..", "..", "package.json");
|
|
10102
|
-
if (!
|
|
10103
|
-
const text = await
|
|
10628
|
+
if (!existsSync22(pkgPath)) return "unknown";
|
|
10629
|
+
const text = await readFile20(pkgPath, "utf8");
|
|
10104
10630
|
const json = JSON.parse(text);
|
|
10105
10631
|
return json.version ?? "unknown";
|
|
10106
10632
|
} catch {
|
|
@@ -10142,7 +10668,7 @@ var init_feedback = __esm({
|
|
|
10142
10668
|
// src/commands/export.ts
|
|
10143
10669
|
import { homedir as homedir13 } from "os";
|
|
10144
10670
|
import { join as join24 } from "path";
|
|
10145
|
-
import { writeFile as
|
|
10671
|
+
import { writeFile as writeFile11, mkdir as mkdir8 } from "fs/promises";
|
|
10146
10672
|
function formatTimestamp(date) {
|
|
10147
10673
|
return date.toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
10148
10674
|
}
|
|
@@ -10208,7 +10734,7 @@ var init_export = __esm({
|
|
|
10208
10734
|
try {
|
|
10209
10735
|
const dir = join24(outputPath, "..");
|
|
10210
10736
|
await mkdir8(dir, { recursive: true });
|
|
10211
|
-
await
|
|
10737
|
+
await writeFile11(outputPath, content, "utf8");
|
|
10212
10738
|
context.addMessage("system", `Exported to: ${outputPath}`);
|
|
10213
10739
|
} catch (e) {
|
|
10214
10740
|
context.addMessage("error", `Failed to export: ${e.message}`);
|
|
@@ -10403,15 +10929,15 @@ var init_plan = __esm({
|
|
|
10403
10929
|
// src/commands/note.ts
|
|
10404
10930
|
import { homedir as homedir14 } from "os";
|
|
10405
10931
|
import { join as join25 } from "path";
|
|
10406
|
-
import { existsSync as
|
|
10407
|
-
import { readFile as
|
|
10932
|
+
import { existsSync as existsSync23 } from "fs";
|
|
10933
|
+
import { readFile as readFile21, writeFile as writeFile12 } from "fs/promises";
|
|
10408
10934
|
function getNotesFilePath() {
|
|
10409
10935
|
return join25(homedir14(), ".msapling", "notes.json");
|
|
10410
10936
|
}
|
|
10411
10937
|
async function readNotes(filePath = getNotesFilePath()) {
|
|
10412
10938
|
try {
|
|
10413
|
-
if (!
|
|
10414
|
-
const raw = await
|
|
10939
|
+
if (!existsSync23(filePath)) return [];
|
|
10940
|
+
const raw = await readFile21(filePath, "utf8");
|
|
10415
10941
|
const parsed = JSON.parse(raw);
|
|
10416
10942
|
if (!Array.isArray(parsed)) return [];
|
|
10417
10943
|
return parsed;
|
|
@@ -10422,7 +10948,7 @@ async function readNotes(filePath = getNotesFilePath()) {
|
|
|
10422
10948
|
async function writeNotes(notes, filePath = getNotesFilePath()) {
|
|
10423
10949
|
const dir = join25(homedir14(), ".msapling");
|
|
10424
10950
|
ensureConfigDir(dir);
|
|
10425
|
-
await
|
|
10951
|
+
await writeFile12(filePath, JSON.stringify(notes, null, 2), "utf8");
|
|
10426
10952
|
}
|
|
10427
10953
|
function formatTimestamp2(iso) {
|
|
10428
10954
|
const d = new Date(iso);
|
|
@@ -10567,8 +11093,8 @@ var init_todo = __esm({
|
|
|
10567
11093
|
|
|
10568
11094
|
// src/commands/outputStyle.ts
|
|
10569
11095
|
import { homedir as homedir15 } from "os";
|
|
10570
|
-
import { join as join26, basename, extname as extname3 } from "path";
|
|
10571
|
-
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";
|
|
10572
11098
|
function stylesDir() {
|
|
10573
11099
|
return join26(homedir15(), ".msapling", "output-styles");
|
|
10574
11100
|
}
|
|
@@ -10594,7 +11120,7 @@ function parseStyleFile(text) {
|
|
|
10594
11120
|
}
|
|
10595
11121
|
function listUserStyles() {
|
|
10596
11122
|
const dir = stylesDir();
|
|
10597
|
-
if (!
|
|
11123
|
+
if (!existsSync24(dir)) return [];
|
|
10598
11124
|
const out = [];
|
|
10599
11125
|
for (const entry of readdirSync3(dir)) {
|
|
10600
11126
|
if (extname3(entry).toLowerCase() !== ".md") continue;
|
|
@@ -10603,7 +11129,7 @@ function listUserStyles() {
|
|
|
10603
11129
|
const text = readFileSync(full, "utf8");
|
|
10604
11130
|
const { description, body } = parseStyleFile(text);
|
|
10605
11131
|
out.push({
|
|
10606
|
-
name:
|
|
11132
|
+
name: basename2(entry, ".md"),
|
|
10607
11133
|
description,
|
|
10608
11134
|
body,
|
|
10609
11135
|
source: "user",
|
|
@@ -10626,7 +11152,7 @@ function findStyle(name) {
|
|
|
10626
11152
|
function getActiveStyleName() {
|
|
10627
11153
|
try {
|
|
10628
11154
|
const f = activeFile();
|
|
10629
|
-
if (!
|
|
11155
|
+
if (!existsSync24(f)) return "default";
|
|
10630
11156
|
return readFileSync(f, "utf8").trim() || "default";
|
|
10631
11157
|
} catch {
|
|
10632
11158
|
return "default";
|
|
@@ -10634,7 +11160,7 @@ function getActiveStyleName() {
|
|
|
10634
11160
|
}
|
|
10635
11161
|
function setActiveStyleName(name) {
|
|
10636
11162
|
const dir = stylesDir();
|
|
10637
|
-
if (!
|
|
11163
|
+
if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
|
|
10638
11164
|
writeFileSync2(activeFile(), `${name}
|
|
10639
11165
|
`, "utf8");
|
|
10640
11166
|
}
|
|
@@ -10647,7 +11173,7 @@ function createUserStyle(name, description, body) {
|
|
|
10647
11173
|
throw new Error(`Invalid style name "${name}" \u2014 use letters, digits, _ and - only.`);
|
|
10648
11174
|
}
|
|
10649
11175
|
const dir = stylesDir();
|
|
10650
|
-
if (!
|
|
11176
|
+
if (!existsSync24(dir)) mkdirSync5(dir, { recursive: true });
|
|
10651
11177
|
const target = join26(dir, `${name}.md`);
|
|
10652
11178
|
const frontmatter = `---
|
|
10653
11179
|
description: ${description.replace(/\n/g, " ")}
|
|
@@ -10819,6 +11345,10 @@ var init_commands = __esm({
|
|
|
10819
11345
|
init_help();
|
|
10820
11346
|
init_chat();
|
|
10821
11347
|
init_broadcast();
|
|
11348
|
+
init_ollama();
|
|
11349
|
+
init_keys();
|
|
11350
|
+
init_memories();
|
|
11351
|
+
init_mdrive();
|
|
10822
11352
|
init_clear();
|
|
10823
11353
|
init_mode();
|
|
10824
11354
|
init_model();
|
|
@@ -10855,6 +11385,10 @@ var init_commands = __esm({
|
|
|
10855
11385
|
chatCommand,
|
|
10856
11386
|
chatsCommand,
|
|
10857
11387
|
broadcastCommand,
|
|
11388
|
+
ollamaCommand,
|
|
11389
|
+
keysCommand,
|
|
11390
|
+
memoriesCommand,
|
|
11391
|
+
mdriveCommand,
|
|
10858
11392
|
clearCommand,
|
|
10859
11393
|
modeCommand,
|
|
10860
11394
|
modelCommand,
|
|
@@ -10951,16 +11485,16 @@ var exec_exports = {};
|
|
|
10951
11485
|
__export(exec_exports, {
|
|
10952
11486
|
runExec: () => runExec
|
|
10953
11487
|
});
|
|
10954
|
-
import { existsSync as
|
|
10955
|
-
import { readFile as
|
|
11488
|
+
import { existsSync as existsSync26 } from "fs";
|
|
11489
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
10956
11490
|
import { homedir as homedir16 } from "os";
|
|
10957
11491
|
import { join as join27 } from "path";
|
|
10958
11492
|
async function loadPersistedSettings() {
|
|
10959
11493
|
const out = { mode: "default", theme: null };
|
|
10960
11494
|
try {
|
|
10961
11495
|
const p = join27(homedir16(), ".msapling", "settings.json");
|
|
10962
|
-
if (!
|
|
10963
|
-
const raw = JSON.parse(await
|
|
11496
|
+
if (!existsSync26(p)) return out;
|
|
11497
|
+
const raw = JSON.parse(await readFile23(p, "utf8"));
|
|
10964
11498
|
const parsed = parseApprovalMode(raw, Date.now());
|
|
10965
11499
|
if (parsed.kind === "ok") out.mode = parsed.mode;
|
|
10966
11500
|
const themeRaw = raw?.theme;
|
|
@@ -11210,13 +11744,13 @@ async function openBrowser(url) {
|
|
|
11210
11744
|
cmd = "xdg-open";
|
|
11211
11745
|
args2 = [url];
|
|
11212
11746
|
}
|
|
11213
|
-
return new Promise((
|
|
11747
|
+
return new Promise((resolve19) => {
|
|
11214
11748
|
try {
|
|
11215
11749
|
const child = spawn10(cmd, args2, { stdio: "ignore", detached: true });
|
|
11216
11750
|
child.unref();
|
|
11217
11751
|
} catch {
|
|
11218
11752
|
}
|
|
11219
|
-
|
|
11753
|
+
resolve19();
|
|
11220
11754
|
});
|
|
11221
11755
|
}
|
|
11222
11756
|
var init_open_browser = __esm({
|
|
@@ -11306,7 +11840,7 @@ var init_checkout = __esm({
|
|
|
11306
11840
|
// src/commands/billing/sub.ts
|
|
11307
11841
|
import * as readline from "readline";
|
|
11308
11842
|
function prompt(rl, question) {
|
|
11309
|
-
return new Promise((
|
|
11843
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11310
11844
|
}
|
|
11311
11845
|
async function runSub(argv) {
|
|
11312
11846
|
const subCmd = argv[0] ?? "";
|
|
@@ -11435,11 +11969,11 @@ var init_sub = __esm({
|
|
|
11435
11969
|
// src/commands/billing/topup.ts
|
|
11436
11970
|
import * as readline2 from "readline";
|
|
11437
11971
|
function prompt2(rl, question) {
|
|
11438
|
-
return new Promise((
|
|
11972
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11439
11973
|
}
|
|
11440
11974
|
function promptDefault(rl, question, defaultVal) {
|
|
11441
11975
|
return new Promise(
|
|
11442
|
-
(
|
|
11976
|
+
(resolve19) => rl.question(`${question} [${defaultVal}]: `, (ans) => resolve19(ans.trim() || defaultVal))
|
|
11443
11977
|
);
|
|
11444
11978
|
}
|
|
11445
11979
|
async function runTopup(argv) {
|
|
@@ -11580,7 +12114,7 @@ var init_redeem = __esm({
|
|
|
11580
12114
|
// src/commands/billing/gift.ts
|
|
11581
12115
|
import * as readline3 from "readline";
|
|
11582
12116
|
function prompt3(rl, question) {
|
|
11583
|
-
return new Promise((
|
|
12117
|
+
return new Promise((resolve19) => rl.question(question, resolve19));
|
|
11584
12118
|
}
|
|
11585
12119
|
async function runGift(argv) {
|
|
11586
12120
|
const subCmd = argv[0] ?? "";
|
|
@@ -11837,7 +12371,7 @@ __export(doctor_exports, {
|
|
|
11837
12371
|
});
|
|
11838
12372
|
import { homedir as homedir17, platform as platform3 } from "os";
|
|
11839
12373
|
import { join as join28 } from "path";
|
|
11840
|
-
import { existsSync as
|
|
12374
|
+
import { existsSync as existsSync27, statSync as statSync6, accessSync } from "fs";
|
|
11841
12375
|
import { readdir as readdir3 } from "fs/promises";
|
|
11842
12376
|
import { exec } from "child_process";
|
|
11843
12377
|
import { promisify } from "util";
|
|
@@ -11861,7 +12395,7 @@ async function checkNodeVersion() {
|
|
|
11861
12395
|
}
|
|
11862
12396
|
async function checkConfigDir() {
|
|
11863
12397
|
const configDir = join28(homedir17(), ".msapling");
|
|
11864
|
-
if (!
|
|
12398
|
+
if (!existsSync27(configDir)) {
|
|
11865
12399
|
return {
|
|
11866
12400
|
name: "Config directory",
|
|
11867
12401
|
status: "WARN",
|
|
@@ -11927,7 +12461,7 @@ async function checkPathConflicts() {
|
|
|
11927
12461
|
const paths = pathEnv.split(platform3() === "win32" ? ";" : ":");
|
|
11928
12462
|
const conflicts = [];
|
|
11929
12463
|
for (const dir of paths) {
|
|
11930
|
-
if (!dir || !
|
|
12464
|
+
if (!dir || !existsSync27(dir)) continue;
|
|
11931
12465
|
try {
|
|
11932
12466
|
const files = await readdir3(dir);
|
|
11933
12467
|
for (const file of files) {
|
|
@@ -13349,16 +13883,16 @@ var init_registry_merger = __esm({
|
|
|
13349
13883
|
// ../core/src/mcp/local_tools.ts
|
|
13350
13884
|
import { spawn as spawn11 } from "child_process";
|
|
13351
13885
|
import { readdir as readdir4, stat as stat4, realpath as realpath2 } from "fs/promises";
|
|
13352
|
-
import { resolve as
|
|
13886
|
+
import { resolve as resolve17 } from "path";
|
|
13353
13887
|
function asResult(text, isError = false) {
|
|
13354
13888
|
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
13355
13889
|
}
|
|
13356
13890
|
async function runCommand(command, cwd) {
|
|
13357
|
-
return new Promise((
|
|
13891
|
+
return new Promise((resolve19) => {
|
|
13358
13892
|
let p;
|
|
13359
13893
|
const timeout = setTimeout(() => {
|
|
13360
13894
|
if (p) p.kill();
|
|
13361
|
-
|
|
13895
|
+
resolve19({ stdout: "", stderr: "Command timed out after 30s", exit_code: -1 });
|
|
13362
13896
|
}, 3e4);
|
|
13363
13897
|
try {
|
|
13364
13898
|
p = spawn11("sh", ["-c", command], {
|
|
@@ -13376,15 +13910,15 @@ async function runCommand(command, cwd) {
|
|
|
13376
13910
|
});
|
|
13377
13911
|
p.on("error", (e) => {
|
|
13378
13912
|
clearTimeout(timeout);
|
|
13379
|
-
|
|
13913
|
+
resolve19({ stdout, stderr: stderr + (e?.message ?? ""), exit_code: -1 });
|
|
13380
13914
|
});
|
|
13381
13915
|
p.on("exit", (code) => {
|
|
13382
13916
|
clearTimeout(timeout);
|
|
13383
|
-
|
|
13917
|
+
resolve19({ stdout, stderr, exit_code: code });
|
|
13384
13918
|
});
|
|
13385
13919
|
} catch (e) {
|
|
13386
13920
|
clearTimeout(timeout);
|
|
13387
|
-
|
|
13921
|
+
resolve19({
|
|
13388
13922
|
stdout: "",
|
|
13389
13923
|
stderr: e?.message ?? "Failed to spawn process",
|
|
13390
13924
|
exit_code: -1
|
|
@@ -13451,7 +13985,7 @@ async function callLocalTool(name, args2, projectRoot) {
|
|
|
13451
13985
|
const command = String(args2.command ?? "");
|
|
13452
13986
|
let cwd = projectRoot;
|
|
13453
13987
|
if (args2.cwd) {
|
|
13454
|
-
cwd =
|
|
13988
|
+
cwd = resolve17(projectRoot, String(args2.cwd));
|
|
13455
13989
|
try {
|
|
13456
13990
|
const resolvedCwd = await realpath2(cwd);
|
|
13457
13991
|
const resolvedRoot = await realpath2(projectRoot);
|
|
@@ -13488,7 +14022,7 @@ ${res.stderr}`
|
|
|
13488
14022
|
return asResult("path is required", true);
|
|
13489
14023
|
}
|
|
13490
14024
|
try {
|
|
13491
|
-
const resolvedPath = await realpath2(
|
|
14025
|
+
const resolvedPath = await realpath2(resolve17(projectRoot, pathArg));
|
|
13492
14026
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13493
14027
|
if (!resolvedPath.startsWith(resolvedRoot)) {
|
|
13494
14028
|
return asResult("Error: path attempts to escape project root", true);
|
|
@@ -13507,7 +14041,7 @@ ${res.stderr}`
|
|
|
13507
14041
|
}
|
|
13508
14042
|
case "local_glob": {
|
|
13509
14043
|
const pattern = String(args2.pattern ?? "");
|
|
13510
|
-
let cwd = args2.cwd ?
|
|
14044
|
+
let cwd = args2.cwd ? resolve17(projectRoot, String(args2.cwd)) : projectRoot;
|
|
13511
14045
|
if (!pattern) {
|
|
13512
14046
|
return asResult("pattern is required", true);
|
|
13513
14047
|
}
|
|
@@ -13536,7 +14070,7 @@ ${res.stderr}`
|
|
|
13536
14070
|
}
|
|
13537
14071
|
if (path2) {
|
|
13538
14072
|
try {
|
|
13539
|
-
const resolvedPath = await realpath2(
|
|
14073
|
+
const resolvedPath = await realpath2(resolve17(projectRoot, path2));
|
|
13540
14074
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13541
14075
|
if (!resolvedPath.startsWith(resolvedRoot)) {
|
|
13542
14076
|
return asResult("Error: path attempts to escape project root", true);
|
|
@@ -13556,7 +14090,7 @@ ${res.stderr}`
|
|
|
13556
14090
|
return asResult("cwd is required", true);
|
|
13557
14091
|
}
|
|
13558
14092
|
try {
|
|
13559
|
-
const resolvedCwd = await realpath2(
|
|
14093
|
+
const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
|
|
13560
14094
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13561
14095
|
if (!resolvedCwd.startsWith(resolvedRoot)) {
|
|
13562
14096
|
return asResult("Error: cwd attempts to escape project root", true);
|
|
@@ -13582,7 +14116,7 @@ ${status.porcelain || "(clean)"}`
|
|
|
13582
14116
|
return asResult("cwd is required", true);
|
|
13583
14117
|
}
|
|
13584
14118
|
try {
|
|
13585
|
-
const resolvedCwd = await realpath2(
|
|
14119
|
+
const resolvedCwd = await realpath2(resolve17(projectRoot, cwdArg));
|
|
13586
14120
|
const resolvedRoot = await realpath2(projectRoot);
|
|
13587
14121
|
if (!resolvedCwd.startsWith(resolvedRoot)) {
|
|
13588
14122
|
return asResult("Error: cwd attempts to escape project root", true);
|
|
@@ -13698,7 +14232,7 @@ __export(server_exports, {
|
|
|
13698
14232
|
runStdioWithRegistry: () => runStdioWithRegistry
|
|
13699
14233
|
});
|
|
13700
14234
|
import { readdirSync as readdirSync4, readFileSync as readFileSync2, statSync as statSync7 } from "fs";
|
|
13701
|
-
import { join as join29, relative as relative14, resolve as
|
|
14235
|
+
import { join as join29, relative as relative14, resolve as resolve18 } from "path";
|
|
13702
14236
|
function asResult2(text, isError = false) {
|
|
13703
14237
|
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
13704
14238
|
}
|
|
@@ -14056,13 +14590,13 @@ var init_server = __esm({
|
|
|
14056
14590
|
if (inflight === 0) {
|
|
14057
14591
|
return [];
|
|
14058
14592
|
}
|
|
14059
|
-
const forcedResponses = await new Promise((
|
|
14060
|
-
this._drainResolve = () =>
|
|
14593
|
+
const forcedResponses = await new Promise((resolve19) => {
|
|
14594
|
+
this._drainResolve = () => resolve19([]);
|
|
14061
14595
|
setTimeout(() => {
|
|
14062
14596
|
this._drainResolve = null;
|
|
14063
14597
|
const remaining = Array.from(this._inflightCalls.values());
|
|
14064
14598
|
if (remaining.length === 0) {
|
|
14065
|
-
|
|
14599
|
+
resolve19([]);
|
|
14066
14600
|
return;
|
|
14067
14601
|
}
|
|
14068
14602
|
process.stderr.write(
|
|
@@ -14078,7 +14612,7 @@ var init_server = __esm({
|
|
|
14078
14612
|
}
|
|
14079
14613
|
}));
|
|
14080
14614
|
this._inflightCalls.clear();
|
|
14081
|
-
|
|
14615
|
+
resolve19(errorResponses);
|
|
14082
14616
|
}, DRAIN_TIMEOUT_MS);
|
|
14083
14617
|
});
|
|
14084
14618
|
return forcedResponses;
|
|
@@ -14356,7 +14890,7 @@ ${r.response ?? ""}`;
|
|
|
14356
14890
|
return asResult2(JSON.stringify(result));
|
|
14357
14891
|
}
|
|
14358
14892
|
case "msapling_project_context": {
|
|
14359
|
-
const root =
|
|
14893
|
+
const root = resolve18(String(args2.path ?? "."));
|
|
14360
14894
|
const maxFiles = Number.isFinite(args2.max_files) ? Number(args2.max_files) : 30;
|
|
14361
14895
|
const maxKB = Number.isFinite(args2.max_file_size_kb) ? Number(args2.max_file_size_kb) : 50;
|
|
14362
14896
|
const files = buildFileTree(root, maxFiles);
|
|
@@ -14484,7 +15018,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
14484
15018
|
var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
14485
15019
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
14486
15020
|
"\u25CF MSapling CLI v",
|
|
14487
|
-
"2.3.6-beta.
|
|
15021
|
+
"2.3.6-beta.25"
|
|
14488
15022
|
] }),
|
|
14489
15023
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
14490
15024
|
] });
|
|
@@ -14978,9 +15512,9 @@ ${prompt4}` : prompt4;
|
|
|
14978
15512
|
if (proc.stderr) proc.stderr.on("data", (chunk) => {
|
|
14979
15513
|
stderr += chunk.toString();
|
|
14980
15514
|
});
|
|
14981
|
-
await new Promise((
|
|
15515
|
+
await new Promise((resolve19, reject) => {
|
|
14982
15516
|
proc.on("close", (code) => {
|
|
14983
|
-
if (code === 0 || code === null)
|
|
15517
|
+
if (code === 0 || code === null) resolve19();
|
|
14984
15518
|
else reject(new Error(`Process exited with code ${code}`));
|
|
14985
15519
|
});
|
|
14986
15520
|
proc.on("error", reject);
|
|
@@ -15007,10 +15541,10 @@ ${prompt4}` : prompt4;
|
|
|
15007
15541
|
for (const mention of fileMentions) {
|
|
15008
15542
|
const filePath = mention.slice(1);
|
|
15009
15543
|
try {
|
|
15010
|
-
const { existsSync:
|
|
15011
|
-
const { readFile:
|
|
15012
|
-
if (
|
|
15013
|
-
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");
|
|
15014
15548
|
const MAX_LEN = 32768;
|
|
15015
15549
|
const truncated = content.length > MAX_LEN ? content.slice(0, MAX_LEN) + "\n...[TRUNCATED]" : content;
|
|
15016
15550
|
finalCmd += `
|
|
@@ -15062,8 +15596,8 @@ ${finalCmd}`;
|
|
|
15062
15596
|
init_esm_shims();
|
|
15063
15597
|
init_src3();
|
|
15064
15598
|
init_parseApprovalMode();
|
|
15065
|
-
import { readFile as
|
|
15066
|
-
import { existsSync as
|
|
15599
|
+
import { readFile as readFile22 } from "fs/promises";
|
|
15600
|
+
import { existsSync as existsSync25 } from "fs";
|
|
15067
15601
|
async function initSession(ctx) {
|
|
15068
15602
|
try {
|
|
15069
15603
|
const { settings } = await loadSettings(
|
|
@@ -15080,8 +15614,8 @@ async function initSession(ctx) {
|
|
|
15080
15614
|
const { homedir: homedir18 } = await import("os");
|
|
15081
15615
|
const { join: join31 } = await import("path");
|
|
15082
15616
|
const userSettingsPath = join31(homedir18(), ".msapling", "settings.json");
|
|
15083
|
-
if (
|
|
15084
|
-
const userText = await
|
|
15617
|
+
if (existsSync25(userSettingsPath)) {
|
|
15618
|
+
const userText = await readFile22(userSettingsPath, "utf8");
|
|
15085
15619
|
let parsed;
|
|
15086
15620
|
try {
|
|
15087
15621
|
parsed = JSON.parse(userText);
|
|
@@ -15181,8 +15715,8 @@ var App = ({ compact: compact2 = false }) => {
|
|
|
15181
15715
|
const storage = useRef(new StorageManager()).current;
|
|
15182
15716
|
const client = useRef(new MSaplingClient()).current;
|
|
15183
15717
|
const requestApproval = useCallback((request) => {
|
|
15184
|
-
return new Promise((
|
|
15185
|
-
setPendingApproval({ request, resolve:
|
|
15718
|
+
return new Promise((resolve19) => {
|
|
15719
|
+
setPendingApproval({ request, resolve: resolve19 });
|
|
15186
15720
|
});
|
|
15187
15721
|
}, []);
|
|
15188
15722
|
const agent = useRef(new Agent(client, process.cwd(), requestApproval)).current;
|