@mtreeai/msapling-cli 2.3.6-beta.26 → 2.3.6-beta.28
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 +722 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -59,6 +59,28 @@ __export(src_exports, {
|
|
|
59
59
|
MSaplingClient: () => MSaplingClient,
|
|
60
60
|
MSaplingError: () => MSaplingError
|
|
61
61
|
});
|
|
62
|
+
function normalizeDetail(detail) {
|
|
63
|
+
if (detail == null) return "";
|
|
64
|
+
if (typeof detail === "string") return detail;
|
|
65
|
+
if (Array.isArray(detail)) {
|
|
66
|
+
return detail.map((d) => {
|
|
67
|
+
if (!d || typeof d !== "object") return String(d);
|
|
68
|
+
const o = d;
|
|
69
|
+
const loc = Array.isArray(o.loc) ? o.loc.join(".") : "";
|
|
70
|
+
return [o.msg, loc && `(${loc})`].filter(Boolean).join(" ");
|
|
71
|
+
}).filter(Boolean).join("; ");
|
|
72
|
+
}
|
|
73
|
+
if (typeof detail === "object") {
|
|
74
|
+
const o = detail;
|
|
75
|
+
if (typeof o.msg === "string") return o.msg;
|
|
76
|
+
try {
|
|
77
|
+
return JSON.stringify(detail);
|
|
78
|
+
} catch {
|
|
79
|
+
return String(detail);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return String(detail);
|
|
83
|
+
}
|
|
62
84
|
var MSaplingError, MSaplingClient;
|
|
63
85
|
var init_src = __esm({
|
|
64
86
|
"../api-client/src/index.ts"() {
|
|
@@ -143,7 +165,7 @@ var init_src = __esm({
|
|
|
143
165
|
let code = "unknown";
|
|
144
166
|
try {
|
|
145
167
|
const err = await response.json();
|
|
146
|
-
detail = err.detail || detail;
|
|
168
|
+
detail = normalizeDetail(err.detail) || detail;
|
|
147
169
|
code = err.code || code;
|
|
148
170
|
} catch (e) {
|
|
149
171
|
}
|
|
@@ -334,6 +356,98 @@ var init_src = __esm({
|
|
|
334
356
|
async disableOllama() {
|
|
335
357
|
return await this.request("/api/ollama/disable", { method: "POST" });
|
|
336
358
|
}
|
|
359
|
+
// Parity Task Card implementations
|
|
360
|
+
// Card 1: Usage Tracking (synced from /api/usage/sync-offline)
|
|
361
|
+
async syncOfflineUsage() {
|
|
362
|
+
return await this.request("/api/usage/sync-offline", { method: "POST" });
|
|
363
|
+
}
|
|
364
|
+
// Card 2: Budget Buckets (7 bucket types)
|
|
365
|
+
async getBillingBuckets() {
|
|
366
|
+
return await this.request("/api/billing/buckets");
|
|
367
|
+
}
|
|
368
|
+
// Card 4: Image Generation
|
|
369
|
+
async generateImage(prompt4, model) {
|
|
370
|
+
return await this.request("/api/image/generate", {
|
|
371
|
+
method: "POST",
|
|
372
|
+
body: JSON.stringify({ prompt: prompt4, model })
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
// Card 5: Voice/Audio Operations
|
|
376
|
+
async listVoices() {
|
|
377
|
+
return await this.request("/api/audio/voices");
|
|
378
|
+
}
|
|
379
|
+
async speak(text, voice) {
|
|
380
|
+
return await this.request("/api/audio/speak", {
|
|
381
|
+
method: "POST",
|
|
382
|
+
body: JSON.stringify({ text, voice })
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
// Card 8: Chat Sharing
|
|
386
|
+
async shareChat(chatId, expiryDays) {
|
|
387
|
+
return await this.request(`/api/share/chat/${encodeURIComponent(chatId)}/share`, {
|
|
388
|
+
method: "POST",
|
|
389
|
+
body: JSON.stringify({ expiry_days: expiryDays })
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
async listShares() {
|
|
393
|
+
return await this.request("/api/share");
|
|
394
|
+
}
|
|
395
|
+
async fetchSharedChat(token) {
|
|
396
|
+
return await this.request(`/api/shared/${encodeURIComponent(token)}`);
|
|
397
|
+
}
|
|
398
|
+
// Card 9: Notifications (preferences only)
|
|
399
|
+
async getNotificationPreferences() {
|
|
400
|
+
return await this.request("/api/notifications/preferences");
|
|
401
|
+
}
|
|
402
|
+
async setNotificationPreferences(prefs) {
|
|
403
|
+
return await this.request("/api/notifications/preferences", {
|
|
404
|
+
method: "PATCH",
|
|
405
|
+
body: JSON.stringify(prefs)
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
// Card 10: MLineage Events List
|
|
409
|
+
async listMLineageEvents() {
|
|
410
|
+
return await this.request("/api/mlineage/events");
|
|
411
|
+
}
|
|
412
|
+
// Card 11: Per-Project Model Config
|
|
413
|
+
async setProjectModel(projectId, model) {
|
|
414
|
+
return await this.request(`/api/projects/${encodeURIComponent(projectId)}`, {
|
|
415
|
+
method: "PATCH",
|
|
416
|
+
body: JSON.stringify({ default_model: model })
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
// Card 12: MFA/TOTP
|
|
420
|
+
async enrollMFA(method) {
|
|
421
|
+
return await this.request("/api/mfa/enroll", {
|
|
422
|
+
method: "POST",
|
|
423
|
+
body: JSON.stringify({ method })
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
async verifyMFA(code) {
|
|
427
|
+
return await this.request("/api/mfa/verify", {
|
|
428
|
+
method: "POST",
|
|
429
|
+
body: JSON.stringify({ code })
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
// Card 13: MCP Client Surface
|
|
433
|
+
async mcpConnect(serverUrl) {
|
|
434
|
+
return await this.request("/api/mcp/connect", {
|
|
435
|
+
method: "POST",
|
|
436
|
+
body: JSON.stringify({ server_url: serverUrl })
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
async mcpTools() {
|
|
440
|
+
return await this.request("/api/mcp/tools");
|
|
441
|
+
}
|
|
442
|
+
async mcpInvoke(method, args2) {
|
|
443
|
+
return await this.request("/api/mcp/invoke", {
|
|
444
|
+
method: "POST",
|
|
445
|
+
body: JSON.stringify({ method, args: args2 })
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
async mcpDisconnect() {
|
|
449
|
+
return await this.request("/api/mcp/disconnect", { method: "POST" });
|
|
450
|
+
}
|
|
337
451
|
// CLI-KEYS-BYOK-01 (Iter 35): BYOK provider-key management. Per LAB
|
|
338
452
|
// routers/keys.py — /api/keys/{status,save,{provider}}.
|
|
339
453
|
async getProviderKeys() {
|
|
@@ -710,6 +824,32 @@ var init_src = __esm({
|
|
|
710
824
|
async getActiveTasks() {
|
|
711
825
|
return this.request("/api/task-monitor/active");
|
|
712
826
|
}
|
|
827
|
+
/**
|
|
828
|
+
* Webhook Management (LAB-WEBHOOK-CRUD-01)
|
|
829
|
+
*/
|
|
830
|
+
async listWebhooks() {
|
|
831
|
+
return this.request("/api/webhooks");
|
|
832
|
+
}
|
|
833
|
+
async createWebhook(url, events) {
|
|
834
|
+
return this.request("/api/webhooks", {
|
|
835
|
+
method: "POST",
|
|
836
|
+
body: JSON.stringify({ url, events })
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
async deleteWebhook(id) {
|
|
840
|
+
await this.request(`/api/webhooks/${encodeURIComponent(id)}`, {
|
|
841
|
+
method: "DELETE"
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
async listWebhookDeliveries(webhookId) {
|
|
845
|
+
const path2 = webhookId ? `/api/webhooks/deliveries?webhook_id=${encodeURIComponent(webhookId)}` : "/api/webhooks/deliveries";
|
|
846
|
+
return this.request(path2);
|
|
847
|
+
}
|
|
848
|
+
async retryWebhookDelivery(deliveryId) {
|
|
849
|
+
return this.request(`/api/webhooks/deliveries/${encodeURIComponent(deliveryId)}/retry`, {
|
|
850
|
+
method: "POST"
|
|
851
|
+
});
|
|
852
|
+
}
|
|
713
853
|
/**
|
|
714
854
|
* Wakeup Management (LAB-CHAT-PARITY-04)
|
|
715
855
|
*/
|
|
@@ -771,7 +911,10 @@ var init_src = __esm({
|
|
|
771
911
|
}
|
|
772
912
|
if (!response.ok) {
|
|
773
913
|
const err = await response.json().catch(() => ({ detail: response.statusText }));
|
|
774
|
-
throw new MSaplingError(
|
|
914
|
+
throw new MSaplingError(
|
|
915
|
+
normalizeDetail(err.detail) || "Stream request failed",
|
|
916
|
+
response.status
|
|
917
|
+
);
|
|
775
918
|
}
|
|
776
919
|
if (!response.body) throw new Error("No response body");
|
|
777
920
|
const reader = response.body.getReader();
|
|
@@ -9550,11 +9693,19 @@ var init_usage = __esm({
|
|
|
9550
9693
|
init_esm_shims();
|
|
9551
9694
|
usageCommand = {
|
|
9552
9695
|
name: "usage",
|
|
9553
|
-
|
|
9696
|
+
args: "[--json] [--since DATE]",
|
|
9697
|
+
description: "Show detailed usage, fuel balance, and daily quota; sync offline usage",
|
|
9554
9698
|
category: "chat",
|
|
9555
9699
|
handler: async (args2, context) => {
|
|
9556
9700
|
try {
|
|
9701
|
+
const isJson = args2.includes("--json");
|
|
9557
9702
|
const user = await context.client.getLiveUsage();
|
|
9703
|
+
await context.client.syncOfflineUsage().catch(() => {
|
|
9704
|
+
});
|
|
9705
|
+
if (isJson) {
|
|
9706
|
+
context.addMessage("system", JSON.stringify(user, null, 2));
|
|
9707
|
+
return;
|
|
9708
|
+
}
|
|
9558
9709
|
context.addMessage("system", "MSapling Usage Dashboard:");
|
|
9559
9710
|
context.addMessage("system", ` - Fuel Credits: $${user.fuel_credits.toFixed(4)}`);
|
|
9560
9711
|
context.addMessage("system", ` - Daily Spending Limit: ${user.monthly_spending_limit ? "$" + user.monthly_spending_limit : "Unlimited"}`);
|
|
@@ -9655,12 +9806,31 @@ var init_project = __esm({
|
|
|
9655
9806
|
LETTERS2 = "abcdefghijklmnopqrstuvwxyz";
|
|
9656
9807
|
projectCommand = {
|
|
9657
9808
|
name: "project",
|
|
9658
|
-
args: "[number|letter|name|id]",
|
|
9659
|
-
description: "List or switch active project",
|
|
9809
|
+
args: "[number|letter|name|id|config]",
|
|
9810
|
+
description: "List or switch active project, or set per-project config",
|
|
9660
9811
|
category: "project",
|
|
9661
9812
|
handler: async (args2, context) => {
|
|
9662
9813
|
const arg = args2.join(" ").trim();
|
|
9663
9814
|
const currentId = context.getProjectId() || null;
|
|
9815
|
+
if (args2[0] === "config") {
|
|
9816
|
+
const modelIdx = args2.indexOf("--model");
|
|
9817
|
+
const model = modelIdx >= 0 ? args2[modelIdx + 1] : void 0;
|
|
9818
|
+
if (!model) {
|
|
9819
|
+
context.addMessage("system", "Usage: /project config --model <MODEL>");
|
|
9820
|
+
return;
|
|
9821
|
+
}
|
|
9822
|
+
if (!currentId) {
|
|
9823
|
+
context.addMessage("error", "No active project. Use /project <id> first.");
|
|
9824
|
+
return;
|
|
9825
|
+
}
|
|
9826
|
+
try {
|
|
9827
|
+
await context.client.setProjectModel(currentId, model);
|
|
9828
|
+
context.addMessage("system", `Project default model set to: ${model}`);
|
|
9829
|
+
} catch (e) {
|
|
9830
|
+
context.addMessage("error", `Failed to set model: ${e.message}`);
|
|
9831
|
+
}
|
|
9832
|
+
return;
|
|
9833
|
+
}
|
|
9664
9834
|
if (args2[0] === "new" || args2[0] === "create") {
|
|
9665
9835
|
const name = args2.slice(1).join(" ").trim();
|
|
9666
9836
|
if (!name) {
|
|
@@ -10607,7 +10777,7 @@ var init_version = __esm({
|
|
|
10607
10777
|
description: "Show version information for CLI and core packages",
|
|
10608
10778
|
category: "debug",
|
|
10609
10779
|
handler: async (_args, context) => {
|
|
10610
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
10780
|
+
const cliVersion = true ? "2.3.6-beta.28" : "(dev)";
|
|
10611
10781
|
const coreVersion = true ? "2.3.2" : "(dev)";
|
|
10612
10782
|
const runtime = process.version;
|
|
10613
10783
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -10616,7 +10786,7 @@ var init_version = __esm({
|
|
|
10616
10786
|
context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
|
|
10617
10787
|
context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
|
|
10618
10788
|
try {
|
|
10619
|
-
const ts = "2026-05-
|
|
10789
|
+
const ts = "2026-05-29T17:03:26.902Z";
|
|
10620
10790
|
if (ts && ts !== "__BUILD_TIMESTAMP__") {
|
|
10621
10791
|
context.addMessage("system", row2("Build Timestamp", ts));
|
|
10622
10792
|
}
|
|
@@ -11334,6 +11504,529 @@ var init_totp = __esm({
|
|
|
11334
11504
|
}
|
|
11335
11505
|
});
|
|
11336
11506
|
|
|
11507
|
+
// src/commands/budget.ts
|
|
11508
|
+
var budgetCommand;
|
|
11509
|
+
var init_budget = __esm({
|
|
11510
|
+
"src/commands/budget.ts"() {
|
|
11511
|
+
"use strict";
|
|
11512
|
+
init_esm_shims();
|
|
11513
|
+
budgetCommand = {
|
|
11514
|
+
name: "budget",
|
|
11515
|
+
description: "Show budget buckets (lifetime, sub, top_up, free, guest, byok, ollama)",
|
|
11516
|
+
category: "config",
|
|
11517
|
+
handler: async (args2, context) => {
|
|
11518
|
+
try {
|
|
11519
|
+
const data = await context.client.getBillingBuckets();
|
|
11520
|
+
context.addMessage("system", "Budget Buckets:");
|
|
11521
|
+
if (data && typeof data === "object") {
|
|
11522
|
+
for (const [key, val] of Object.entries(data)) {
|
|
11523
|
+
const bucket = val;
|
|
11524
|
+
const remaining = bucket.remaining ?? bucket.balance ?? 0;
|
|
11525
|
+
const limit = bucket.limit ?? bucket.cap ?? 0;
|
|
11526
|
+
context.addMessage("system", ` - ${key}: $${remaining.toFixed(4)} / $${limit.toFixed(4)}`);
|
|
11527
|
+
}
|
|
11528
|
+
} else {
|
|
11529
|
+
context.addMessage("system", JSON.stringify(data, null, 2));
|
|
11530
|
+
}
|
|
11531
|
+
} catch (e) {
|
|
11532
|
+
context.addMessage("error", `Failed to fetch budget: ${e.message}`);
|
|
11533
|
+
}
|
|
11534
|
+
}
|
|
11535
|
+
};
|
|
11536
|
+
}
|
|
11537
|
+
});
|
|
11538
|
+
|
|
11539
|
+
// src/commands/image.ts
|
|
11540
|
+
var imageCommand;
|
|
11541
|
+
var init_image = __esm({
|
|
11542
|
+
"src/commands/image.ts"() {
|
|
11543
|
+
"use strict";
|
|
11544
|
+
init_esm_shims();
|
|
11545
|
+
imageCommand = {
|
|
11546
|
+
name: "image",
|
|
11547
|
+
args: "<prompt> [--model MODEL] [--output FILE]",
|
|
11548
|
+
description: "Generate an image from a text prompt",
|
|
11549
|
+
category: "chat",
|
|
11550
|
+
handler: async (args2, context) => {
|
|
11551
|
+
let prompt4 = "";
|
|
11552
|
+
let model = "dall-e-3";
|
|
11553
|
+
let outputFile = null;
|
|
11554
|
+
for (let i = 0; i < args2.length; i++) {
|
|
11555
|
+
if (args2[i] === "--model" && i + 1 < args2.length) {
|
|
11556
|
+
model = args2[++i];
|
|
11557
|
+
continue;
|
|
11558
|
+
}
|
|
11559
|
+
if (args2[i] === "--output" && i + 1 < args2.length) {
|
|
11560
|
+
outputFile = args2[++i];
|
|
11561
|
+
continue;
|
|
11562
|
+
}
|
|
11563
|
+
prompt4 += (prompt4 ? " " : "") + args2[i];
|
|
11564
|
+
}
|
|
11565
|
+
if (!prompt4) {
|
|
11566
|
+
context.addMessage("system", "Usage: /image <prompt> [--model MODEL] [--output FILE]");
|
|
11567
|
+
return;
|
|
11568
|
+
}
|
|
11569
|
+
try {
|
|
11570
|
+
const result = await context.client.generateImage(prompt4, model);
|
|
11571
|
+
context.addMessage("system", `Image generated: ${result.url ?? result.image_url ?? "processing"}`);
|
|
11572
|
+
} catch (e) {
|
|
11573
|
+
context.addMessage("error", `Image generation failed: ${e.message}`);
|
|
11574
|
+
}
|
|
11575
|
+
}
|
|
11576
|
+
};
|
|
11577
|
+
}
|
|
11578
|
+
});
|
|
11579
|
+
|
|
11580
|
+
// src/commands/voice.ts
|
|
11581
|
+
var voiceCommand;
|
|
11582
|
+
var init_voice = __esm({
|
|
11583
|
+
"src/commands/voice.ts"() {
|
|
11584
|
+
"use strict";
|
|
11585
|
+
init_esm_shims();
|
|
11586
|
+
voiceCommand = {
|
|
11587
|
+
name: "voice",
|
|
11588
|
+
args: "[list|speak|transcribe] [args...]",
|
|
11589
|
+
description: "Voice operations: list, speak, or transcribe audio",
|
|
11590
|
+
category: "chat",
|
|
11591
|
+
handler: async (args2, context) => {
|
|
11592
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
11593
|
+
const rest = args2.slice(1);
|
|
11594
|
+
try {
|
|
11595
|
+
if (sub === "list") {
|
|
11596
|
+
const voices = await context.client.listVoices();
|
|
11597
|
+
context.addMessage("system", "Available voices:");
|
|
11598
|
+
if (Array.isArray(voices)) {
|
|
11599
|
+
for (const voice of voices) {
|
|
11600
|
+
context.addMessage("system", ` - ${voice.id ?? voice.name}: ${voice.name ?? voice.id}`);
|
|
11601
|
+
}
|
|
11602
|
+
} else if (typeof voices === "object") {
|
|
11603
|
+
for (const [key, val] of Object.entries(voices)) {
|
|
11604
|
+
context.addMessage("system", ` - ${key}`);
|
|
11605
|
+
}
|
|
11606
|
+
}
|
|
11607
|
+
return;
|
|
11608
|
+
}
|
|
11609
|
+
if (sub === "speak") {
|
|
11610
|
+
const text = rest.join(" ").trim();
|
|
11611
|
+
if (!text) {
|
|
11612
|
+
context.addMessage("system", "Usage: /voice speak --text <TEXT> --voice <VOICE>");
|
|
11613
|
+
return;
|
|
11614
|
+
}
|
|
11615
|
+
const voiceIdx = rest.indexOf("--voice");
|
|
11616
|
+
const voice = voiceIdx >= 0 ? rest[voiceIdx + 1] : "default";
|
|
11617
|
+
const result = await context.client.speak(text, voice);
|
|
11618
|
+
context.addMessage("system", `Audio generated: ${result.url ?? result.audio_url ?? "processing"}`);
|
|
11619
|
+
return;
|
|
11620
|
+
}
|
|
11621
|
+
if (sub === "transcribe") {
|
|
11622
|
+
context.addMessage("system", "Transcribe: pipe audio file to this command (not yet implemented)");
|
|
11623
|
+
return;
|
|
11624
|
+
}
|
|
11625
|
+
context.addMessage("error", `Unknown /voice subcommand '${sub}'. Try: list, speak, transcribe.`);
|
|
11626
|
+
} catch (e) {
|
|
11627
|
+
context.addMessage("error", `Voice: ${e.message}`);
|
|
11628
|
+
}
|
|
11629
|
+
}
|
|
11630
|
+
};
|
|
11631
|
+
}
|
|
11632
|
+
});
|
|
11633
|
+
|
|
11634
|
+
// src/commands/wakeup.ts
|
|
11635
|
+
var wakeupCommand;
|
|
11636
|
+
var init_wakeup = __esm({
|
|
11637
|
+
"src/commands/wakeup.ts"() {
|
|
11638
|
+
"use strict";
|
|
11639
|
+
init_esm_shims();
|
|
11640
|
+
wakeupCommand = {
|
|
11641
|
+
name: "wakeup",
|
|
11642
|
+
args: "[create|list|cancel] [...args]",
|
|
11643
|
+
description: "Manage wakeups (scheduled tasks): create, list, or cancel",
|
|
11644
|
+
category: "config",
|
|
11645
|
+
handler: async (args2, context) => {
|
|
11646
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
11647
|
+
const rest = args2.slice(1);
|
|
11648
|
+
try {
|
|
11649
|
+
if (sub === "list") {
|
|
11650
|
+
const wakeups = await context.client.listWakeups();
|
|
11651
|
+
context.addMessage("system", "Wakeups:");
|
|
11652
|
+
if (Array.isArray(wakeups)) {
|
|
11653
|
+
for (const wu of wakeups) {
|
|
11654
|
+
context.addMessage("system", ` - ${wu.id}: ${wu.reason ?? wu.prompt ?? "scheduled"}`);
|
|
11655
|
+
}
|
|
11656
|
+
} else {
|
|
11657
|
+
context.addMessage("system", JSON.stringify(wakeups, null, 2));
|
|
11658
|
+
}
|
|
11659
|
+
return;
|
|
11660
|
+
}
|
|
11661
|
+
if (sub === "create") {
|
|
11662
|
+
const delayIdx = rest.indexOf("--delay");
|
|
11663
|
+
const delay = delayIdx >= 0 ? Number(rest[delayIdx + 1]) : 60;
|
|
11664
|
+
const reasonIdx = rest.indexOf("--reason");
|
|
11665
|
+
const reason = reasonIdx >= 0 ? rest[reasonIdx + 1] : void 0;
|
|
11666
|
+
const promptIdx = rest.indexOf("--prompt");
|
|
11667
|
+
const prompt4 = promptIdx >= 0 ? rest.slice(promptIdx + 1).join(" ") : void 0;
|
|
11668
|
+
const result = await context.client.createWakeup({
|
|
11669
|
+
delay_seconds: delay,
|
|
11670
|
+
reason,
|
|
11671
|
+
prompt: prompt4
|
|
11672
|
+
});
|
|
11673
|
+
context.addMessage("system", `Wakeup created: ${result.id ?? "ok"}`);
|
|
11674
|
+
return;
|
|
11675
|
+
}
|
|
11676
|
+
if (sub === "cancel") {
|
|
11677
|
+
const id = rest[0];
|
|
11678
|
+
if (!id) {
|
|
11679
|
+
context.addMessage("system", "Usage: /wakeup cancel <ID>");
|
|
11680
|
+
return;
|
|
11681
|
+
}
|
|
11682
|
+
await context.client.cancelWakeup(id);
|
|
11683
|
+
context.addMessage("system", `Wakeup cancelled: ${id}`);
|
|
11684
|
+
return;
|
|
11685
|
+
}
|
|
11686
|
+
context.addMessage("error", `Unknown /wakeup subcommand '${sub}'. Try: list, create, cancel.`);
|
|
11687
|
+
} catch (e) {
|
|
11688
|
+
context.addMessage("error", `Wakeup: ${e.message}`);
|
|
11689
|
+
}
|
|
11690
|
+
}
|
|
11691
|
+
};
|
|
11692
|
+
}
|
|
11693
|
+
});
|
|
11694
|
+
|
|
11695
|
+
// src/commands/share.ts
|
|
11696
|
+
var shareCommand;
|
|
11697
|
+
var init_share = __esm({
|
|
11698
|
+
"src/commands/share.ts"() {
|
|
11699
|
+
"use strict";
|
|
11700
|
+
init_esm_shims();
|
|
11701
|
+
shareCommand = {
|
|
11702
|
+
name: "share",
|
|
11703
|
+
args: "[create|list|fetch] [...args]",
|
|
11704
|
+
description: "Share chats: create, list, or fetch shared conversations",
|
|
11705
|
+
category: "chat",
|
|
11706
|
+
handler: async (args2, context) => {
|
|
11707
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
11708
|
+
const rest = args2.slice(1);
|
|
11709
|
+
try {
|
|
11710
|
+
if (sub === "list") {
|
|
11711
|
+
const shares = await context.client.listShares();
|
|
11712
|
+
context.addMessage("system", "Shared Chats:");
|
|
11713
|
+
if (Array.isArray(shares)) {
|
|
11714
|
+
for (const share of shares) {
|
|
11715
|
+
const expiry = share.expiry_at ? ` (expires ${share.expiry_at})` : "";
|
|
11716
|
+
context.addMessage("system", ` - ${share.token}: chat ${share.chat_id}${expiry}`);
|
|
11717
|
+
}
|
|
11718
|
+
} else {
|
|
11719
|
+
context.addMessage("system", JSON.stringify(shares, null, 2));
|
|
11720
|
+
}
|
|
11721
|
+
return;
|
|
11722
|
+
}
|
|
11723
|
+
if (sub === "create") {
|
|
11724
|
+
const chatId = rest[0];
|
|
11725
|
+
const expiryIdx = rest.indexOf("--expiry");
|
|
11726
|
+
const expiry = expiryIdx >= 0 ? Number(rest[expiryIdx + 1]) : void 0;
|
|
11727
|
+
if (!chatId) {
|
|
11728
|
+
context.addMessage("system", "Usage: /share create <CHAT-ID> [--expiry DAYS]");
|
|
11729
|
+
return;
|
|
11730
|
+
}
|
|
11731
|
+
const result = await context.client.shareChat(chatId, expiry);
|
|
11732
|
+
context.addMessage("system", `Share created: ${result.token ?? result.url ?? "ok"}`);
|
|
11733
|
+
return;
|
|
11734
|
+
}
|
|
11735
|
+
if (sub === "fetch") {
|
|
11736
|
+
const token = rest[0];
|
|
11737
|
+
if (!token) {
|
|
11738
|
+
context.addMessage("system", "Usage: /share fetch <TOKEN>");
|
|
11739
|
+
return;
|
|
11740
|
+
}
|
|
11741
|
+
const result = await context.client.fetchSharedChat(token);
|
|
11742
|
+
context.addMessage("system", `Fetched shared chat: ${result.chat_id ?? result.id}`);
|
|
11743
|
+
return;
|
|
11744
|
+
}
|
|
11745
|
+
context.addMessage("error", `Unknown /share subcommand '${sub}'. Try: list, create, fetch.`);
|
|
11746
|
+
} catch (e) {
|
|
11747
|
+
context.addMessage("error", `Share: ${e.message}`);
|
|
11748
|
+
}
|
|
11749
|
+
}
|
|
11750
|
+
};
|
|
11751
|
+
}
|
|
11752
|
+
});
|
|
11753
|
+
|
|
11754
|
+
// src/commands/notify.ts
|
|
11755
|
+
var notifyCommand;
|
|
11756
|
+
var init_notify = __esm({
|
|
11757
|
+
"src/commands/notify.ts"() {
|
|
11758
|
+
"use strict";
|
|
11759
|
+
init_esm_shims();
|
|
11760
|
+
notifyCommand = {
|
|
11761
|
+
name: "notify",
|
|
11762
|
+
args: "[preferences] [--get|--set KEY=VALUE]",
|
|
11763
|
+
description: "Manage notification preferences (SSE stream not yet implemented)",
|
|
11764
|
+
category: "config",
|
|
11765
|
+
handler: async (args2, context) => {
|
|
11766
|
+
try {
|
|
11767
|
+
if (args2.length === 0 || args2[0] === "preferences" || args2[0] === "--get") {
|
|
11768
|
+
const prefs = await context.client.getNotificationPreferences();
|
|
11769
|
+
context.addMessage("system", "Notification Preferences:");
|
|
11770
|
+
context.addMessage("system", JSON.stringify(prefs, null, 2));
|
|
11771
|
+
return;
|
|
11772
|
+
}
|
|
11773
|
+
if (args2[0] === "--set") {
|
|
11774
|
+
const updates = {};
|
|
11775
|
+
for (let i = 1; i < args2.length; i++) {
|
|
11776
|
+
const pair = args2[i].split("=");
|
|
11777
|
+
if (pair.length === 2) {
|
|
11778
|
+
updates[pair[0]] = pair[1] === "true" ? true : pair[1] === "false" ? false : pair[1];
|
|
11779
|
+
}
|
|
11780
|
+
}
|
|
11781
|
+
const result = await context.client.setNotificationPreferences(updates);
|
|
11782
|
+
context.addMessage("system", `Preferences updated: ${result.status ?? "ok"}`);
|
|
11783
|
+
return;
|
|
11784
|
+
}
|
|
11785
|
+
context.addMessage("error", "Usage: /notify [--get] or /notify --set KEY=VALUE ...");
|
|
11786
|
+
} catch (e) {
|
|
11787
|
+
context.addMessage("error", `Notify: ${e.message}`);
|
|
11788
|
+
}
|
|
11789
|
+
}
|
|
11790
|
+
};
|
|
11791
|
+
}
|
|
11792
|
+
});
|
|
11793
|
+
|
|
11794
|
+
// src/commands/mlineage.ts
|
|
11795
|
+
var mlineageCommand;
|
|
11796
|
+
var init_mlineage = __esm({
|
|
11797
|
+
"src/commands/mlineage.ts"() {
|
|
11798
|
+
"use strict";
|
|
11799
|
+
init_esm_shims();
|
|
11800
|
+
mlineageCommand = {
|
|
11801
|
+
name: "mlineage",
|
|
11802
|
+
args: "[events] [--follow]",
|
|
11803
|
+
description: "List MLineage events (follow mode not yet implemented)",
|
|
11804
|
+
category: "chat",
|
|
11805
|
+
handler: async (args2, context) => {
|
|
11806
|
+
try {
|
|
11807
|
+
const follow = args2.includes("--follow");
|
|
11808
|
+
const events = await context.client.listMLineageEvents();
|
|
11809
|
+
context.addMessage("system", "MLineage Events:");
|
|
11810
|
+
if (Array.isArray(events)) {
|
|
11811
|
+
for (const evt of events) {
|
|
11812
|
+
context.addMessage("system", ` - ${evt.id}: ${evt.type} @ ${evt.timestamp}`);
|
|
11813
|
+
}
|
|
11814
|
+
} else {
|
|
11815
|
+
context.addMessage("system", JSON.stringify(events, null, 2));
|
|
11816
|
+
}
|
|
11817
|
+
if (follow) {
|
|
11818
|
+
context.addMessage("system", "(follow mode not yet implemented)");
|
|
11819
|
+
}
|
|
11820
|
+
} catch (e) {
|
|
11821
|
+
context.addMessage("error", `MLineage: ${e.message}`);
|
|
11822
|
+
}
|
|
11823
|
+
}
|
|
11824
|
+
};
|
|
11825
|
+
}
|
|
11826
|
+
});
|
|
11827
|
+
|
|
11828
|
+
// src/commands/mfa.ts
|
|
11829
|
+
var mfaCommand;
|
|
11830
|
+
var init_mfa = __esm({
|
|
11831
|
+
"src/commands/mfa.ts"() {
|
|
11832
|
+
"use strict";
|
|
11833
|
+
init_esm_shims();
|
|
11834
|
+
mfaCommand = {
|
|
11835
|
+
name: "mfa",
|
|
11836
|
+
args: "[enroll|verify] [...args]",
|
|
11837
|
+
description: "Enroll or verify MFA/TOTP",
|
|
11838
|
+
category: "config",
|
|
11839
|
+
handler: async (args2, context) => {
|
|
11840
|
+
const sub = (args2[0] ?? "status").toLowerCase();
|
|
11841
|
+
const rest = args2.slice(1);
|
|
11842
|
+
try {
|
|
11843
|
+
if (sub === "enroll") {
|
|
11844
|
+
const method = rest[0] ?? "totp";
|
|
11845
|
+
const result = await context.client.enrollMFA(method);
|
|
11846
|
+
context.addMessage("system", `MFA enrollment initiated: ${method}`);
|
|
11847
|
+
if (result.qr_code) {
|
|
11848
|
+
context.addMessage("system", `QR Code: ${result.qr_code}`);
|
|
11849
|
+
}
|
|
11850
|
+
if (result.secret) {
|
|
11851
|
+
context.addMessage("system", `Secret: ${result.secret}`);
|
|
11852
|
+
}
|
|
11853
|
+
return;
|
|
11854
|
+
}
|
|
11855
|
+
if (sub === "verify") {
|
|
11856
|
+
const code = rest[0];
|
|
11857
|
+
if (!code) {
|
|
11858
|
+
context.addMessage("system", "Usage: /mfa verify <CODE>");
|
|
11859
|
+
return;
|
|
11860
|
+
}
|
|
11861
|
+
const result = await context.client.verifyMFA(code);
|
|
11862
|
+
context.addMessage("system", `MFA verified: ${result.status ?? "ok"}`);
|
|
11863
|
+
return;
|
|
11864
|
+
}
|
|
11865
|
+
context.addMessage("error", `Unknown /mfa subcommand '${sub}'. Try: enroll, verify.`);
|
|
11866
|
+
} catch (e) {
|
|
11867
|
+
context.addMessage("error", `MFA: ${e.message}`);
|
|
11868
|
+
}
|
|
11869
|
+
}
|
|
11870
|
+
};
|
|
11871
|
+
}
|
|
11872
|
+
});
|
|
11873
|
+
|
|
11874
|
+
// src/commands/mcp.ts
|
|
11875
|
+
var mcpCommand;
|
|
11876
|
+
var init_mcp = __esm({
|
|
11877
|
+
"src/commands/mcp.ts"() {
|
|
11878
|
+
"use strict";
|
|
11879
|
+
init_esm_shims();
|
|
11880
|
+
mcpCommand = {
|
|
11881
|
+
name: "mcp",
|
|
11882
|
+
args: "[connect|invoke|tools|disconnect] [...args]",
|
|
11883
|
+
description: "MCP client surface: connect, invoke, list tools, disconnect",
|
|
11884
|
+
category: "config",
|
|
11885
|
+
handler: async (args2, context) => {
|
|
11886
|
+
const sub = (args2[0] ?? "tools").toLowerCase();
|
|
11887
|
+
const rest = args2.slice(1);
|
|
11888
|
+
try {
|
|
11889
|
+
if (sub === "connect") {
|
|
11890
|
+
const url = rest[0];
|
|
11891
|
+
if (!url) {
|
|
11892
|
+
context.addMessage("system", "Usage: /mcp connect <server-url>");
|
|
11893
|
+
return;
|
|
11894
|
+
}
|
|
11895
|
+
const result = await context.client.mcpConnect(url);
|
|
11896
|
+
context.addMessage("system", `MCP Connected: ${result.status ?? "ok"}`);
|
|
11897
|
+
return;
|
|
11898
|
+
}
|
|
11899
|
+
if (sub === "tools") {
|
|
11900
|
+
const tools = await context.client.mcpTools();
|
|
11901
|
+
context.addMessage("system", "Available MCP Tools:");
|
|
11902
|
+
if (Array.isArray(tools)) {
|
|
11903
|
+
for (const tool of tools) {
|
|
11904
|
+
context.addMessage("system", ` - ${tool.name}: ${tool.description ?? ""}`);
|
|
11905
|
+
}
|
|
11906
|
+
} else if (typeof tools === "object") {
|
|
11907
|
+
context.addMessage("system", JSON.stringify(tools, null, 2));
|
|
11908
|
+
}
|
|
11909
|
+
return;
|
|
11910
|
+
}
|
|
11911
|
+
if (sub === "invoke") {
|
|
11912
|
+
const method = rest[0];
|
|
11913
|
+
if (!method) {
|
|
11914
|
+
context.addMessage("system", "Usage: /mcp invoke <method> [args...]");
|
|
11915
|
+
return;
|
|
11916
|
+
}
|
|
11917
|
+
const argsStr = rest.slice(1).join(" ");
|
|
11918
|
+
let argsObj;
|
|
11919
|
+
try {
|
|
11920
|
+
argsObj = argsStr ? JSON.parse(argsStr) : void 0;
|
|
11921
|
+
} catch {
|
|
11922
|
+
argsObj = { raw: argsStr };
|
|
11923
|
+
}
|
|
11924
|
+
const result = await context.client.mcpInvoke(method, argsObj);
|
|
11925
|
+
context.addMessage("system", `MCP Result: ${JSON.stringify(result)}`);
|
|
11926
|
+
return;
|
|
11927
|
+
}
|
|
11928
|
+
if (sub === "disconnect") {
|
|
11929
|
+
const result = await context.client.mcpDisconnect();
|
|
11930
|
+
context.addMessage("system", `MCP Disconnected: ${result.status ?? "ok"}`);
|
|
11931
|
+
return;
|
|
11932
|
+
}
|
|
11933
|
+
context.addMessage("error", `Unknown /mcp subcommand '${sub}'. Try: connect, tools, invoke, disconnect.`);
|
|
11934
|
+
} catch (e) {
|
|
11935
|
+
context.addMessage("error", `MCP: ${e.message}`);
|
|
11936
|
+
}
|
|
11937
|
+
}
|
|
11938
|
+
};
|
|
11939
|
+
}
|
|
11940
|
+
});
|
|
11941
|
+
|
|
11942
|
+
// src/commands/webhook.ts
|
|
11943
|
+
var webhookCommand;
|
|
11944
|
+
var init_webhook = __esm({
|
|
11945
|
+
"src/commands/webhook.ts"() {
|
|
11946
|
+
"use strict";
|
|
11947
|
+
init_esm_shims();
|
|
11948
|
+
webhookCommand = {
|
|
11949
|
+
name: "webhook",
|
|
11950
|
+
args: "[list|add|rm|deliveries|retry] [...args]",
|
|
11951
|
+
description: "Manage webhooks: create, list, delete, and view delivery logs",
|
|
11952
|
+
category: "project",
|
|
11953
|
+
handler: async (args2, context) => {
|
|
11954
|
+
const sub = (args2[0] ?? "list").toLowerCase();
|
|
11955
|
+
const rest = args2.slice(1);
|
|
11956
|
+
try {
|
|
11957
|
+
if (sub === "list") {
|
|
11958
|
+
const webhooks = await context.client.listWebhooks();
|
|
11959
|
+
context.addMessage("system", "Webhooks:");
|
|
11960
|
+
if (Array.isArray(webhooks) && webhooks.length > 0) {
|
|
11961
|
+
for (const wh of webhooks) {
|
|
11962
|
+
const id = wh.id ?? wh.webhook_id ?? "?";
|
|
11963
|
+
const url = wh.url ?? "?";
|
|
11964
|
+
const events = wh.events ? wh.events.join(", ") : "";
|
|
11965
|
+
context.addMessage("system", ` - ${id}: ${url} (${events})`);
|
|
11966
|
+
}
|
|
11967
|
+
} else {
|
|
11968
|
+
context.addMessage("system", " (no webhooks)");
|
|
11969
|
+
}
|
|
11970
|
+
return;
|
|
11971
|
+
}
|
|
11972
|
+
if (sub === "add") {
|
|
11973
|
+
const url = rest[0];
|
|
11974
|
+
const events = rest.slice(1);
|
|
11975
|
+
if (!url || events.length === 0) {
|
|
11976
|
+
context.addMessage("system", "Usage: /webhook add <url> <event1> [event2] ...");
|
|
11977
|
+
return;
|
|
11978
|
+
}
|
|
11979
|
+
const result = await context.client.createWebhook(url, events);
|
|
11980
|
+
const id = result.id ?? result.webhook_id ?? "?";
|
|
11981
|
+
context.addMessage("system", `Webhook created: ${id} \u2192 ${url}`);
|
|
11982
|
+
return;
|
|
11983
|
+
}
|
|
11984
|
+
if (sub === "rm" || sub === "delete") {
|
|
11985
|
+
const id = rest[0];
|
|
11986
|
+
if (!id) {
|
|
11987
|
+
context.addMessage("system", "Usage: /webhook rm <id>");
|
|
11988
|
+
return;
|
|
11989
|
+
}
|
|
11990
|
+
await context.client.deleteWebhook(id);
|
|
11991
|
+
context.addMessage("system", `Deleted webhook: ${id}`);
|
|
11992
|
+
return;
|
|
11993
|
+
}
|
|
11994
|
+
if (sub === "deliveries") {
|
|
11995
|
+
const webhookId = rest[0] || void 0;
|
|
11996
|
+
const deliveries = await context.client.listWebhookDeliveries(webhookId);
|
|
11997
|
+
const title = webhookId ? `Deliveries for webhook ${webhookId}:` : "Recent deliveries:";
|
|
11998
|
+
context.addMessage("system", title);
|
|
11999
|
+
if (Array.isArray(deliveries) && deliveries.length > 0) {
|
|
12000
|
+
for (const d of deliveries) {
|
|
12001
|
+
const id = d.id ?? d.delivery_id ?? "?";
|
|
12002
|
+
const status = d.status ?? "?";
|
|
12003
|
+
const at = d.delivered_at ?? d.created_at ?? "?";
|
|
12004
|
+
context.addMessage("system", ` - ${id}: ${status} (${at})`);
|
|
12005
|
+
}
|
|
12006
|
+
} else {
|
|
12007
|
+
context.addMessage("system", " (no deliveries)");
|
|
12008
|
+
}
|
|
12009
|
+
return;
|
|
12010
|
+
}
|
|
12011
|
+
if (sub === "retry") {
|
|
12012
|
+
const deliveryId = rest[0];
|
|
12013
|
+
if (!deliveryId) {
|
|
12014
|
+
context.addMessage("system", "Usage: /webhook retry <delivery-id>");
|
|
12015
|
+
return;
|
|
12016
|
+
}
|
|
12017
|
+
const result = await context.client.retryWebhookDelivery(deliveryId);
|
|
12018
|
+
context.addMessage("system", `Retrying delivery: ${deliveryId} (${result.status ?? "queued"})`);
|
|
12019
|
+
return;
|
|
12020
|
+
}
|
|
12021
|
+
context.addMessage("error", `Unknown /webhook subcommand '${sub}'. Try: list, add, rm, deliveries, retry.`);
|
|
12022
|
+
} catch (e) {
|
|
12023
|
+
context.addMessage("error", `Webhook: ${e.message}`);
|
|
12024
|
+
}
|
|
12025
|
+
}
|
|
12026
|
+
};
|
|
12027
|
+
}
|
|
12028
|
+
});
|
|
12029
|
+
|
|
11337
12030
|
// src/commands/index.ts
|
|
11338
12031
|
var commands_exports = {};
|
|
11339
12032
|
__export(commands_exports, {
|
|
@@ -11387,6 +12080,16 @@ var init_commands = __esm({
|
|
|
11387
12080
|
init_todo();
|
|
11388
12081
|
init_outputStyle();
|
|
11389
12082
|
init_totp();
|
|
12083
|
+
init_budget();
|
|
12084
|
+
init_image();
|
|
12085
|
+
init_voice();
|
|
12086
|
+
init_wakeup();
|
|
12087
|
+
init_share();
|
|
12088
|
+
init_notify();
|
|
12089
|
+
init_mlineage();
|
|
12090
|
+
init_mfa();
|
|
12091
|
+
init_mcp();
|
|
12092
|
+
init_webhook();
|
|
11390
12093
|
commands = [
|
|
11391
12094
|
loginCommand,
|
|
11392
12095
|
unlockCommand,
|
|
@@ -11426,7 +12129,17 @@ var init_commands = __esm({
|
|
|
11426
12129
|
noteCommand,
|
|
11427
12130
|
todoCommand,
|
|
11428
12131
|
outputStyleCommand,
|
|
11429
|
-
totpCommand
|
|
12132
|
+
totpCommand,
|
|
12133
|
+
budgetCommand,
|
|
12134
|
+
imageCommand,
|
|
12135
|
+
voiceCommand,
|
|
12136
|
+
wakeupCommand,
|
|
12137
|
+
shareCommand,
|
|
12138
|
+
notifyCommand,
|
|
12139
|
+
mlineageCommand,
|
|
12140
|
+
mfaCommand,
|
|
12141
|
+
mcpCommand,
|
|
12142
|
+
webhookCommand
|
|
11430
12143
|
];
|
|
11431
12144
|
}
|
|
11432
12145
|
});
|
|
@@ -15029,7 +15742,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
15029
15742
|
var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
15030
15743
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
15031
15744
|
"\u25CF MSapling CLI v",
|
|
15032
|
-
"2.3.6-beta.
|
|
15745
|
+
"2.3.6-beta.28"
|
|
15033
15746
|
] }),
|
|
15034
15747
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
15035
15748
|
] });
|
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.28",
|
|
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",
|