motebit 1.11.3 → 1.12.0

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 +781 -224
  2. package/package.json +13 -13
package/dist/index.js CHANGED
@@ -1690,10 +1690,14 @@ function modelVendorHint(model) {
1690
1690
  return "groq";
1691
1691
  if (m4.startsWith("claude"))
1692
1692
  return "anthropic";
1693
+ if (m4.startsWith("gpt-oss"))
1694
+ return "local";
1693
1695
  if (m4.startsWith("gpt-") || /^o[0-9]/.test(m4))
1694
1696
  return "openai";
1695
1697
  if (m4.startsWith("gemini"))
1696
1698
  return "google";
1699
+ if (m4.startsWith("deepseek-r1"))
1700
+ return "local";
1697
1701
  if (m4.startsWith("deepseek"))
1698
1702
  return "deepseek";
1699
1703
  if (m4.includes(":") || /^(llama|mistral|qwen|phi|gemma|smollm)/.test(m4))
@@ -1712,7 +1716,27 @@ function providerAcceptsModel(provider, model) {
1712
1716
  return hint === "groq" || hint === "local";
1713
1717
  return hint === provider;
1714
1718
  }
1715
- var ANTHROPIC_MODELS, OPENAI_MODELS, GOOGLE_MODELS, DEEPSEEK_MODELS, GROQ_MODELS, LOCAL_SERVER_SUGGESTED_MODELS, OLLAMA_SUGGESTED_MODELS, PROXY_MODELS, DEFAULT_ANTHROPIC_MODEL, DEFAULT_OPENAI_MODEL, DEFAULT_GOOGLE_MODEL, DEFAULT_DEEPSEEK_MODEL, DEFAULT_GROQ_MODEL, DEFAULT_OLLAMA_MODEL, DEFAULT_LOCAL_SERVER_MODEL, DEFAULT_PROXY_MODEL;
1719
+ function modelCapabilityTier(model) {
1720
+ const m4 = model.trim().toLowerCase();
1721
+ if (m4 === "")
1722
+ return "capable";
1723
+ const sizeTag = /[:\-_](\d+(?:\.\d+)?)b(?:[-_.:]|$)/.exec(m4);
1724
+ if (sizeTag != null) {
1725
+ return parseFloat(sizeTag[1]) < 7 ? "minimal" : "capable";
1726
+ }
1727
+ const base = m4.split(":")[0];
1728
+ if (MINIMAL_FAMILIES.some((f7) => base.startsWith(f7))) {
1729
+ return "minimal";
1730
+ }
1731
+ if (base.endsWith("-mini") || base.endsWith("-nano") || base.includes("flash")) {
1732
+ return "capable";
1733
+ }
1734
+ if (FRONTIER_PREFIXES.some((p5) => base.startsWith(p5))) {
1735
+ return "frontier";
1736
+ }
1737
+ return "capable";
1738
+ }
1739
+ var ANTHROPIC_MODELS, OPENAI_MODELS, GOOGLE_MODELS, DEEPSEEK_MODELS, GROQ_MODELS, LOCAL_SERVER_SUGGESTED_MODELS, OLLAMA_SUGGESTED_MODELS, PROXY_MODELS, DEFAULT_ANTHROPIC_MODEL, DEFAULT_OPENAI_MODEL, DEFAULT_GOOGLE_MODEL, DEFAULT_DEEPSEEK_MODEL, DEFAULT_GROQ_MODEL, DEFAULT_OLLAMA_MODEL, DEFAULT_LOCAL_SERVER_MODEL, DEFAULT_PROXY_MODEL, MODEL_DEFAULT_REVIEW_BY, MINIMAL_FAMILIES, FRONTIER_PREFIXES;
1716
1740
  var init_models = __esm({
1717
1741
  "../../packages/sdk/dist/models.js"() {
1718
1742
  "use strict";
@@ -1739,14 +1763,20 @@ var init_models = __esm({
1739
1763
  DEEPSEEK_MODELS = ["deepseek-chat"];
1740
1764
  GROQ_MODELS = ["llama-3.3-70b-versatile", "openai/gpt-oss-120b"];
1741
1765
  LOCAL_SERVER_SUGGESTED_MODELS = [
1742
- "llama3.2",
1743
- "llama3.1",
1744
- "llama3",
1745
- "mistral",
1746
- "codellama",
1747
- "gemma2",
1748
- "phi3",
1749
- "qwen2"
1766
+ "qwen3",
1767
+ // balanced all-rounder, tool-capable — the first-run default
1768
+ "gpt-oss",
1769
+ // OpenAI open-weights — best small tool-use class (~16GB)
1770
+ "gemma3",
1771
+ // Google open family
1772
+ "llama4",
1773
+ // Meta current family
1774
+ "phi4-mini",
1775
+ // minimal-hardware tier (entry laptops, iGPU)
1776
+ "deepseek-r1",
1777
+ // reasoning-class open weights
1778
+ "mistral-small3.2"
1779
+ // Mistral current small
1750
1780
  ];
1751
1781
  OLLAMA_SUGGESTED_MODELS = LOCAL_SERVER_SUGGESTED_MODELS;
1752
1782
  PROXY_MODELS = [
@@ -1765,9 +1795,37 @@ var init_models = __esm({
1765
1795
  DEFAULT_GOOGLE_MODEL = "gemini-2.5-flash";
1766
1796
  DEFAULT_DEEPSEEK_MODEL = "deepseek-chat";
1767
1797
  DEFAULT_GROQ_MODEL = "llama-3.3-70b-versatile";
1768
- DEFAULT_OLLAMA_MODEL = "llama3.2";
1798
+ DEFAULT_OLLAMA_MODEL = "qwen3";
1769
1799
  DEFAULT_LOCAL_SERVER_MODEL = DEFAULT_OLLAMA_MODEL;
1770
1800
  DEFAULT_PROXY_MODEL = "claude-sonnet-4-6";
1801
+ MODEL_DEFAULT_REVIEW_BY = {
1802
+ anthropic: "2026-10-31",
1803
+ openai: "2026-10-31",
1804
+ google: "2026-10-31",
1805
+ deepseek: "2026-10-31",
1806
+ groq: "2026-10-31",
1807
+ "local-server": "2026-10-31",
1808
+ proxy: "2026-10-31"
1809
+ };
1810
+ MINIMAL_FAMILIES = [
1811
+ "llama3.2",
1812
+ // 1B/3B family — the witnessed weak-model floor
1813
+ "phi4-mini",
1814
+ "phi-3",
1815
+ "phi3",
1816
+ "smollm",
1817
+ "tinyllama",
1818
+ "gpt-5.4-nano"
1819
+ ];
1820
+ FRONTIER_PREFIXES = [
1821
+ "claude-fable",
1822
+ "claude-mythos",
1823
+ "claude-opus",
1824
+ "claude-sonnet",
1825
+ "gpt-5.4",
1826
+ // bare flagship; -mini/-nano handled before this check
1827
+ "gemini-2.5-pro"
1828
+ ];
1771
1829
  }
1772
1830
  });
1773
1831
 
@@ -4403,6 +4461,7 @@ __export(dist_exports2, {
4403
4461
  MEMORY_SOURCE_MARKER_UNKNOWN: () => MEMORY_SOURCE_MARKER_UNKNOWN,
4404
4462
  MERKLE_TREE_VERSION_REGISTRY: () => MERKLE_TREE_VERSION_REGISTRY,
4405
4463
  MICRO: () => MICRO,
4464
+ MODEL_DEFAULT_REVIEW_BY: () => MODEL_DEFAULT_REVIEW_BY,
4406
4465
  MaxProductLogSemiring: () => MaxProductLogSemiring,
4407
4466
  MemoryType: () => MemoryType,
4408
4467
  MotebitType: () => MotebitType,
@@ -4515,6 +4574,7 @@ __export(dist_exports2, {
4515
4574
  maxSensitivity: () => maxSensitivity,
4516
4575
  migrateAppearanceConfig: () => migrateAppearanceConfig,
4517
4576
  migrateVoiceConfig: () => migrateVoiceConfig,
4577
+ modelCapabilityTier: () => modelCapabilityTier,
4518
4578
  modelVendorHint: () => modelVendorHint,
4519
4579
  normalizeLocalServerEndpoint: () => normalizeLocalServerEndpoint,
4520
4580
  oklchToRgb: () => oklchToRgb,
@@ -22572,7 +22632,15 @@ var init_sanitizer = __esm({
22572
22632
  /\b(?:pretend|act\s+as\s+if|roleplay)\b/i,
22573
22633
  /\bdo\s+not\s+(?:follow|obey|listen)\b/i,
22574
22634
  /\b(?:override|bypass|ignore)\s+(?:safety|policy|rules|constraints)\b/i,
22575
- /<\s*(?:system|prompt|instruction)/i,
22635
+ // Exact tag shape only (`<system>`, `< prompt >`, `<instructions/>`).
22636
+ // The old open-prefix form (`<\s*(?:system|prompt|instruction)`) fired on
22637
+ // TypeScript generics (`Array<PromptTemplate>`), JSX components, and any
22638
+ // docs page whose prose puts these words after a `<` — witnessed live
22639
+ // 2026-07-31 flagging motebit's own CLI docs (#499). An attack needs the
22640
+ // tag to CLOSE to read as chat-template framing; attribute-carrying
22641
+ // variants fall through to the directive-density and boundary layers
22642
+ // (the [EXTERNAL_DATA] wrap is the defense — detection is signal).
22643
+ /<\s*(?:system|prompt|instruction)s?\s*\/?>/i,
22576
22644
  // --- Chat template injection ---
22577
22645
  /<\|im_start\|>\s*system/i,
22578
22646
  /<\|im_end\|>/i,
@@ -25587,7 +25655,7 @@ var init_config2 = __esm({
25587
25655
  "src/config.ts"() {
25588
25656
  "use strict";
25589
25657
  init_esm_shims();
25590
- VERSION = true ? "1.11.3" : "0.0.0-dev";
25658
+ VERSION = true ? "1.12.0" : "0.0.0-dev";
25591
25659
  CONFIG_DIR = process.env["MOTEBIT_CONFIG_DIR"] ?? path2.join(os.homedir(), ".motebit");
25592
25660
  CONFIG_PATH = path2.join(CONFIG_DIR, "config.json");
25593
25661
  RELAY_DIR = path2.join(CONFIG_DIR, "relay");
@@ -59694,6 +59762,8 @@ var init_motebit_runtime = __esm({
59694
59762
  /** Allowed proactive capability names. Empty by default — fail-closed
59695
59763
  * sovereign default. User opts in explicitly via runtime config. */
59696
59764
  _proactiveCapabilities;
59765
+ /** #501 — config override: offer R4_MONEY tools to minimal-tier models. */
59766
+ _offerMoneyToolsToMinimalModels;
59697
59767
  /** Auto-anchor policy; null when disabled. Stored by reference so the
59698
59768
  * submitter can be rotated by the surface without re-constructing the
59699
59769
  * runtime. */
@@ -59875,8 +59945,11 @@ var init_motebit_runtime = __esm({
59875
59945
  });
59876
59946
  this._proactiveCapabilities = new Set(config.proactiveCapabilities ?? []);
59877
59947
  this._proactiveAnchor = config.proactiveAnchor ?? null;
59948
+ this._offerMoneyToolsToMinimalModels = config.offerMoneyToolsToMinimalModels ?? false;
59878
59949
  this.scopedToolRegistry = new ScopedToolRegistry(this.toolRegistry, {
59879
59950
  allows: (toolName) => {
59951
+ if (!this.tierAllowsTool(toolName))
59952
+ return false;
59880
59953
  const presence = this.presence.get();
59881
59954
  if (presence.mode === "responsive" || presence.mode === "idle")
59882
59955
  return true;
@@ -60285,6 +60358,39 @@ var init_motebit_runtime = __esm({
60285
60358
  get currentModel() {
60286
60359
  return this.provider?.model ?? null;
60287
60360
  }
60361
+ /**
60362
+ * Capability-tiered tool admission (#501): may the CURRENT model be
60363
+ * offered `toolName`? True unless the model is `minimal`-tier AND the
60364
+ * tool classifies at `R4_MONEY` AND the config override is off. Keys on
60365
+ * the SAME `classifyTool` vocabulary the approval gate uses, so any
60366
+ * future money tool inherits the policy at birth — and a rail-less
60367
+ * `delegate_to_agent` (R2 without a payment builder) stays offered:
60368
+ * the tool crosses the withholding line exactly when it can move money.
60369
+ */
60370
+ tierAllowsTool(toolName) {
60371
+ if (this._offerMoneyToolsToMinimalModels)
60372
+ return true;
60373
+ const model = this.provider?.model ?? null;
60374
+ if (model == null || modelCapabilityTier(model) !== "minimal")
60375
+ return true;
60376
+ const def = this.toolRegistry.list().find((t3) => t3.name === toolName);
60377
+ if (def == null)
60378
+ return true;
60379
+ return classifyTool(def).risk < RiskLevel.R4_MONEY;
60380
+ }
60381
+ /**
60382
+ * Surface-honesty readout (#501): true when the current model's tier is
60383
+ * withholding at least one registered money tool. Surfaces render ONE
60384
+ * calm line from this (launch / model switch) — never a toast.
60385
+ */
60386
+ get moneyToolsWithheld() {
60387
+ if (this._offerMoneyToolsToMinimalModels)
60388
+ return false;
60389
+ const model = this.provider?.model ?? null;
60390
+ if (model == null || modelCapabilityTier(model) !== "minimal")
60391
+ return false;
60392
+ return this.toolRegistry.list().some((t3) => classifyTool(t3).risk >= RiskLevel.R4_MONEY);
60393
+ }
60288
60394
  setModel(model) {
60289
60395
  if (!this.provider)
60290
60396
  throw new Error("No AI provider configured");
@@ -86332,7 +86438,6 @@ function createTerminalRenderer(io) {
86332
86438
  if (result === "submit") {
86333
86439
  submit();
86334
86440
  } else if (result === "exit") {
86335
- io.write("\n");
86336
86441
  destroyTerminal();
86337
86442
  process.exit(0);
86338
86443
  } else {
@@ -86368,6 +86473,22 @@ function createTerminalRenderer(io) {
86368
86473
  reject();
86369
86474
  }
86370
86475
  }
86476
+ function finalize2() {
86477
+ let scrollback = "";
86478
+ if (tail2 !== "") {
86479
+ scrollback += tail2 + "\n";
86480
+ tail2 = "";
86481
+ }
86482
+ if (inputActive) {
86483
+ scrollback += buildInputRow().row + "\n";
86484
+ inputResolver = null;
86485
+ inputRejecter = null;
86486
+ inputActive = false;
86487
+ }
86488
+ statusRow = null;
86489
+ modeRow = null;
86490
+ commit(scrollback);
86491
+ }
86371
86492
  return {
86372
86493
  writeOutput: writeOutput2,
86373
86494
  writeLine: writeLine2,
@@ -86377,7 +86498,8 @@ function createTerminalRenderer(io) {
86377
86498
  setModeRow: setModeRow2,
86378
86499
  handleEvent,
86379
86500
  repaint: () => commit(""),
86380
- detach
86501
+ detach,
86502
+ finalize: finalize2
86381
86503
  };
86382
86504
  }
86383
86505
  function applyEvent(state, event) {
@@ -86593,6 +86715,7 @@ function initTerminal() {
86593
86715
  function destroyTerminal() {
86594
86716
  if (!initialized) return;
86595
86717
  initialized = false;
86718
+ renderer.finalize();
86596
86719
  process.stdin.removeListener("data", onStdinData);
86597
86720
  process.stdout.removeListener("resize", onResize);
86598
86721
  if (process.stdin.isTTY) {
@@ -87160,6 +87283,10 @@ async function createRuntime(config, motebitId, toolRegistry, mcpServers, person
87160
87283
  // (enableInteractiveDelegation). Absent ⇒ delegation degrades to
87161
87284
  // relay-mode honestly.
87162
87285
  ...solanaWallet ? { solanaWallet } : {},
87286
+ // #501 — sovereign override for capability-tiered tool admission.
87287
+ // Default (absent/false): a minimal-tier model is never offered
87288
+ // R4_MONEY tools; the owner can restore full exposure in config.
87289
+ ...loadFullConfig().offer_money_tools_to_minimal_models === true ? { offerMoneyToolsToMinimalModels: true } : {},
87163
87290
  policy: {
87164
87291
  operatorMode: config.operator,
87165
87292
  pathAllowList: config.allowedPaths,
@@ -101753,7 +101880,7 @@ function admitModelForProvider(provider, model) {
101753
101880
  const flag = VENDOR_PROVIDER_FLAG[hint];
101754
101881
  return {
101755
101882
  admissible: false,
101756
- teach: `${model} is a hosted ${hint} model \u2014 a local server can't serve it. ` + (flag != null ? `Restart with --provider ${flag}, or pick a local model (e.g. /model llama3.2).` : `Pick a local model instead (e.g. /model llama3.2).`)
101883
+ teach: `${model} is a hosted ${hint} model \u2014 a local server can't serve it. ` + (flag != null ? `Restart with --provider ${flag}, or pick a local model (e.g. /model ${DEFAULT_LOCAL_SERVER_MODEL}).` : `Pick a local model instead (e.g. /model ${DEFAULT_LOCAL_SERVER_MODEL}).`)
101757
101884
  };
101758
101885
  }
101759
101886
  if (!providerAcceptsModel(provider, model)) {
@@ -101765,6 +101892,7 @@ function admitModelForProvider(provider, model) {
101765
101892
  }
101766
101893
  return { admissible: true };
101767
101894
  }
101895
+ var MONEY_TOOLS_WITHHELD_NOTICE = "money tools withheld from this model (minimal tier) \u2014 set offer_money_tools_to_minimal_models in ~/.motebit/config.json if you mean it";
101768
101896
 
101769
101897
  // src/index.ts
101770
101898
  init_dist8();
@@ -102254,6 +102382,7 @@ function renderPreflight(pf, dim2) {
102254
102382
 
102255
102383
  // src/args.ts
102256
102384
  init_esm_shims();
102385
+ init_dist2();
102257
102386
  init_config2();
102258
102387
  init_colors();
102259
102388
  import { parseArgs } from "util";
@@ -102480,7 +102609,10 @@ var COMMANDS = [
102480
102609
  { usage: "/proposal <id> [accept|reject|counter]", desc: "Respond to a proposal" },
102481
102610
  { usage: "/operator", desc: "Show operator mode status" },
102482
102611
  { usage: "/invoke <cap> <prompt>", desc: "Invoke a capability deterministically (no AI loop)" },
102483
- { usage: "/receipt <task-id>", desc: "Re-render an archived receipt (offline-verified)" },
102612
+ {
102613
+ usage: "/receipt [task-id-prefix]",
102614
+ desc: "Re-render an archived receipt (offline-verified); no arg = latest"
102615
+ },
102484
102616
  { usage: "/voice [on|off]", desc: "Toggle TTS voice output (opt-in, off by default)" },
102485
102617
  { usage: "/say <text>", desc: "Speak text via TTS (requires voice provider)" },
102486
102618
  { usage: "/skills", desc: "List installed skills with provenance badges" },
@@ -102662,7 +102794,7 @@ function printVersion() {
102662
102794
  console.log(VERSION);
102663
102795
  }
102664
102796
  function defaultModelForProvider(provider) {
102665
- return provider === "local-server" ? "llama3.2" : provider === "openai" ? "gpt-5.4-mini" : provider === "google" ? "gemini-2.5-flash" : provider === "groq" ? "llama-3.3-70b-versatile" : provider === "deepseek" ? "deepseek-chat" : "claude-sonnet-4-6";
102797
+ return provider === "local-server" ? DEFAULT_LOCAL_SERVER_MODEL : provider === "openai" ? DEFAULT_OPENAI_MODEL : provider === "google" ? DEFAULT_GOOGLE_MODEL : provider === "groq" ? DEFAULT_GROQ_MODEL : provider === "deepseek" ? DEFAULT_DEEPSEEK_MODEL : DEFAULT_ANTHROPIC_MODEL;
102666
102798
  }
102667
102799
  function printBanner(opts) {
102668
102800
  const W2 = 56;
@@ -102803,8 +102935,20 @@ function archiveReceipt(receipt) {
102803
102935
  if (!receipt.task_id) return;
102804
102936
  ARCHIVE.set(receipt.task_id, receipt);
102805
102937
  }
102806
- function getArchivedReceipt(taskId) {
102807
- return ARCHIVE.get(taskId);
102938
+ function findArchivedReceipt(idOrPrefix) {
102939
+ const prefix = idOrPrefix.replace(/…$/, "");
102940
+ if (prefix === "") return { kind: "miss" };
102941
+ const exact = ARCHIVE.get(prefix);
102942
+ if (exact) return { kind: "hit", receipt: exact };
102943
+ const matches = [...ARCHIVE.keys()].filter((id) => id.startsWith(prefix));
102944
+ if (matches.length === 1) return { kind: "hit", receipt: ARCHIVE.get(matches[0]) };
102945
+ if (matches.length > 1) return { kind: "ambiguous", taskIds: matches };
102946
+ return { kind: "miss" };
102947
+ }
102948
+ function latestArchivedReceipt() {
102949
+ let last;
102950
+ for (const r2 of ARCHIVE.values()) last = r2;
102951
+ return last;
102808
102952
  }
102809
102953
  var CAPABILITY_PRICES_USD = {
102810
102954
  review_pr: 0.01,
@@ -104564,202 +104708,6 @@ async function electAttachOrCoordinate(fullConfig, motebitId, runtimeRef) {
104564
104708
  init_esm_shims();
104565
104709
  init_colors();
104566
104710
  init_terminal();
104567
- init_statusline();
104568
- init_status_render();
104569
- async function renderStream(stream) {
104570
- let pendingApproval = null;
104571
- let status = null;
104572
- let thinking = null;
104573
- const stopThinking = () => {
104574
- thinking?.stop();
104575
- thinking = null;
104576
- };
104577
- const stopStatus = () => {
104578
- stopThinking();
104579
- const elapsed = status?.stop() ?? 0;
104580
- status = null;
104581
- return elapsed;
104582
- };
104583
- thinking = startStatus("thinking");
104584
- try {
104585
- for await (const raw of stream) {
104586
- const chunk = raw;
104587
- switch (chunk.type) {
104588
- case "text":
104589
- stopThinking();
104590
- if (typeof chunk.text === "string") writeOutput(chunk.text);
104591
- break;
104592
- case "tool_status": {
104593
- const name = chunk.name ?? "tool";
104594
- if (chunk.status === "calling") {
104595
- if (name === "delegate_to_agent" && status) break;
104596
- stopThinking();
104597
- status = name === "delegate_to_agent" ? startStatus("delegating") : startStatus("running", name);
104598
- } else if (status) {
104599
- writeLine(
104600
- ` ${action("\u25CF")} ${action(name)} ${meta(`\xB7 done \xB7 ${formatElapsed(0, stopStatus())}`)}`
104601
- );
104602
- thinking = startStatus("thinking");
104603
- }
104604
- break;
104605
- }
104606
- case "approval_request":
104607
- pendingApproval = {
104608
- name: chunk.name ?? "tool",
104609
- args: chunk.args ?? {},
104610
- ...chunk.risk_level != null ? { riskLevel: chunk.risk_level } : {}
104611
- };
104612
- break;
104613
- case "delegation_start":
104614
- if (status) break;
104615
- stopThinking();
104616
- status = startStatus("delegating", chunk.tool ?? "task");
104617
- break;
104618
- case "delegation_complete":
104619
- stopStatus();
104620
- if (chunk.receipt?.task_id != null) {
104621
- writeLine(
104622
- dim(`[receipt ${chunk.receipt.task_id.slice(0, 8)} \xB7 ${chunk.receipt.status ?? ""}]`)
104623
- );
104624
- }
104625
- thinking = startStatus("thinking");
104626
- break;
104627
- case "injection_warning":
104628
- writeLine(`${warn2("\u26A0")} suspicious content in ${chunk.tool_name ?? "tool"} output`);
104629
- break;
104630
- case "approval_expired":
104631
- stopStatus();
104632
- writeLine(
104633
- `${warn2("[this approval expired before your answer arrived \u2014 nothing was executed]")}
104634
- ${dim(`(${chunk.tool_name ?? "the tool"} was never run; no money moved. Ask again when ready.)`)}`
104635
- );
104636
- break;
104637
- case "approval_voided":
104638
- stopStatus();
104639
- writeLine(
104640
- `${warn2("[your new message set aside the pending approval \u2014 nothing was executed]")}
104641
- ${dim(`(${chunk.tool_name ?? "the tool"} was never run; no money moved. It can be proposed again.)`)}`
104642
- );
104643
- break;
104644
- case "invoke_error":
104645
- stopStatus();
104646
- writeLine(
104647
- `${warn2(`[invoke failed${chunk.code != null ? ` \xB7 ${chunk.code}` : ""}]`)} ${chunk.message ?? ""}`
104648
- );
104649
- break;
104650
- case "task_step_narration":
104651
- if (typeof chunk.text === "string") {
104652
- status?.step(chunk.text.trim());
104653
- writeLine(` ${meta("\xB7 " + chunk.text.trim())}`);
104654
- }
104655
- break;
104656
- default:
104657
- break;
104658
- }
104659
- }
104660
- } catch (err2) {
104661
- writeLine(`${warn2("[coordinator error]")} ${err2 instanceof Error ? err2.message : String(err2)}`);
104662
- } finally {
104663
- stopStatus();
104664
- }
104665
- return { pendingApproval };
104666
- }
104667
- async function renderTurn(client, motebitId, stream) {
104668
- let current2 = stream;
104669
- for (; ; ) {
104670
- const { pendingApproval } = await renderStream(current2);
104671
- if (pendingApproval === null) return;
104672
- for (const line of renderApprovalRequest({
104673
- name: pendingApproval.name,
104674
- args: pendingApproval.args,
104675
- ...pendingApproval.riskLevel != null ? { riskLevel: pendingApproval.riskLevel } : {}
104676
- })) {
104677
- writeLine(line);
104678
- }
104679
- const answer = await askQuestion(` ${warn2("Allow?")} ${dim("(y/n)")} `);
104680
- const approved = answer.trim().toLowerCase() === "y";
104681
- current2 = client.resolveApproval(approved, motebitId);
104682
- }
104683
- }
104684
- var ATTACHED_HELP = `
104685
- Attached mode \u2014 the coordinator process owns the runtime; this terminal renders.
104686
- <text> chat with your motebit (proxied to the coordinator)
104687
- /invoke <cap> <text> invoke a capability deterministically
104688
- /help this help
104689
- /exit leave (the coordinator keeps running)
104690
- Other slash commands need the runtime in-process: exit, stop the coordinator, and re-run \`motebit\`.
104691
- `;
104692
- async function runAttachedRepl(client, motebitId) {
104693
- writeOutput(
104694
- `
104695
- ${dim("Attached to the machine's coordinator runtime")} ${dim(`(pid ${client.coordinatorPid})`)}
104696
- ${dim("This terminal renders; the coordinator acts. /help for what's available.")}
104697
-
104698
- `
104699
- );
104700
- setModeRow(renderModeRow({ attachedPid: client.coordinatorPid }));
104701
- let closed = false;
104702
- client.onClose(() => {
104703
- closed = true;
104704
- writeOutput(
104705
- `
104706
- ${warn2("Coordinator exited.")} Run \`motebit\` again to take over as coordinator.
104707
- `
104708
- );
104709
- destroyTerminal();
104710
- process.exit(0);
104711
- });
104712
- for (; ; ) {
104713
- if (closed) return;
104714
- let line;
104715
- try {
104716
- line = await readInput(prompt("you>") + " ");
104717
- } catch {
104718
- break;
104719
- }
104720
- const trimmed = line.trim();
104721
- if (trimmed === "") continue;
104722
- if (trimmed === "/exit" || trimmed === "/quit" || trimmed === "exit" || trimmed === "quit") {
104723
- writeOutput("Goodbye! (coordinator keeps running)\n");
104724
- break;
104725
- }
104726
- if (trimmed === "/help") {
104727
- writeOutput(ATTACHED_HELP);
104728
- continue;
104729
- }
104730
- if (trimmed.startsWith("/invoke ")) {
104731
- const rest = trimmed.slice("/invoke ".length).trim();
104732
- const space = rest.indexOf(" ");
104733
- const capability = space === -1 ? rest : rest.slice(0, space);
104734
- const prompt2 = space === -1 ? "" : rest.slice(space + 1);
104735
- if (capability === "") {
104736
- writeOutput(`${warn2("usage:")} /invoke <capability> <prompt>
104737
- `);
104738
- continue;
104739
- }
104740
- writeOutput(prompt("mote>") + " ");
104741
- await renderTurn(client, motebitId, client.invoke(capability, prompt2));
104742
- writeOutput("\n");
104743
- continue;
104744
- }
104745
- if (trimmed.startsWith("/")) {
104746
- writeOutput(
104747
- `${dim(`${trimmed.split(" ")[0]} needs the runtime in-process \u2014 not available in attached mode.`)}
104748
- ${dim("Stop the coordinator and re-run `motebit` to use it.")}
104749
- `
104750
- );
104751
- continue;
104752
- }
104753
- writeOutput(prompt("mote>") + " ");
104754
- await renderTurn(client, motebitId, client.chat(trimmed));
104755
- writeOutput("\n");
104756
- }
104757
- client.close();
104758
- destroyTerminal();
104759
- }
104760
-
104761
- // src/index.ts
104762
- init_colors();
104763
104711
 
104764
104712
  // src/slash-commands.ts
104765
104713
  init_esm_shims();
@@ -106421,14 +106369,25 @@ async function handleInvokeCommand(args, deps) {
106421
106369
  async function handleReceiptCommand(args, deps) {
106422
106370
  const out = deps.out ?? ((s3) => console.log(s3));
106423
106371
  const taskId = args.trim();
106372
+ let receipt;
106424
106373
  if (!taskId) {
106425
- out(error2("Usage: /receipt <task-id>"));
106426
- return;
106427
- }
106428
- const receipt = getArchivedReceipt(taskId);
106429
- if (!receipt) {
106430
- out(warn2(`No archived receipt for task_id=${taskId}`));
106431
- return;
106374
+ receipt = latestArchivedReceipt();
106375
+ if (!receipt) {
106376
+ out(warn2("No receipts archived this session. Usage: /receipt [task-id-prefix]"));
106377
+ return;
106378
+ }
106379
+ } else {
106380
+ const found = findArchivedReceipt(taskId);
106381
+ if (found.kind === "ambiguous") {
106382
+ out(warn2(`Prefix "${taskId}" matches ${found.taskIds.length} receipts:`));
106383
+ for (const id of found.taskIds) out(dim(` ${id}`));
106384
+ return;
106385
+ }
106386
+ if (found.kind === "miss") {
106387
+ out(warn2(`No archived receipt matches "${taskId}" this session.`));
106388
+ return;
106389
+ }
106390
+ receipt = found.receipt;
106432
106391
  }
106433
106392
  out("");
106434
106393
  await renderReceipt(receipt, out);
@@ -106469,6 +106428,369 @@ async function drainInvokeStream(stream, out, voice) {
106469
106428
  }
106470
106429
  }
106471
106430
 
106431
+ // etc/cli-surface.json
106432
+ var cli_surface_default = {
106433
+ subcommands: {
106434
+ approvals: [
106435
+ "approve",
106436
+ "deny",
106437
+ "list",
106438
+ "show"
106439
+ ],
106440
+ attest: [],
106441
+ balance: [],
106442
+ credentials: [],
106443
+ delegate: [],
106444
+ discover: [],
106445
+ doctor: [],
106446
+ export: [],
106447
+ federation: [
106448
+ "mesh",
106449
+ "peer",
106450
+ "peer-remove",
106451
+ "peers",
106452
+ "status"
106453
+ ],
106454
+ fund: [],
106455
+ goal: [
106456
+ "add",
106457
+ "list",
106458
+ "outcomes",
106459
+ "pause",
106460
+ "remove",
106461
+ "resume"
106462
+ ],
106463
+ grant: [],
106464
+ id: [],
106465
+ init: [],
106466
+ keychain: [],
106467
+ ledger: [],
106468
+ logs: [],
106469
+ lsp: [],
106470
+ migrate: [],
106471
+ "migrate-keyring": [],
106472
+ ps: [],
106473
+ register: [],
106474
+ relay: [
106475
+ "up"
106476
+ ],
106477
+ restore: [],
106478
+ rotate: [],
106479
+ run: [],
106480
+ schema: [],
106481
+ seed: [],
106482
+ serve: [],
106483
+ skills: [],
106484
+ smoke: [],
106485
+ up: [],
106486
+ verify: [
106487
+ "identity"
106488
+ ],
106489
+ "verify-release": [],
106490
+ wallet: [],
106491
+ withdraw: []
106492
+ },
106493
+ flags: [
106494
+ {
106495
+ name: "address-only",
106496
+ type: "boolean",
106497
+ default: false
106498
+ },
106499
+ {
106500
+ name: "all",
106501
+ type: "boolean",
106502
+ default: false
106503
+ },
106504
+ {
106505
+ name: "allow-commands",
106506
+ type: "string"
106507
+ },
106508
+ {
106509
+ name: "allowed-paths",
106510
+ type: "string"
106511
+ },
106512
+ {
106513
+ name: "auto-approve",
106514
+ type: "boolean",
106515
+ default: false
106516
+ },
106517
+ {
106518
+ name: "block-commands",
106519
+ type: "string"
106520
+ },
106521
+ {
106522
+ name: "budget",
106523
+ type: "string"
106524
+ },
106525
+ {
106526
+ name: "cadence-hours",
106527
+ type: "string"
106528
+ },
106529
+ {
106530
+ name: "capability",
106531
+ type: "string"
106532
+ },
106533
+ {
106534
+ name: "days",
106535
+ type: "string"
106536
+ },
106537
+ {
106538
+ name: "db-path",
106539
+ type: "string"
106540
+ },
106541
+ {
106542
+ name: "destination",
106543
+ type: "string"
106544
+ },
106545
+ {
106546
+ name: "direct",
106547
+ type: "boolean",
106548
+ default: false
106549
+ },
106550
+ {
106551
+ name: "dry-run",
106552
+ type: "boolean",
106553
+ default: false
106554
+ },
106555
+ {
106556
+ name: "event-type",
106557
+ type: "string"
106558
+ },
106559
+ {
106560
+ name: "every",
106561
+ type: "string"
106562
+ },
106563
+ {
106564
+ name: "facilitator-url",
106565
+ type: "string"
106566
+ },
106567
+ {
106568
+ name: "federation-url",
106569
+ type: "string"
106570
+ },
106571
+ {
106572
+ name: "file",
106573
+ type: "string",
106574
+ short: "f"
106575
+ },
106576
+ {
106577
+ name: "force",
106578
+ type: "boolean",
106579
+ default: false
106580
+ },
106581
+ {
106582
+ name: "grant",
106583
+ type: "string"
106584
+ },
106585
+ {
106586
+ name: "help",
106587
+ type: "boolean",
106588
+ default: false,
106589
+ short: "h"
106590
+ },
106591
+ {
106592
+ name: "identity",
106593
+ type: "string"
106594
+ },
106595
+ {
106596
+ name: "json",
106597
+ type: "boolean",
106598
+ default: false
106599
+ },
106600
+ {
106601
+ name: "lifetime-usd",
106602
+ type: "string"
106603
+ },
106604
+ {
106605
+ name: "limit",
106606
+ type: "string"
106607
+ },
106608
+ {
106609
+ name: "max-tokens",
106610
+ type: "string"
106611
+ },
106612
+ {
106613
+ name: "model",
106614
+ type: "string"
106615
+ },
106616
+ {
106617
+ name: "network",
106618
+ type: "string"
106619
+ },
106620
+ {
106621
+ name: "no-stream",
106622
+ type: "boolean",
106623
+ default: false
106624
+ },
106625
+ {
106626
+ name: "once",
106627
+ type: "boolean",
106628
+ default: false
106629
+ },
106630
+ {
106631
+ name: "operator",
106632
+ type: "boolean",
106633
+ default: false
106634
+ },
106635
+ {
106636
+ name: "output",
106637
+ type: "string",
106638
+ short: "o"
106639
+ },
106640
+ {
106641
+ name: "passphrase",
106642
+ type: "boolean",
106643
+ default: false
106644
+ },
106645
+ {
106646
+ name: "pay-new-agents",
106647
+ type: "boolean",
106648
+ default: false
106649
+ },
106650
+ {
106651
+ name: "pay-to-address",
106652
+ type: "string"
106653
+ },
106654
+ {
106655
+ name: "plan",
106656
+ type: "boolean",
106657
+ default: false
106658
+ },
106659
+ {
106660
+ name: "port",
106661
+ type: "string"
106662
+ },
106663
+ {
106664
+ name: "presentation",
106665
+ type: "boolean",
106666
+ default: false
106667
+ },
106668
+ {
106669
+ name: "price",
106670
+ type: "string"
106671
+ },
106672
+ {
106673
+ name: "project",
106674
+ type: "string"
106675
+ },
106676
+ {
106677
+ name: "provider",
106678
+ type: "string",
106679
+ default: "anthropic"
106680
+ },
106681
+ {
106682
+ name: "prune",
106683
+ type: "boolean",
106684
+ default: false
106685
+ },
106686
+ {
106687
+ name: "reason",
106688
+ type: "string"
106689
+ },
106690
+ {
106691
+ name: "routing-strategy",
106692
+ type: "string"
106693
+ },
106694
+ {
106695
+ name: "scope",
106696
+ type: "string"
106697
+ },
106698
+ {
106699
+ name: "self-test",
106700
+ type: "boolean",
106701
+ default: false
106702
+ },
106703
+ {
106704
+ name: "serve-port",
106705
+ type: "string"
106706
+ },
106707
+ {
106708
+ name: "serve-transport",
106709
+ type: "string"
106710
+ },
106711
+ {
106712
+ name: "solana-rpc-url",
106713
+ type: "string"
106714
+ },
106715
+ {
106716
+ name: "sovereign",
106717
+ type: "boolean",
106718
+ default: false
106719
+ },
106720
+ {
106721
+ name: "subject",
106722
+ type: "string"
106723
+ },
106724
+ {
106725
+ name: "sync-token",
106726
+ type: "string"
106727
+ },
106728
+ {
106729
+ name: "sync-url",
106730
+ type: "string"
106731
+ },
106732
+ {
106733
+ name: "tail",
106734
+ type: "boolean",
106735
+ default: false
106736
+ },
106737
+ {
106738
+ name: "target",
106739
+ type: "string"
106740
+ },
106741
+ {
106742
+ name: "tools",
106743
+ type: "string"
106744
+ },
106745
+ {
106746
+ name: "version",
106747
+ type: "boolean",
106748
+ default: false,
106749
+ short: "v"
106750
+ },
106751
+ {
106752
+ name: "voice",
106753
+ type: "boolean",
106754
+ default: false
106755
+ },
106756
+ {
106757
+ name: "waive",
106758
+ type: "boolean",
106759
+ default: false
106760
+ },
106761
+ {
106762
+ name: "wall-clock",
106763
+ type: "string"
106764
+ },
106765
+ {
106766
+ name: "window-hours",
106767
+ type: "string"
106768
+ },
106769
+ {
106770
+ name: "window-usd",
106771
+ type: "string"
106772
+ }
106773
+ ],
106774
+ exitCodes: [
106775
+ 0,
106776
+ 1,
106777
+ 2,
106778
+ 130
106779
+ ],
106780
+ onDiskLayout: [
106781
+ "config.json",
106782
+ "dev-keyring.json",
106783
+ "identity.md",
106784
+ "motebit.db",
106785
+ "motebit.md",
106786
+ "relay",
106787
+ "relay/relay.db",
106788
+ "smoke-x402-buyer-eoa.txt",
106789
+ "smoke-x402-worker-eoa.txt",
106790
+ "update-check.json"
106791
+ ]
106792
+ };
106793
+
106472
106794
  // src/slash-commands.ts
106473
106795
  function isSlashCommand(input) {
106474
106796
  return input.startsWith("/");
@@ -106491,6 +106813,17 @@ function resolveBareCommand(input) {
106491
106813
  if (name === "ledger" && words.length === 2) return `/ledger ${words[1]}`;
106492
106814
  return null;
106493
106815
  }
106816
+ function detectShellInvocation(input) {
106817
+ if (input.includes("?")) return null;
106818
+ const words = input.trim().split(/\s+/);
106819
+ if (words.length < 2 || words[0] !== "motebit") return null;
106820
+ const second = words[1];
106821
+ const known = second.startsWith("--") ? CLI_FLAG_NAMES.has(second.slice(2).split("=")[0].toLowerCase()) : CLI_SUBCOMMAND_NAMES.has(second.toLowerCase());
106822
+ if (!known) return null;
106823
+ return " that's a shell command \u2014 type `quit`, then run it in your terminal";
106824
+ }
106825
+ var CLI_SUBCOMMAND_NAMES = new Set(Object.keys(cli_surface_default.subcommands));
106826
+ var CLI_FLAG_NAMES = new Set(cli_surface_default.flags.map((f7) => f7.name.toLowerCase()));
106494
106827
  function renderProvenanceBadge(record) {
106495
106828
  const status = record.provenance_status;
106496
106829
  if (status === "verified") return success("[verified]");
@@ -106826,7 +107159,10 @@ ${summary}`);
106826
107159
  "gpt-5.4-mini": "gpt-5.4-mini",
106827
107160
  "gpt-5.4-nano": "gpt-5.4-nano",
106828
107161
  o3: "o3",
107162
+ qwen3: "qwen3",
107163
+ "gpt-oss": "gpt-oss",
106829
107164
  "llama3.2": "llama3.2",
107165
+ // legacy alias — still resolvable, no longer suggested
106830
107166
  mistral: "mistral"
106831
107167
  };
106832
107168
  const envKey = config.provider === "openai" ? process.env["OPENAI_API_KEY"] : process.env["ANTHROPIC_API_KEY"];
@@ -106917,6 +107253,10 @@ Unknown model: ${cyan(args)}
106917
107253
  break;
106918
107254
  }
106919
107255
  runtime.setModel(modelId);
107256
+ if (runtime.moneyToolsWithheld) {
107257
+ console.log(`
107258
+ ${dim(MONEY_TOOLS_WITHHELD_NOTICE)}`);
107259
+ }
106920
107260
  if (fullConfig) {
106921
107261
  fullConfig.default_model = modelId;
106922
107262
  const persistable = ["anthropic", "openai", "google", "local-server", "proxy"];
@@ -108593,6 +108933,209 @@ Curiosity targets (${targets.length}):
108593
108933
  }
108594
108934
  }
108595
108935
 
108936
+ // src/attached-repl.ts
108937
+ init_statusline();
108938
+ init_status_render();
108939
+ async function renderStream(stream) {
108940
+ let pendingApproval = null;
108941
+ let status = null;
108942
+ let thinking = null;
108943
+ const stopThinking = () => {
108944
+ thinking?.stop();
108945
+ thinking = null;
108946
+ };
108947
+ const stopStatus = () => {
108948
+ stopThinking();
108949
+ const elapsed = status?.stop() ?? 0;
108950
+ status = null;
108951
+ return elapsed;
108952
+ };
108953
+ thinking = startStatus("thinking");
108954
+ try {
108955
+ for await (const raw of stream) {
108956
+ const chunk = raw;
108957
+ switch (chunk.type) {
108958
+ case "text":
108959
+ stopThinking();
108960
+ if (typeof chunk.text === "string") writeOutput(chunk.text);
108961
+ break;
108962
+ case "tool_status": {
108963
+ const name = chunk.name ?? "tool";
108964
+ if (chunk.status === "calling") {
108965
+ if (name === "delegate_to_agent" && status) break;
108966
+ stopThinking();
108967
+ status = name === "delegate_to_agent" ? startStatus("delegating") : startStatus("running", name);
108968
+ } else if (status) {
108969
+ writeLine(
108970
+ ` ${action("\u25CF")} ${action(name)} ${meta(`\xB7 done \xB7 ${formatElapsed(0, stopStatus())}`)}`
108971
+ );
108972
+ thinking = startStatus("thinking");
108973
+ }
108974
+ break;
108975
+ }
108976
+ case "approval_request":
108977
+ pendingApproval = {
108978
+ name: chunk.name ?? "tool",
108979
+ args: chunk.args ?? {},
108980
+ ...chunk.risk_level != null ? { riskLevel: chunk.risk_level } : {}
108981
+ };
108982
+ break;
108983
+ case "delegation_start":
108984
+ if (status) break;
108985
+ stopThinking();
108986
+ status = startStatus("delegating", chunk.tool ?? "task");
108987
+ break;
108988
+ case "delegation_complete":
108989
+ stopStatus();
108990
+ if (chunk.receipt?.task_id != null) {
108991
+ writeLine(
108992
+ dim(`[receipt ${chunk.receipt.task_id.slice(0, 8)} \xB7 ${chunk.receipt.status ?? ""}]`)
108993
+ );
108994
+ }
108995
+ thinking = startStatus("thinking");
108996
+ break;
108997
+ case "injection_warning":
108998
+ writeLine(`${warn2("\u26A0")} suspicious content in ${chunk.tool_name ?? "tool"} output`);
108999
+ break;
109000
+ case "approval_expired":
109001
+ stopStatus();
109002
+ writeLine(
109003
+ `${warn2("[this approval expired before your answer arrived \u2014 nothing was executed]")}
109004
+ ${dim(`(${chunk.tool_name ?? "the tool"} was never run; no money moved. Ask again when ready.)`)}`
109005
+ );
109006
+ break;
109007
+ case "approval_voided":
109008
+ stopStatus();
109009
+ writeLine(
109010
+ `${warn2("[your new message set aside the pending approval \u2014 nothing was executed]")}
109011
+ ${dim(`(${chunk.tool_name ?? "the tool"} was never run; no money moved. It can be proposed again.)`)}`
109012
+ );
109013
+ break;
109014
+ case "invoke_error":
109015
+ stopStatus();
109016
+ writeLine(
109017
+ `${warn2(`[invoke failed${chunk.code != null ? ` \xB7 ${chunk.code}` : ""}]`)} ${chunk.message ?? ""}`
109018
+ );
109019
+ break;
109020
+ case "task_step_narration":
109021
+ if (typeof chunk.text === "string") {
109022
+ status?.step(chunk.text.trim());
109023
+ writeLine(` ${meta("\xB7 " + chunk.text.trim())}`);
109024
+ }
109025
+ break;
109026
+ default:
109027
+ break;
109028
+ }
109029
+ }
109030
+ } catch (err2) {
109031
+ writeLine(`${warn2("[coordinator error]")} ${err2 instanceof Error ? err2.message : String(err2)}`);
109032
+ } finally {
109033
+ stopStatus();
109034
+ }
109035
+ return { pendingApproval };
109036
+ }
109037
+ async function renderTurn(client, motebitId, stream) {
109038
+ let current2 = stream;
109039
+ for (; ; ) {
109040
+ const { pendingApproval } = await renderStream(current2);
109041
+ if (pendingApproval === null) return;
109042
+ for (const line of renderApprovalRequest({
109043
+ name: pendingApproval.name,
109044
+ args: pendingApproval.args,
109045
+ ...pendingApproval.riskLevel != null ? { riskLevel: pendingApproval.riskLevel } : {}
109046
+ })) {
109047
+ writeLine(line);
109048
+ }
109049
+ const answer = await askQuestion(` ${warn2("Allow?")} ${dim("(y/n)")} `);
109050
+ const approved = answer.trim().toLowerCase() === "y";
109051
+ current2 = client.resolveApproval(approved, motebitId);
109052
+ }
109053
+ }
109054
+ var ATTACHED_HELP = `
109055
+ Attached mode \u2014 the coordinator process owns the runtime; this terminal renders.
109056
+ <text> chat with your motebit (proxied to the coordinator)
109057
+ /invoke <cap> <text> invoke a capability deterministically
109058
+ /help this help
109059
+ /exit leave (the coordinator keeps running)
109060
+ Other slash commands need the runtime in-process: exit, stop the coordinator, and re-run \`motebit\`.
109061
+ `;
109062
+ async function runAttachedRepl(client, motebitId) {
109063
+ writeOutput(
109064
+ `
109065
+ ${dim("Attached to the machine's coordinator runtime")} ${dim(`(pid ${client.coordinatorPid})`)}
109066
+ ${dim("This terminal renders; the coordinator acts. /help for what's available.")}
109067
+
109068
+ `
109069
+ );
109070
+ setModeRow(renderModeRow({ attachedPid: client.coordinatorPid }));
109071
+ let closed = false;
109072
+ client.onClose(() => {
109073
+ closed = true;
109074
+ writeOutput(
109075
+ `
109076
+ ${warn2("Coordinator exited.")} Run \`motebit\` again to take over as coordinator.
109077
+ `
109078
+ );
109079
+ destroyTerminal();
109080
+ process.exit(0);
109081
+ });
109082
+ for (; ; ) {
109083
+ if (closed) return;
109084
+ let line;
109085
+ try {
109086
+ line = await readInput(prompt("you>") + " ");
109087
+ } catch {
109088
+ break;
109089
+ }
109090
+ const trimmed = line.trim();
109091
+ if (trimmed === "") continue;
109092
+ if (trimmed === "/exit" || trimmed === "/quit" || trimmed === "exit" || trimmed === "quit") {
109093
+ writeOutput("Goodbye! (coordinator keeps running)\n");
109094
+ break;
109095
+ }
109096
+ if (trimmed === "/help") {
109097
+ writeOutput(ATTACHED_HELP);
109098
+ continue;
109099
+ }
109100
+ if (trimmed.startsWith("/invoke ")) {
109101
+ const rest = trimmed.slice("/invoke ".length).trim();
109102
+ const space = rest.indexOf(" ");
109103
+ const capability = space === -1 ? rest : rest.slice(0, space);
109104
+ const prompt2 = space === -1 ? "" : rest.slice(space + 1);
109105
+ if (capability === "") {
109106
+ writeOutput(`${warn2("usage:")} /invoke <capability> <prompt>
109107
+ `);
109108
+ continue;
109109
+ }
109110
+ writeOutput(prompt("mote>") + " ");
109111
+ await renderTurn(client, motebitId, client.invoke(capability, prompt2));
109112
+ writeOutput("\n");
109113
+ continue;
109114
+ }
109115
+ if (trimmed.startsWith("/")) {
109116
+ writeOutput(
109117
+ `${dim(`${trimmed.split(" ")[0]} needs the runtime in-process \u2014 not available in attached mode.`)}
109118
+ ${dim("Stop the coordinator and re-run `motebit` to use it.")}
109119
+ `
109120
+ );
109121
+ continue;
109122
+ }
109123
+ const shellTeach = detectShellInvocation(trimmed);
109124
+ if (shellTeach != null) {
109125
+ writeOutput(dim(shellTeach) + "\n\n");
109126
+ continue;
109127
+ }
109128
+ writeOutput(prompt("mote>") + " ");
109129
+ await renderTurn(client, motebitId, client.chat(trimmed));
109130
+ writeOutput("\n");
109131
+ }
109132
+ client.close();
109133
+ destroyTerminal();
109134
+ }
109135
+
109136
+ // src/index.ts
109137
+ init_colors();
109138
+
108596
109139
  // src/subcommands/index.ts
108597
109140
  init_esm_shims();
108598
109141
 
@@ -126065,13 +126608,13 @@ async function main() {
126065
126608
  runtimeRef
126066
126609
  });
126067
126610
  } catch (err2) {
126611
+ destroyTerminal();
126068
126612
  console.error(
126069
126613
  `Runtime-host election failed: ${err2 instanceof Error ? err2.message : String(err2)}`
126070
126614
  );
126071
126615
  console.error(
126072
126616
  "Another motebit process may be coordinating with an incompatible build. Stop it and retry."
126073
126617
  );
126074
- destroyTerminal();
126075
126618
  process.exit(1);
126076
126619
  }
126077
126620
  if (election.role === "frontend") {
@@ -126247,7 +126790,8 @@ async function main() {
126247
126790
  moteDb.close();
126248
126791
  };
126249
126792
  process.on("SIGINT", () => {
126250
- console.log("\nGoodbye!");
126793
+ destroyTerminal();
126794
+ console.log("Goodbye!");
126251
126795
  void shutdown().then(() => process.exit(0));
126252
126796
  });
126253
126797
  const toolCount = toolRegistry.size;
@@ -126274,6 +126818,10 @@ async function main() {
126274
126818
  }
126275
126819
  refreshUpdateCheckInBackground();
126276
126820
  }
126821
+ if (runtime.moneyToolsWithheld) {
126822
+ console.log(dim(` ${MONEY_TOOLS_WITHHELD_NOTICE}`));
126823
+ console.log();
126824
+ }
126277
126825
  if (isFirstLaunch) {
126278
126826
  try {
126279
126827
  const activationRunId = crypto.randomUUID();
@@ -126339,6 +126887,15 @@ async function main() {
126339
126887
  const bareSlash = resolveBareCommand(trimmed);
126340
126888
  const effective = bareSlash ?? trimmed;
126341
126889
  if (bareSlash != null) console.log(dim(` \u2192 ${bareSlash}`));
126890
+ if (bareSlash == null) {
126891
+ const shellTeach = detectShellInvocation(trimmed);
126892
+ if (shellTeach != null) {
126893
+ console.log(dim(shellTeach));
126894
+ console.log();
126895
+ prompt2();
126896
+ return;
126897
+ }
126898
+ }
126342
126899
  if (isSlashCommand(effective)) {
126343
126900
  const { command: command2, args } = parseSlashCommand(effective);
126344
126901
  await handleSlashCommand(command2, args, runtime, config, fullConfig, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "motebit",
3
- "version": "1.11.3",
3
+ "version": "1.12.0",
4
4
  "type": "module",
5
5
  "description": "Reference runtime and operator console for sovereign AI agents — REPL, daemon, delegation, MCP server. Persistent Ed25519 identity, signed execution receipts, governance at the boundary.",
6
6
  "main": "./dist/index.js",
@@ -76,35 +76,35 @@
76
76
  "typescript": "^5.6.0",
77
77
  "vitest": "^4.1.10",
78
78
  "@motebit/ai-core": "0.0.0-private",
79
- "@motebit/core-identity": "0.0.0-private",
80
79
  "@motebit/behavior-engine": "0.0.0-private",
80
+ "@motebit/core-identity": "0.0.0-private",
81
81
  "@motebit/crypto": "3.19.1",
82
82
  "@motebit/encryption": "0.0.0-private",
83
- "@motebit/event-log": "0.0.0-private",
84
83
  "@motebit/gradient": "0.0.0-private",
85
- "@motebit/mcp-server": "0.0.0-private",
86
- "@motebit/memory-graph": "0.0.0-private",
84
+ "@motebit/event-log": "0.0.0-private",
87
85
  "@motebit/identity-file": "0.0.0-private",
88
- "@motebit/persistence": "0.0.0-private",
89
86
  "@motebit/mcp-client": "0.0.0-private",
87
+ "@motebit/memory-graph": "0.0.0-private",
90
88
  "@motebit/protocol": "3.15.1",
91
- "@motebit/policy": "0.0.0-private",
89
+ "@motebit/persistence": "0.0.0-private",
92
90
  "@motebit/planner": "0.0.0-private",
93
91
  "@motebit/privacy-layer": "0.0.0-private",
94
92
  "@motebit/relay": "0.0.0-private",
95
- "@motebit/runtime": "0.0.0-private",
96
93
  "@motebit/relay-client": "0.0.0-private",
97
- "@motebit/sdk": "2.6.0",
94
+ "@motebit/runtime": "0.0.0-private",
95
+ "@motebit/policy": "0.0.0-private",
96
+ "@motebit/sdk": "2.7.0",
97
+ "@motebit/mcp-server": "0.0.0-private",
98
98
  "@motebit/runtime-host": "0.0.0-private",
99
+ "@motebit/skills": "0.0.0-private",
99
100
  "@motebit/self-knowledge": "0.0.0-private",
100
101
  "@motebit/state-vector": "0.0.0-private",
101
- "@motebit/skills": "0.0.0-private",
102
- "@motebit/tools": "0.0.0-private",
103
102
  "@motebit/verify": "1.8.12",
104
- "@motebit/voice": "0.0.0-private",
105
103
  "@motebit/sync-engine": "0.0.0-private",
104
+ "@motebit/tools": "0.0.0-private",
105
+ "@motebit/wire-schemas": "0.0.0-private",
106
106
  "@motebit/wallet-solana": "0.0.0-private",
107
- "@motebit/wire-schemas": "0.0.0-private"
107
+ "@motebit/voice": "0.0.0-private"
108
108
  },
109
109
  "scripts": {
110
110
  "start": "tsx src/index.ts",