mixdog 0.9.96 → 0.9.97

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 (170) hide show
  1. package/README.md +0 -17
  2. package/package.json +8 -7
  3. package/scripts/build-tui.mjs +6 -6
  4. package/scripts/{channel-daemon-stub.mjs → daemon-stub.mjs} +18 -12
  5. package/src/defaults/skills/setup/SKILL.md +1 -1
  6. package/src/lib/keychain-cjs.cjs +1 -1
  7. package/src/lib/mixdog-debug.cjs +2 -3
  8. package/src/rules/lead/01-general.md +1 -2
  9. package/src/rules/lead/lead-tool.md +0 -3
  10. package/src/rules/shared/01-tool.md +11 -10
  11. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +4 -13
  12. package/src/runtime/agent/orchestrator/mcp/client.mjs +81 -33
  13. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +3 -6
  14. package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -2
  15. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +8 -6
  16. package/src/runtime/agent/orchestrator/session/compact.mjs +1 -1
  17. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +22 -4
  18. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +20 -2
  19. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +4 -3
  20. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +40 -25
  21. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +2 -3
  22. package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +12 -6
  23. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +38 -2
  24. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +10 -3
  25. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +4 -0
  26. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +59 -42
  27. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +3 -2
  28. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +12 -22
  29. package/src/runtime/agent/orchestrator/tools/builtin/binary-file.mjs +92 -19
  30. package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +2 -2
  31. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +2 -0
  32. package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -4
  33. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +80 -30
  34. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +41 -22
  35. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +6 -2
  36. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +55 -11
  37. package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +12 -1
  38. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +55 -18
  39. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -0
  40. package/src/runtime/agent/orchestrator/tools/env-scrub.mjs +1 -2
  41. package/src/runtime/agent/orchestrator/tools/lib/pwsh-standby-pool.mjs +2 -2
  42. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +1 -1
  43. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +67 -21
  44. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +2 -1
  45. package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
  46. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -1
  47. package/src/runtime/channels/lib/config.mjs +33 -33
  48. package/src/runtime/channels/lib/inbound-handler.mjs +7 -7
  49. package/src/runtime/channels/lib/interaction-handlers.mjs +6 -6
  50. package/src/runtime/channels/lib/memory-client.mjs +31 -157
  51. package/src/runtime/channels/lib/output-forwarder.mjs +16 -16
  52. package/src/runtime/channels/lib/owned-runtime.mjs +60 -60
  53. package/src/runtime/channels/lib/owner-heartbeat.mjs +1 -1
  54. package/src/runtime/channels/lib/{backend-dispatch.mjs → provider-dispatch.mjs} +6 -6
  55. package/src/runtime/channels/lib/runtime-paths.mjs +4 -30
  56. package/src/runtime/channels/lib/status-snapshot.mjs +3 -3
  57. package/src/runtime/channels/lib/tool-dispatch.mjs +4 -4
  58. package/src/runtime/channels/lib/worker-bootstrap.mjs +1 -1
  59. package/src/runtime/channels/lib/worker-ipc.mjs +7 -7
  60. package/src/runtime/channels/lib/worker-main.mjs +38 -38
  61. package/src/runtime/channels/{backends → providers}/discord-access.mjs +1 -1
  62. package/src/runtime/channels/{backends → providers}/discord-gateway.mjs +1 -1
  63. package/src/runtime/channels/{backends → providers}/discord.mjs +3 -3
  64. package/src/runtime/channels/{backends → providers}/telegram.mjs +12 -12
  65. package/src/runtime/channels/tool-defs.mjs +1 -1
  66. package/src/runtime/memory/index.mjs +72 -211
  67. package/src/runtime/memory/lib/agent-ipc.mjs +9 -8
  68. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +2 -2
  69. package/src/runtime/memory/lib/http-router.mjs +1 -6
  70. package/src/runtime/memory/lib/memory-config-flags.mjs +1 -1
  71. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +4 -1
  72. package/src/runtime/memory/lib/memory-daemon-lifecycle.mjs +5 -0
  73. package/src/runtime/memory/lib/memory-log.mjs +1 -1
  74. package/src/runtime/memory/lib/memory-process-lock.mjs +5 -60
  75. package/src/runtime/memory/lib/memory.mjs +1 -1
  76. package/src/runtime/memory/lib/session-ingest.mjs +1 -1
  77. package/src/runtime/search/index.mjs +2 -2
  78. package/src/runtime/shared/abort-race.mjs +70 -0
  79. package/src/runtime/shared/child-spawn-gate.mjs +101 -63
  80. package/src/runtime/shared/config.mjs +11 -24
  81. package/src/runtime/shared/llm/index.mjs +1 -1
  82. package/src/runtime/shared/owner-fair-gate.mjs +134 -0
  83. package/src/runtime/shared/resource-admission.mjs +6 -5
  84. package/src/runtime/shared/tool-execution-owner.mjs +12 -0
  85. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  86. package/src/runtime/shared/tool-surface.mjs +91 -22
  87. package/src/runtime/shared/tool-workload-gates.mjs +29 -0
  88. package/src/runtime/shared/turn-snapshot.mjs +17 -2
  89. package/src/session-runtime/channel-config-api.mjs +5 -5
  90. package/src/session-runtime/config-lifecycle.mjs +27 -27
  91. package/src/session-runtime/lifecycle-api.mjs +22 -3
  92. package/src/session-runtime/memory-runtime-prewarm.mjs +15 -0
  93. package/src/session-runtime/prewarm.mjs +1 -1
  94. package/src/session-runtime/provider-models.mjs +1 -1
  95. package/src/session-runtime/remote-control.mjs +6 -7
  96. package/src/session-runtime/runtime-core.mjs +52 -28
  97. package/src/session-runtime/self-update.mjs +1 -1
  98. package/src/session-runtime/session-lifecycle.mjs +36 -15
  99. package/src/session-runtime/session-title.mjs +1 -1
  100. package/src/session-runtime/session-turn-api.mjs +55 -15
  101. package/src/session-runtime/settings-api.mjs +7 -7
  102. package/src/standalone/agent-dispatch-broker.mjs +1 -1
  103. package/src/standalone/channel-admin.mjs +42 -53
  104. package/src/standalone/{channel-daemon-client.mjs → channel-client.mjs} +16 -18
  105. package/src/standalone/{channel-daemon-transport.mjs → channel-transport.mjs} +45 -46
  106. package/src/standalone/channel-worker.mjs +124 -647
  107. package/src/standalone/{backend-daemon.mjs → daemon.mjs} +187 -132
  108. package/src/standalone/memory-runtime-proxy.mjs +58 -1
  109. package/src/standalone/{engine-daemon-client.mjs → session-client.mjs} +151 -86
  110. package/src/standalone/session-protocol.mjs +8 -4
  111. package/src/standalone/session-runtime-pool.mjs +393 -0
  112. package/src/standalone/session-runtime-record.mjs +20 -0
  113. package/src/standalone/session-runtime-worker.mjs +203 -0
  114. package/src/standalone/{engine-daemon-service.mjs → session-service.mjs} +170 -157
  115. package/src/standalone/{engine-daemon-transport.mjs → session-transport.mjs} +139 -61
  116. package/src/standalone/session-wire.mjs +55 -0
  117. package/src/tui/App.jsx +4 -4
  118. package/src/tui/app/app-format.mjs +1 -1
  119. package/src/tui/app/channel-pickers.mjs +41 -41
  120. package/src/tui/app/input-parsers.mjs +2 -2
  121. package/src/tui/app/onboarding-steps.mjs +2 -2
  122. package/src/tui/app/project-picker.mjs +8 -8
  123. package/src/tui/app/prompt-submit.mjs +8 -8
  124. package/src/tui/app/settings-picker.mjs +25 -25
  125. package/src/tui/app/use-prompt-queue-history.mjs +1 -1
  126. package/src/tui/app/use-transcript-scroll.mjs +1 -1
  127. package/src/tui/components/ToolExecution.jsx +1 -1
  128. package/src/tui/components/prompt-input/restore-policy.mjs +1 -1
  129. package/src/tui/components/tool-execution/surface-detail.mjs +1 -1
  130. package/src/tui/dist/index.mjs +154 -127
  131. package/src/tui/hooks/useSession.mjs +16 -0
  132. package/src/tui/index.jsx +11 -11
  133. package/src/tui/{engine → session}/agent-envelope.mjs +3 -3
  134. package/src/tui/{engine → session}/agent-job-feed.mjs +4 -4
  135. package/src/tui/{engine → session}/boot-profile.mjs +2 -2
  136. package/src/tui/{engine → session}/context-state.mjs +3 -3
  137. package/src/tui/{engine → session}/labels.mjs +2 -2
  138. package/src/tui/{engine → session}/live-share.mjs +7 -7
  139. package/src/tui/{engine → session}/notice-text.mjs +2 -2
  140. package/src/tui/{engine → session}/notification-plan.mjs +3 -3
  141. package/src/tui/session/oauth-flows.mjs +140 -0
  142. package/src/tui/{engine → session}/prompt-history.mjs +3 -3
  143. package/src/tui/{engine → session}/queue-helpers.mjs +2 -2
  144. package/src/tui/{engine → session}/render-timing.mjs +2 -2
  145. package/src/tui/{engine → session}/session-api-ext.mjs +30 -17
  146. package/src/tui/{engine → session}/session-api.mjs +7 -60
  147. package/src/tui/{engine → session}/session-flow.mjs +1 -1
  148. package/src/tui/{engine → session}/session-stats.mjs +3 -3
  149. package/src/tui/{engine → session}/tool-approval.mjs +3 -3
  150. package/src/tui/{engine → session}/tool-call-fields.mjs +2 -2
  151. package/src/tui/{engine → session}/tool-card-results.mjs +4 -4
  152. package/src/tui/{engine → session}/tool-result-status.mjs +5 -5
  153. package/src/tui/{engine → session}/tool-result-text.mjs +3 -3
  154. package/src/tui/{engine → session}/transcript-spill.mjs +34 -34
  155. package/src/tui/{engine → session}/turn.mjs +29 -107
  156. package/src/tui/{engine-local-session.mjs → session-local.mjs} +59 -75
  157. package/src/tui/session.mjs +22 -0
  158. package/src/ui/statusline-segments.mjs +1 -1
  159. package/src/ui/statusline.mjs +1 -1
  160. package/vendor/ink/build/components/App.js +10 -1
  161. package/src/session-runtime/memory-daemon-probe.mjs +0 -61
  162. package/src/standalone/engine-daemon-protocol.mjs +0 -32
  163. package/src/tui/engine/turn-watchdog.mjs +0 -92
  164. package/src/tui/engine.mjs +0 -22
  165. package/src/tui/hooks/useEngine.mjs +0 -16
  166. /package/src/runtime/agent/orchestrator/session/compact/{engine.mjs → runner.mjs} +0 -0
  167. /package/src/runtime/channels/{backends → providers}/discord-attachments.mjs +0 -0
  168. /package/src/tui/{engine → session}/agent-response-tail.mjs +0 -0
  169. /package/src/tui/{engine → session}/frame-batched-store.mjs +0 -0
  170. /package/src/tui/{engine → session}/tui-steering-persist.mjs +0 -0
@@ -4,7 +4,7 @@ import * as path from "path";
4
4
  import { performance } from "perf_hooks";
5
5
  import { createRequire } from "module";
6
6
  const _require = createRequire(import.meta.url);
7
- import { loadConfig, createBackend, loadProfileConfig, DATA_DIR } from "./config.mjs";
7
+ import { loadConfig, createProvider, loadProfileConfig, DATA_DIR } from "./config.mjs";
8
8
  import { resolveVoiceRuntime } from "./voice-runtime-fetcher.mjs";
9
9
  import { ensureReady, stopVoiceWhisperServer } from "./whisper-server.mjs";
10
10
  import { loadConfig as loadAgentConfig } from "../../agent/orchestrator/config.mjs";
@@ -63,7 +63,7 @@ import {
63
63
  } from "./crash-log.mjs";
64
64
  import { dropTrace, preview, _dtIdxFlush } from "./index-drop-trace.mjs";
65
65
  import { createVoiceTranscription } from "./voice-transcription.mjs";
66
- import { createBackendDispatch } from "./backend-dispatch.mjs";
66
+ import { createProviderDispatch } from "./provider-dispatch.mjs";
67
67
  import { createParentBridge } from "./parent-bridge.mjs";
68
68
  import { createInboundRouting } from "./inbound-routing.mjs";
69
69
  import { createToolDispatch } from "./tool-dispatch.mjs";
@@ -136,7 +136,7 @@ if (isMixdogDebug()) {
136
136
  }
137
137
  const _bootLog = path.join(DATA_DIR, "boot.log");
138
138
  let config = await loadConfig();
139
- let backend = createBackend(config);
139
+ let provider = createProvider(config);
140
140
  const INSTANCE_ID = makeInstanceId();
141
141
  const TERMINAL_LEAD_PID = getTerminalLeadPid();
142
142
  runWorkerBootstrap({
@@ -178,14 +178,14 @@ let typingChannelId = null;
178
178
  const pendingSetup = new PendingInteractionStore();
179
179
  function startServerTyping(channelId) {
180
180
  if (typingChannelId && typingChannelId !== channelId) {
181
- backend.stopTyping(typingChannelId);
181
+ provider.stopTyping(typingChannelId);
182
182
  }
183
183
  typingChannelId = channelId;
184
- backend.startTyping(channelId);
184
+ provider.startTyping(channelId);
185
185
  }
186
186
  function stopServerTyping() {
187
187
  if (typingChannelId) {
188
- backend.stopTyping(typingChannelId);
188
+ provider.stopTyping(typingChannelId);
189
189
  typingChannelId = null;
190
190
  }
191
191
  }
@@ -219,23 +219,23 @@ const forwarder = new OutputForwarder({
219
219
  if (!channelBridgeActive) {
220
220
  throw new Error("send() called while channel bridge is inactive");
221
221
  }
222
- await backend.sendMessage(ch, text, opts);
222
+ await provider.sendMessage(ch, text, opts);
223
223
  },
224
- formatOutgoing: (text) => backend.formatOutgoing ? backend.formatOutgoing(text) : text,
224
+ formatOutgoing: (text) => provider.formatOutgoing ? provider.formatOutgoing(text) : text,
225
225
  recordAssistantTurn: async () => {
226
226
  },
227
227
  react: (ch, mid, emoji) => {
228
228
  if (!channelBridgeActive) return Promise.resolve();
229
- return backend.react(ch, mid, emoji);
229
+ return provider.react(ch, mid, emoji);
230
230
  },
231
231
  removeReaction: (ch, mid, emoji) => {
232
232
  if (!channelBridgeActive) return Promise.resolve();
233
- return backend.removeReaction(ch, mid, emoji);
233
+ return provider.removeReaction(ch, mid, emoji);
234
234
  },
235
- // Watchdog backstop: force the backend to tear down + rebuild a wedged
235
+ // Watchdog backstop: force the provider to tear down + rebuild a wedged
236
236
  // client so an over-budget send fails fast and the queue releases.
237
- resetBackend: async () => {
238
- if (typeof backend?._resetClient === "function") await backend._resetClient();
237
+ resetProvider: async () => {
238
+ if (typeof provider?._resetClient === "function") await provider._resetClient();
239
239
  }
240
240
  }, statusState);
241
241
  forwarder.setOnIdle(() => {
@@ -305,7 +305,7 @@ let eventPipeline = null;
305
305
  let bridgeRuntimeConnected = false;
306
306
  // Stop-requested signal: set by stopOwnedRuntime() when it runs during the
307
307
  // startOwnedRuntime() in-flight window (bridgeRuntimeStarting=true). Checked
308
- // by startOwnedRuntime() right after backend.connect() resolves so the
308
+ // by startOwnedRuntime() right after provider.connect() resolves so the
309
309
  // in-flight start does not revive owner state after the stop already tore
310
310
  // the partial-start state down.
311
311
  const ACTIVE_OWNER_STALE_MS = 1e4;
@@ -313,7 +313,7 @@ const ACTIVE_OWNER_STALE_MS = 1e4;
313
313
  // bindingReady gates all send paths until the boot-time refreshBridgeOwnership
314
314
  // ({ restoreBinding: true }) call completes. Without this, scheduler/webhook
315
315
  // emissions fired within the first ~few hundred ms after restart drop because
316
- // the Discord backend binding has not yet been established.
316
+ // the Discord provider binding has not yet been established.
317
317
  let bindingReadyStatus = "pending";
318
318
  let _bindingReadyResolve;
319
319
  const bindingReady = new Promise((r) => { _bindingReadyResolve = r; });
@@ -328,7 +328,7 @@ const {
328
328
  } = createOwnerHeartbeat();
329
329
  // ── Owned-runtime lifecycle ─────────────────────────────────────────────────
330
330
  // Extracted -> lib/owned-runtime.mjs. Owns its own start/stop/refresh in-flight
331
- // flags + ownership timer + memory-drain timer; shares config/backend/
331
+ // flags + ownership timer + memory-drain timer; shares config/provider/
332
332
  // bridgeRuntimeConnected/webhookServer/eventPipeline with the worker via get/set.
333
333
  const {
334
334
  startAutomationRuntime,
@@ -343,8 +343,8 @@ const {
343
343
  } = createOwnedRuntime({
344
344
  getConfig: () => config,
345
345
  setConfig: (v) => { config = v; },
346
- getBackend: () => backend,
347
- setBackend: (v) => { backend = v; },
346
+ getProvider: () => provider,
347
+ setProvider: (v) => { provider = v; },
348
348
  getBridgeRuntimeConnected: () => bridgeRuntimeConnected,
349
349
  setBridgeRuntimeConnected: (v) => { bridgeRuntimeConnected = v; },
350
350
  getWebhookServer: () => webhookServer,
@@ -423,10 +423,10 @@ function forwardLifecycleToDiscord(channelId, content) {
423
423
  // falling back to statusState.channelId can route to a stale/unrelated
424
424
  // channel when the caller did not supply one intentionally.
425
425
  const target = channelId || null;
426
- dropTrace("send.lifecycle.entry", { channelId: target || "(none)", bindingReadyStatus, backendPresent: !!backend?.sendMessage, preview: preview(content) });
427
- if (!target || !backend?.sendMessage) return;
426
+ dropTrace("send.lifecycle.entry", { channelId: target || "(none)", bindingReadyStatus, providerPresent: !!provider?.sendMessage, preview: preview(content) });
427
+ if (!target || !provider?.sendMessage) return;
428
428
  void bindingReady.then(() =>
429
- backend.sendMessage(target, content)
429
+ provider.sendMessage(target, content)
430
430
  .then(() => dropTrace("send.lifecycle.ok", { channelId: target }))
431
431
  .catch((err) => dropTrace("send.lifecycle.err", { channelId: target, err: String(err) }))
432
432
  ).catch(() => {});
@@ -451,7 +451,7 @@ scheduler.setSendHandler(async (channelId, text) => {
451
451
  await bindingReady;
452
452
  dropTrace("send.scheduler.ready", { channelId });
453
453
  try {
454
- await backend.sendMessage(channelId, text);
454
+ await provider.sendMessage(channelId, text);
455
455
  dropTrace("send.scheduler.ok", { channelId });
456
456
  } catch (err) {
457
457
  dropTrace("send.scheduler.err", { channelId, err: String(err) });
@@ -476,10 +476,10 @@ function wireWebhookHandlers() {
476
476
  prompt,
477
477
  });
478
478
  const mode = String(delivery || "app");
479
- if ((mode === "channel" || mode === "both") && run?.result && backend?.sendMessage) {
479
+ if ((mode === "channel" || mode === "both") && run?.result && provider?.sendMessage) {
480
480
  const target = scheduler.resolveChannel("");
481
481
  if (target) {
482
- void bindingReady.then(() => backend.sendMessage(target, run.result))
482
+ void bindingReady.then(() => provider.sendMessage(target, run.result))
483
483
  .catch((err) => dropTrace("send.webhook.err", { channelId: target, err: String(err) }));
484
484
  }
485
485
  }
@@ -503,7 +503,7 @@ const {
503
503
  pendingPermRequests,
504
504
  refreshToolExecConsumerMarker,
505
505
  } = createInteractionHandlers({
506
- getBackend: () => backend,
506
+ getProvider: () => provider,
507
507
  getConfig: () => config,
508
508
  getBridgeRuntimeConnected: () => bridgeRuntimeConnected,
509
509
  instanceId: INSTANCE_ID,
@@ -536,7 +536,7 @@ import { TOOL_DEFS } from '../tool-defs.mjs';
536
536
  // bottom of this file (parent's `callWorker` → `handleToolCall`). There is no
537
537
  // orphan worker-level MCP Server: the parent (server.mjs) owns the single
538
538
  // connected transport and routes CallTool through the IPC `call` path.
539
- const BACKEND_TOOLS = /* @__PURE__ */ new Set(["reply", "fetch"]);
539
+ const PROVIDER_TOOLS = /* @__PURE__ */ new Set(["reply", "fetch"]);
540
540
  // ── Inbound routing / dedup / ownership helpers ─────────────────────────────
541
541
  // Extracted → lib/inbound-routing.mjs. Bound to live config/identity getters.
542
542
  const {
@@ -548,17 +548,17 @@ const {
548
548
  getInstanceId: () => INSTANCE_ID,
549
549
  getChannelOwnerPath,
550
550
  });
551
- // ── Backend-tool dispatch helpers ───────────────────────────────────────────
552
- // Each helper dispatches through the local backend (this process is always the
553
- // owner in opt-in remote mode). Extracted → lib/backend-dispatch.mjs. Bound to
554
- // live config/backend getters so runtime reloads keep the original file-level
551
+ // ── Provider-tool dispatch helpers ───────────────────────────────────────────
552
+ // Each helper dispatches through the local provider (this process is always the
553
+ // owner in opt-in remote mode). Extracted → lib/provider-dispatch.mjs. Bound to
554
+ // live config/provider getters so runtime reloads keep the original file-level
555
555
  // reference semantics.
556
556
  const {
557
557
  dispatchReply,
558
558
  dispatchFetch,
559
- } = createBackendDispatch({
559
+ } = createProviderDispatch({
560
560
  getConfig: () => config,
561
- getBackend: () => backend,
561
+ getProvider: () => provider,
562
562
  scheduler,
563
563
  });
564
564
  // ── Worker/HTTP tool-call dispatch ──────────────────────────────────────────
@@ -574,7 +574,7 @@ const {
574
574
  handleToolCallWithBridgeRetry,
575
575
  } = createToolDispatch({
576
576
  getForwarder: () => forwarder,
577
- BACKEND_TOOLS,
577
+ PROVIDER_TOOLS,
578
578
  isChannelsDegraded,
579
579
  dispatchReply,
580
580
  dispatchFetch,
@@ -623,7 +623,7 @@ const {
623
623
  },
624
624
  });
625
625
  createInboundHandler({
626
- getBackend: () => backend,
626
+ getProvider: () => provider,
627
627
  getConfig: () => config,
628
628
  getBridgeRuntimeConnected: () => bridgeRuntimeConnected,
629
629
  getChannelBridgeActive: () => channelBridgeActive,
@@ -727,10 +727,10 @@ async function stop() {
727
727
  }
728
728
  }
729
729
  // ── IPC worker mode ──────────────────────────────────────────────
730
- // Skipped under the machine-global daemon (MIXDOG_CHANNEL_DAEMON=1): the
731
- // daemon entry (src/standalone/channel-daemon.mjs) drives start()/stop() and
730
+ // Skipped under the machine-global host (MIXDOG_DAEMON_HOST=1): the daemon
731
+ // entry (src/standalone/daemon.mjs) drives start()/stop() and
732
732
  // its own HTTP+SSE transport instead of the parent node-IPC call/notify loop.
733
- if (_isWorkerMode && process.send && process.env.MIXDOG_CHANNEL_DAEMON !== '1') {
733
+ if (_isWorkerMode && process.send && process.env.MIXDOG_DAEMON_HOST !== '1') {
734
734
  runWorkerIpc({
735
735
  start,
736
736
  stop,
@@ -739,7 +739,7 @@ if (_isWorkerMode && process.send && process.env.MIXDOG_CHANNEL_DAEMON !== '1')
739
739
  clearServerPid,
740
740
  instanceId: INSTANCE_ID,
741
741
  statusState,
742
- getBackend: () => backend,
742
+ getProvider: () => provider,
743
743
  getConfig: () => config,
744
744
  pendingPermRequests,
745
745
  refreshToolExecConsumerMarker,
@@ -1,5 +1,5 @@
1
1
  // Access-config helpers extracted from discord.mjs. Pure functions with no
2
- // dependency on the backend instance; behavior is identical to the originals.
2
+ // dependency on the provider instance; behavior is identical to the originals.
3
3
 
4
4
  function defaultAccess() {
5
5
  return {
@@ -1,5 +1,5 @@
1
1
  // Gateway connect / login / event-listener wiring extracted from discord.mjs.
2
- // Implemented as instance-method installers that operate on a DiscordBackend
2
+ // Implemented as instance-method installers that operate on a DiscordProvider
3
3
  // `self`. Behavior is byte-identical to the originals; only the host object is
4
4
  // passed explicitly instead of via `this`.
5
5
 
@@ -40,7 +40,7 @@ const RESET_BACKOFF_CAP_MS = 60_000;
40
40
  // (abandoned) promise to actually settle before giving up with unknown outcome.
41
41
  const SETTLE_CAP_MS = 15_000;
42
42
  const RECENT_SENT_CAP = 200;
43
- class DiscordBackend {
43
+ class DiscordProvider {
44
44
  name = "discord";
45
45
  MAX_MESSAGE_LENGTH = MAX_DISCORD_MESSAGE;
46
46
  onMessage = null;
@@ -231,7 +231,7 @@ class DiscordBackend {
231
231
  // chunks that already landed.
232
232
  //
233
233
  // Continuation spacing is decided by the session/turn-local OutputForwarder.
234
- // This backend is daemon-global, so scheduler traffic or another client
234
+ // This provider is daemon-global, so scheduler traffic or another client
235
235
  // must never change the first/subsequent-message decision. A retry token
236
236
  // remains authoritative so a partial resend is byte-identical.
237
237
  const resumeToken = opts?.resumeToken;
@@ -726,5 +726,5 @@ class DiscordBackend {
726
726
  }
727
727
  }
728
728
  export {
729
- DiscordBackend
729
+ DiscordProvider
730
730
  };
@@ -68,11 +68,11 @@ function normalizeAccess(parsed) {
68
68
  };
69
69
  }
70
70
 
71
- // Telegram Bot API backend. Mirrors DiscordBackend's PUBLIC surface (the members
72
- // index.mjs / output-forwarder rely on) so createBackend() can hand either one to
71
+ // Telegram Bot API provider. Mirrors DiscordProvider's PUBLIC surface (the members
72
+ // index.mjs / output-forwarder rely on) so createProvider() can hand either one to
73
73
  // the same runtime with no call-site changes. INBOUND via long-poll getUpdates;
74
74
  // OUTBOUND as plain text (no parse_mode) so code fences survive verbatim.
75
- class TelegramBackend {
75
+ class TelegramProvider {
76
76
  name = "telegram";
77
77
  MAX_MESSAGE_LENGTH = MAX_TELEGRAM_MESSAGE;
78
78
  onMessage = null;
@@ -113,7 +113,7 @@ class TelegramBackend {
113
113
  return text;
114
114
  }
115
115
  // Fold the single configured main channel id into access.channels, mirroring
116
- // DiscordBackend.readConfigAccess(). Read live so a channel change applies
116
+ // DiscordProvider.readConfigAccess(). Read live so a channel change applies
117
117
  // without a restart. Falls back to initialAccess if the read throws.
118
118
  readConfigAccess() {
119
119
  try {
@@ -132,7 +132,7 @@ class TelegramBackend {
132
132
  }
133
133
  loadAccess() {
134
134
  // The main chat is auto-allowed (single-source channel setup, mirrors
135
- // DiscordBackend.loadAccess) so a configured mainChannelId is enough for
135
+ // DiscordProvider.loadAccess) so a configured mainChannelId is enough for
136
136
  // both inbound gating and outbound. Base off the live config so all
137
137
  // configured channels (not just main) are seen without a restart.
138
138
  const a = this.readConfigAccess();
@@ -167,7 +167,7 @@ class TelegramBackend {
167
167
  // POST <method> with a JSON body; parse the JSON envelope and normalize
168
168
  // Telegram's error shape into a thrown Error that carries `.status` and
169
169
  // `.retryAfter` so sendMessage's retry loop can key off them exactly like
170
- // the Discord backend keys off discord.js error fields.
170
+ // the Discord provider keys off discord.js error fields.
171
171
  async _api(method, body, { signal } = {}) {
172
172
  const url = `${API_BASE}/bot${this.token}/${method}`;
173
173
  let res;
@@ -198,7 +198,7 @@ class TelegramBackend {
198
198
  }
199
199
  // ── Lifecycle ──────────────────────────────────────────────────────
200
200
  async connect() {
201
- // Re-entry guard mirrors DiscordBackend.connect(): a second connect() while
201
+ // Re-entry guard mirrors DiscordProvider.connect(): a second connect() while
202
202
  // one is in flight/settled returns the same promise (no duplicate loops).
203
203
  if (this._connectPromise) return this._connectPromise;
204
204
  this._connectPromise = (async () => {
@@ -273,7 +273,7 @@ class TelegramBackend {
273
273
  const text = msg.text ?? msg.caption ?? "";
274
274
  const receivedAtMs = Date.now();
275
275
  // Mirror discord.mjs handleInbound's onMessage object shape so downstream
276
- // routing (resolveInboundRoute etc.) is backend-agnostic. Telegram has no
276
+ // routing (resolveInboundRoute etc.) is provider-agnostic. Telegram has no
277
277
  // thread/parent concept here → parentChatId null; attachments unsupported
278
278
  // in scope 1 → [].
279
279
  if (this.onMessage) {
@@ -301,7 +301,7 @@ class TelegramBackend {
301
301
  this._connectPromise = null;
302
302
  }
303
303
  // ── Outbound ───────────────────────────────────────────────────────
304
- // Mirrors DiscordBackend.sendMessage: OWNS chunking + per-chunk retry + the
304
+ // Mirrors DiscordProvider.sendMessage: OWNS chunking + per-chunk retry + the
305
305
  // opaque resume-token contract so output-forwarder (which passes whole text
306
306
  // and hands opts.resumeToken back on retry) works unchanged.
307
307
  async sendMessage(chatId, text, opts) {
@@ -318,7 +318,7 @@ class TelegramBackend {
318
318
  // Opaque resume token. Shape parity with discord.mjs:
319
319
  // { hash, nextChunkIdx, sentIds, prefixed, limit }. Telegram has no
320
320
  // continuation-prefix requirement, so `prefixed` is always false — it is
321
- // emitted only so the token shape matches across backends.
321
+ // emitted only so the token shape matches across providers.
322
322
  const contentHash = createHash("md5").update(String(text)).digest("hex");
323
323
  const resumeToken = opts?.resumeToken;
324
324
  let startIdx = 0;
@@ -486,7 +486,7 @@ class TelegramBackend {
486
486
  }
487
487
  // ── Typing indicator ───────────────────────────────────────────────
488
488
  // sendChatAction "typing" lasts ~5s server-side, so refresh on an interval
489
- // while active — mirrors DiscordBackend.startTyping's interval model.
489
+ // while active — mirrors DiscordProvider.startTyping's interval model.
490
490
  startTyping(channelId) {
491
491
  this.stopTyping(channelId);
492
492
  const fire = () => {
@@ -507,6 +507,6 @@ class TelegramBackend {
507
507
  }
508
508
 
509
509
  export {
510
- TelegramBackend,
510
+ TelegramProvider,
511
511
  MAX_TELEGRAM_MESSAGE
512
512
  };
@@ -46,7 +46,7 @@ export const TOOL_DEFS = [
46
46
  },
47
47
  // memory and recall_memory tools are now provided by memory-service.mjs via MCP
48
48
  // react/edit_message/download_attachment tools removed (no remaining
49
- // callers); backend editMessage/downloadAttachment/react methods stay for
49
+ // callers); provider editMessage/downloadAttachment/react methods stay for
50
50
  // internal use.
51
51
  // schedule_status/trigger_schedule/schedule_control tools removed (no
52
52
  // remaining callers). activate_channel_bridge/reload_config are NOT model-