mixdog 0.9.95 → 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 (282) hide show
  1. package/LICENSES/Apache-2.0.txt +201 -0
  2. package/LICENSES/MIT.txt +56 -0
  3. package/LICENSES/codex-NOTICE.txt +6 -0
  4. package/NOTICE.md +46 -9
  5. package/README.md +0 -17
  6. package/package.json +16 -12
  7. package/scripts/.tmp-coverage-report.mjs +96 -0
  8. package/scripts/build-tui.mjs +17 -1
  9. package/scripts/{channel-daemon-stub.mjs → daemon-stub.mjs} +18 -12
  10. package/scripts/fixtures/patch-replay-corpus.json +98 -0
  11. package/src/defaults/mixdog-config.template.json +5 -8
  12. package/src/defaults/skills/setup/SKILL.md +1 -1
  13. package/src/lib/keychain-cjs.cjs +1 -1
  14. package/src/lib/mixdog-debug.cjs +2 -3
  15. package/src/rules/agent/30-explorer.md +7 -4
  16. package/src/rules/lead/01-general.md +1 -2
  17. package/src/rules/lead/lead-tool.md +0 -3
  18. package/src/rules/shared/01-tool.md +21 -29
  19. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +18 -2
  20. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +31 -1
  21. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +6 -17
  22. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +12 -1
  23. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +4 -13
  24. package/src/runtime/agent/orchestrator/config.mjs +246 -67
  25. package/src/runtime/agent/orchestrator/mcp/client.mjs +104 -41
  26. package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +23 -0
  27. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +113 -14
  28. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +5 -1
  29. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +32 -11
  30. package/src/runtime/agent/orchestrator/providers/gemini.mjs +89 -2
  31. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +12 -1
  32. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +19 -1
  33. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +144 -39
  34. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +22 -8
  35. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +15 -1
  36. package/src/runtime/agent/orchestrator/providers/openai-transport-policy.mjs +1 -1
  37. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +3 -4
  38. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +3 -6
  39. package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -2
  40. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +67 -7
  41. package/src/runtime/agent/orchestrator/providers/stream-json-pool.mjs +291 -0
  42. package/src/runtime/agent/orchestrator/providers/stream-json-worker.mjs +21 -0
  43. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +36 -10
  44. package/src/runtime/agent/orchestrator/session/compact.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +22 -33
  46. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +13 -0
  47. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +2 -2
  48. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +0 -24
  49. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +21 -29
  50. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +7 -10
  51. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +45 -25
  52. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +2 -3
  53. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +142 -84
  54. package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +12 -6
  55. package/src/runtime/agent/orchestrator/session/manager/runtime-loaders.mjs +4 -0
  56. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +31 -1
  57. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +38 -2
  58. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +29 -9
  59. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -0
  60. package/src/runtime/agent/orchestrator/session/result-classification.mjs +65 -0
  61. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +86 -8
  62. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +10 -3
  63. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +4 -0
  64. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +71 -42
  65. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +4 -33
  66. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -5
  67. package/src/runtime/agent/orchestrator/stall-policy.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +2 -2
  69. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +35 -1
  70. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +116 -26
  71. package/src/runtime/agent/orchestrator/tools/builtin/binary-file.mjs +92 -19
  72. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +8 -9
  73. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/tools/builtin/device-paths.mjs +2 -2
  75. package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +2 -2
  76. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +6 -15
  77. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +12 -26
  78. package/src/runtime/agent/orchestrator/tools/builtin/read-image.mjs +5 -5
  79. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +83 -33
  80. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +42 -45
  81. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +27 -9
  82. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +7 -0
  83. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +17 -39
  84. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +73 -0
  85. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +1 -1
  86. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-spawn.mjs +0 -2
  87. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +3 -8
  88. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +30 -0
  89. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +5 -5
  90. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +142 -26
  91. package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +12 -1
  92. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +47 -19
  93. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +3 -2
  94. package/src/runtime/agent/orchestrator/tools/env-scrub.mjs +1 -2
  95. package/src/runtime/agent/orchestrator/tools/lib/pwsh-standby-pool.mjs +83 -13
  96. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +39 -1
  97. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +94 -20
  99. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +16 -0
  100. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +108 -12
  101. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +12 -11
  102. package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +63 -9
  104. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +2 -2
  105. package/src/runtime/channels/lib/config.mjs +34 -34
  106. package/src/runtime/channels/lib/inbound-handler.mjs +8 -8
  107. package/src/runtime/channels/lib/interaction-handlers.mjs +6 -6
  108. package/src/runtime/channels/lib/memory-client.mjs +31 -157
  109. package/src/runtime/channels/lib/output-forwarder.mjs +16 -16
  110. package/src/runtime/channels/lib/owned-runtime.mjs +60 -60
  111. package/src/runtime/channels/lib/owner-heartbeat.mjs +1 -1
  112. package/src/runtime/channels/lib/{backend-dispatch.mjs → provider-dispatch.mjs} +6 -6
  113. package/src/runtime/channels/lib/runtime-paths.mjs +4 -30
  114. package/src/runtime/channels/lib/scheduler.mjs +2 -2
  115. package/src/runtime/channels/lib/status-snapshot.mjs +3 -3
  116. package/src/runtime/channels/lib/tool-dispatch.mjs +4 -4
  117. package/src/runtime/channels/lib/worker-bootstrap.mjs +1 -1
  118. package/src/runtime/channels/lib/worker-ipc.mjs +7 -7
  119. package/src/runtime/channels/lib/worker-main.mjs +38 -38
  120. package/src/runtime/channels/{backends → providers}/discord-access.mjs +1 -1
  121. package/src/runtime/channels/{backends → providers}/discord-gateway.mjs +1 -1
  122. package/src/runtime/channels/{backends → providers}/discord.mjs +3 -3
  123. package/src/runtime/channels/{backends → providers}/telegram.mjs +12 -12
  124. package/src/runtime/channels/tool-defs.mjs +1 -1
  125. package/src/runtime/memory/index.mjs +76 -248
  126. package/src/runtime/memory/lib/agent-ipc.mjs +146 -81
  127. package/src/runtime/memory/lib/compact-vector-cache.mjs +88 -0
  128. package/src/runtime/memory/lib/core-memory-store.mjs +18 -1
  129. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +13 -34
  130. package/src/runtime/memory/lib/embedding-provider.mjs +47 -26
  131. package/src/runtime/memory/lib/embedding-worker.mjs +30 -34
  132. package/src/runtime/memory/lib/http-router.mjs +9 -6
  133. package/src/runtime/memory/lib/ko-morph.mjs +3 -20
  134. package/src/runtime/memory/lib/memory-action-handlers.mjs +2 -1
  135. package/src/runtime/memory/lib/memory-config-flags.mjs +1 -1
  136. package/src/runtime/memory/lib/memory-cycle1.mjs +1 -0
  137. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +4 -2
  138. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +1 -0
  139. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +4 -1
  140. package/src/runtime/memory/lib/memory-cycle3.mjs +3 -1
  141. package/src/runtime/memory/lib/memory-daemon-lifecycle.mjs +5 -0
  142. package/src/runtime/memory/lib/memory-log.mjs +1 -1
  143. package/src/runtime/memory/lib/memory-process-lock.mjs +5 -60
  144. package/src/runtime/memory/lib/memory.mjs +1 -1
  145. package/src/runtime/memory/lib/pg/process.mjs +32 -9
  146. package/src/runtime/memory/lib/session-ingest.mjs +1 -1
  147. package/src/runtime/memory/tool-defs.mjs +1 -5
  148. package/src/runtime/search/index.mjs +2 -2
  149. package/src/runtime/search/tool-defs.mjs +2 -2
  150. package/src/runtime/shared/abort-race.mjs +70 -0
  151. package/src/runtime/shared/agent-route-config.mjs +119 -0
  152. package/src/runtime/shared/atomic-file.mjs +80 -4
  153. package/src/runtime/shared/channel-notification-routing.mjs +2 -2
  154. package/src/runtime/shared/child-guardian.mjs +204 -108
  155. package/src/runtime/shared/child-spawn-gate.mjs +139 -72
  156. package/src/runtime/shared/config.mjs +120 -47
  157. package/src/runtime/shared/llm/index.mjs +1 -1
  158. package/src/runtime/shared/owner-fair-gate.mjs +134 -0
  159. package/src/runtime/shared/resource-admission.mjs +150 -100
  160. package/src/runtime/shared/stream-progress.mjs +6 -0
  161. package/src/runtime/shared/tool-execution-owner.mjs +12 -0
  162. package/src/runtime/shared/tool-result-summary.mjs +1 -1
  163. package/src/runtime/shared/tool-surface.mjs +91 -27
  164. package/src/runtime/shared/tool-workload-gates.mjs +29 -0
  165. package/src/runtime/shared/turn-snapshot.mjs +47 -6
  166. package/src/runtime/shared/turn-worktree-snapshot.mjs +14 -2
  167. package/src/session-runtime/channel-config-api.mjs +5 -5
  168. package/src/session-runtime/config-helpers.mjs +39 -37
  169. package/src/session-runtime/config-lifecycle.mjs +27 -27
  170. package/src/session-runtime/lifecycle-api.mjs +22 -3
  171. package/src/session-runtime/memory-runtime-prewarm.mjs +15 -0
  172. package/src/session-runtime/model-route-api.mjs +7 -5
  173. package/src/session-runtime/prewarm.mjs +1 -1
  174. package/src/session-runtime/provider-auth-api.mjs +0 -7
  175. package/src/session-runtime/provider-models.mjs +1 -1
  176. package/src/session-runtime/remote-control.mjs +6 -7
  177. package/src/session-runtime/runtime-core.mjs +63 -39
  178. package/src/session-runtime/runtime-tunables.mjs +4 -4
  179. package/src/session-runtime/self-update.mjs +1 -1
  180. package/src/session-runtime/session-lifecycle.mjs +45 -17
  181. package/src/session-runtime/session-title.mjs +1 -1
  182. package/src/session-runtime/session-turn-api.mjs +96 -24
  183. package/src/session-runtime/settings-api.mjs +12 -24
  184. package/src/session-runtime/tool-defs.mjs +3 -3
  185. package/src/session-runtime/workflow-agents-api.mjs +55 -81
  186. package/src/session-runtime/workflow.mjs +14 -24
  187. package/src/standalone/agent-dispatch-broker.mjs +198 -0
  188. package/src/standalone/agent-tool/helpers.mjs +2 -2
  189. package/src/standalone/agent-tool/spawn-flow.mjs +2 -0
  190. package/src/standalone/agent-tool/spawn-preset.mjs +11 -21
  191. package/src/standalone/agent-tool/tool-def.mjs +0 -14
  192. package/src/standalone/channel-admin.mjs +53 -64
  193. package/src/standalone/{channel-daemon-client.mjs → channel-client.mjs} +33 -19
  194. package/src/standalone/{channel-daemon-transport.mjs → channel-transport.mjs} +127 -46
  195. package/src/standalone/channel-worker.mjs +124 -647
  196. package/src/standalone/{backend-daemon.mjs → daemon.mjs} +270 -154
  197. package/src/standalone/explore-tool.mjs +187 -70
  198. package/src/standalone/fair-call-scheduler.mjs +264 -0
  199. package/src/standalone/memory-runtime-proxy.mjs +58 -1
  200. package/src/standalone/session-client.mjs +1134 -0
  201. package/src/standalone/session-protocol.mjs +192 -0
  202. package/src/standalone/session-runtime-pool.mjs +393 -0
  203. package/src/standalone/session-runtime-record.mjs +20 -0
  204. package/src/standalone/session-runtime-worker.mjs +203 -0
  205. package/src/standalone/{engine-daemon-service.mjs → session-service.mjs} +481 -224
  206. package/src/standalone/{engine-daemon-transport.mjs → session-transport.mjs} +390 -121
  207. package/src/standalone/session-wire.mjs +55 -0
  208. package/src/tui/App.jsx +34 -21
  209. package/src/tui/app/app-format.mjs +1 -1
  210. package/src/tui/app/app-view.jsx +5 -2
  211. package/src/tui/app/channel-pickers.mjs +41 -41
  212. package/src/tui/app/core-memory-picker.mjs +19 -19
  213. package/src/tui/app/doctor.mjs +5 -11
  214. package/src/tui/app/input-parsers.mjs +2 -2
  215. package/src/tui/app/message-selector.mjs +103 -0
  216. package/src/tui/app/onboarding-steps.mjs +3 -4
  217. package/src/tui/app/project-picker.mjs +80 -56
  218. package/src/tui/app/prompt-submit.mjs +48 -43
  219. package/src/tui/app/resume-picker.mjs +2 -2
  220. package/src/tui/app/route-pickers.mjs +3 -1
  221. package/src/tui/app/settings-picker.mjs +31 -33
  222. package/src/tui/app/transcript-window.mjs +38 -0
  223. package/src/tui/app/use-prompt-draft-flow.mjs +5 -7
  224. package/src/tui/app/use-prompt-handlers.mjs +86 -21
  225. package/src/tui/app/use-prompt-hint.mjs +3 -2
  226. package/src/tui/app/use-prompt-queue-history.mjs +10 -3
  227. package/src/tui/app/use-transcript-scroll.mjs +10 -3
  228. package/src/tui/app/use-transcript-window.mjs +50 -17
  229. package/src/tui/components/PromptInput.jsx +71 -38
  230. package/src/tui/components/Spinner.jsx +1 -1
  231. package/src/tui/components/ToolExecution.jsx +1 -1
  232. package/src/tui/components/prompt-input/edit-helpers.mjs +9 -11
  233. package/src/tui/components/prompt-input/escape-policy.mjs +42 -0
  234. package/src/tui/components/prompt-input/immediate-render.mjs +0 -10
  235. package/src/tui/components/prompt-input/interrupt-policy.mjs +10 -0
  236. package/src/tui/components/prompt-input/restore-policy.mjs +10 -0
  237. package/src/tui/components/tool-execution/surface-detail.mjs +1 -1
  238. package/src/tui/dist/index.mjs +1031 -1676
  239. package/src/tui/hooks/useSession.mjs +16 -0
  240. package/src/tui/index.jsx +12 -13
  241. package/src/tui/{engine → session}/agent-envelope.mjs +3 -3
  242. package/src/tui/{engine → session}/agent-job-feed.mjs +4 -4
  243. package/src/tui/{engine → session}/boot-profile.mjs +2 -2
  244. package/src/tui/{engine → session}/context-state.mjs +3 -3
  245. package/src/tui/{engine → session}/labels.mjs +2 -2
  246. package/src/tui/{engine → session}/live-share.mjs +38 -4
  247. package/src/tui/{engine → session}/notice-text.mjs +2 -2
  248. package/src/tui/{engine → session}/notification-plan.mjs +3 -3
  249. package/src/tui/session/oauth-flows.mjs +140 -0
  250. package/src/tui/{engine → session}/prompt-history.mjs +3 -3
  251. package/src/tui/{engine → session}/queue-helpers.mjs +2 -2
  252. package/src/tui/{engine → session}/render-timing.mjs +2 -2
  253. package/src/tui/{engine → session}/session-api-ext.mjs +30 -20
  254. package/src/tui/{engine → session}/session-api.mjs +110 -93
  255. package/src/tui/{engine → session}/session-flow.mjs +8 -2
  256. package/src/tui/{engine → session}/session-stats.mjs +3 -3
  257. package/src/tui/{engine → session}/tool-approval.mjs +3 -3
  258. package/src/tui/{engine → session}/tool-call-fields.mjs +2 -2
  259. package/src/tui/{engine → session}/tool-card-results.mjs +8 -6
  260. package/src/tui/{engine → session}/tool-result-status.mjs +5 -5
  261. package/src/tui/{engine → session}/tool-result-text.mjs +13 -3
  262. package/src/tui/{engine → session}/transcript-spill.mjs +34 -34
  263. package/src/tui/{engine → session}/turn.mjs +38 -176
  264. package/src/tui/{engine-local-session.mjs → session-local.mjs} +103 -103
  265. package/src/tui/session.mjs +22 -0
  266. package/src/tui/spinner-meta.mjs +4 -4
  267. package/src/tui/spinner-verbs.mjs +51 -3
  268. package/src/ui/statusline-segments.mjs +1 -1
  269. package/src/ui/statusline.mjs +1 -1
  270. package/vendor/ink/build/components/App.js +10 -1
  271. package/src/session-runtime/memory-daemon-probe.mjs +0 -61
  272. package/src/standalone/engine-daemon-client.mjs +0 -894
  273. package/src/standalone/engine-daemon-local-bridge.mjs +0 -20
  274. package/src/standalone/engine-daemon-protocol.mjs +0 -33
  275. package/src/tui/engine/turn-watchdog.mjs +0 -92
  276. package/src/tui/engine.mjs +0 -22
  277. package/src/tui/hooks/useEngine.mjs +0 -16
  278. /package/src/runtime/agent/orchestrator/session/compact/{engine.mjs → runner.mjs} +0 -0
  279. /package/src/runtime/channels/{backends → providers}/discord-attachments.mjs +0 -0
  280. /package/src/tui/{engine → session}/agent-response-tail.mjs +0 -0
  281. /package/src/tui/{engine → session}/frame-batched-store.mjs +0 -0
  282. /package/src/tui/{engine → session}/tui-steering-persist.mjs +0 -0
@@ -1,13 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import { __mixdogMemoryLog } from './lib/memory-log.mjs';
3
3
 
4
- process.removeAllListeners('warning')
5
- process.on('warning', () => {})
6
-
7
- // V8 compile cache: the memory runtime is its own long-lived child process
8
- // (spawned by the channel daemon / standalone proxy) and never passes through
9
- // cli.mjs, so it pays full ESM parse cost on every boot without this. Same
10
- // best-effort guard as cli.mjs.
4
+ // V8 compile cache: the memory runtime is a separate long-lived child in
5
+ // product mode. The standalone MCP entry uses the same module directly.
11
6
  try {
12
7
  const { enableCompileCache } = await import('node:module')
13
8
  enableCompileCache?.()
@@ -26,12 +21,6 @@ import { readPluginVersion, readPromotionCodeFingerprint } from './lib/promotion
26
21
  const PLUGIN_VERSION = readPluginVersion(PLUGIN_ROOT)
27
22
  const BOOT_PROMOTION_CODE_FINGERPRINT = readPromotionCodeFingerprint(PLUGIN_ROOT)
28
23
 
29
- try { os.setPriority(os.constants.priority.PRIORITY_BELOW_NORMAL) } catch {}
30
- try {
31
- const { env } = await import('@huggingface/transformers')
32
- env.backends.onnx.wasm.numThreads = 1
33
- } catch {}
34
-
35
24
  import { Server } from '@modelcontextprotocol/sdk/server/index.js'
36
25
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
37
26
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
@@ -67,9 +56,7 @@ import {
67
56
  import { configureEmbedding, embedText, embedTexts, getEmbeddingDims, getEmbeddingDtype, getEmbeddingModelId, getKnownDimsForCurrentModel, isEmbeddingModelReady, primeEmbeddingDims, shutdownEmbeddingProvider, warmupEmbeddingProvider } from './lib/embedding-provider.mjs'
68
57
  import { startLlmWorker, stopLlmWorker } from './lib/llm-worker-host.mjs'
69
58
  import { runCycle1, runCycle2, runCycle3, runUnifiedGate, parseInterval, syncRootEmbedding, flushRawEmbeddings, applySimpleStatus, applyUpdate, applyMerge, CYCLE2_ACTIVE_TARGET_CAP } from './lib/memory-cycle.mjs'
70
- import { loadConfig as loadAgentConfig } from '../agent/orchestrator/config.mjs'
71
- import { initProviders } from '../agent/orchestrator/providers/registry.mjs'
72
- import { makeAgentDispatch } from '../agent/orchestrator/agent-runtime/agent-dispatch.mjs'
59
+ import { callAgentDispatch } from './lib/agent-ipc.mjs'
73
60
  import { getInFlightCycle1 } from './lib/memory-cycle1.mjs'
74
61
  import { claimAndMarkScheduledCycle, markCycleRequest, resolveCoalesceMaxRetries, scheduleCoalescedCycleRetry } from './lib/memory-cycle-requests.mjs'
75
62
  import { searchRelevantHybrid } from './lib/memory-recall-store.mjs'
@@ -110,8 +97,14 @@ import {
110
97
  assertSecondaryPgAttachable as _assertSecondaryPgAttachable,
111
98
  } from './lib/memory-config-flags.mjs'
112
99
  const IS_MEMORY_ENTRY = !!process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href
113
- const USE_ARG_DATA_DIR = IS_MEMORY_ENTRY || process.env.MIXDOG_WORKER_MODE === '1'
100
+ if (IS_MEMORY_ENTRY) {
101
+ process.removeAllListeners('warning')
102
+ process.on('warning', () => {})
103
+ try { os.setPriority(os.constants.priority.PRIORITY_BELOW_NORMAL) } catch {}
104
+ }
105
+ const USE_ARG_DATA_DIR = IS_MEMORY_ENTRY
114
106
  const DATA_DIR = process.env.MIXDOG_DATA_DIR || (USE_ARG_DATA_DIR ? process.argv[2] : '') || resolvePluginData()
107
+ const INTEGRATED_DAEMON_HOST = process.env.MIXDOG_DAEMON_HOST === '1' && !IS_MEMORY_ENTRY
115
108
  if (!DATA_DIR) {
116
109
  __mixdogMemoryLog('[memory-service] memory data dir not set and no explicit data dir provided\n')
117
110
  process.exit(1)
@@ -132,9 +125,6 @@ function memoryProfile(event, fields = {}) {
132
125
  import {
133
126
  parsePositivePid,
134
127
  isPidAliveLocal,
135
- tryAcquireMemoryOwnerLock as _tryAcquireMemoryOwnerLock,
136
- releaseMemoryOwnerLock as _releaseMemoryOwnerLock,
137
- killPreviousServer as _killPreviousServer,
138
128
  acquireLock as _acquireLock,
139
129
  releaseLock as _releaseLock,
140
130
  } from './lib/memory-process-lock.mjs'
@@ -175,19 +165,6 @@ const _daemonLifecycle = createMemoryDaemonLifecycle({
175
165
  const { touchDaemonIdleTimer, registerClient, deregisterClient } = _daemonLifecycle
176
166
 
177
167
  const LOCK_FILE = path.join(DATA_DIR, '.memory-service.lock')
178
- // Owner-election lock. Separate from LOCK_FILE so single-instance mode keeps
179
- // its kill-the-previous protocol while multi-instance fork-proxy workers use
180
- // atomic CAS for takeover. Created via fs.openSync(path,'wx') — node guarantees
181
- // EEXIST when another process won the race.
182
- const OWNER_LOCK_FILE = path.join(DATA_DIR, '.memory-owner.lock')
183
-
184
- function tryAcquireMemoryOwnerLock() {
185
- return _tryAcquireMemoryOwnerLock(OWNER_LOCK_FILE, __mixdogMemoryLog)
186
- }
187
-
188
- function releaseMemoryOwnerLock() {
189
- return _releaseMemoryOwnerLock(OWNER_LOCK_FILE)
190
- }
191
168
 
192
169
  const BASE_PORT = 3350
193
170
  const MAX_PORT = 3357
@@ -196,10 +173,6 @@ let _traceDb = null
196
173
 
197
174
  const MEMORY_INSTRUCTIONS_TEXT = ''
198
175
 
199
- function killPreviousServer(pid) {
200
- return _killPreviousServer(pid, __mixdogMemoryLog)
201
- }
202
-
203
176
  function acquireLock() {
204
177
  return _acquireLock(LOCK_FILE, __mixdogMemoryLog)
205
178
  }
@@ -358,36 +331,9 @@ async function _initStore() {
358
331
  } else {
359
332
  __mixdogMemoryLog('[memory-service] secondary mode; skipping llm worker\n')
360
333
  }
361
- // Initialize the in-process provider registry so cycle1 can run the agent dispatch
362
- // LLM locally (makeAgentDispatch → session manager → provider.send). In
363
- // standalone the memory worker runs as a detached HTTP daemon whose parent
364
- // has disconnected IPC, so the legacy callAgentDispatch() IPC path is dead on
365
- // arrival. Mirror the channels worker boot (channels/index.mjs:
366
- // loadAgentConfig() + initProviders) so the registry is populated before any
367
- // cycle1 dispatch. The gate MUST match _startCycle1Run's makeAgentDispatch
368
- // injection condition: cycle1 may dispatch in-process whenever cycles are
369
- // enabled OR the llm worker is enabled (both exclude secondary mode), so
370
- // registering only under the llm-worker gate would leave a hole where
371
- // MIXDOG_MEMORY_DISABLE_LLM_WORKER=1 + cycles enabled hits an empty registry
372
- // and fails with "Provider not found". Non-fatal: a failure here is logged
373
- // and cycle1's own callLlm surfaces the unresolved-provider error per call.
374
- // Registry must be available whenever cycles COULD run in this process, not
375
- // just when they are currently enabled: recap can be toggled on at runtime
376
- // (memoryCyclesEnabled() now includes the recap flag), so gate registry init
377
- // on the cycle-capable conditions (not secondary, env not hard-disabled) OR
378
- // the llm worker gate — never on the runtime recap flag itself, or enabling
379
- // recap later would hit an empty registry and fail with "Provider not found".
380
- const cyclesCapable = !memorySecondaryMode() && !envFlagEnabled('MIXDOG_MEMORY_DISABLE_CYCLES')
381
- if (cyclesCapable || memoryLlmWorkerEnabled()) {
382
- try {
383
- const agentCfg = loadAgentConfig()
384
- const providersStartedAt = performance.now()
385
- await initProviders(agentCfg.providers || {})
386
- memoryProfile('providers:init:done', { ms: (performance.now() - providersStartedAt).toFixed(1) })
387
- } catch (e) {
388
- process.stderr.write(`[memory-service] initProviders failed (non-fatal): ${e instanceof Error ? e.message : String(e)}\n`)
389
- }
390
- }
334
+ // Provider/session/agent modules live once in the daemon. Memory
335
+ // cycles cross the authenticated loopback broker instead of initializing a
336
+ // second registry in this process.
391
337
  _bootTimestamp = Date.now()
392
338
  const offsetsStartedAt = performance.now()
393
339
  await loadTranscriptOffsets()
@@ -437,7 +383,7 @@ async function setCycleLastRun(kind, ts) {
437
383
  // getters (getDb/getConfig/setConfig) plus runners and LLM adapters.
438
384
  const CYCLE_STATE_FILE = path.join(DATA_DIR, 'memory-cycle-state.json')
439
385
 
440
- const _cycleLlmAdapters = createCycleLlmAdapters({ makeAgentDispatch })
386
+ const _cycleLlmAdapters = createCycleLlmAdapters({ callAgentDispatch })
441
387
  const { getCycle1CallLlm, getCycle2CallLlm, getCycle3CallLlm } = _cycleLlmAdapters
442
388
 
443
389
  const _cycleScheduler = createCycleScheduler({
@@ -620,31 +566,61 @@ export { TOOL_DEFS, handleToolCall, buildSessionCoreMemoryPayload }
620
566
  export { MEMORY_INSTRUCTIONS_TEXT as instructions }
621
567
  export { acquireLock, releaseLock }
622
568
  export { cwdFromTranscriptPath }
623
- function sendMemoryWorkerMessage(message) {
624
- return safeIpcSend(process, message, {
625
- onError: (error) => {
626
- const code = error?.code ? ` code=${error.code}` : ''
627
- __mixdogMemoryLog(`[memory-worker] IPC send failed${code}: ${error?.message || error}\n`)
628
- },
569
+
570
+ /** In-process write surface used by the unified channel/session daemon. */
571
+ export async function appendEntry(data = {}) {
572
+ await init()
573
+ const role = String(data.role ?? 'user')
574
+ const content = String(data.content ?? '')
575
+ const cleaned = cleanMemoryText(content)
576
+ if (!cleaned || !cleaned.trim()) return { error: content ? 'empty after clean' : 'content required' }
577
+ const sourceRef = String(data.sourceRef ?? `manual:${Date.now()}-${process.pid}`)
578
+ const sessionId = data.sessionId ?? null
579
+ const tsMs = parseTsToMs(data.ts ?? Date.now())
580
+ const projectId = resolveProjectScope(typeof data.cwd === 'string' && data.cwd ? data.cwd : null)
581
+ const result = await db.query(`
582
+ INSERT INTO entries(ts, role, content, source_ref, session_id, project_id)
583
+ VALUES ($1, $2, $3, $4, $5, $6)
584
+ ON CONFLICT DO NOTHING
585
+ RETURNING id
586
+ `, [tsMs, role, cleaned, sourceRef, sessionId, projectId])
587
+ const insertedId = result.rows[0]?.id ?? null
588
+ return {
589
+ ok: true,
590
+ id: insertedId !== null ? Number(insertedId) : null,
591
+ changes: Number(result.rowCount ?? result.affectedRows ?? 0),
592
+ }
593
+ }
594
+
595
+ /** In-process transcript ingest surface used by the unified daemon. */
596
+ export async function ingestTranscript(filePath, { cwd } = {}) {
597
+ await init()
598
+ if (!filePath) return { error: 'filePath required' }
599
+ const ingested = await ingestTranscriptFile(filePath, { cwd })
600
+ return { ok: true, ingested }
601
+ }
602
+
603
+ /** Direct trace sink for agent orchestration running in this daemon process. */
604
+ export async function recordTraceEvents(events = []) {
605
+ await init()
606
+ if (!Array.isArray(events)) throw new TypeError('events must be an array')
607
+ if (events.length > 500) throw new RangeError('too many events (max 500)')
608
+ if (!_traceDb) {
609
+ _traceDb = await openTraceDatabase(DATA_DIR)
610
+ registerTraceExitDrain(_traceDb)
611
+ }
612
+ enqueueTraceEvents(_traceDb, events)
613
+ void insertAgentCalls(_traceDb, events).catch((error) => {
614
+ __mixdogMemoryLog(`[trace] insertAgentCalls error: ${error?.message}\n`)
629
615
  })
616
+ return { ok: true, queued: events.length }
630
617
  }
631
618
  export async function init() {
632
619
  if (_initialized) return
633
620
  __mixdogMemoryLog(`[boot-time] tag=memory-init-start tMs=${Date.now()}\n`)
634
- if (process.env.MIXDOG_WORKER_MODE === '1' && process.send) {
635
- // Single-worker daemon: acquire the owner lock (which reclaims a crashed
636
- // predecessor's stale, dead-PID lock). If a LIVE peer still holds it — an
637
- // anomaly, since server-main forks exactly one memory worker — exit so
638
- // server-main respawns us instead of running a second owner.
639
- if (!tryAcquireMemoryOwnerLock()) {
640
- __mixdogMemoryLog('[memory-service] live peer holds owner lock — exiting for respawn\n')
641
- process.exit(0)
642
- }
643
- process.on('exit', releaseMemoryOwnerLock)
644
- }
645
621
  const runtimeReady = _beginRuntimeInit()
646
622
  let boundPort = null
647
- if (!memorySecondaryMode()) {
623
+ if (!memorySecondaryMode() && !INTEGRATED_DAEMON_HOST) {
648
624
  boundPort = await _startHttpServer()
649
625
  advertiseMemoryPort(boundPort)
650
626
  try {
@@ -663,11 +639,10 @@ export async function init() {
663
639
  } else {
664
640
  await runtimeReady
665
641
  }
642
+ __mixdogMemoryLog(`[memory-service] init() complete (entries unified mode, version=${PLUGIN_VERSION})\n`)
666
643
  if (process.env.MIXDOG_WORKER_MODE === '1' && process.send) {
667
- __mixdogMemoryLog(`[boot-time] tag=memory-ready tMs=${Date.now()}\n`)
668
- sendMemoryWorkerMessage({ type: 'ready', port: boundPort })
644
+ safeIpcSend(process, { type: 'ready', port: boundPort })
669
645
  }
670
- __mixdogMemoryLog(`[memory-service] init() complete (entries unified mode, version=${PLUGIN_VERSION})\n`)
671
646
  touchDaemonIdleTimer('init')
672
647
  }
673
648
 
@@ -702,49 +677,11 @@ export async function stop() {
702
677
  await closeDatabase(DATA_DIR)
703
678
  // Stop the PG postmaster after the connection pools have been drained.
704
679
  // closeDatabase() only ends the client pool; without this the child
705
- // postmaster keeps running after the memory service exits.
680
+ // postmaster keeps running after the unified daemon exits.
706
681
  if (!memorySecondaryMode()) {
707
682
  try {
708
- // Conservative check: only skip stopPgForShutdown when the owner
709
- // record is unambiguously (a) a memory-runtime-daemon owner record
710
- // (kind check — guards against a stale/foreign pid reusing this pid
711
- // number for an unrelated process) and (b) that pid is alive AND not
712
- // this process. Any read/parse failure or ambiguous state falls back
713
- // to stopping PG (previous unconditional behavior) rather than
714
- // risking an orphaned PG postmaster.
715
- const anotherOwnerAlive = await (async () => {
716
- try {
717
- const { readSingletonOwner } = await import('../shared/singleton-owner.mjs')
718
- const ownerPath = path.join(DATA_DIR, 'memory-runtime-owner.json')
719
- const { owner, alive } = readSingletonOwner(ownerPath)
720
- if (!alive) return false
721
- if (owner?.kind !== 'memory-runtime-daemon') return false
722
- const ownerPid = Number(owner?.pid)
723
- if (!Number.isInteger(ownerPid) || ownerPid === process.pid) return false
724
- // Best-effort process-name check (mirrors supervisor.mjs's
725
- // isPostgresPid pattern) — confirms the pid is actually a node
726
- // process before trusting it as a live sibling memory owner.
727
- // Falls back to true (trust the owner file) when the platform
728
- // check is unavailable or inconclusive.
729
- try {
730
- if (process.platform === 'win32') {
731
- const { execFileSync } = await import('node:child_process')
732
- const out = execFileSync('tasklist', ['/FI', `PID eq ${ownerPid}`, '/FO', 'CSV', '/NH'], { encoding: 'utf8', windowsHide: true })
733
- if (!String(out || '').toLowerCase().includes('node')) return false
734
- } else if (process.platform === 'linux') {
735
- const comm = fs.readFileSync(`/proc/${ownerPid}/comm`, 'utf8').trim()
736
- if (!comm.includes('node')) return false
737
- }
738
- } catch { /* inconclusive — trust the owner file (already alive+kind-matched) */ }
739
- return true
740
- } catch { return false }
741
- })()
742
- if (anotherOwnerAlive) {
743
- __mixdogMemoryLog('[memory-service] shutdown: another live memory owner holds memory-runtime-owner.json — leaving PG running\n')
744
- } else {
745
- const { stopPgForShutdown } = await import('./lib/pg/supervisor.mjs')
746
- await stopPgForShutdown()
747
- }
683
+ const { stopPgForShutdown } = await import('./lib/pg/supervisor.mjs')
684
+ await stopPgForShutdown()
748
685
  } catch {}
749
686
  } else {
750
687
  __mixdogMemoryLog('[memory-service] secondary mode; leaving shared PG running\n')
@@ -811,120 +748,9 @@ function _startHttpServer() {
811
748
  return _httpReadyPromise
812
749
  }
813
750
 
814
- if (process.env.MIXDOG_WORKER_MODE === '1' && process.send) {
815
- // SIGTERM/SIGINT handler for worker mode: call stop() (fsyncs,
816
- // removes port file) then exit(0). Prevents taskkill /F from bypassing
817
- // graceful shutdown and leaving pgdata in an inconsistent checkpoint state.
818
- let _stopInFlight = false
819
- let _syncPgStopRequested = false
820
- const _workerSignalHandler = (sig) => {
821
- if (_stopInFlight) {
822
- __mixdogMemoryLog(`[memory-worker] ${sig} — stop already in flight, ignoring\n`)
823
- return
824
- }
825
- _stopInFlight = true
826
- _syncPgStopRequested = true
827
- __mixdogMemoryLog(`[memory-worker] received ${sig} — calling stop() for clean shutdown\n`)
828
- const _exitTimer = setTimeout(() => {
829
- __mixdogMemoryLog(`[memory-worker] stop() timed out after 6000ms — forcing exit(2)\n`)
830
- process.exit(2)
831
- }, 6000)
832
- stop().then(() => {
833
- clearTimeout(_exitTimer)
834
- __mixdogMemoryLog(`[memory-worker] stop() complete — exiting cleanly\n`)
835
- process.exit(0)
836
- }).catch((e) => {
837
- clearTimeout(_exitTimer)
838
- __mixdogMemoryLog(`[memory-worker] stop() error on ${sig}: ${e && (e.message || e)}\n`)
839
- process.exit(1)
840
- })
841
- }
842
- process.on('SIGTERM', () => _workerSignalHandler('SIGTERM'))
843
- process.on('SIGINT', () => _workerSignalHandler('SIGINT'))
844
-
845
- // Windows-safe last resort: SIGTERM may TerminateProcess before the async
846
- // stop() path runs, orphaning PG mid-write. Best-effort sync pg_ctl stop on
847
- // exit (no-op after a completed graceful stop). Skip in secondary mode — we
848
- // do not own the shared PG there.
849
- if (!memorySecondaryMode()) process.on('exit', () => {
850
- // Do not stop shared PG on an unexpected Memory crash. The singleton proxy
851
- // will respawn a daemon that can attach to the still-healthy cluster. The
852
- // sync stop is only a last resort after an explicit shutdown signal began.
853
- if (_syncPgStopRequested) {
854
- try { stopPgForShutdownSync() } catch {}
855
- }
856
- })
857
-
858
- // callId → AbortController for in-flight IPC calls (cancel handler uses this).
859
- const _inFlightCalls = new Map()
860
-
861
- process.on('message', async (msg) => {
862
- // Handle parent-initiated graceful shutdown IPC message.
863
- if (msg.type === 'shutdown') {
864
- __mixdogMemoryLog('[memory-worker] received IPC shutdown — calling stop()\n')
865
- _workerSignalHandler('IPC:shutdown')
866
- return
867
- }
868
- if (msg.type === 'cancel' && msg.callId) {
869
- const entry = _inFlightCalls.get(msg.callId)
870
- if (entry) {
871
- // Mark cancelled so the in-flight call's result/error branch below
872
- // does not double-respond after the AbortController fires.
873
- entry.cancelled = true
874
- entry.ac.abort()
875
- _inFlightCalls.delete(msg.callId)
876
- sendMemoryWorkerMessage({ type: 'result', callId: msg.callId, error: 'cancelled' })
877
- }
878
- return
879
- }
880
- if (msg.type !== 'call' || !msg.callId) return
881
- const entry = { ac: new AbortController(), cancelled: false }
882
- _inFlightCalls.set(msg.callId, entry)
883
- try {
884
- let result
885
- try {
886
- result = await handleToolCall(msg.name, msg.args || {}, entry.ac.signal)
887
- } finally {
888
- _inFlightCalls.delete(msg.callId)
889
- }
890
- if (!entry.cancelled) sendMemoryWorkerMessage({ type: 'result', callId: msg.callId, result })
891
- } catch (e) {
892
- if (!entry.cancelled) sendMemoryWorkerMessage({ type: 'result', callId: msg.callId, error: e.message })
893
- }
894
- })
895
- init().catch(e => {
896
- let detail
897
- try {
898
- const parts = []
899
- if (e?.name) parts.push(`name=${e.name}`)
900
- if (e?.code) parts.push(`code=${e.code}`)
901
- if (e?.errno) parts.push(`errno=${e.errno}`)
902
- if (e?.syscall) parts.push(`syscall=${e.syscall}`)
903
- if (e?.path) parts.push(`path=${e.path}`)
904
- if (e?.message) parts.push(`message=${e.message}`)
905
- let stringified = null
906
- try { stringified = JSON.stringify(e, Object.getOwnPropertyNames(e || {})) } catch {}
907
- if (stringified && stringified !== '{}' && stringified !== '"{}"') parts.push(`json=${stringified}`)
908
- if (e?.stack) parts.push(`\nstack=\n${e.stack}`)
909
- if (parts.length === 0) parts.push(`raw=${typeof e}:${String(e)}`)
910
- detail = parts.join(' | ')
911
- } catch (logErr) {
912
- detail = `(error formatting failed: ${logErr?.message}) raw=${String(e)}`
913
- }
914
- __mixdogMemoryLog(`[memory-worker] init failed: ${detail}\n`)
915
- // Signal degraded state to parent before exiting so it records the failure
916
- // rather than treating this as a normal pre-ready crash.
917
- sendMemoryWorkerMessage({ type: 'ready', degraded: true, error: detail.slice(0, 800) })
918
- process.exit(1)
919
- })
920
- }
921
-
922
- // Standalone MCP launcher path. When this module is the entry script AND no
923
- // MIXDOG_WORKER_MODE flag is set, we own stdio and bring up the full MCP
924
- // server with acquireLock + StdioServerTransport. Server-main spawnWorker
925
- // also forks this file with MIXDOG_WORKER_MODE='1'; that path uses the IPC
926
- // handler block above and acquireLock/init() as the single memory owner.
927
- if (IS_MEMORY_ENTRY && process.env.MIXDOG_WORKER_MODE !== '1') {
751
+ // Standalone MCP launcher path. Product mode imports this module into the
752
+ // unified daemon; running the module directly owns stdio for MCP clients.
753
+ if (IS_MEMORY_ENTRY) {
928
754
  ;(async () => {
929
755
  acquireLock()
930
756
  process.on('exit', releaseLock)
@@ -941,10 +767,12 @@ if (IS_MEMORY_ENTRY && process.env.MIXDOG_WORKER_MODE !== '1') {
941
767
  process.on('SIGINT', stopFromSignal)
942
768
  process.on('SIGTERM', stopFromSignal)
943
769
  await init()
944
- const transport = new StdioServerTransport()
945
- await mcp.connect(transport)
946
- await new Promise((resolve) => { mcp.onclose = resolve })
947
- await stop()
770
+ if (!(process.env.MIXDOG_WORKER_MODE === '1' && process.send)) {
771
+ const transport = new StdioServerTransport()
772
+ await mcp.connect(transport)
773
+ await new Promise((resolve) => { mcp.onclose = resolve })
774
+ await stop()
775
+ }
948
776
  })().catch((err) => {
949
777
  __mixdogMemoryLog(`[memory-service] startup failed: ${err.stack || err.message}\n`)
950
778
  process.exit(1)