mixdog 0.9.25 → 0.9.27
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/package.json +2 -1
- package/scripts/arg-guard-test.mjs +68 -0
- package/scripts/compacted-placeholder-scrub-test.mjs +77 -0
- package/scripts/steering-fold-provenance-test.mjs +71 -0
- package/scripts/webhook-smoke.mjs +46 -53
- package/src/cli.mjs +40 -4
- package/src/defaults/skills/setup/SKILL.md +6 -1
- package/src/rules/shared/01-tool.md +11 -4
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +17 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +2 -2
- package/src/runtime/agent/orchestrator/mcp/client.mjs +28 -10
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +51 -15
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +164 -9
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +14 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +7 -3
- package/src/runtime/channels/lib/config.mjs +13 -11
- package/src/runtime/channels/lib/memory-client.mjs +22 -2
- package/src/runtime/channels/lib/owned-runtime.mjs +1 -1
- package/src/runtime/channels/lib/scheduler.mjs +226 -208
- package/src/runtime/channels/lib/status-snapshot.mjs +16 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +7 -318
- package/src/runtime/channels/lib/webhook.mjs +98 -150
- package/src/runtime/channels/lib/worker-main.mjs +1 -1
- package/src/runtime/memory/index.mjs +50 -25
- package/src/runtime/memory/lib/cycle-scheduler.mjs +3 -1
- package/src/runtime/memory/lib/memory-config-flags.mjs +13 -1
- package/src/runtime/memory/lib/pg/adapter.mjs +6 -1
- package/src/runtime/memory/lib/pg/process.mjs +19 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +125 -14
- package/src/runtime/memory/lib/query-handlers.mjs +102 -0
- package/src/runtime/memory/lib/recall-format.mjs +60 -22
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +20 -6
- package/src/runtime/memory/tool-defs.mjs +3 -3
- package/src/runtime/shared/child-guardian.mjs +2 -2
- package/src/runtime/shared/open-url.mjs +2 -1
- package/src/runtime/shared/schedules-db.mjs +350 -0
- package/src/runtime/shared/service-discovery.mjs +169 -0
- package/src/runtime/shared/spawn-flags.mjs +27 -0
- package/src/runtime/shared/staged-install-worker.mjs +14 -0
- package/src/runtime/shared/staged-update.mjs +530 -0
- package/src/runtime/shared/tool-primitives.mjs +3 -1
- package/src/runtime/shared/tool-surface.mjs +19 -3
- package/src/runtime/shared/update-checker.mjs +54 -10
- package/src/runtime/shared/webhooks-db.mjs +405 -0
- package/src/session-runtime/channel-config-api.mjs +13 -13
- package/src/session-runtime/lifecycle-api.mjs +12 -0
- package/src/session-runtime/runtime-core.mjs +41 -23
- package/src/standalone/agent-tool/tool-def.mjs +1 -1
- package/src/standalone/agent-tool.mjs +42 -11
- package/src/standalone/channel-admin.mjs +173 -121
- package/src/standalone/channel-worker.mjs +2 -2
- package/src/standalone/memory-runtime-proxy.mjs +10 -5
- package/src/tui/App.jsx +32 -10
- package/src/tui/app/channel-pickers.mjs +9 -9
- package/src/tui/app/clipboard.mjs +14 -0
- package/src/tui/app/doctor.mjs +1 -1
- package/src/tui/app/maintenance-pickers.mjs +17 -7
- package/src/tui/app/settings-picker.mjs +2 -2
- package/src/tui/app/transcript-window.mjs +63 -7
- package/src/tui/app/use-mouse-input.mjs +19 -6
- package/src/tui/components/Spinner.jsx +5 -2
- package/src/tui/components/StatusLine.jsx +7 -7
- package/src/tui/components/ToolExecution.jsx +36 -62
- package/src/tui/display-width.mjs +18 -8
- package/src/tui/dist/index.mjs +502 -324
- package/src/tui/engine/session-api-ext.mjs +12 -12
- package/src/tui/hooks/useSharedTick.mjs +103 -0
- package/src/tui/index.jsx +12 -2
- package/src/tui/markdown/format-token.mjs +46 -8
- package/src/tui/markdown/render-ansi.mjs +24 -1
- package/src/tui/markdown/stream-fence.mjs +60 -0
- package/src/tui/markdown/streaming-markdown.mjs +22 -1
- package/src/ui/statusline-segments.mjs +12 -1
- package/vendor/ink/build/display-width.js +10 -8
- package/src/runtime/shared/schedules-store.mjs +0 -82
|
@@ -3,7 +3,7 @@ import { join } from "path";
|
|
|
3
3
|
import { DiscordBackend } from "../backends/discord.mjs";
|
|
4
4
|
import { TelegramBackend } from "../backends/telegram.mjs";
|
|
5
5
|
import { readSection, updateSection, CONFIG_PATH as MIXDOG_CONFIG_PATH, getDiscordToken, getTelegramToken, diagnoseDiscordTokenValue } from "../../shared/config.mjs";
|
|
6
|
-
import { listSchedules } from "../../shared/schedules-
|
|
6
|
+
import { listSchedules } from "../../shared/schedules-db.mjs";
|
|
7
7
|
import { resolvePluginData } from "../../shared/plugin-paths.mjs";
|
|
8
8
|
const DATA_DIR = resolvePluginData();
|
|
9
9
|
const CONFIG_FILE = MIXDOG_CONFIG_PATH;
|
|
@@ -63,19 +63,21 @@ function resolveChannelId(raw = {}, backend = "discord") {
|
|
|
63
63
|
return "";
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function loadConfig() {
|
|
66
|
+
async function loadConfig() {
|
|
67
67
|
try {
|
|
68
68
|
let raw = readSection("channels");
|
|
69
69
|
raw = raw && typeof raw === "object" ? raw : {};
|
|
70
|
-
// Schedules
|
|
71
|
-
//
|
|
72
|
-
// / `raw.interactive` arrays in mixdog-config.json
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
// Schedules are the PG `scheduler.schedules` table (single source of
|
|
71
|
+
// truth). The legacy SCHEDULE.md store and the `raw.schedules.items` /
|
|
72
|
+
// `raw.nonInteractive` / `raw.interactive` arrays in mixdog-config.json
|
|
73
|
+
// are no longer read. Done one-shots are dropped so they never re-arm.
|
|
74
|
+
const scheduleEntries = (await listSchedules())
|
|
75
|
+
.filter((s) => s.enabled !== false && s.status !== "done");
|
|
76
|
+
// `target` drives routing: 'channel' → non-interactive dispatch to the
|
|
77
|
+
// schedule's channel_id; 'session' → inject into the current (Lead)
|
|
78
|
+
// session. Mirrors the webhook model.
|
|
79
|
+
raw.nonInteractive = scheduleEntries.filter((s) => s.target === "channel");
|
|
80
|
+
raw.interactive = scheduleEntries.filter((s) => s.target === "session");
|
|
79
81
|
const accessChannels = { ...raw.access?.channels ?? {} };
|
|
80
82
|
// voice config lives at the top level of mixdog-config.json (peer of
|
|
81
83
|
// channels), so readSection("channels") never sees it. Pull it explicitly.
|
|
@@ -4,6 +4,7 @@ import os from 'node:os'
|
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
6
6
|
import { createStandaloneMemoryRuntime } from '../../../standalone/memory-runtime-proxy.mjs'
|
|
7
|
+
import { readServicePort, markServiceUnreachable, isConnRefuseError } from '../../shared/service-discovery.mjs'
|
|
7
8
|
|
|
8
9
|
const RUNTIME_ROOT = process.env.MIXDOG_RUNTIME_ROOT
|
|
9
10
|
? path.resolve(process.env.MIXDOG_RUNTIME_ROOT)
|
|
@@ -60,9 +61,28 @@ function isConnRefusedLike(err) {
|
|
|
60
61
|
|| /ECONNREFUSED|missing memory_port|memory-service timeout/i.test(msg)
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
// A discovery advert validates only the owner pid, which can be a recycled pid
|
|
65
|
+
// living on an unrelated process while its advertised port is dead. This client
|
|
66
|
+
// has no separate /health probe, so on a connect-level failure we distrust the
|
|
67
|
+
// port: mark it unreachable (readServicePort then skips it → legacy fallback)
|
|
68
|
+
// and drop the port cache so the next getMemoryPort re-resolves.
|
|
69
|
+
function _distrustMemoryPort(port, err) {
|
|
70
|
+
// Connection-level failures ONLY. A 'memory-service timeout' means the daemon
|
|
71
|
+
// is slow-but-alive — distrusting it would false-route to legacy/buffer.
|
|
72
|
+
if (port && isConnRefuseError(err)) {
|
|
73
|
+
markServiceUnreachable('memory', port)
|
|
74
|
+
_portCache = null
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
async function getMemoryPort() {
|
|
64
79
|
const now = Date.now()
|
|
65
80
|
if (_portCache && (now - _portCache.ts) < 5_000) return _portCache.port
|
|
81
|
+
// Prefer the single-writer discovery advert (discovery/memory.json), which
|
|
82
|
+
// validates the owner pid is alive. Fall back to the legacy
|
|
83
|
+
// active-instance.json memory_port field for cross-version compat.
|
|
84
|
+
const advertPort = readServicePort('memory', { requirePid: false })
|
|
85
|
+
if (advertPort) { _portCache = { port: advertPort, mtime: 0, ts: now }; return advertPort }
|
|
66
86
|
try {
|
|
67
87
|
const stat = await fs.promises.stat(ACTIVE_INSTANCE_FILE)
|
|
68
88
|
const mtime = stat.mtimeMs
|
|
@@ -115,8 +135,8 @@ async function memoryFetch(method, endpoint, body = null, timeoutMs = 10_000, {
|
|
|
115
135
|
resolve(parsed)
|
|
116
136
|
})
|
|
117
137
|
})
|
|
118
|
-
req.on('error', reject)
|
|
119
|
-
req.on('timeout', () => { req.destroy();
|
|
138
|
+
req.on('error', err => { _distrustMemoryPort(port, err); reject(err) })
|
|
139
|
+
req.on('timeout', () => { req.destroy(); const err = new Error('memory-service timeout'); _distrustMemoryPort(port, err); reject(err) })
|
|
120
140
|
if (payload) req.write(payload)
|
|
121
141
|
req.end()
|
|
122
142
|
})
|
|
@@ -407,7 +407,7 @@ async function refreshBridgeOwnership(options = {}) {
|
|
|
407
407
|
async function reloadRuntimeConfig() {
|
|
408
408
|
const previousBackend = getBackend();
|
|
409
409
|
const previousBackendName = previousBackend?.name || "";
|
|
410
|
-
setConfig(loadConfig());
|
|
410
|
+
setConfig(await loadConfig());
|
|
411
411
|
scheduler.reloadConfig(
|
|
412
412
|
getConfig().nonInteractive ?? [],
|
|
413
413
|
getConfig().interactive ?? [],
|