@mtreeai/msapling-cli 2.3.6-beta.21 → 2.3.6-beta.23
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 +238 -19
- 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,
|
|
@@ -256,8 +266,45 @@ var init_src = __esm({
|
|
|
256
266
|
body: JSON.stringify(symbol)
|
|
257
267
|
});
|
|
258
268
|
}
|
|
269
|
+
// CLI-PROJECT-CREATE-01 (Iter 34): create a new project. Per LAB
|
|
270
|
+
// projects.py:239 — POST /api/projects/ with {project_name}.
|
|
271
|
+
async createProject(name) {
|
|
272
|
+
return await this.request("/api/projects/", {
|
|
273
|
+
method: "POST",
|
|
274
|
+
body: JSON.stringify({ project_name: name })
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// CLI-CHAT-CREATE-01 (Iter 34): create a new chat in a project. Per LAB
|
|
278
|
+
// projects.py:365 — POST /api/projects/chat/new with
|
|
279
|
+
// {project_name, slot_label?, chat_name?, model?, client_type?}.
|
|
280
|
+
async createChat(opts) {
|
|
281
|
+
return await this.request("/api/projects/chat/new", {
|
|
282
|
+
method: "POST",
|
|
283
|
+
body: JSON.stringify({
|
|
284
|
+
project_name: opts.projectName,
|
|
285
|
+
slot_label: opts.title,
|
|
286
|
+
chat_name: opts.title,
|
|
287
|
+
model: opts.model,
|
|
288
|
+
client_type: "cli"
|
|
289
|
+
})
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
// CLI-BROADCAST-01 (Iter 34): broadcast a prompt to sibling chats in a
|
|
293
|
+
// project. Per LAB broadcast.py:145 — POST /api/broadcast/execute with
|
|
294
|
+
// {project_name, prompt, source_chat_id?, max_targets?}.
|
|
295
|
+
async broadcastExecute(opts) {
|
|
296
|
+
return await this.request("/api/broadcast/execute", {
|
|
297
|
+
method: "POST",
|
|
298
|
+
body: JSON.stringify({
|
|
299
|
+
project_name: opts.projectName,
|
|
300
|
+
prompt: opts.prompt,
|
|
301
|
+
source_chat_id: opts.sourceChatId,
|
|
302
|
+
max_targets: opts.maxTargets
|
|
303
|
+
})
|
|
304
|
+
});
|
|
305
|
+
}
|
|
259
306
|
async getModels() {
|
|
260
|
-
return await this.request("/api/models");
|
|
307
|
+
return await this.request("/api/benchmark/models");
|
|
261
308
|
}
|
|
262
309
|
/**
|
|
263
310
|
* Fetch the canonical tool registry from the backend.
|
|
@@ -8578,7 +8625,41 @@ function resolveChat(arg, chats) {
|
|
|
8578
8625
|
}
|
|
8579
8626
|
return { kind: "error", message: `no chat matches '${trimmed}'. Run /chat (no args) for the list.` };
|
|
8580
8627
|
}
|
|
8628
|
+
async function createChat(args2, context) {
|
|
8629
|
+
let title = "";
|
|
8630
|
+
let model;
|
|
8631
|
+
for (let i = 0; i < args2.length; i++) {
|
|
8632
|
+
if (args2[i] === "--model" && i + 1 < args2.length) {
|
|
8633
|
+
model = args2[i + 1];
|
|
8634
|
+
i++;
|
|
8635
|
+
} else {
|
|
8636
|
+
title += (title ? " " : "") + args2[i];
|
|
8637
|
+
}
|
|
8638
|
+
}
|
|
8639
|
+
try {
|
|
8640
|
+
const overview = await context.client.me();
|
|
8641
|
+
const currentId = context.getProjectId();
|
|
8642
|
+
const project = overview.projects.find((p) => p.id === currentId) ?? overview.projects[0];
|
|
8643
|
+
if (!project) {
|
|
8644
|
+
context.addMessage("error", "No active project. Use /project new <name> or /project <id> first.");
|
|
8645
|
+
return;
|
|
8646
|
+
}
|
|
8647
|
+
const result = await context.client.createChat({
|
|
8648
|
+
projectName: project.name,
|
|
8649
|
+
title: title || void 0,
|
|
8650
|
+
model: model || void 0
|
|
8651
|
+
});
|
|
8652
|
+
context.addMessage("system", `Created chat "${result.title}" (${result.chat_id}) using ${result.model}`);
|
|
8653
|
+
context.setActiveChatId(result.chat_id);
|
|
8654
|
+
await context.refreshOverview();
|
|
8655
|
+
} catch (e) {
|
|
8656
|
+
context.addMessage("error", `Failed to create chat: ${e.message}`);
|
|
8657
|
+
}
|
|
8658
|
+
}
|
|
8581
8659
|
async function listChats(args2, context) {
|
|
8660
|
+
if (args2[0] === "new" || args2[0] === "create") {
|
|
8661
|
+
return createChat(args2.slice(1), context);
|
|
8662
|
+
}
|
|
8582
8663
|
const arg = args2.join(" ").trim();
|
|
8583
8664
|
const result = await fetchChatsForCurrentProject(context);
|
|
8584
8665
|
if ("error" in result) {
|
|
@@ -8633,6 +8714,74 @@ var init_chat = __esm({
|
|
|
8633
8714
|
}
|
|
8634
8715
|
});
|
|
8635
8716
|
|
|
8717
|
+
// src/commands/broadcast.ts
|
|
8718
|
+
var broadcastCommand;
|
|
8719
|
+
var init_broadcast = __esm({
|
|
8720
|
+
"src/commands/broadcast.ts"() {
|
|
8721
|
+
"use strict";
|
|
8722
|
+
init_esm_shims();
|
|
8723
|
+
broadcastCommand = {
|
|
8724
|
+
name: "broadcast",
|
|
8725
|
+
aliases: ["bcast"],
|
|
8726
|
+
args: "[--max N] [--exclude-current] <prompt>",
|
|
8727
|
+
description: "Send a prompt to every sibling chat in the active project (rate-limited 10/min).",
|
|
8728
|
+
category: "chat",
|
|
8729
|
+
handler: async (args2, context) => {
|
|
8730
|
+
let maxTargets = 8;
|
|
8731
|
+
let excludeCurrent = false;
|
|
8732
|
+
const promptParts = [];
|
|
8733
|
+
for (let i = 0; i < args2.length; i++) {
|
|
8734
|
+
if (args2[i] === "--max" && i + 1 < args2.length) {
|
|
8735
|
+
const n = Number(args2[i + 1]);
|
|
8736
|
+
if (Number.isFinite(n) && n > 0) maxTargets = Math.min(32, Math.floor(n));
|
|
8737
|
+
i++;
|
|
8738
|
+
continue;
|
|
8739
|
+
}
|
|
8740
|
+
if (args2[i] === "--exclude-current") {
|
|
8741
|
+
excludeCurrent = true;
|
|
8742
|
+
continue;
|
|
8743
|
+
}
|
|
8744
|
+
promptParts.push(args2[i]);
|
|
8745
|
+
}
|
|
8746
|
+
const prompt4 = promptParts.join(" ").trim();
|
|
8747
|
+
if (!prompt4) {
|
|
8748
|
+
context.addMessage("system", "Usage: /broadcast [--max N] [--exclude-current] <prompt>");
|
|
8749
|
+
return;
|
|
8750
|
+
}
|
|
8751
|
+
try {
|
|
8752
|
+
const overview = await context.client.me();
|
|
8753
|
+
const currentId = context.getProjectId();
|
|
8754
|
+
const project = overview.projects.find((p) => p.id === currentId) ?? overview.projects[0];
|
|
8755
|
+
if (!project) {
|
|
8756
|
+
context.addMessage("error", "No active project. Use /project <id> first.");
|
|
8757
|
+
return;
|
|
8758
|
+
}
|
|
8759
|
+
const result = await context.client.broadcastExecute({
|
|
8760
|
+
projectName: project.name,
|
|
8761
|
+
prompt: prompt4,
|
|
8762
|
+
sourceChatId: excludeCurrent ? context.activeChatId ?? void 0 : void 0,
|
|
8763
|
+
maxTargets
|
|
8764
|
+
});
|
|
8765
|
+
context.addMessage(
|
|
8766
|
+
"system",
|
|
8767
|
+
`Broadcast queued: ${result.broadcast_id} \u2192 ${result.target_chat_ids?.length ?? 0} chat(s) in project '${project.name}'.`
|
|
8768
|
+
);
|
|
8769
|
+
if (Array.isArray(result.target_chat_ids) && result.target_chat_ids.length > 0) {
|
|
8770
|
+
for (const cid of result.target_chat_ids.slice(0, 8)) {
|
|
8771
|
+
context.addMessage("system", ` - ${cid}`);
|
|
8772
|
+
}
|
|
8773
|
+
if (result.target_chat_ids.length > 8) {
|
|
8774
|
+
context.addMessage("system", ` \u2026and ${result.target_chat_ids.length - 8} more.`);
|
|
8775
|
+
}
|
|
8776
|
+
}
|
|
8777
|
+
} catch (e) {
|
|
8778
|
+
context.addMessage("error", `Broadcast failed: ${e.message}`);
|
|
8779
|
+
}
|
|
8780
|
+
}
|
|
8781
|
+
};
|
|
8782
|
+
}
|
|
8783
|
+
});
|
|
8784
|
+
|
|
8636
8785
|
// src/commands/clear.ts
|
|
8637
8786
|
var clearCommand;
|
|
8638
8787
|
var init_clear = __esm({
|
|
@@ -8790,8 +8939,47 @@ Current: ${current}`);
|
|
|
8790
8939
|
}
|
|
8791
8940
|
return;
|
|
8792
8941
|
}
|
|
8793
|
-
|
|
8794
|
-
|
|
8942
|
+
try {
|
|
8943
|
+
const models = await context.client.getModels();
|
|
8944
|
+
const list = models.filter((m) => !!m.id);
|
|
8945
|
+
const trimmed = newModel.trim();
|
|
8946
|
+
const exact = list.find((m) => m.id === trimmed);
|
|
8947
|
+
if (exact) {
|
|
8948
|
+
context.setModel(exact.id);
|
|
8949
|
+
context.addMessage("system", `Model switched to: ${exact.id}`);
|
|
8950
|
+
return;
|
|
8951
|
+
}
|
|
8952
|
+
if (/^\d+$/.test(trimmed)) {
|
|
8953
|
+
const idx = parseInt(trimmed, 10) - 1;
|
|
8954
|
+
if (idx >= 0 && idx < list.length && list[idx].id) {
|
|
8955
|
+
context.setModel(list[idx].id);
|
|
8956
|
+
context.addMessage("system", `Model switched to: ${list[idx].id}`);
|
|
8957
|
+
return;
|
|
8958
|
+
}
|
|
8959
|
+
}
|
|
8960
|
+
const lower = trimmed.toLowerCase();
|
|
8961
|
+
const subs = list.filter((m) => (m.id ?? "").toLowerCase().includes(lower));
|
|
8962
|
+
if (subs.length === 1) {
|
|
8963
|
+
context.setModel(subs[0].id);
|
|
8964
|
+
context.addMessage("system", `Model switched to: ${subs[0].id}`);
|
|
8965
|
+
return;
|
|
8966
|
+
}
|
|
8967
|
+
if (subs.length > 1 && subs.length <= 10) {
|
|
8968
|
+
context.addMessage(
|
|
8969
|
+
"error",
|
|
8970
|
+
`'${trimmed}' matches ${subs.length} models: ${subs.map((m) => m.id).join(", ")}`
|
|
8971
|
+
);
|
|
8972
|
+
return;
|
|
8973
|
+
}
|
|
8974
|
+
if (subs.length > 10) {
|
|
8975
|
+
context.addMessage("error", `'${trimmed}' matches ${subs.length} models \u2014 be more specific.`);
|
|
8976
|
+
return;
|
|
8977
|
+
}
|
|
8978
|
+
context.addMessage("error", `No model matches '${trimmed}'. Run /model (no args) for the list of ${list.length} models.`);
|
|
8979
|
+
} catch (e) {
|
|
8980
|
+
context.setModel(newModel);
|
|
8981
|
+
context.addMessage("system", `Model switched to: ${newModel} (unverified \u2014 model catalog unreachable: ${e.message})`);
|
|
8982
|
+
}
|
|
8795
8983
|
}
|
|
8796
8984
|
};
|
|
8797
8985
|
}
|
|
@@ -8936,6 +9124,22 @@ var init_project = __esm({
|
|
|
8936
9124
|
handler: async (args2, context) => {
|
|
8937
9125
|
const arg = args2.join(" ").trim();
|
|
8938
9126
|
const currentId = context.getProjectId() || null;
|
|
9127
|
+
if (args2[0] === "new" || args2[0] === "create") {
|
|
9128
|
+
const name = args2.slice(1).join(" ").trim();
|
|
9129
|
+
if (!name) {
|
|
9130
|
+
context.addMessage("system", "Usage: /project new <name>");
|
|
9131
|
+
return;
|
|
9132
|
+
}
|
|
9133
|
+
try {
|
|
9134
|
+
const result = await context.client.createProject(name);
|
|
9135
|
+
context.addMessage("system", `Created project "${result.project}" (${result.project_id})`);
|
|
9136
|
+
context.setProjectId(result.project_id);
|
|
9137
|
+
await context.refreshOverview();
|
|
9138
|
+
} catch (e) {
|
|
9139
|
+
context.addMessage("error", `Failed to create project: ${e.message}`);
|
|
9140
|
+
}
|
|
9141
|
+
return;
|
|
9142
|
+
}
|
|
8939
9143
|
let projects = [];
|
|
8940
9144
|
try {
|
|
8941
9145
|
const overview = await context.client.me();
|
|
@@ -9462,7 +9666,7 @@ var init_benchmark = __esm({
|
|
|
9462
9666
|
let models = modelArg ?? [];
|
|
9463
9667
|
if (!models.length) {
|
|
9464
9668
|
try {
|
|
9465
|
-
const resp = await context.client.
|
|
9669
|
+
const resp = await context.client.request("/api/benchmark/models");
|
|
9466
9670
|
const list = Array.isArray(resp) ? resp : resp?.models ?? [];
|
|
9467
9671
|
models = list.slice(0, 4).map((m) => m.id ?? m.model_id ?? "").filter(Boolean);
|
|
9468
9672
|
} catch {
|
|
@@ -9688,14 +9892,14 @@ var init_status = __esm({
|
|
|
9688
9892
|
context.addMessage("error", `Health check failed: ${e.message}`);
|
|
9689
9893
|
}
|
|
9690
9894
|
try {
|
|
9691
|
-
const countData = await context.client["request"]("/api/stream/active-count");
|
|
9895
|
+
const countData = await context.client["request"]("/api/chat/stream/active-count");
|
|
9692
9896
|
const count = countData?.count ?? countData?.active_count ?? 0;
|
|
9693
9897
|
context.addMessage("system", `[INFO] Active Streams: ${count}`);
|
|
9694
9898
|
} catch (e) {
|
|
9695
9899
|
context.addMessage("system", ` Active Streams: unavailable (${e.message})`);
|
|
9696
9900
|
}
|
|
9697
9901
|
try {
|
|
9698
|
-
const providerData = await context.client["request"]("/api/
|
|
9902
|
+
const providerData = await context.client["request"]("/api/provider/circuit-summary");
|
|
9699
9903
|
const providers = providerData?.providers ?? (Array.isArray(providerData) ? providerData : []);
|
|
9700
9904
|
if (providers.length > 0) {
|
|
9701
9905
|
context.addMessage("system", " Provider Circuits:");
|
|
@@ -9866,7 +10070,7 @@ var init_version = __esm({
|
|
|
9866
10070
|
description: "Show version information for CLI and core packages",
|
|
9867
10071
|
category: "debug",
|
|
9868
10072
|
handler: async (_args, context) => {
|
|
9869
|
-
const cliVersion = true ? "2.3.6-beta.
|
|
10073
|
+
const cliVersion = true ? "2.3.6-beta.23" : "(dev)";
|
|
9870
10074
|
const coreVersion = true ? "2.3.2" : "(dev)";
|
|
9871
10075
|
const runtime = process.version;
|
|
9872
10076
|
context.addMessage("system", "MSapling Version Info");
|
|
@@ -9875,7 +10079,7 @@ var init_version = __esm({
|
|
|
9875
10079
|
context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
|
|
9876
10080
|
context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
|
|
9877
10081
|
try {
|
|
9878
|
-
const ts = "2026-05-
|
|
10082
|
+
const ts = "2026-05-28T19:20:38.494Z";
|
|
9879
10083
|
if (ts && ts !== "__BUILD_TIMESTAMP__") {
|
|
9880
10084
|
context.addMessage("system", row2("Build Timestamp", ts));
|
|
9881
10085
|
}
|
|
@@ -10614,6 +10818,7 @@ var init_commands = __esm({
|
|
|
10614
10818
|
init_exit();
|
|
10615
10819
|
init_help();
|
|
10616
10820
|
init_chat();
|
|
10821
|
+
init_broadcast();
|
|
10617
10822
|
init_clear();
|
|
10618
10823
|
init_mode();
|
|
10619
10824
|
init_model();
|
|
@@ -10649,6 +10854,7 @@ var init_commands = __esm({
|
|
|
10649
10854
|
helpCommand,
|
|
10650
10855
|
chatCommand,
|
|
10651
10856
|
chatsCommand,
|
|
10857
|
+
broadcastCommand,
|
|
10652
10858
|
clearCommand,
|
|
10653
10859
|
modeCommand,
|
|
10654
10860
|
modelCommand,
|
|
@@ -10874,9 +11080,22 @@ async function apiFetch(path2, opts = {}) {
|
|
|
10874
11080
|
return fetch(`${getBaseURL()}${path2}`, { ...opts, headers, body });
|
|
10875
11081
|
}
|
|
10876
11082
|
async function fetchBalance() {
|
|
10877
|
-
const res = await apiFetch("/api/billing/
|
|
11083
|
+
const res = await apiFetch("/api/billing/settings");
|
|
10878
11084
|
if (!res.ok) throw new Error(`Balance fetch failed: ${res.status}`);
|
|
10879
|
-
|
|
11085
|
+
const data = await res.json();
|
|
11086
|
+
return {
|
|
11087
|
+
tier: data.tier ?? "free",
|
|
11088
|
+
is_pro: data.tier && !["free", "guest"].includes(String(data.tier).toLowerCase()),
|
|
11089
|
+
is_founder: false,
|
|
11090
|
+
fuel_credits: Number(data?.fuel?.total ?? 0),
|
|
11091
|
+
fuel_credits_purchased: Number(data?.fuel?.purchased ?? 0),
|
|
11092
|
+
auto_topup: {
|
|
11093
|
+
enabled: !!data?.auto_topup?.enabled,
|
|
11094
|
+
threshold_usd: Number(data?.auto_topup?.threshold_usd ?? 0),
|
|
11095
|
+
amount_usd: Number(data?.auto_topup?.amount_usd ?? 0),
|
|
11096
|
+
max_per_month_usd: Number(data?.auto_topup?.max_per_month_usd ?? 0)
|
|
11097
|
+
}
|
|
11098
|
+
};
|
|
10880
11099
|
}
|
|
10881
11100
|
async function fetchFounderStatus() {
|
|
10882
11101
|
const res = await apiFetch("/api/billing/founder-status");
|
|
@@ -14265,7 +14484,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
14265
14484
|
var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
|
|
14266
14485
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
14267
14486
|
"\u25CF MSapling CLI v",
|
|
14268
|
-
"2.3.6-beta.
|
|
14487
|
+
"2.3.6-beta.23"
|
|
14269
14488
|
] }),
|
|
14270
14489
|
/* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
|
|
14271
14490
|
] });
|
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.23",
|
|
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",
|