@mtreeai/msapling-cli 2.3.6-beta.20 → 2.3.6-beta.22
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 +190 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -171,15 +171,20 @@ var init_src = __esm({
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
async me() {
|
|
174
|
-
const
|
|
174
|
+
const [overviewData, billingData] = await Promise.all([
|
|
175
|
+
this.request("/api/projects/overview"),
|
|
176
|
+
this.request("/api/billing/settings").catch(() => null)
|
|
177
|
+
]);
|
|
178
|
+
const data = overviewData;
|
|
179
|
+
const fuel = billingData?.fuel ?? {};
|
|
175
180
|
return {
|
|
176
181
|
user: {
|
|
177
182
|
id: data.user_id,
|
|
178
183
|
email: data.email,
|
|
179
|
-
tier: data.tier,
|
|
184
|
+
tier: billingData?.tier ?? data.tier,
|
|
180
185
|
is_pro: data.is_pro,
|
|
181
|
-
fuel_credits: data.fuel_credits,
|
|
182
|
-
fuel_credits_purchased: data.fuel_credits_purchased || 0,
|
|
186
|
+
fuel_credits: typeof fuel.total === "number" ? fuel.total : data.fuel_credits,
|
|
187
|
+
fuel_credits_purchased: typeof fuel.purchased === "number" ? fuel.purchased : data.fuel_credits_purchased || 0,
|
|
183
188
|
monthly_spending_limit: data.monthly_spending_limit || null,
|
|
184
189
|
cost_byok: data.cost_byok || 0,
|
|
185
190
|
tokens_byok: data.tokens_byok || 0,
|
|
@@ -203,14 +208,19 @@ var init_src = __esm({
|
|
|
203
208
|
};
|
|
204
209
|
}
|
|
205
210
|
async getLiveUsage() {
|
|
206
|
-
const
|
|
211
|
+
const [billingData, overviewData] = await Promise.all([
|
|
212
|
+
this.request("/api/billing/settings").catch(() => null),
|
|
213
|
+
this.request("/api/projects/overview").catch(() => ({}))
|
|
214
|
+
]);
|
|
215
|
+
const fuel = billingData?.fuel ?? {};
|
|
216
|
+
const data = overviewData;
|
|
207
217
|
return {
|
|
208
218
|
id: data.user_id,
|
|
209
219
|
email: data.email,
|
|
210
|
-
tier: data.tier,
|
|
220
|
+
tier: billingData?.tier ?? data.tier,
|
|
211
221
|
is_pro: data.is_pro,
|
|
212
|
-
fuel_credits: data.fuel_credits,
|
|
213
|
-
fuel_credits_purchased: data.fuel_credits_purchased || 0,
|
|
222
|
+
fuel_credits: typeof fuel.total === "number" ? fuel.total : data.fuel_credits,
|
|
223
|
+
fuel_credits_purchased: typeof fuel.purchased === "number" ? fuel.purchased : data.fuel_credits_purchased || 0,
|
|
214
224
|
monthly_spending_limit: data.monthly_spending_limit || null,
|
|
215
225
|
cost_byok: data.cost_byok || 0,
|
|
216
226
|
tokens_byok: data.tokens_byok || 0,
|
|
@@ -8534,26 +8544,101 @@ var init_help = __esm({
|
|
|
8534
8544
|
});
|
|
8535
8545
|
|
|
8536
8546
|
// src/commands/chat.ts
|
|
8537
|
-
|
|
8547
|
+
function labelFor(i) {
|
|
8548
|
+
return i < 9 ? String(i + 1) : LETTERS[i - 9] ?? `#${i + 1}`;
|
|
8549
|
+
}
|
|
8550
|
+
async function fetchChatsForCurrentProject(context) {
|
|
8551
|
+
try {
|
|
8552
|
+
const data = await context.client.request("/api/projects/");
|
|
8553
|
+
const currentId = context.getProjectId() || null;
|
|
8554
|
+
const overview = await context.client.me();
|
|
8555
|
+
const activeProject = overview.projects.find((p) => p.id === currentId) ?? overview.projects[0];
|
|
8556
|
+
if (!activeProject) return { error: "No active project; use /project first." };
|
|
8557
|
+
const bucket = data.projects?.[activeProject.name];
|
|
8558
|
+
return {
|
|
8559
|
+
projectName: activeProject.name,
|
|
8560
|
+
chats: bucket?.chats ?? []
|
|
8561
|
+
};
|
|
8562
|
+
} catch (e) {
|
|
8563
|
+
return { error: `Failed to fetch chats: ${e.message}` };
|
|
8564
|
+
}
|
|
8565
|
+
}
|
|
8566
|
+
function resolveChat(arg, chats) {
|
|
8567
|
+
const trimmed = arg.trim();
|
|
8568
|
+
if (!trimmed) return { kind: "error", message: "empty argument" };
|
|
8569
|
+
const uuidHit = chats.find((c) => c.id === trimmed);
|
|
8570
|
+
if (uuidHit) return { kind: "ok", id: uuidHit.id, title: uuidHit.title };
|
|
8571
|
+
if (/^\d+$/.test(trimmed)) {
|
|
8572
|
+
const n = parseInt(trimmed, 10);
|
|
8573
|
+
if (n >= 1 && n <= chats.length) return { kind: "ok", id: chats[n - 1].id, title: chats[n - 1].title };
|
|
8574
|
+
return { kind: "error", message: `no chat at index ${n} (have ${chats.length})` };
|
|
8575
|
+
}
|
|
8576
|
+
if (/^[a-zA-Z]$/.test(trimmed)) {
|
|
8577
|
+
const idx = 9 + LETTERS.indexOf(trimmed.toLowerCase());
|
|
8578
|
+
if (idx >= 9 && idx < chats.length) return { kind: "ok", id: chats[idx].id, title: chats[idx].title };
|
|
8579
|
+
}
|
|
8580
|
+
const lower = trimmed.toLowerCase();
|
|
8581
|
+
const matches2 = chats.filter((c) => (c.title ?? "").toLowerCase().includes(lower));
|
|
8582
|
+
if (matches2.length === 1) return { kind: "ok", id: matches2[0].id, title: matches2[0].title };
|
|
8583
|
+
if (matches2.length > 1) {
|
|
8584
|
+
return {
|
|
8585
|
+
kind: "error",
|
|
8586
|
+
message: `'${trimmed}' matches ${matches2.length} chats: ${matches2.map((m) => m.title).join(", ")}`
|
|
8587
|
+
};
|
|
8588
|
+
}
|
|
8589
|
+
return { kind: "error", message: `no chat matches '${trimmed}'. Run /chat (no args) for the list.` };
|
|
8590
|
+
}
|
|
8591
|
+
async function listChats(args2, context) {
|
|
8592
|
+
const arg = args2.join(" ").trim();
|
|
8593
|
+
const result = await fetchChatsForCurrentProject(context);
|
|
8594
|
+
if ("error" in result) {
|
|
8595
|
+
context.addMessage("error", result.error);
|
|
8596
|
+
return;
|
|
8597
|
+
}
|
|
8598
|
+
const { projectName, chats } = result;
|
|
8599
|
+
if (!arg) {
|
|
8600
|
+
if (chats.length === 0) {
|
|
8601
|
+
context.addMessage("system", `No chats in project '${projectName}'. Send a message to start one.`);
|
|
8602
|
+
return;
|
|
8603
|
+
}
|
|
8604
|
+
context.addMessage("system", `Chats in '${projectName}':`);
|
|
8605
|
+
chats.forEach((c, i) => {
|
|
8606
|
+
const label = labelFor(i);
|
|
8607
|
+
const star = c.id === context.activeChatId ? " \u2605" : "";
|
|
8608
|
+
const model = c.model ? ` [${c.model}]` : "";
|
|
8609
|
+
context.addMessage("system", ` ${label}. ${c.title ?? c.id}${model}${star}`);
|
|
8610
|
+
});
|
|
8611
|
+
context.addMessage("system", "");
|
|
8612
|
+
context.addMessage("system", "Switch via /chat <number|letter|title> (e.g. /chat 1 or /chat audit)");
|
|
8613
|
+
return;
|
|
8614
|
+
}
|
|
8615
|
+
const resolved = resolveChat(arg, chats);
|
|
8616
|
+
if (resolved.kind === "error") {
|
|
8617
|
+
context.addMessage("error", resolved.message);
|
|
8618
|
+
return;
|
|
8619
|
+
}
|
|
8620
|
+
context.setActiveChatId(resolved.id);
|
|
8621
|
+
context.addMessage("system", `Switched to chat: ${resolved.title ?? resolved.id}`);
|
|
8622
|
+
await context.refreshOverview();
|
|
8623
|
+
}
|
|
8624
|
+
var LETTERS, chatCommand, chatsCommand;
|
|
8538
8625
|
var init_chat = __esm({
|
|
8539
8626
|
"src/commands/chat.ts"() {
|
|
8540
8627
|
"use strict";
|
|
8541
8628
|
init_esm_shims();
|
|
8629
|
+
LETTERS = "abcdefghijklmnopqrstuvwxyz";
|
|
8542
8630
|
chatCommand = {
|
|
8543
8631
|
name: "chat",
|
|
8544
|
-
args: "
|
|
8545
|
-
description: "
|
|
8632
|
+
args: "[number|letter|title|id]",
|
|
8633
|
+
description: "List chats in the current project, or switch to one",
|
|
8546
8634
|
category: "chat",
|
|
8547
|
-
handler: async (args2, context) =>
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
context.addMessage("system", `Switched to chat: ${chatId}`);
|
|
8555
|
-
await context.refreshOverview();
|
|
8556
|
-
}
|
|
8635
|
+
handler: async (args2, context) => listChats(args2, context)
|
|
8636
|
+
};
|
|
8637
|
+
chatsCommand = {
|
|
8638
|
+
name: "chats",
|
|
8639
|
+
description: "List chats in the current project (alias for /chat with no args)",
|
|
8640
|
+
category: "chat",
|
|
8641
|
+
handler: async (_args, context) => listChats([], context)
|
|
8557
8642
|
};
|
|
8558
8643
|
}
|
|
8559
8644
|
});
|
|
@@ -8819,34 +8904,80 @@ var init_memory = __esm({
|
|
|
8819
8904
|
});
|
|
8820
8905
|
|
|
8821
8906
|
// src/commands/project.ts
|
|
8822
|
-
|
|
8907
|
+
function labelFor2(i) {
|
|
8908
|
+
return i < 9 ? String(i + 1) : LETTERS2[i - 9] ?? `#${i + 1}`;
|
|
8909
|
+
}
|
|
8910
|
+
function resolveProject(arg, list) {
|
|
8911
|
+
const trimmed = arg.trim();
|
|
8912
|
+
if (!trimmed) return { kind: "error", message: "empty argument" };
|
|
8913
|
+
const uuidHit = list.find((p) => p.id === trimmed);
|
|
8914
|
+
if (uuidHit) return { kind: "ok", id: uuidHit.id };
|
|
8915
|
+
if (/^\d+$/.test(trimmed)) {
|
|
8916
|
+
const n = parseInt(trimmed, 10);
|
|
8917
|
+
if (n >= 1 && n <= list.length) return { kind: "ok", id: list[n - 1].id };
|
|
8918
|
+
return { kind: "error", message: `no project at index ${n} (have ${list.length})` };
|
|
8919
|
+
}
|
|
8920
|
+
if (/^[a-zA-Z]$/.test(trimmed)) {
|
|
8921
|
+
const idx = 9 + LETTERS2.indexOf(trimmed.toLowerCase());
|
|
8922
|
+
if (idx >= 9 && idx < list.length) return { kind: "ok", id: list[idx].id };
|
|
8923
|
+
}
|
|
8924
|
+
const lower = trimmed.toLowerCase();
|
|
8925
|
+
const matches2 = list.filter((p) => (p.name ?? "").toLowerCase().includes(lower));
|
|
8926
|
+
if (matches2.length === 1) return { kind: "ok", id: matches2[0].id };
|
|
8927
|
+
if (matches2.length > 1) {
|
|
8928
|
+
return {
|
|
8929
|
+
kind: "error",
|
|
8930
|
+
message: `'${trimmed}' matches ${matches2.length} projects: ${matches2.map((m) => m.name).join(", ")}`
|
|
8931
|
+
};
|
|
8932
|
+
}
|
|
8933
|
+
return { kind: "error", message: `no project matches '${trimmed}'. Run /project (no args) for the list.` };
|
|
8934
|
+
}
|
|
8935
|
+
var LETTERS2, projectCommand;
|
|
8823
8936
|
var init_project = __esm({
|
|
8824
8937
|
"src/commands/project.ts"() {
|
|
8825
8938
|
"use strict";
|
|
8826
8939
|
init_esm_shims();
|
|
8940
|
+
LETTERS2 = "abcdefghijklmnopqrstuvwxyz";
|
|
8827
8941
|
projectCommand = {
|
|
8828
8942
|
name: "project",
|
|
8829
|
-
args: "[
|
|
8943
|
+
args: "[number|letter|name|id]",
|
|
8830
8944
|
description: "List or switch active project",
|
|
8831
8945
|
category: "project",
|
|
8832
8946
|
handler: async (args2, context) => {
|
|
8833
|
-
const
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8947
|
+
const arg = args2.join(" ").trim();
|
|
8948
|
+
const currentId = context.getProjectId() || null;
|
|
8949
|
+
let projects = [];
|
|
8950
|
+
try {
|
|
8951
|
+
const overview = await context.client.me();
|
|
8952
|
+
projects = overview.projects;
|
|
8953
|
+
} catch (e) {
|
|
8954
|
+
context.addMessage("error", `Failed to fetch projects: ${e.message}`);
|
|
8955
|
+
return;
|
|
8956
|
+
}
|
|
8957
|
+
if (!arg) {
|
|
8958
|
+
if (projects.length === 0) {
|
|
8959
|
+
context.addMessage("system", "No projects found.");
|
|
8960
|
+
return;
|
|
8845
8961
|
}
|
|
8962
|
+
context.addMessage("system", "Available Projects:");
|
|
8963
|
+
projects.forEach((p, i) => {
|
|
8964
|
+
const label = labelFor2(i);
|
|
8965
|
+
const star = p.id === currentId ? " \u2605" : "";
|
|
8966
|
+
const usage = p.chat_count != null && p.chat_limit != null ? ` (${p.chat_count}/${p.chat_limit} chats)` : "";
|
|
8967
|
+
context.addMessage("system", ` ${label}. ${p.name ?? p.id}${usage}${star}`);
|
|
8968
|
+
});
|
|
8969
|
+
context.addMessage("system", "");
|
|
8970
|
+
context.addMessage("system", "Switch via /project <number|letter|name> (e.g. /project 2 or /project audit)");
|
|
8846
8971
|
return;
|
|
8847
8972
|
}
|
|
8848
|
-
|
|
8849
|
-
|
|
8973
|
+
const resolved = resolveProject(arg, projects);
|
|
8974
|
+
if (resolved.kind === "error") {
|
|
8975
|
+
context.addMessage("error", resolved.message);
|
|
8976
|
+
return;
|
|
8977
|
+
}
|
|
8978
|
+
const picked = projects.find((p) => p.id === resolved.id);
|
|
8979
|
+
context.setProjectId(resolved.id);
|
|
8980
|
+
context.addMessage("system", `Project switched to: ${picked.name ?? resolved.id}`);
|
|
8850
8981
|
await context.refreshOverview();
|
|
8851
8982
|
}
|
|
8852
8983
|
};
|
|
@@ -9341,7 +9472,7 @@ var init_benchmark = __esm({
|
|
|
9341
9472
|
let models = modelArg ?? [];
|
|
9342
9473
|
if (!models.length) {
|
|
9343
9474
|
try {
|
|
9344
|
-
const resp = await context.client.
|
|
9475
|
+
const resp = await context.client.request("/api/benchmark/models");
|
|
9345
9476
|
const list = Array.isArray(resp) ? resp : resp?.models ?? [];
|
|
9346
9477
|
models = list.slice(0, 4).map((m) => m.id ?? m.model_id ?? "").filter(Boolean);
|
|
9347
9478
|
} catch {
|
|
@@ -9567,14 +9698,14 @@ var init_status = __esm({
|
|
|
9567
9698
|
context.addMessage("error", `Health check failed: ${e.message}`);
|
|
9568
9699
|
}
|
|
9569
9700
|
try {
|
|
9570
|
-
const countData = await context.client["request"]("/api/stream/active-count");
|
|
9701
|
+
const countData = await context.client["request"]("/api/chat/stream/active-count");
|
|
9571
9702
|
const count = countData?.count ?? countData?.active_count ?? 0;
|
|
9572
9703
|
context.addMessage("system", `[INFO] Active Streams: ${count}`);
|
|
9573
9704
|
} catch (e) {
|
|
9574
9705
|
context.addMessage("system", ` Active Streams: unavailable (${e.message})`);
|
|
9575
9706
|
}
|
|
9576
9707
|
try {
|
|
9577
|
-
const providerData = await context.client["request"]("/api/
|
|
9708
|
+
const providerData = await context.client["request"]("/api/provider/circuit-summary");
|
|
9578
9709
|
const providers = providerData?.providers ?? (Array.isArray(providerData) ? providerData : []);
|
|
9579
9710
|
if (providers.length > 0) {
|
|
9580
9711
|
context.addMessage("system", " Provider Circuits:");
|
|
@@ -9745,7 +9876,7 @@ var init_version = __esm({
|
|
|
9745
9876
|
description: "Show version information for CLI and core packages",
|
|
9746
9877
|
category: "debug",
|
|
9747
9878
|
handler: async (_args, context) => {
|
|
9748
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
9879
|
+
const cliVersion = true ? "2.3.6-beta.22" : "(dev)";
|
|
9749
9880
|
const coreVersion = true ? "2.3.2" : "(dev)";
|
|
9750
9881
|
const runtime = process.version;
|
|
9751
9882
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -9754,7 +9885,7 @@ var init_version = __esm({
|
|
|
9754
9885
|
context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
|
|
9755
9886
|
context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
|
|
9756
9887
|
try {
|
|
9757
|
-
const ts = "2026-05-
|
|
9888
|
+
const ts = "2026-05-28T19:10:28.448Z";
|
|
9758
9889
|
if (ts && ts !== "__BUILD_TIMESTAMP__") {
|
|
9759
9890
|
context.addMessage("system", row2("Build Timestamp", ts));
|
|
9760
9891
|
}
|
|
@@ -10527,6 +10658,7 @@ var init_commands = __esm({
|
|
|
10527
10658
|
exitCommand,
|
|
10528
10659
|
helpCommand,
|
|
10529
10660
|
chatCommand,
|
|
10661
|
+
chatsCommand,
|
|
10530
10662
|
clearCommand,
|
|
10531
10663
|
modeCommand,
|
|
10532
10664
|
modelCommand,
|
|
@@ -10752,9 +10884,22 @@ async function apiFetch(path2, opts = {}) {
|
|
|
10752
10884
|
return fetch(`${getBaseURL()}${path2}`, { ...opts, headers, body });
|
|
10753
10885
|
}
|
|
10754
10886
|
async function fetchBalance() {
|
|
10755
|
-
const res = await apiFetch("/api/billing/
|
|
10887
|
+
const res = await apiFetch("/api/billing/settings");
|
|
10756
10888
|
if (!res.ok) throw new Error(`Balance fetch failed: ${res.status}`);
|
|
10757
|
-
|
|
10889
|
+
const data = await res.json();
|
|
10890
|
+
return {
|
|
10891
|
+
tier: data.tier ?? "free",
|
|
10892
|
+
is_pro: data.tier && !["free", "guest"].includes(String(data.tier).toLowerCase()),
|
|
10893
|
+
is_founder: false,
|
|
10894
|
+
fuel_credits: Number(data?.fuel?.total ?? 0),
|
|
10895
|
+
fuel_credits_purchased: Number(data?.fuel?.purchased ?? 0),
|
|
10896
|
+
auto_topup: {
|
|
10897
|
+
enabled: !!data?.auto_topup?.enabled,
|
|
10898
|
+
threshold_usd: Number(data?.auto_topup?.threshold_usd ?? 0),
|
|
10899
|
+
amount_usd: Number(data?.auto_topup?.amount_usd ?? 0),
|
|
10900
|
+
max_per_month_usd: Number(data?.auto_topup?.max_per_month_usd ?? 0)
|
|
10901
|
+
}
|
|
10902
|
+
};
|
|
10758
10903
|
}
|
|
10759
10904
|
async function fetchFounderStatus() {
|
|
10760
10905
|
const res = await apiFetch("/api/billing/founder-status");
|
|
@@ -14143,7 +14288,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
14143
14288
|
var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
14144
14289
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
14145
14290
|
"\u25CF MSapling CLI v",
|
|
14146
|
-
"2.3.6-beta.
|
|
14291
|
+
"2.3.6-beta.22"
|
|
14147
14292
|
] }),
|
|
14148
14293
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
14149
14294
|
] });
|
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.22",
|
|
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",
|