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.
- package/README.md +0 -17
- package/package.json +8 -7
- package/scripts/build-tui.mjs +6 -6
- package/scripts/{channel-daemon-stub.mjs → daemon-stub.mjs} +18 -12
- package/src/defaults/skills/setup/SKILL.md +1 -1
- package/src/lib/keychain-cjs.cjs +1 -1
- package/src/lib/mixdog-debug.cjs +2 -3
- package/src/rules/lead/01-general.md +1 -2
- package/src/rules/lead/lead-tool.md +0 -3
- package/src/rules/shared/01-tool.md +11 -10
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +4 -13
- package/src/runtime/agent/orchestrator/mcp/client.mjs +81 -33
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +3 -6
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +8 -6
- package/src/runtime/agent/orchestrator/session/compact.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +22 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +40 -25
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +38 -2
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +59 -42
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +12 -22
- package/src/runtime/agent/orchestrator/tools/builtin/binary-file.mjs +92 -19
- package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +80 -30
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +41 -22
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +55 -11
- package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +55 -18
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -0
- package/src/runtime/agent/orchestrator/tools/env-scrub.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/lib/pwsh-standby-pool.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +67 -21
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -1
- package/src/runtime/channels/lib/config.mjs +33 -33
- package/src/runtime/channels/lib/inbound-handler.mjs +7 -7
- package/src/runtime/channels/lib/interaction-handlers.mjs +6 -6
- package/src/runtime/channels/lib/memory-client.mjs +31 -157
- package/src/runtime/channels/lib/output-forwarder.mjs +16 -16
- package/src/runtime/channels/lib/owned-runtime.mjs +60 -60
- package/src/runtime/channels/lib/owner-heartbeat.mjs +1 -1
- package/src/runtime/channels/lib/{backend-dispatch.mjs → provider-dispatch.mjs} +6 -6
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -30
- package/src/runtime/channels/lib/status-snapshot.mjs +3 -3
- package/src/runtime/channels/lib/tool-dispatch.mjs +4 -4
- package/src/runtime/channels/lib/worker-bootstrap.mjs +1 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +7 -7
- package/src/runtime/channels/lib/worker-main.mjs +38 -38
- package/src/runtime/channels/{backends → providers}/discord-access.mjs +1 -1
- package/src/runtime/channels/{backends → providers}/discord-gateway.mjs +1 -1
- package/src/runtime/channels/{backends → providers}/discord.mjs +3 -3
- package/src/runtime/channels/{backends → providers}/telegram.mjs +12 -12
- package/src/runtime/channels/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +72 -211
- package/src/runtime/memory/lib/agent-ipc.mjs +9 -8
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +2 -2
- package/src/runtime/memory/lib/http-router.mjs +1 -6
- package/src/runtime/memory/lib/memory-config-flags.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +4 -1
- package/src/runtime/memory/lib/memory-daemon-lifecycle.mjs +5 -0
- package/src/runtime/memory/lib/memory-log.mjs +1 -1
- package/src/runtime/memory/lib/memory-process-lock.mjs +5 -60
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/session-ingest.mjs +1 -1
- package/src/runtime/search/index.mjs +2 -2
- package/src/runtime/shared/abort-race.mjs +70 -0
- package/src/runtime/shared/child-spawn-gate.mjs +101 -63
- package/src/runtime/shared/config.mjs +11 -24
- package/src/runtime/shared/llm/index.mjs +1 -1
- package/src/runtime/shared/owner-fair-gate.mjs +134 -0
- package/src/runtime/shared/resource-admission.mjs +6 -5
- package/src/runtime/shared/tool-execution-owner.mjs +12 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +91 -22
- package/src/runtime/shared/tool-workload-gates.mjs +29 -0
- package/src/runtime/shared/turn-snapshot.mjs +17 -2
- package/src/session-runtime/channel-config-api.mjs +5 -5
- package/src/session-runtime/config-lifecycle.mjs +27 -27
- package/src/session-runtime/lifecycle-api.mjs +22 -3
- package/src/session-runtime/memory-runtime-prewarm.mjs +15 -0
- package/src/session-runtime/prewarm.mjs +1 -1
- package/src/session-runtime/provider-models.mjs +1 -1
- package/src/session-runtime/remote-control.mjs +6 -7
- package/src/session-runtime/runtime-core.mjs +52 -28
- package/src/session-runtime/self-update.mjs +1 -1
- package/src/session-runtime/session-lifecycle.mjs +36 -15
- package/src/session-runtime/session-title.mjs +1 -1
- package/src/session-runtime/session-turn-api.mjs +55 -15
- package/src/session-runtime/settings-api.mjs +7 -7
- package/src/standalone/agent-dispatch-broker.mjs +1 -1
- package/src/standalone/channel-admin.mjs +42 -53
- package/src/standalone/{channel-daemon-client.mjs → channel-client.mjs} +16 -18
- package/src/standalone/{channel-daemon-transport.mjs → channel-transport.mjs} +45 -46
- package/src/standalone/channel-worker.mjs +124 -647
- package/src/standalone/{backend-daemon.mjs → daemon.mjs} +187 -132
- package/src/standalone/memory-runtime-proxy.mjs +58 -1
- package/src/standalone/{engine-daemon-client.mjs → session-client.mjs} +151 -86
- package/src/standalone/session-protocol.mjs +8 -4
- package/src/standalone/session-runtime-pool.mjs +393 -0
- package/src/standalone/session-runtime-record.mjs +20 -0
- package/src/standalone/session-runtime-worker.mjs +203 -0
- package/src/standalone/{engine-daemon-service.mjs → session-service.mjs} +170 -157
- package/src/standalone/{engine-daemon-transport.mjs → session-transport.mjs} +139 -61
- package/src/standalone/session-wire.mjs +55 -0
- package/src/tui/App.jsx +4 -4
- package/src/tui/app/app-format.mjs +1 -1
- package/src/tui/app/channel-pickers.mjs +41 -41
- package/src/tui/app/input-parsers.mjs +2 -2
- package/src/tui/app/onboarding-steps.mjs +2 -2
- package/src/tui/app/project-picker.mjs +8 -8
- package/src/tui/app/prompt-submit.mjs +8 -8
- package/src/tui/app/settings-picker.mjs +25 -25
- package/src/tui/app/use-prompt-queue-history.mjs +1 -1
- package/src/tui/app/use-transcript-scroll.mjs +1 -1
- package/src/tui/components/ToolExecution.jsx +1 -1
- package/src/tui/components/prompt-input/restore-policy.mjs +1 -1
- package/src/tui/components/tool-execution/surface-detail.mjs +1 -1
- package/src/tui/dist/index.mjs +154 -127
- package/src/tui/hooks/useSession.mjs +16 -0
- package/src/tui/index.jsx +11 -11
- package/src/tui/{engine → session}/agent-envelope.mjs +3 -3
- package/src/tui/{engine → session}/agent-job-feed.mjs +4 -4
- package/src/tui/{engine → session}/boot-profile.mjs +2 -2
- package/src/tui/{engine → session}/context-state.mjs +3 -3
- package/src/tui/{engine → session}/labels.mjs +2 -2
- package/src/tui/{engine → session}/live-share.mjs +7 -7
- package/src/tui/{engine → session}/notice-text.mjs +2 -2
- package/src/tui/{engine → session}/notification-plan.mjs +3 -3
- package/src/tui/session/oauth-flows.mjs +140 -0
- package/src/tui/{engine → session}/prompt-history.mjs +3 -3
- package/src/tui/{engine → session}/queue-helpers.mjs +2 -2
- package/src/tui/{engine → session}/render-timing.mjs +2 -2
- package/src/tui/{engine → session}/session-api-ext.mjs +30 -17
- package/src/tui/{engine → session}/session-api.mjs +7 -60
- package/src/tui/{engine → session}/session-flow.mjs +1 -1
- package/src/tui/{engine → session}/session-stats.mjs +3 -3
- package/src/tui/{engine → session}/tool-approval.mjs +3 -3
- package/src/tui/{engine → session}/tool-call-fields.mjs +2 -2
- package/src/tui/{engine → session}/tool-card-results.mjs +4 -4
- package/src/tui/{engine → session}/tool-result-status.mjs +5 -5
- package/src/tui/{engine → session}/tool-result-text.mjs +3 -3
- package/src/tui/{engine → session}/transcript-spill.mjs +34 -34
- package/src/tui/{engine → session}/turn.mjs +29 -107
- package/src/tui/{engine-local-session.mjs → session-local.mjs} +59 -75
- package/src/tui/session.mjs +22 -0
- package/src/ui/statusline-segments.mjs +1 -1
- package/src/ui/statusline.mjs +1 -1
- package/vendor/ink/build/components/App.js +10 -1
- package/src/session-runtime/memory-daemon-probe.mjs +0 -61
- package/src/standalone/engine-daemon-protocol.mjs +0 -32
- package/src/tui/engine/turn-watchdog.mjs +0 -92
- package/src/tui/engine.mjs +0 -22
- package/src/tui/hooks/useEngine.mjs +0 -16
- /package/src/runtime/agent/orchestrator/session/compact/{engine.mjs → runner.mjs} +0 -0
- /package/src/runtime/channels/{backends → providers}/discord-attachments.mjs +0 -0
- /package/src/tui/{engine → session}/agent-response-tail.mjs +0 -0
- /package/src/tui/{engine → session}/frame-batched-store.mjs +0 -0
- /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,
|
|
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 {
|
|
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
|
|
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
|
-
|
|
181
|
+
provider.stopTyping(typingChannelId);
|
|
182
182
|
}
|
|
183
183
|
typingChannelId = channelId;
|
|
184
|
-
|
|
184
|
+
provider.startTyping(channelId);
|
|
185
185
|
}
|
|
186
186
|
function stopServerTyping() {
|
|
187
187
|
if (typingChannelId) {
|
|
188
|
-
|
|
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
|
|
222
|
+
await provider.sendMessage(ch, text, opts);
|
|
223
223
|
},
|
|
224
|
-
formatOutgoing: (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
|
|
229
|
+
return provider.react(ch, mid, emoji);
|
|
230
230
|
},
|
|
231
231
|
removeReaction: (ch, mid, emoji) => {
|
|
232
232
|
if (!channelBridgeActive) return Promise.resolve();
|
|
233
|
-
return
|
|
233
|
+
return provider.removeReaction(ch, mid, emoji);
|
|
234
234
|
},
|
|
235
|
-
// Watchdog backstop: force the
|
|
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
|
-
|
|
238
|
-
if (typeof
|
|
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
|
|
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
|
|
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/
|
|
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
|
-
|
|
347
|
-
|
|
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,
|
|
427
|
-
if (!target || !
|
|
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
|
-
|
|
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
|
|
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 &&
|
|
479
|
+
if ((mode === "channel" || mode === "both") && run?.result && provider?.sendMessage) {
|
|
480
480
|
const target = scheduler.resolveChannel("");
|
|
481
481
|
if (target) {
|
|
482
|
-
void bindingReady.then(() =>
|
|
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
|
-
|
|
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
|
|
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
|
-
// ──
|
|
552
|
-
// Each helper dispatches through the local
|
|
553
|
-
// owner in opt-in remote mode). Extracted → lib/
|
|
554
|
-
// live config/
|
|
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
|
-
} =
|
|
559
|
+
} = createProviderDispatch({
|
|
560
560
|
getConfig: () => config,
|
|
561
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
731
|
-
//
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
729
|
+
DiscordProvider
|
|
730
730
|
};
|
|
@@ -68,11 +68,11 @@ function normalizeAccess(parsed) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// Telegram Bot API
|
|
72
|
-
// index.mjs / output-forwarder rely on) so
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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);
|
|
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-
|