@mtreeai/msapling-cli 2.3.6-beta.19 → 2.3.6-beta.20

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.
Files changed (2) hide show
  1. package/dist/index.js +842 -42
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -457,9 +457,9 @@ var init_src = __esm({
457
457
  * Single-turn chat: send a prompt, accumulate the streaming response into
458
458
  * a single string. Used by the MCP `msapling_chat` tool.
459
459
  */
460
- async chatOnce(prompt, model, chatId) {
460
+ async chatOnce(prompt4, model, chatId) {
461
461
  let acc = "";
462
- for await (const chunk of this.streamChat({ content: prompt, model, chat_id: chatId ?? "" })) {
462
+ for await (const chunk of this.streamChat({ content: prompt4, model, chat_id: chatId ?? "" })) {
463
463
  if (chunk.delta) acc += chunk.delta;
464
464
  else if (chunk.content) acc += chunk.content;
465
465
  }
@@ -470,10 +470,10 @@ var init_src = __esm({
470
470
  * one row per model with status + response or error. Used by the MCP
471
471
  * `msapling_multi_chat` tool and the existing /swarm slash command path.
472
472
  */
473
- async multiChat(prompt, models) {
473
+ async multiChat(prompt4, models) {
474
474
  const results = await Promise.all(models.map(async (model) => {
475
475
  try {
476
- const response = await this.chatOnce(prompt, model);
476
+ const response = await this.chatOnce(prompt4, model);
477
477
  return { model, status: "ok", response };
478
478
  } catch (e) {
479
479
  return { model, status: "error", error: e?.message ?? String(e) };
@@ -2365,7 +2365,7 @@ var init_DispatchAgentTool = __esm({
2365
2365
  isError: true
2366
2366
  };
2367
2367
  }
2368
- const prompt = args2.prompt.trim().slice(0, MAX_PROMPT_CHARS);
2368
+ const prompt4 = args2.prompt.trim().slice(0, MAX_PROMPT_CHARS);
2369
2369
  const model = typeof args2.model === "string" && args2.model.trim() ? args2.model.trim() : DEFAULT_SUB_AGENT_MODEL;
2370
2370
  const chatId = typeof args2.chat_id === "string" && args2.chat_id.trim() ? args2.chat_id.trim() : this.parentChatId;
2371
2371
  const description = typeof args2.description === "string" && args2.description.trim() ? args2.description.trim() : "sub-task";
@@ -2378,7 +2378,7 @@ var init_DispatchAgentTool = __esm({
2378
2378
  );
2379
2379
  const streamPromise = (async () => {
2380
2380
  const stream = this.client.streamChat({
2381
- prompt,
2381
+ prompt: prompt4,
2382
2382
  model,
2383
2383
  // No tools — sub-agent is read/reasoning only.
2384
2384
  tools: [],
@@ -4248,7 +4248,7 @@ var init_ShadowService = __esm({
4248
4248
  * that regex might miss.
4249
4249
  */
4250
4250
  async redact(text) {
4251
- const prompt = `You are a security shadow. Redact all API keys, secrets, and private credentials from the following text.
4251
+ const prompt4 = `You are a security shadow. Redact all API keys, secrets, and private credentials from the following text.
4252
4252
  Return the text exactly as is, but replace secrets with [REDACTED].
4253
4253
  If no secrets are found, return the text UNCHANGED.
4254
4254
 
@@ -4256,7 +4256,7 @@ var init_ShadowService = __esm({
4256
4256
  ${text}`;
4257
4257
  let result = "";
4258
4258
  for await (const chunk of this.client.streamChat({
4259
- prompt,
4259
+ prompt: prompt4,
4260
4260
  model: this.shadowModel,
4261
4261
  history: []
4262
4262
  })) {
@@ -4268,14 +4268,14 @@ var init_ShadowService = __esm({
4268
4268
  * Shadow Verification: Double-check a primary model's plan or tool call.
4269
4269
  */
4270
4270
  async verifyAction(action, context) {
4271
- const prompt = `Review this proposed agent action for safety and logical correctness.
4271
+ const prompt4 = `Review this proposed agent action for safety and logical correctness.
4272
4272
  CONTEXT: ${context}
4273
4273
  PROPOSED ACTION: ${action}
4274
4274
 
4275
4275
  Respond in JSON: { "approved": boolean, "reasoning": "string" }`;
4276
4276
  let response = "";
4277
4277
  for await (const chunk of this.client.streamChat({
4278
- prompt,
4278
+ prompt: prompt4,
4279
4279
  model: this.shadowModel,
4280
4280
  history: []
4281
4281
  })) {
@@ -4293,14 +4293,14 @@ var init_ShadowService = __esm({
4293
4293
  * Double-Read: Read a file using the shadow model to verify findings.
4294
4294
  */
4295
4295
  async doubleRead(filePath, content, query) {
4296
- const prompt = `Verification Read of ${filePath}.
4296
+ const prompt4 = `Verification Read of ${filePath}.
4297
4297
  The primary agent is looking for: ${query}
4298
4298
 
4299
4299
  FILE CONTENT:
4300
4300
  ${content}`;
4301
4301
  let response = "";
4302
4302
  for await (const chunk of this.client.streamChat({
4303
- prompt,
4303
+ prompt: prompt4,
4304
4304
  model: this.shadowModel,
4305
4305
  history: []
4306
4306
  })) {
@@ -4458,7 +4458,15 @@ var init_ToolExecutor = __esm({
4458
4458
  mdrive;
4459
4459
  voice;
4460
4460
  shadow;
4461
- toolsEnabled = false;
4461
+ // CLI-TOOLS-ENABLED-DEFAULT-ON-01 (Iter 30): default to true so the CLI's
4462
+ // 19 client-side tools are actually advertised to the backend in
4463
+ // ChatMessagePayload.tools. Previously false, and nothing in the CLI ever
4464
+ // called setToolsEnabled(true), so getToolSchemas() always returned [] and
4465
+ // the LLM had no idea tools existed — which is why every chat refused
4466
+ // file/shell access. Side effects are still gated by the permission mode
4467
+ // (default prompts before each call) and the persistent trust store.
4468
+ // Opt out via MSAPLING_TOOLS_ENABLED=false.
4469
+ toolsEnabled = process.env.MSAPLING_TOOLS_ENABLED !== "false";
4462
4470
  mode = "default";
4463
4471
  approvalCallback = null;
4464
4472
  /**
@@ -4696,12 +4704,14 @@ Please approve the diff in the UI to sync this change locally.`
4696
4704
  const builtin = Array.from(this.tools.values()).map((t) => ({
4697
4705
  name: t.name,
4698
4706
  description: t.description,
4699
- parameters: t.parameters
4707
+ parameters: t.parameters,
4708
+ input_schema: t.parameters
4700
4709
  }));
4701
4710
  const mcp = this.getMCPTools().map(({ server, tool }) => ({
4702
4711
  name: tool.name,
4703
4712
  description: tool.description ? `[mcp:${server}] ${tool.description}` : `[mcp:${server}]`,
4704
- parameters: tool.inputSchema ?? {}
4713
+ parameters: tool.inputSchema ?? {},
4714
+ input_schema: tool.inputSchema ?? {}
4705
4715
  }));
4706
4716
  return [...builtin, ...mcp];
4707
4717
  }
@@ -5017,11 +5027,11 @@ var init_Agent = __esm({
5017
5027
  * Returns null when the backend stream did not include a usage chunk (e.g.
5018
5028
  * old backend versions or local/offline models that omit billing data).
5019
5029
  */
5020
- async runWorkerTurn(chatId, prompt, model, onContent) {
5030
+ async runWorkerTurn(chatId, prompt4, model, onContent) {
5021
5031
  if (this.hooks) {
5022
5032
  const outcomes = await this.hooks.fire({
5023
5033
  event: "user-prompt-submit",
5024
- payload: prompt,
5034
+ payload: prompt4,
5025
5035
  cwd: this.projectRoot
5026
5036
  });
5027
5037
  const blocker = HookRunner.anyBlocked(outcomes);
@@ -5033,7 +5043,7 @@ var init_Agent = __esm({
5033
5043
  }
5034
5044
  const config = await this.getProjectConfig();
5035
5045
  const MAX_WORKER_TURN_DEPTH = 25;
5036
- const queue = [prompt];
5046
+ const queue = [prompt4];
5037
5047
  let rounds = 0;
5038
5048
  let streamUsage = null;
5039
5049
  while (queue.length > 0 && rounds < MAX_WORKER_TURN_DEPTH) {
@@ -5122,9 +5132,9 @@ ${next}`;
5122
5132
  }
5123
5133
  return streamUsage;
5124
5134
  }
5125
- async run(prompt, model) {
5135
+ async run(prompt4, model) {
5126
5136
  let fullResponse = "";
5127
- const stream = this.client.streamChat({ prompt, model });
5137
+ const stream = this.client.streamChat({ prompt: prompt4, model });
5128
5138
  for await (const chunk of stream) {
5129
5139
  if (chunk.content) fullResponse += chunk.content;
5130
5140
  }
@@ -7976,6 +7986,47 @@ ${combinedData}`;
7976
7986
  });
7977
7987
 
7978
7988
  // ../core/src/index.ts
7989
+ var src_exports2 = {};
7990
+ __export(src_exports2, {
7991
+ APPROVAL_GATED: () => APPROVAL_GATED,
7992
+ Agent: () => Agent,
7993
+ AsyncMutex: () => AsyncMutex,
7994
+ BashTool: () => BashTool,
7995
+ ContextBudget: () => ContextBudget,
7996
+ DEFAULT_SETTINGS: () => DEFAULT_SETTINGS,
7997
+ DeleteFileTool: () => DeleteFileTool,
7998
+ DispatchAgentTool: () => DispatchAgentTool,
7999
+ GlobFilesTool: () => GlobFilesTool,
8000
+ GrepSearchTool: () => GrepSearchTool,
8001
+ HookRunner: () => HookRunner,
8002
+ ListDirectoryTool: () => ListDirectoryTool,
8003
+ MCPClient: () => MCPClient,
8004
+ MCPClientError: () => MCPClientError,
8005
+ MCPRegistry: () => MCPRegistry,
8006
+ MoveFileTool: () => MoveFileTool,
8007
+ MultiEditFileTool: () => MultiEditFileTool,
8008
+ NotebookEditTool: () => NotebookEditTool,
8009
+ NotebookReadTool: () => NotebookReadTool,
8010
+ PatchFileTool: () => PatchFileTool,
8011
+ StorageManager: () => StorageManager,
8012
+ SwarmManager: () => SwarmManager,
8013
+ TodoReadTool: () => TodoReadTool,
8014
+ TodoStore: () => TodoStore,
8015
+ TodoWriteTool: () => TodoWriteTool,
8016
+ ToolExecutor: () => ToolExecutor,
8017
+ TrustStore: () => TrustStore,
8018
+ WebFetchTool: () => WebFetchTool,
8019
+ WriteFileTool: () => WriteFileTool,
8020
+ buildCompactionPrompt: () => buildCompactionPrompt,
8021
+ buildHwContext: () => buildHwContext,
8022
+ ensureConfigDir: () => ensureConfigDir,
8023
+ formatCell: () => formatCell,
8024
+ formatNotebookHeader: () => formatNotebookHeader,
8025
+ formatTodos: () => formatTodos,
8026
+ loadProjectConfig: () => loadProjectConfig,
8027
+ loadSettings: () => loadSettings,
8028
+ takeSnapshot: () => takeSnapshot
8029
+ });
7979
8030
  var init_src3 = __esm({
7980
8031
  "../core/src/index.ts"() {
7981
8032
  "use strict";
@@ -8023,11 +8074,11 @@ function setRawModeGuarded(stdin, mode) {
8023
8074
  } catch (e) {
8024
8075
  }
8025
8076
  }
8026
- async function promptPassword(prompt) {
8077
+ async function promptPassword(prompt4) {
8027
8078
  return new Promise((resolve18) => {
8028
8079
  const stdin = process.stdin;
8029
8080
  const stdout = process.stdout;
8030
- stdout.write(prompt);
8081
+ stdout.write(prompt4);
8031
8082
  const wasRaw = stdin.isRaw ?? false;
8032
8083
  setRawModeGuarded(stdin, true);
8033
8084
  let password = "";
@@ -8906,12 +8957,12 @@ var init_review = __esm({
8906
8957
  } catch (e) {
8907
8958
  content = `Review target: ${target}`;
8908
8959
  }
8909
- const prompt = `Please review the following code/target for issues, best practices, and bugs:
8960
+ const prompt4 = `Please review the following code/target for issues, best practices, and bugs:
8910
8961
 
8911
8962
  ${content}`;
8912
8963
  context.addMessage("user", `/review ${target}`);
8913
8964
  if (context.runAgent) {
8914
- await context.runAgent(prompt);
8965
+ await context.runAgent(prompt4);
8915
8966
  } else {
8916
8967
  context.addMessage("error", "Agent execution from commands not wired up. Use regular prompt for now.");
8917
8968
  }
@@ -8938,15 +8989,15 @@ var init_swarm = __esm({
8938
8989
  description: `Run the prompt against ${DEFAULT_MODELS.length} models in parallel; synthesize.`,
8939
8990
  category: "swarm",
8940
8991
  handler: async (args2, context) => {
8941
- const prompt = args2.join(" ").trim();
8942
- if (!prompt) {
8992
+ const prompt4 = args2.join(" ").trim();
8993
+ if (!prompt4) {
8943
8994
  context.addMessage("system", "Usage: /swarm <prompt>");
8944
8995
  return;
8945
8996
  }
8946
8997
  const tasks = DEFAULT_MODELS.map((model, i) => ({
8947
8998
  id: `w${i + 1}`,
8948
8999
  name: `worker-${i + 1}`,
8949
- prompt,
9000
+ prompt: prompt4,
8950
9001
  model
8951
9002
  }));
8952
9003
  const initialWorkers = tasks.map((t) => ({
@@ -9046,13 +9097,13 @@ var init_recipe = __esm({
9046
9097
  return;
9047
9098
  }
9048
9099
  const name = args2[0];
9049
- const prompt = args2.slice(1).join(" ").trim();
9100
+ const prompt4 = args2.slice(1).join(" ").trim();
9050
9101
  const path2 = findRecipe(name, cwd);
9051
9102
  if (!path2) {
9052
9103
  context.addMessage("error", `Recipe '${name}' not found. Tried: ${RECIPE_DIRS.map((d) => `${d}/${name}{,_workflow}.{yaml,yml}`).join(", ")}`);
9053
9104
  return;
9054
9105
  }
9055
- if (!prompt) {
9106
+ if (!prompt4) {
9056
9107
  context.addMessage("system", `Usage: /recipe ${name} <prompt> (the prompt fills $SELECTION / $PROMPT in step templates)`);
9057
9108
  return;
9058
9109
  }
@@ -9086,7 +9137,7 @@ var init_recipe = __esm({
9086
9137
  const sysPrompt = String(params.system_prompt ?? "");
9087
9138
  const tpl = String(params.prompt_template ?? "$PROMPT");
9088
9139
  const model = String(params.model ?? context.getModel());
9089
- const rendered = renderTemplate(tpl, { prompt });
9140
+ const rendered = renderTemplate(tpl, { prompt: prompt4 });
9090
9141
  context.addMessage("system", `${stepLabel} (model: ${model})`);
9091
9142
  const fullPrompt = sysPrompt ? `[System: ${sysPrompt}]
9092
9143
 
@@ -9201,13 +9252,13 @@ var init_skill = __esm({
9201
9252
  return;
9202
9253
  }
9203
9254
  const ref = args2[0];
9204
- const prompt = args2.slice(1).join(" ").trim();
9255
+ const prompt4 = args2.slice(1).join(" ").trim();
9205
9256
  const skill = findSkill(root, ref);
9206
9257
  if (!skill) {
9207
9258
  context.addMessage("error", `No skill matches '${ref}'. Run /skill (no args) for the list.`);
9208
9259
  return;
9209
9260
  }
9210
- if (!prompt) {
9261
+ if (!prompt4) {
9211
9262
  context.addMessage("system", `Usage: /skill ${skill.domain}/${skill.name} <prompt>`);
9212
9263
  return;
9213
9264
  }
@@ -9224,7 +9275,7 @@ ${body.trim()}
9224
9275
 
9225
9276
  ---
9226
9277
 
9227
- ${prompt}`;
9278
+ ${prompt4}`;
9228
9279
  if (context.runAgent) {
9229
9280
  context.addMessage("system", `Running /skill ${skill.domain}/${skill.name}...`);
9230
9281
  await context.runAgent(fullPrompt);
@@ -9694,7 +9745,7 @@ var init_version = __esm({
9694
9745
  description: "Show version information for CLI and core packages",
9695
9746
  category: "debug",
9696
9747
  handler: async (_args, context) => {
9697
- const cliVersion = true ? "2.3.6-beta.19" : "(dev)";
9748
+ const cliVersion = true ? "2.3.6-beta.20" : "(dev)";
9698
9749
  const coreVersion = true ? "2.3.2" : "(dev)";
9699
9750
  const runtime = process.version;
9700
9751
  context.addMessage("system", "MSapling Version Info");
@@ -9703,7 +9754,7 @@ var init_version = __esm({
9703
9754
  context.addMessage("system", row2("Core (@msapling/core)", coreVersion));
9704
9755
  context.addMessage("system", row2("Runtime (Node/Bun)", runtime));
9705
9756
  try {
9706
- const ts = "2026-05-28T18:28:54.068Z";
9757
+ const ts = "2026-05-28T18:54:30.369Z";
9707
9758
  if (ts && ts !== "__BUILD_TIMESTAMP__") {
9708
9759
  context.addMessage("system", row2("Build Timestamp", ts));
9709
9760
  }
@@ -10673,6 +10724,727 @@ var init_exec = __esm({
10673
10724
  }
10674
10725
  });
10675
10726
 
10727
+ // src/commands/billing/api.ts
10728
+ async function getAuthToken() {
10729
+ if (process.env.MSAPLING_AUTH_TOKEN) return process.env.MSAPLING_AUTH_TOKEN;
10730
+ try {
10731
+ const { StorageManager: StorageManager3 } = await Promise.resolve().then(() => (init_src3(), src_exports2));
10732
+ const sm = new StorageManager3();
10733
+ return await sm.loadToken();
10734
+ } catch {
10735
+ return null;
10736
+ }
10737
+ }
10738
+ function getBaseURL() {
10739
+ return (process.env.MSAPLING_API_URL ?? "https://api.msapling.com").replace(/\/$/, "");
10740
+ }
10741
+ async function apiFetch(path2, opts = {}) {
10742
+ const token = await getAuthToken();
10743
+ const headers = {
10744
+ "X-Surface": "cli",
10745
+ "Content-Type": "application/json",
10746
+ ...opts.headers
10747
+ };
10748
+ if (token) {
10749
+ headers["Authorization"] = `Bearer ${token}`;
10750
+ }
10751
+ const body = opts.json !== void 0 ? JSON.stringify(opts.json) : opts.body;
10752
+ return fetch(`${getBaseURL()}${path2}`, { ...opts, headers, body });
10753
+ }
10754
+ async function fetchBalance() {
10755
+ const res = await apiFetch("/api/billing/balance");
10756
+ if (!res.ok) throw new Error(`Balance fetch failed: ${res.status}`);
10757
+ return res.json();
10758
+ }
10759
+ async function fetchFounderStatus() {
10760
+ const res = await apiFetch("/api/billing/founder-status");
10761
+ if (!res.ok) return { lifetime_total_spots: 50, lifetime_sold: 0, lifetime_spots_remaining: 50 };
10762
+ return res.json();
10763
+ }
10764
+ async function postCheckout(payload) {
10765
+ const res = await apiFetch("/api/billing/checkout", { method: "POST", json: payload });
10766
+ if (!res.ok) {
10767
+ const err = await res.json().catch(() => ({}));
10768
+ throw new Error(err.detail ?? `Checkout failed: ${res.status}`);
10769
+ }
10770
+ return res.json();
10771
+ }
10772
+ async function fetchCheckoutStatus(token) {
10773
+ const res = await apiFetch(`/api/billing/checkout/${token}/status`);
10774
+ if (!res.ok) return { state: "expired" };
10775
+ return res.json();
10776
+ }
10777
+ async function patchAutoTopup(payload) {
10778
+ const res = await apiFetch("/api/billing/auto-topup", { method: "PATCH", json: payload });
10779
+ if (!res.ok) throw new Error(`Auto-topup update failed: ${res.status}`);
10780
+ return res.json();
10781
+ }
10782
+ async function postSubscriptionCancel() {
10783
+ const res = await apiFetch("/subscription/cancel", { method: "POST" });
10784
+ if (!res.ok) throw new Error(`Cancel failed: ${res.status}`);
10785
+ return res.json();
10786
+ }
10787
+ async function fetchUserLookup(username) {
10788
+ const res = await apiFetch(`/api/users/lookup?username=${encodeURIComponent(username)}`);
10789
+ if (res.status === 404) return null;
10790
+ if (!res.ok) throw new Error(`User lookup failed: ${res.status}`);
10791
+ return res.json();
10792
+ }
10793
+ async function postGiftRedeem(code) {
10794
+ const res = await apiFetch("/api/billing/gift/redeem", { method: "POST", json: { code } });
10795
+ if (!res.ok) {
10796
+ const err = await res.json().catch(() => ({}));
10797
+ throw new Error(err.detail ?? `Redeem failed: ${res.status}`);
10798
+ }
10799
+ return res.json();
10800
+ }
10801
+ var init_api = __esm({
10802
+ "src/commands/billing/api.ts"() {
10803
+ "use strict";
10804
+ init_esm_shims();
10805
+ }
10806
+ });
10807
+
10808
+ // src/commands/billing/format.ts
10809
+ function formatTier(tier) {
10810
+ const map = {
10811
+ free: "Free",
10812
+ monthly: "Pro ($20/mo)",
10813
+ lifetime: "Lifetime ($129 once, Founder)",
10814
+ pro: "Pro"
10815
+ };
10816
+ return map[tier.toLowerCase()] ?? tier;
10817
+ }
10818
+ function formatUSD(amount) {
10819
+ return `$${amount.toFixed(2)}`;
10820
+ }
10821
+ function formatCredits(amount) {
10822
+ return `${amount.toFixed(4)} credits`;
10823
+ }
10824
+ function formatCreditsAsUSD(credits) {
10825
+ return formatUSD(credits * CREDIT_RATE_USD);
10826
+ }
10827
+ function formatSubSummary(info) {
10828
+ const tierLabel = formatTier(info.tier);
10829
+ const creditsStr = formatCredits(info.fuel_credits);
10830
+ const lines = [
10831
+ `Tier: ${tierLabel}`,
10832
+ `Credits: ${creditsStr} (${formatCreditsAsUSD(info.fuel_credits)})`
10833
+ ];
10834
+ if (info.auto_topup.enabled) {
10835
+ lines.push(
10836
+ `Auto-topup: ON \u2014 tops up ${formatUSD(info.auto_topup.amount_usd)} when below ${formatUSD(info.auto_topup.threshold_usd)} (cap ${formatUSD(info.auto_topup.max_per_month_usd)}/mo)`
10837
+ );
10838
+ } else {
10839
+ lines.push("Auto-topup: OFF");
10840
+ }
10841
+ return lines.join("\n");
10842
+ }
10843
+ var CREDIT_RATE_USD, TOPUP_MENU;
10844
+ var init_format = __esm({
10845
+ "src/commands/billing/format.ts"() {
10846
+ "use strict";
10847
+ init_esm_shims();
10848
+ CREDIT_RATE_USD = 1.556;
10849
+ TOPUP_MENU = [
10850
+ { key: "fuel_5", label: "5 credits \u2014 $7.78" },
10851
+ { key: "fuel_10", label: "10 credits \u2014 $15.56" }
10852
+ ];
10853
+ }
10854
+ });
10855
+
10856
+ // src/commands/billing/open-browser.ts
10857
+ import { spawn as spawn10 } from "child_process";
10858
+ async function openBrowser(url) {
10859
+ const platform4 = process.platform;
10860
+ let cmd;
10861
+ let args2;
10862
+ if (platform4 === "win32") {
10863
+ cmd = "cmd";
10864
+ args2 = ["/c", "start", "", url];
10865
+ } else if (platform4 === "darwin") {
10866
+ cmd = "open";
10867
+ args2 = [url];
10868
+ } else {
10869
+ cmd = "xdg-open";
10870
+ args2 = [url];
10871
+ }
10872
+ return new Promise((resolve18) => {
10873
+ try {
10874
+ const child = spawn10(cmd, args2, { stdio: "ignore", detached: true });
10875
+ child.unref();
10876
+ } catch {
10877
+ }
10878
+ resolve18();
10879
+ });
10880
+ }
10881
+ var init_open_browser = __esm({
10882
+ "src/commands/billing/open-browser.ts"() {
10883
+ "use strict";
10884
+ init_esm_shims();
10885
+ }
10886
+ });
10887
+
10888
+ // src/commands/billing/checkout.ts
10889
+ async function runCheckout(opts) {
10890
+ const surface = opts.surface ?? "cli";
10891
+ const log = opts.onStatus ?? (() => {
10892
+ });
10893
+ log("Creating checkout session...");
10894
+ const session = await postCheckout({
10895
+ product: opts.product,
10896
+ surface,
10897
+ recipient: opts.recipient,
10898
+ gift_method: opts.gift_method
10899
+ });
10900
+ log(`Opening browser: ${session.checkout_url}`);
10901
+ await openBrowser(session.checkout_url);
10902
+ log("Browser opened. Complete payment in the browser, then return here.");
10903
+ log("Waiting for payment confirmation (up to 15 minutes)...");
10904
+ const sseResult = await _watchViaSSE(session.checkout_token, log);
10905
+ if (sseResult !== null) return sseResult;
10906
+ return _watchViaPoll(session.checkout_token, log);
10907
+ }
10908
+ async function _watchViaSSE(token, log) {
10909
+ try {
10910
+ const res = await apiFetch(`/api/billing/checkout/${token}/watch`, {
10911
+ headers: { Accept: "text/event-stream" }
10912
+ });
10913
+ if (!res.ok || !res.body) return null;
10914
+ const reader = res.body.getReader();
10915
+ const decoder = new TextDecoder();
10916
+ const deadline = Date.now() + MAX_POLL_MS;
10917
+ let buffer = "";
10918
+ while (Date.now() < deadline) {
10919
+ const { value, done } = await reader.read();
10920
+ if (done) break;
10921
+ buffer += decoder.decode(value, { stream: true });
10922
+ const lines = buffer.split("\n");
10923
+ buffer = lines.pop() ?? "";
10924
+ for (const line of lines) {
10925
+ if (line.startsWith("data: ")) {
10926
+ try {
10927
+ const payload = JSON.parse(line.slice(6));
10928
+ if (TERMINAL_STATES.has(payload.state)) {
10929
+ return payload;
10930
+ }
10931
+ } catch {
10932
+ }
10933
+ }
10934
+ }
10935
+ }
10936
+ return null;
10937
+ } catch {
10938
+ return null;
10939
+ }
10940
+ }
10941
+ async function _watchViaPoll(token, log) {
10942
+ const deadline = Date.now() + MAX_POLL_MS;
10943
+ while (Date.now() < deadline) {
10944
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
10945
+ const status = await fetchCheckoutStatus(token);
10946
+ if (TERMINAL_STATES.has(status.state)) {
10947
+ return status;
10948
+ }
10949
+ }
10950
+ return { state: "expired" };
10951
+ }
10952
+ var TERMINAL_STATES, POLL_INTERVAL_MS, MAX_POLL_MS;
10953
+ var init_checkout = __esm({
10954
+ "src/commands/billing/checkout.ts"() {
10955
+ "use strict";
10956
+ init_esm_shims();
10957
+ init_api();
10958
+ init_open_browser();
10959
+ TERMINAL_STATES = /* @__PURE__ */ new Set(["completed", "cancelled", "expired"]);
10960
+ POLL_INTERVAL_MS = 2e3;
10961
+ MAX_POLL_MS = 14 * 60 * 1e3;
10962
+ }
10963
+ });
10964
+
10965
+ // src/commands/billing/sub.ts
10966
+ import * as readline from "readline";
10967
+ function prompt(rl, question) {
10968
+ return new Promise((resolve18) => rl.question(question, resolve18));
10969
+ }
10970
+ async function runSub(argv) {
10971
+ const subCmd = argv[0] ?? "";
10972
+ if (subCmd === "upgrade") {
10973
+ return runSubUpgrade(argv.slice(1));
10974
+ }
10975
+ if (subCmd === "manage") {
10976
+ return runSubManage();
10977
+ }
10978
+ if (subCmd === "cancel") {
10979
+ return runSubCancel();
10980
+ }
10981
+ try {
10982
+ const balance = await fetchBalance();
10983
+ console.log("\n--- MSapling Subscription ---");
10984
+ console.log(formatSubSummary(balance));
10985
+ console.log("");
10986
+ } catch (e) {
10987
+ console.error(`Error fetching subscription status: ${e.message}`);
10988
+ process.exit(1);
10989
+ }
10990
+ }
10991
+ async function runSubUpgrade(flags) {
10992
+ const wantPro = flags.includes("--pro");
10993
+ const wantLifetime = flags.includes("--lifetime");
10994
+ let product;
10995
+ if (wantPro) {
10996
+ product = "monthly";
10997
+ } else if (wantLifetime) {
10998
+ product = "lifetime";
10999
+ } else {
11000
+ let founderRemaining = null;
11001
+ try {
11002
+ const fs3 = await fetchFounderStatus();
11003
+ founderRemaining = fs3.lifetime_spots_remaining;
11004
+ } catch {
11005
+ founderRemaining = null;
11006
+ }
11007
+ console.log("\n--- Upgrade MSapling ---");
11008
+ console.log("1) Pro \u2014 $20.00/month");
11009
+ const lifetimeLabel = founderRemaining !== null ? `Lifetime \u2014 $129.00 one-time (${founderRemaining} founder spots remaining)` : "Lifetime \u2014 $129.00 one-time (50 founder spots)";
11010
+ console.log(`2) ${lifetimeLabel}`);
11011
+ console.log("0) Cancel");
11012
+ console.log("");
11013
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
11014
+ const choice = (await prompt(rl, "Select option: ")).trim();
11015
+ rl.close();
11016
+ if (choice === "1") {
11017
+ product = "monthly";
11018
+ } else if (choice === "2") {
11019
+ product = "lifetime";
11020
+ } else {
11021
+ console.log("Upgrade cancelled.");
11022
+ return;
11023
+ }
11024
+ }
11025
+ console.log(`
11026
+ Starting checkout for ${product}...`);
11027
+ try {
11028
+ const result = await runCheckout({
11029
+ product,
11030
+ surface: "cli",
11031
+ onStatus: (msg) => console.log(msg)
11032
+ });
11033
+ if (result.state === "completed") {
11034
+ console.log(`
11035
+ Payment confirmed. Your plan has been upgraded to ${formatTier(product)}.`);
11036
+ } else {
11037
+ console.log(`
11038
+ Checkout ${result.state}. No charges were made.`);
11039
+ }
11040
+ } catch (e) {
11041
+ console.error(`Checkout error: ${e.message}`);
11042
+ process.exit(1);
11043
+ }
11044
+ }
11045
+ async function runSubManage() {
11046
+ console.log(
11047
+ "\nCustomer Portal endpoint (/api/billing/portal) is not yet implemented.\nTo manage your subscription, visit: https://msapling.com/billing\n"
11048
+ );
11049
+ }
11050
+ async function runSubCancel() {
11051
+ try {
11052
+ const balance = await fetchBalance();
11053
+ if (!balance.is_pro && balance.tier !== "monthly") {
11054
+ console.log("You are not on a Pro subscription. Nothing to cancel.");
11055
+ return;
11056
+ }
11057
+ console.log(`
11058
+ Current plan: ${formatTier(balance.tier)}`);
11059
+ } catch (e) {
11060
+ console.error(`Error fetching subscription: ${e.message}`);
11061
+ process.exit(1);
11062
+ }
11063
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
11064
+ const confirm1 = (await prompt(rl, "Are you sure you want to cancel? [y/N] ")).trim().toLowerCase();
11065
+ if (confirm1 !== "y") {
11066
+ rl.close();
11067
+ console.log("Cancelled \u2014 no changes made.");
11068
+ return;
11069
+ }
11070
+ const confirm2 = (await prompt(rl, "Type 'cancel' to confirm: ")).trim().toLowerCase();
11071
+ rl.close();
11072
+ if (confirm2 !== "cancel") {
11073
+ console.log("Cancelled \u2014 no changes made.");
11074
+ return;
11075
+ }
11076
+ try {
11077
+ await postSubscriptionCancel();
11078
+ console.log("\nSubscription cancelled. You retain access until the end of your billing period.");
11079
+ } catch (e) {
11080
+ console.error(`Cancel failed: ${e.message}`);
11081
+ process.exit(1);
11082
+ }
11083
+ }
11084
+ var init_sub = __esm({
11085
+ "src/commands/billing/sub.ts"() {
11086
+ "use strict";
11087
+ init_esm_shims();
11088
+ init_api();
11089
+ init_format();
11090
+ init_checkout();
11091
+ }
11092
+ });
11093
+
11094
+ // src/commands/billing/topup.ts
11095
+ import * as readline2 from "readline";
11096
+ function prompt2(rl, question) {
11097
+ return new Promise((resolve18) => rl.question(question, resolve18));
11098
+ }
11099
+ function promptDefault(rl, question, defaultVal) {
11100
+ return new Promise(
11101
+ (resolve18) => rl.question(`${question} [${defaultVal}]: `, (ans) => resolve18(ans.trim() || defaultVal))
11102
+ );
11103
+ }
11104
+ async function runTopup(argv) {
11105
+ const subCmd = argv[0] ?? "";
11106
+ if (subCmd === "auto") {
11107
+ return runTopupAuto();
11108
+ }
11109
+ console.log("\n--- MSapling Fuel Top-Up ---");
11110
+ TOPUP_MENU.forEach((item, i) => console.log(`${i + 1}) ${item.label}`));
11111
+ console.log("0) Cancel");
11112
+ console.log("");
11113
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
11114
+ const choice = (await prompt2(rl, "Select option: ")).trim();
11115
+ rl.close();
11116
+ const index = parseInt(choice, 10);
11117
+ if (!index || index < 1 || index > TOPUP_MENU.length) {
11118
+ console.log("Top-up cancelled.");
11119
+ return;
11120
+ }
11121
+ const product = TOPUP_MENU[index - 1].key;
11122
+ console.log(`
11123
+ Starting checkout for ${TOPUP_MENU[index - 1].label}...`);
11124
+ try {
11125
+ const result = await runCheckout({
11126
+ product,
11127
+ surface: "cli",
11128
+ onStatus: (msg) => console.log(msg)
11129
+ });
11130
+ if (result.state === "completed") {
11131
+ try {
11132
+ const balance = await fetchBalance();
11133
+ console.log(
11134
+ `
11135
+ Payment confirmed. New balance: ${formatCredits(balance.fuel_credits)} (${formatUSD(
11136
+ balance.fuel_credits
11137
+ )}).`
11138
+ );
11139
+ } catch {
11140
+ console.log("\nPayment confirmed. Run `msapling sub` to see updated balance.");
11141
+ }
11142
+ } else {
11143
+ console.log(`
11144
+ Checkout ${result.state}. No charges were made.`);
11145
+ }
11146
+ } catch (e) {
11147
+ console.error(`Checkout error: ${e.message}`);
11148
+ process.exit(1);
11149
+ }
11150
+ }
11151
+ async function runTopupAuto() {
11152
+ let balance;
11153
+ try {
11154
+ balance = await fetchBalance();
11155
+ } catch (e) {
11156
+ console.error(`Error fetching settings: ${e.message}`);
11157
+ process.exit(1);
11158
+ }
11159
+ const at = balance.auto_topup;
11160
+ console.log("\n--- Auto-Topup Settings ---");
11161
+ console.log(`Enabled: ${at.enabled ? "yes" : "no"}`);
11162
+ console.log(`Threshold: ${formatUSD(at.threshold_usd)} (topup when below this)`);
11163
+ console.log(`Amount: ${formatUSD(at.amount_usd)} per topup`);
11164
+ console.log(`Monthly cap: ${formatUSD(at.max_per_month_usd)}`);
11165
+ console.log("");
11166
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
11167
+ const edit = (await prompt2(rl, "Edit settings? [y/N] ")).trim().toLowerCase();
11168
+ if (edit !== "y") {
11169
+ rl.close();
11170
+ return;
11171
+ }
11172
+ const enabledStr = await promptDefault(rl, "Enable auto-topup? (yes/no)", at.enabled ? "yes" : "no");
11173
+ const threshStr = await promptDefault(rl, "Threshold USD (min $1)", String(at.threshold_usd));
11174
+ const amountStr = await promptDefault(rl, "Topup amount USD (min $5)", String(at.amount_usd));
11175
+ const capStr = await promptDefault(rl, "Monthly cap USD (min $10)", String(at.max_per_month_usd));
11176
+ rl.close();
11177
+ const enabled = enabledStr.toLowerCase().startsWith("y") || enabledStr === "1";
11178
+ const threshold = parseFloat(threshStr);
11179
+ const amount = parseFloat(amountStr);
11180
+ const cap = parseFloat(capStr);
11181
+ if (isNaN(threshold) || isNaN(amount) || isNaN(cap)) {
11182
+ console.error("Invalid values \u2014 no changes made.");
11183
+ process.exit(1);
11184
+ }
11185
+ try {
11186
+ await patchAutoTopup({
11187
+ enabled,
11188
+ threshold_usd: threshold,
11189
+ amount_usd: amount,
11190
+ monthly_cap_usd: cap
11191
+ });
11192
+ console.log("Auto-topup settings updated.");
11193
+ } catch (e) {
11194
+ console.error(`Update failed: ${e.message}`);
11195
+ process.exit(1);
11196
+ }
11197
+ }
11198
+ var init_topup = __esm({
11199
+ "src/commands/billing/topup.ts"() {
11200
+ "use strict";
11201
+ init_esm_shims();
11202
+ init_api();
11203
+ init_format();
11204
+ init_checkout();
11205
+ }
11206
+ });
11207
+
11208
+ // src/commands/billing/redeem.ts
11209
+ var redeem_exports = {};
11210
+ __export(redeem_exports, {
11211
+ runRedeem: () => runRedeem
11212
+ });
11213
+ async function runRedeem(argv) {
11214
+ const code = (argv[0] ?? "").trim().toUpperCase();
11215
+ if (!code) {
11216
+ console.error("Usage: msapling gift redeem <code> (e.g. MSAPL-GIFT-ABCD-EFGH)");
11217
+ process.exit(1);
11218
+ }
11219
+ try {
11220
+ const result = await postGiftRedeem(code);
11221
+ if (result.applied) {
11222
+ console.log(`Gift applied: ${result.message}`);
11223
+ } else {
11224
+ console.log(`Could not apply gift: ${result.message}`);
11225
+ }
11226
+ } catch (e) {
11227
+ console.error(`Redeem failed: ${e.message}`);
11228
+ process.exit(1);
11229
+ }
11230
+ }
11231
+ var init_redeem = __esm({
11232
+ "src/commands/billing/redeem.ts"() {
11233
+ "use strict";
11234
+ init_esm_shims();
11235
+ init_api();
11236
+ }
11237
+ });
11238
+
11239
+ // src/commands/billing/gift.ts
11240
+ import * as readline3 from "readline";
11241
+ function prompt3(rl, question) {
11242
+ return new Promise((resolve18) => rl.question(question, resolve18));
11243
+ }
11244
+ async function runGift(argv) {
11245
+ const subCmd = argv[0] ?? "";
11246
+ if (subCmd === "sub") return runGiftSub(argv.slice(1));
11247
+ if (subCmd === "credits") return runGiftCredits(argv.slice(1));
11248
+ if (subCmd === "redeem") return runRedeem(argv.slice(1));
11249
+ console.error("Usage: msapling gift sub <user> | credits <user> <5|10> | redeem <code>");
11250
+ process.exit(1);
11251
+ }
11252
+ async function _resolveRecipient(username) {
11253
+ const clean = username.replace(/^@/, "");
11254
+ try {
11255
+ const user = await fetchUserLookup(clean);
11256
+ if (user === null) {
11257
+ console.error(`User @${clean} not found.`);
11258
+ process.exit(1);
11259
+ }
11260
+ } catch (e) {
11261
+ console.error(`User lookup failed: ${e.message}`);
11262
+ process.exit(1);
11263
+ }
11264
+ return clean;
11265
+ }
11266
+ async function _giftMethodMenu() {
11267
+ console.log("\n1) Direct \u2014 applied to recipient immediately after payment");
11268
+ console.log("2) Redeemable code \u2014 90-day expiry, share anywhere");
11269
+ console.log("");
11270
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
11271
+ const choice = (await prompt3(rl, "Select gift method: ")).trim();
11272
+ rl.close();
11273
+ if (choice === "1") return "direct";
11274
+ if (choice === "2") return "code";
11275
+ console.error("Invalid choice.");
11276
+ process.exit(1);
11277
+ }
11278
+ async function runGiftSub(argv) {
11279
+ const usernameRaw = argv[0] ?? "";
11280
+ if (!usernameRaw) {
11281
+ console.error("Usage: msapling gift sub <username|@username>");
11282
+ process.exit(1);
11283
+ }
11284
+ const recipient = await _resolveRecipient(usernameRaw);
11285
+ console.log(`
11286
+ Gifting Pro subscription to @${recipient}`);
11287
+ const giftMethod = await _giftMethodMenu();
11288
+ try {
11289
+ const result = await runCheckout({
11290
+ product: "gift_monthly",
11291
+ surface: "cli",
11292
+ recipient,
11293
+ gift_method: giftMethod,
11294
+ onStatus: (msg) => console.log(msg)
11295
+ });
11296
+ if (result.state === "completed") {
11297
+ if (giftMethod === "direct") {
11298
+ console.log(`
11299
+ Gifted to @${recipient}. They will see the upgrade on next login.`);
11300
+ } else {
11301
+ const code = result.gift_code;
11302
+ if (code) {
11303
+ console.log(`
11304
+ Gift code generated:`);
11305
+ console.log(`
11306
+ ${code}
11307
+ `);
11308
+ console.log(`Share this code with @${recipient}. It expires in 90 days.`);
11309
+ console.log(`They can redeem it with: msapling gift redeem ${code}`);
11310
+ } else {
11311
+ console.log(`
11312
+ Payment confirmed. Gift code will be emailed to you shortly.`);
11313
+ }
11314
+ }
11315
+ } else {
11316
+ console.log(`
11317
+ Checkout ${result.state}. No charges were made.`);
11318
+ }
11319
+ } catch (e) {
11320
+ console.error(`Gift checkout error: ${e.message}`);
11321
+ process.exit(1);
11322
+ }
11323
+ }
11324
+ async function runGiftCredits(argv) {
11325
+ const usernameRaw = argv[0] ?? "";
11326
+ const countStr = argv[1] ?? "";
11327
+ if (!usernameRaw || !countStr) {
11328
+ console.error("Usage: msapling gift credits <username|@username> <5|10>");
11329
+ process.exit(1);
11330
+ }
11331
+ const count = parseInt(countStr, 10);
11332
+ if (count !== 5 && count !== 10) {
11333
+ console.error("Credit amount must be 5 or 10.");
11334
+ process.exit(1);
11335
+ }
11336
+ const recipient = await _resolveRecipient(usernameRaw);
11337
+ const product = `gift_fuel_${count}`;
11338
+ const priceLabel = count === 5 ? "$7.78" : "$15.56";
11339
+ console.log(`
11340
+ Gifting ${count} credits (${priceLabel}) to @${recipient}`);
11341
+ const giftMethod = await _giftMethodMenu();
11342
+ try {
11343
+ const result = await runCheckout({
11344
+ product,
11345
+ surface: "cli",
11346
+ recipient,
11347
+ gift_method: giftMethod,
11348
+ onStatus: (msg) => console.log(msg)
11349
+ });
11350
+ if (result.state === "completed") {
11351
+ if (giftMethod === "direct") {
11352
+ console.log(`
11353
+ ${count} credits gifted to @${recipient}.`);
11354
+ } else {
11355
+ const code = result.gift_code;
11356
+ if (code) {
11357
+ console.log(`
11358
+ Gift code generated:`);
11359
+ console.log(`
11360
+ ${code}
11361
+ `);
11362
+ console.log(`Share this code with @${recipient}. It expires in 90 days.`);
11363
+ console.log(`They can redeem it with: msapling gift redeem ${code}`);
11364
+ } else {
11365
+ console.log(`
11366
+ Payment confirmed. Gift code will be emailed to you shortly.`);
11367
+ }
11368
+ }
11369
+ } else {
11370
+ console.log(`
11371
+ Checkout ${result.state}. No charges were made.`);
11372
+ }
11373
+ } catch (e) {
11374
+ console.error(`Gift checkout error: ${e.message}`);
11375
+ process.exit(1);
11376
+ }
11377
+ }
11378
+ var init_gift = __esm({
11379
+ "src/commands/billing/gift.ts"() {
11380
+ "use strict";
11381
+ init_esm_shims();
11382
+ init_api();
11383
+ init_checkout();
11384
+ init_redeem();
11385
+ }
11386
+ });
11387
+
11388
+ // src/commands/billing/index.ts
11389
+ var billing_exports = {};
11390
+ __export(billing_exports, {
11391
+ dispatchBillingCommand: () => dispatchBillingCommand,
11392
+ printBillingHelp: () => printBillingHelp
11393
+ });
11394
+ async function dispatchBillingCommand(cmd, argv) {
11395
+ switch (cmd) {
11396
+ case "sub":
11397
+ return runSub(argv);
11398
+ case "topup":
11399
+ return runTopup(argv);
11400
+ case "gift":
11401
+ return runGift(argv);
11402
+ default: {
11403
+ const _exhaustive = cmd;
11404
+ console.error(`Unknown billing command: ${_exhaustive}`);
11405
+ process.exit(1);
11406
+ }
11407
+ }
11408
+ }
11409
+ function printBillingHelp() {
11410
+ const lines = [
11411
+ "",
11412
+ "MSapling Billing Commands",
11413
+ "",
11414
+ " msapling sub Show current tier and credits balance",
11415
+ " msapling sub upgrade Interactive upgrade menu (Pro / Lifetime)",
11416
+ " msapling sub upgrade --pro Upgrade to Pro directly ($20/mo)",
11417
+ " msapling sub upgrade --lifetime Upgrade to Lifetime directly ($129)",
11418
+ " msapling sub manage Open Stripe Customer Portal in browser",
11419
+ " msapling sub cancel Cancel Pro subscription (double confirm)",
11420
+ "",
11421
+ " msapling topup Buy fuel credits (5 or 10)",
11422
+ " msapling topup auto View/edit auto-topup settings",
11423
+ "",
11424
+ " msapling gift sub <user> Gift a Pro subscription to @user",
11425
+ " msapling gift credits <user> <5|10> Gift credits to @user",
11426
+ " msapling gift redeem <code> Redeem a gift code (MSAPL-GIFT-XXXX-XXXX)",
11427
+ "",
11428
+ "Pricing:",
11429
+ " Pro: $20.00/month",
11430
+ " Lifetime: $129.00 one-time (50 founder spots)",
11431
+ " 5 credits: $7.78",
11432
+ " 10 credits: $15.56",
11433
+ " 1 credit = $1.556",
11434
+ ""
11435
+ ];
11436
+ console.log(lines.join("\n"));
11437
+ }
11438
+ var init_billing = __esm({
11439
+ "src/commands/billing/index.ts"() {
11440
+ "use strict";
11441
+ init_esm_shims();
11442
+ init_sub();
11443
+ init_topup();
11444
+ init_gift();
11445
+ }
11446
+ });
11447
+
10676
11448
  // src/runtime/doctorRedact.ts
10677
11449
  function redactSecrets(text) {
10678
11450
  let out = text;
@@ -12234,7 +13006,7 @@ var init_registry_merger = __esm({
12234
13006
  });
12235
13007
 
12236
13008
  // ../core/src/mcp/local_tools.ts
12237
- import { spawn as spawn10 } from "child_process";
13009
+ import { spawn as spawn11 } from "child_process";
12238
13010
  import { readdir as readdir4, stat as stat4, realpath as realpath2 } from "fs/promises";
12239
13011
  import { resolve as resolve16 } from "path";
12240
13012
  function asResult(text, isError = false) {
@@ -12248,7 +13020,7 @@ async function runCommand(command, cwd) {
12248
13020
  resolve18({ stdout: "", stderr: "Command timed out after 30s", exit_code: -1 });
12249
13021
  }, 3e4);
12250
13022
  try {
12251
- p = spawn10("sh", ["-c", command], {
13023
+ p = spawn11("sh", ["-c", command], {
12252
13024
  cwd: cwd || process.cwd(),
12253
13025
  stdio: ["ignore", "pipe", "pipe"],
12254
13026
  timeout: 3e4
@@ -13371,7 +14143,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
13371
14143
  var Header = () => /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
13372
14144
  /* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
13373
14145
  "\u25CF MSapling CLI v",
13374
- "2.3.6-beta.19"
14146
+ "2.3.6-beta.20"
13375
14147
  ] }),
13376
14148
  /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Platinum Tier Architecture" }) })
13377
14149
  ] });
@@ -13752,7 +14524,7 @@ function formatContextBudgetLabel(snap) {
13752
14524
  init_esm_shims();
13753
14525
  function createIdleAwarePoll(pollingIntervalRef, lastActivityRef, client, setUser) {
13754
14526
  const IDLE_THRESHOLD_MS = 5 * 60 * 1e3;
13755
- const POLL_INTERVAL_MS = 3e4;
14527
+ const POLL_INTERVAL_MS2 = 3e4;
13756
14528
  if (pollingIntervalRef.current !== null) return;
13757
14529
  pollingIntervalRef.current = setInterval(async () => {
13758
14530
  const timeSinceActivity = Date.now() - lastActivityRef.current;
@@ -13768,7 +14540,7 @@ function createIdleAwarePoll(pollingIntervalRef, lastActivityRef, client, setUse
13768
14540
  setUser(liveUser);
13769
14541
  } catch (e) {
13770
14542
  }
13771
- }, POLL_INTERVAL_MS);
14543
+ }, POLL_INTERVAL_MS2);
13772
14544
  }
13773
14545
 
13774
14546
  // src/state/commandHandler.ts
@@ -13810,7 +14582,7 @@ function buildHandleCommand(ctx) {
13810
14582
  setSwarmWorkers: ctx.setSwarmWorkers,
13811
14583
  getPlan: ctx.getPlan,
13812
14584
  setPlan: ctx.setPlan,
13813
- runAgent: async (prompt) => {
14585
+ runAgent: async (prompt4) => {
13814
14586
  ctx.setIsRunning(true);
13815
14587
  let chatId = ctx.activeChatId;
13816
14588
  if (!chatId) {
@@ -13820,7 +14592,7 @@ function buildHandleCommand(ctx) {
13820
14592
  const plan = ctx.getPlan();
13821
14593
  const finalPrompt = plan && plan.length > 0 ? `${buildPlanPrefix(plan)}
13822
14594
 
13823
- ${prompt}` : prompt;
14595
+ ${prompt4}` : prompt4;
13824
14596
  try {
13825
14597
  const usage = await ctx.agent.runWorkerTurn(chatId, finalPrompt, ctx.activeModel, (chunk) => {
13826
14598
  ctx.updateAssistantMessage(chunk);
@@ -14301,6 +15073,10 @@ function handleCliArgs(args2) {
14301
15073
  console.log(" msapling mcp serve run as MCP stdio server (Claude Code / Cursor / Windsurf integration)");
14302
15074
  console.log(" msapling doctor run diagnostic health checks");
14303
15075
  console.log(" msapling doctor --debug run doctor with full environment dump");
15076
+ console.log(" msapling sub subscription & tier management (sub upgrade|manage|cancel)");
15077
+ console.log(" msapling topup buy fuel credits (5 or 10) or configure auto-topup");
15078
+ console.log(" msapling gift gift Pro / credits to another user, or redeem a code");
15079
+ console.log(" msapling redeem <code> redeem a gift code (alias for `msapling gift redeem`)");
14304
15080
  console.log(" msapling --version print version and exit");
14305
15081
  console.log(" msapling --help print this message");
14306
15082
  console.log("Inside the REPL: type /help for slash-command help.");
@@ -14316,6 +15092,30 @@ function handleCliArgs(args2) {
14316
15092
  process.exit(exitCode);
14317
15093
  })().catch((e) => {
14318
15094
  process.stderr.write(`[msapling-exec] fatal: ${e?.message ?? e}
15095
+ `);
15096
+ process.exit(1);
15097
+ });
15098
+ return false;
15099
+ }
15100
+ if (args2[0] === "sub" || args2[0] === "topup" || args2[0] === "gift") {
15101
+ (async () => {
15102
+ const { dispatchBillingCommand: dispatchBillingCommand2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
15103
+ await dispatchBillingCommand2(args2[0], args2.slice(1));
15104
+ process.exit(0);
15105
+ })().catch((e) => {
15106
+ process.stderr.write(`[msapling-billing] fatal: ${e?.message ?? e}
15107
+ `);
15108
+ process.exit(1);
15109
+ });
15110
+ return false;
15111
+ }
15112
+ if (args2[0] === "redeem") {
15113
+ (async () => {
15114
+ const { runRedeem: runRedeem2 } = await Promise.resolve().then(() => (init_redeem(), redeem_exports));
15115
+ await runRedeem2(args2.slice(1));
15116
+ process.exit(0);
15117
+ })().catch((e) => {
15118
+ process.stderr.write(`[msapling-billing] fatal: ${e?.message ?? e}
14319
15119
  `);
14320
15120
  process.exit(1);
14321
15121
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mtreeai/msapling-cli",
3
- "version": "2.3.6-beta.19",
3
+ "version": "2.3.6-beta.20",
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",