mixdog 0.7.18 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (844) hide show
  1. package/README.md +37 -331
  2. package/package.json +67 -99
  3. package/scripts/boot-smoke.mjs +94 -0
  4. package/scripts/build-tui.mjs +52 -0
  5. package/scripts/compact-smoke.mjs +199 -0
  6. package/scripts/lead-workflow-smoke.mjs +598 -0
  7. package/scripts/live-worker-smoke.mjs +239 -0
  8. package/scripts/output-style-smoke.mjs +101 -0
  9. package/scripts/smoke-loop-report.mjs +221 -0
  10. package/scripts/smoke-loop.mjs +201 -0
  11. package/scripts/smoke.mjs +113 -0
  12. package/scripts/tool-failures.mjs +143 -0
  13. package/scripts/tool-smoke.mjs +456 -0
  14. package/src/agents/debugger/AGENT.md +3 -0
  15. package/src/agents/debugger/agent.json +6 -0
  16. package/src/agents/explore/AGENT.md +4 -0
  17. package/src/agents/explore/agent.json +6 -0
  18. package/src/agents/heavy-worker/AGENT.md +3 -0
  19. package/src/agents/heavy-worker/agent.json +6 -0
  20. package/src/agents/maintainer/AGENT.md +3 -0
  21. package/src/agents/maintainer/agent.json +6 -0
  22. package/src/agents/reviewer/AGENT.md +3 -0
  23. package/src/agents/reviewer/agent.json +6 -0
  24. package/src/agents/scheduler-task.md +3 -0
  25. package/src/agents/web-researcher/AGENT.md +3 -0
  26. package/src/agents/web-researcher/agent.json +6 -0
  27. package/src/agents/webhook-handler.md +3 -0
  28. package/src/agents/worker/AGENT.md +3 -0
  29. package/src/agents/worker/agent.json +6 -0
  30. package/src/app.mjs +90 -0
  31. package/src/cli.mjs +11 -0
  32. package/src/defaults/hidden-roles.json +72 -0
  33. package/src/defaults/mixdog-config.template.json +15 -0
  34. package/src/hooks/lib/permission-evaluator.cjs +488 -0
  35. package/src/hooks/lib/settings-loader.cjs +112 -0
  36. package/src/lib/keychain-cjs.cjs +332 -0
  37. package/src/lib/plugin-paths.cjs +28 -0
  38. package/src/lib/rules-builder.cjs +315 -0
  39. package/src/mixdog-session-runtime.mjs +3704 -0
  40. package/src/output-styles/default.md +38 -0
  41. package/src/output-styles/extreme-simple.md +17 -0
  42. package/src/output-styles/simple.md +17 -0
  43. package/src/repl.mjs +322 -0
  44. package/src/rules/bridge/00-common.md +5 -0
  45. package/src/rules/bridge/20-skip-protocol.md +11 -0
  46. package/src/rules/bridge/30-explorer.md +4 -0
  47. package/src/rules/bridge/40-cycle1-agent.md +28 -0
  48. package/src/rules/bridge/41-cycle2-agent.md +59 -0
  49. package/src/rules/lead/00-tool-lead.md +5 -0
  50. package/src/rules/lead/01-general.md +5 -0
  51. package/src/rules/lead/02-channels.md +3 -0
  52. package/src/rules/lead/04-workflow.md +12 -0
  53. package/src/rules/shared/00-language.md +3 -0
  54. package/src/rules/shared/01-tool.md +3 -0
  55. package/src/runtime/agent/orchestrator/bridge-trace.mjs +814 -0
  56. package/src/runtime/agent/orchestrator/cache-mtime.mjs +60 -0
  57. package/src/runtime/agent/orchestrator/config.mjs +446 -0
  58. package/src/runtime/agent/orchestrator/context/collect.mjs +796 -0
  59. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +417 -0
  60. package/src/runtime/agent/orchestrator/internal-roles.mjs +188 -0
  61. package/src/runtime/agent/orchestrator/internal-tools.mjs +88 -0
  62. package/src/runtime/agent/orchestrator/mcp/client.mjs +345 -0
  63. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2104 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +784 -0
  65. package/src/runtime/agent/orchestrator/providers/api-usage.mjs +341 -0
  66. package/src/runtime/agent/orchestrator/providers/gemini.mjs +1679 -0
  67. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +959 -0
  68. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +213 -0
  69. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +38 -0
  70. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +471 -0
  71. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +615 -0
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +808 -0
  73. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +1719 -0
  74. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2587 -0
  75. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +1953 -0
  76. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +136 -0
  77. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +317 -0
  78. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +109 -0
  79. package/src/runtime/agent/orchestrator/providers/registry.mjs +247 -0
  80. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +332 -0
  81. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +11 -0
  82. package/src/runtime/agent/orchestrator/providers/trace-utils.mjs +50 -0
  83. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
  84. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +318 -0
  85. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +367 -0
  86. package/src/runtime/agent/orchestrator/session/compact.mjs +882 -0
  87. package/src/runtime/agent/orchestrator/session/context-utils.mjs +233 -0
  88. package/src/runtime/agent/orchestrator/session/loop.mjs +2320 -0
  89. package/src/runtime/agent/orchestrator/session/manager.mjs +2960 -0
  90. package/src/runtime/agent/orchestrator/session/result-classification.mjs +65 -0
  91. package/src/runtime/agent/orchestrator/session/store.mjs +663 -0
  92. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +166 -0
  93. package/src/runtime/agent/orchestrator/smart-bridge/bridge-llm.mjs +339 -0
  94. package/src/runtime/agent/orchestrator/smart-bridge/cache-strategy.mjs +419 -0
  95. package/src/runtime/agent/orchestrator/stall-policy.mjs +227 -0
  96. package/src/runtime/agent/orchestrator/tool-loop-guard.mjs +235 -0
  97. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +723 -0
  98. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +389 -0
  99. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +637 -0
  100. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +165 -0
  101. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +104 -0
  102. package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +194 -0
  103. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +596 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin/native-edit-runner.mjs +110 -0
  105. package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +153 -0
  106. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
  107. package/src/runtime/agent/orchestrator/tools/builtin/read-open.mjs +189 -0
  108. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +731 -0
  109. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +168 -0
  110. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
  111. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +465 -0
  112. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +160 -0
  113. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +982 -0
  114. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1087 -0
  115. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +231 -0
  116. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +223 -0
  117. package/src/runtime/agent/orchestrator/tools/builtin.mjs +478 -0
  118. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
  119. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4102 -0
  120. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +323 -0
  121. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +154 -0
  122. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +26 -0
  123. package/src/runtime/agent/orchestrator/tools/patch-binary-fetcher.mjs +143 -0
  124. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +18 -0
  125. package/src/runtime/agent/orchestrator/tools/patch.mjs +2772 -0
  126. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +114 -0
  127. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +880 -0
  128. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +312 -0
  129. package/src/runtime/channels/backends/discord.mjs +781 -0
  130. package/src/runtime/channels/data/voice-runtime-manifest.json +138 -0
  131. package/src/runtime/channels/index.mjs +3309 -0
  132. package/src/runtime/channels/lib/config.mjs +285 -0
  133. package/src/runtime/channels/lib/drop-trace.mjs +71 -0
  134. package/src/runtime/channels/lib/event-pipeline.mjs +81 -0
  135. package/src/runtime/channels/lib/holidays.mjs +138 -0
  136. package/src/runtime/channels/lib/hook-pipe-server.mjs +671 -0
  137. package/src/runtime/channels/lib/output-forwarder.mjs +765 -0
  138. package/src/runtime/channels/lib/runtime-paths.mjs +497 -0
  139. package/src/runtime/channels/lib/scheduler.mjs +710 -0
  140. package/src/runtime/channels/lib/session-discovery.mjs +102 -0
  141. package/src/runtime/channels/lib/state-file.mjs +68 -0
  142. package/src/runtime/channels/lib/status-snapshot.mjs +224 -0
  143. package/src/runtime/channels/lib/tool-format.mjs +124 -0
  144. package/src/runtime/channels/lib/transcript-discovery.mjs +195 -0
  145. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +734 -0
  146. package/src/runtime/channels/lib/webhook.mjs +1288 -0
  147. package/src/runtime/channels/tool-defs.mjs +177 -0
  148. package/src/runtime/lib/keychain-cjs.cjs +289 -0
  149. package/src/runtime/memory/data/runtime-manifest.json +40 -0
  150. package/src/runtime/memory/index.mjs +3600 -0
  151. package/src/runtime/memory/lib/core-memory-store.mjs +336 -0
  152. package/src/runtime/memory/lib/embedding-provider.mjs +275 -0
  153. package/src/runtime/memory/lib/embedding-worker.mjs +331 -0
  154. package/src/runtime/memory/lib/memory-cycle-requests.mjs +276 -0
  155. package/src/runtime/memory/lib/memory-cycle1.mjs +783 -0
  156. package/src/runtime/memory/lib/memory-cycle2.mjs +1389 -0
  157. package/src/runtime/memory/lib/memory-cycle3.mjs +646 -0
  158. package/src/runtime/memory/lib/memory-embed.mjs +300 -0
  159. package/src/runtime/memory/lib/memory-ops-policy.mjs +149 -0
  160. package/src/runtime/memory/lib/memory-recall-store.mjs +644 -0
  161. package/src/runtime/memory/lib/memory.mjs +418 -0
  162. package/src/runtime/memory/lib/pg/adapter.mjs +314 -0
  163. package/src/runtime/memory/lib/pg/process.mjs +366 -0
  164. package/src/runtime/memory/lib/pg/supervisor.mjs +495 -0
  165. package/src/runtime/memory/lib/runtime-fetcher.mjs +464 -0
  166. package/src/runtime/memory/lib/trace-store.mjs +734 -0
  167. package/src/runtime/memory/tool-defs.mjs +79 -0
  168. package/src/runtime/search/index.mjs +925 -0
  169. package/src/runtime/search/lib/config.mjs +61 -0
  170. package/src/runtime/search/lib/web-tools.mjs +1278 -0
  171. package/src/runtime/search/tool-defs.mjs +64 -0
  172. package/src/runtime/shared/atomic-file.mjs +435 -0
  173. package/src/runtime/shared/background-tasks.mjs +376 -0
  174. package/src/runtime/shared/child-guardian.mjs +98 -0
  175. package/src/runtime/shared/config.mjs +393 -0
  176. package/src/runtime/shared/err-text.mjs +121 -0
  177. package/src/runtime/shared/launcher-control.mjs +259 -0
  178. package/src/runtime/shared/llm/http-agent.mjs +129 -0
  179. package/src/runtime/shared/open-url.mjs +37 -0
  180. package/src/runtime/shared/plugin-paths.mjs +25 -0
  181. package/src/runtime/shared/process-shutdown.mjs +147 -0
  182. package/src/runtime/shared/schedules-store.mjs +70 -0
  183. package/src/runtime/shared/tool-execution-contract.mjs +104 -0
  184. package/src/runtime/shared/tool-surface.mjs +950 -0
  185. package/src/runtime/shared/user-cwd.mjs +221 -0
  186. package/src/runtime/shared/user-data-guard.mjs +232 -0
  187. package/src/runtime/shared/workspace-router.mjs +259 -0
  188. package/src/standalone/bridge-tool.mjs +1414 -0
  189. package/src/standalone/channel-admin.mjs +366 -0
  190. package/src/standalone/channel-worker-preload.cjs +3 -0
  191. package/src/standalone/channel-worker.mjs +353 -0
  192. package/src/standalone/explore-tool.mjs +233 -0
  193. package/src/standalone/hook-bus.mjs +246 -0
  194. package/src/standalone/plugin-admin.mjs +247 -0
  195. package/src/standalone/provider-admin.mjs +338 -0
  196. package/src/standalone/seeds.mjs +94 -0
  197. package/src/standalone/usage-dashboard.mjs +510 -0
  198. package/src/tui/App.jsx +5438 -0
  199. package/src/tui/components/AnsiText.jsx +199 -0
  200. package/src/tui/components/ContextPanel.jsx +217 -0
  201. package/src/tui/components/Markdown.jsx +205 -0
  202. package/src/tui/components/MarkdownTable.jsx +204 -0
  203. package/src/tui/components/Message.jsx +103 -0
  204. package/src/tui/components/Picker.jsx +317 -0
  205. package/src/tui/components/PromptInput.jsx +584 -0
  206. package/src/tui/components/QueuedCommands.jsx +47 -0
  207. package/src/tui/components/SlashCommandPalette.jsx +114 -0
  208. package/src/tui/components/Spinner.jsx +317 -0
  209. package/src/tui/components/StatusLine.jsx +87 -0
  210. package/src/tui/components/TextEntryPanel.jsx +323 -0
  211. package/src/tui/components/ToolExecution.jsx +772 -0
  212. package/src/tui/components/TurnDone.jsx +78 -0
  213. package/src/tui/components/UsagePanel.jsx +331 -0
  214. package/src/tui/dist/index.mjs +12359 -0
  215. package/src/tui/engine.mjs +2410 -0
  216. package/src/tui/figures.mjs +50 -0
  217. package/src/tui/hooks/useEngine.mjs +16 -0
  218. package/src/tui/index.jsx +254 -0
  219. package/src/tui/input-editing.mjs +242 -0
  220. package/src/tui/markdown/format-token.mjs +194 -0
  221. package/src/tui/paste-attachments.mjs +198 -0
  222. package/src/tui/runtime/shared/process-shutdown.mjs +1 -0
  223. package/src/tui/spinner-verbs.mjs +45 -0
  224. package/src/tui/theme.mjs +67 -0
  225. package/src/tui/time-format.mjs +53 -0
  226. package/src/ui/ansi.mjs +115 -0
  227. package/src/ui/markdown.mjs +195 -0
  228. package/src/ui/statusline.mjs +730 -0
  229. package/src/ui/tool-card.mjs +101 -0
  230. package/src/vendor/statusline/bin/statusline-lib.mjs +805 -0
  231. package/src/vendor/statusline/bin/statusline-route.mjs +596 -0
  232. package/src/vendor/statusline/scripts/lib/gateway-settings.mjs +285 -0
  233. package/src/vendor/statusline/src/gateway/claude-current.mjs +320 -0
  234. package/src/vendor/statusline/src/gateway/route-meta.mjs +753 -0
  235. package/src/vendor/statusline/src/gateway/session-routes.mjs +244 -0
  236. package/src/workflows/default/WORKFLOW.md +7 -0
  237. package/src/workflows/default/workflow.json +14 -0
  238. package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
  239. package/vendor/ink/build/ansi-tokenizer.js +316 -0
  240. package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
  241. package/vendor/ink/build/colorize.d.ts +3 -0
  242. package/vendor/ink/build/colorize.js +48 -0
  243. package/vendor/ink/build/colorize.js.map +1 -0
  244. package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
  245. package/vendor/ink/build/components/AccessibilityContext.js +5 -0
  246. package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
  247. package/vendor/ink/build/components/AnimationContext.d.ts +9 -0
  248. package/vendor/ink/build/components/AnimationContext.js +13 -0
  249. package/vendor/ink/build/components/AnimationContext.js.map +1 -0
  250. package/vendor/ink/build/components/App.d.ts +24 -0
  251. package/vendor/ink/build/components/App.js +554 -0
  252. package/vendor/ink/build/components/App.js.map +1 -0
  253. package/vendor/ink/build/components/AppContext.d.ts +80 -0
  254. package/vendor/ink/build/components/AppContext.js +25 -0
  255. package/vendor/ink/build/components/AppContext.js.map +1 -0
  256. package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
  257. package/vendor/ink/build/components/BackgroundContext.js +3 -0
  258. package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
  259. package/vendor/ink/build/components/Box.d.ts +130 -0
  260. package/vendor/ink/build/components/Box.js +34 -0
  261. package/vendor/ink/build/components/Box.js.map +1 -0
  262. package/vendor/ink/build/components/CursorContext.d.ts +11 -0
  263. package/vendor/ink/build/components/CursorContext.js +8 -0
  264. package/vendor/ink/build/components/CursorContext.js.map +1 -0
  265. package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
  266. package/vendor/ink/build/components/ErrorBoundary.js +23 -0
  267. package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
  268. package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
  269. package/vendor/ink/build/components/ErrorOverview.js +90 -0
  270. package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
  271. package/vendor/ink/build/components/FocusContext.d.ts +16 -0
  272. package/vendor/ink/build/components/FocusContext.js +17 -0
  273. package/vendor/ink/build/components/FocusContext.js.map +1 -0
  274. package/vendor/ink/build/components/Newline.d.ts +13 -0
  275. package/vendor/ink/build/components/Newline.js +8 -0
  276. package/vendor/ink/build/components/Newline.js.map +1 -0
  277. package/vendor/ink/build/components/Spacer.d.ts +7 -0
  278. package/vendor/ink/build/components/Spacer.js +11 -0
  279. package/vendor/ink/build/components/Spacer.js.map +1 -0
  280. package/vendor/ink/build/components/Static.d.ts +24 -0
  281. package/vendor/ink/build/components/Static.js +28 -0
  282. package/vendor/ink/build/components/Static.js.map +1 -0
  283. package/vendor/ink/build/components/StderrContext.d.ts +15 -0
  284. package/vendor/ink/build/components/StderrContext.js +13 -0
  285. package/vendor/ink/build/components/StderrContext.js.map +1 -0
  286. package/vendor/ink/build/components/StdinContext.d.ts +28 -0
  287. package/vendor/ink/build/components/StdinContext.js +20 -0
  288. package/vendor/ink/build/components/StdinContext.js.map +1 -0
  289. package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
  290. package/vendor/ink/build/components/StdoutContext.js +13 -0
  291. package/vendor/ink/build/components/StdoutContext.js.map +1 -0
  292. package/vendor/ink/build/components/Text.d.ts +55 -0
  293. package/vendor/ink/build/components/Text.js +50 -0
  294. package/vendor/ink/build/components/Text.js.map +1 -0
  295. package/vendor/ink/build/components/Transform.d.ts +16 -0
  296. package/vendor/ink/build/components/Transform.js +15 -0
  297. package/vendor/ink/build/components/Transform.js.map +1 -0
  298. package/vendor/ink/build/cursor-helpers.d.ts +39 -0
  299. package/vendor/ink/build/cursor-helpers.js +62 -0
  300. package/vendor/ink/build/cursor-helpers.js.map +1 -0
  301. package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
  302. package/vendor/ink/build/devtools-window-polyfill.js +68 -0
  303. package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
  304. package/vendor/ink/build/devtools.d.ts +1 -0
  305. package/vendor/ink/build/devtools.js +36 -0
  306. package/vendor/ink/build/devtools.js.map +1 -0
  307. package/vendor/ink/build/dom.d.ts +62 -0
  308. package/vendor/ink/build/dom.js +143 -0
  309. package/vendor/ink/build/dom.js.map +1 -0
  310. package/vendor/ink/build/get-max-width.d.ts +3 -0
  311. package/vendor/ink/build/get-max-width.js +10 -0
  312. package/vendor/ink/build/get-max-width.js.map +1 -0
  313. package/vendor/ink/build/hooks/use-animation.d.ts +49 -0
  314. package/vendor/ink/build/hooks/use-animation.js +87 -0
  315. package/vendor/ink/build/hooks/use-animation.js.map +1 -0
  316. package/vendor/ink/build/hooks/use-app.d.ts +5 -0
  317. package/vendor/ink/build/hooks/use-app.js +8 -0
  318. package/vendor/ink/build/hooks/use-app.js.map +1 -0
  319. package/vendor/ink/build/hooks/use-box-metrics.d.ts +59 -0
  320. package/vendor/ink/build/hooks/use-box-metrics.js +81 -0
  321. package/vendor/ink/build/hooks/use-box-metrics.js.map +1 -0
  322. package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
  323. package/vendor/ink/build/hooks/use-cursor.js +29 -0
  324. package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
  325. package/vendor/ink/build/hooks/use-focus-manager.d.ts +43 -0
  326. package/vendor/ink/build/hooks/use-focus-manager.js +18 -0
  327. package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
  328. package/vendor/ink/build/hooks/use-focus.d.ts +30 -0
  329. package/vendor/ink/build/hooks/use-focus.js +43 -0
  330. package/vendor/ink/build/hooks/use-focus.js.map +1 -0
  331. package/vendor/ink/build/hooks/use-input.d.ts +132 -0
  332. package/vendor/ink/build/hooks/use-input.js +126 -0
  333. package/vendor/ink/build/hooks/use-input.js.map +1 -0
  334. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +6 -0
  335. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +12 -0
  336. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  337. package/vendor/ink/build/hooks/use-paste.d.ts +35 -0
  338. package/vendor/ink/build/hooks/use-paste.js +62 -0
  339. package/vendor/ink/build/hooks/use-paste.js.map +1 -0
  340. package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
  341. package/vendor/ink/build/hooks/use-stderr.js +8 -0
  342. package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
  343. package/vendor/ink/build/hooks/use-stdin.d.ts +7 -0
  344. package/vendor/ink/build/hooks/use-stdin.js +9 -0
  345. package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
  346. package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
  347. package/vendor/ink/build/hooks/use-stdout.js +8 -0
  348. package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
  349. package/vendor/ink/build/hooks/use-window-size.d.ts +18 -0
  350. package/vendor/ink/build/hooks/use-window-size.js +22 -0
  351. package/vendor/ink/build/hooks/use-window-size.js.map +1 -0
  352. package/vendor/ink/build/index.d.ts +42 -0
  353. package/vendor/ink/build/index.js +24 -0
  354. package/vendor/ink/build/index.js.map +1 -0
  355. package/vendor/ink/build/ink.d.ts +146 -0
  356. package/vendor/ink/build/ink.js +1022 -0
  357. package/vendor/ink/build/ink.js.map +1 -0
  358. package/vendor/ink/build/input-parser.d.ts +10 -0
  359. package/vendor/ink/build/input-parser.js +194 -0
  360. package/vendor/ink/build/input-parser.js.map +1 -0
  361. package/vendor/ink/build/instances.d.ts +3 -0
  362. package/vendor/ink/build/instances.js +8 -0
  363. package/vendor/ink/build/instances.js.map +1 -0
  364. package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
  365. package/vendor/ink/build/kitty-keyboard.js +32 -0
  366. package/vendor/ink/build/kitty-keyboard.js.map +1 -0
  367. package/vendor/ink/build/log-update.d.ts +20 -0
  368. package/vendor/ink/build/log-update.js +261 -0
  369. package/vendor/ink/build/log-update.js.map +1 -0
  370. package/vendor/ink/build/measure-element.d.ts +20 -0
  371. package/vendor/ink/build/measure-element.js +13 -0
  372. package/vendor/ink/build/measure-element.js.map +1 -0
  373. package/vendor/ink/build/measure-text.d.ts +6 -0
  374. package/vendor/ink/build/measure-text.js +21 -0
  375. package/vendor/ink/build/measure-text.js.map +1 -0
  376. package/vendor/ink/build/output.d.ts +35 -0
  377. package/vendor/ink/build/output.js +328 -0
  378. package/vendor/ink/build/output.js.map +1 -0
  379. package/vendor/ink/build/parse-keypress.d.ts +20 -0
  380. package/vendor/ink/build/parse-keypress.js +495 -0
  381. package/vendor/ink/build/parse-keypress.js.map +1 -0
  382. package/vendor/ink/build/reconciler.d.ts +4 -0
  383. package/vendor/ink/build/reconciler.js +306 -0
  384. package/vendor/ink/build/reconciler.js.map +1 -0
  385. package/vendor/ink/build/render-background.d.ts +4 -0
  386. package/vendor/ink/build/render-background.js +25 -0
  387. package/vendor/ink/build/render-background.js.map +1 -0
  388. package/vendor/ink/build/render-border.d.ts +4 -0
  389. package/vendor/ink/build/render-border.js +84 -0
  390. package/vendor/ink/build/render-border.js.map +1 -0
  391. package/vendor/ink/build/render-node-to-output.d.ts +14 -0
  392. package/vendor/ink/build/render-node-to-output.js +162 -0
  393. package/vendor/ink/build/render-node-to-output.js.map +1 -0
  394. package/vendor/ink/build/render-to-string.d.ts +38 -0
  395. package/vendor/ink/build/render-to-string.js +116 -0
  396. package/vendor/ink/build/render-to-string.js.map +1 -0
  397. package/vendor/ink/build/render.d.ts +176 -0
  398. package/vendor/ink/build/render.js +71 -0
  399. package/vendor/ink/build/render.js.map +1 -0
  400. package/vendor/ink/build/renderer.d.ts +8 -0
  401. package/vendor/ink/build/renderer.js +64 -0
  402. package/vendor/ink/build/renderer.js.map +1 -0
  403. package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
  404. package/vendor/ink/build/sanitize-ansi.js +27 -0
  405. package/vendor/ink/build/sanitize-ansi.js.map +1 -0
  406. package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
  407. package/vendor/ink/build/squash-text-nodes.js +36 -0
  408. package/vendor/ink/build/squash-text-nodes.js.map +1 -0
  409. package/vendor/ink/build/styles.d.ts +302 -0
  410. package/vendor/ink/build/styles.js +303 -0
  411. package/vendor/ink/build/styles.js.map +1 -0
  412. package/vendor/ink/build/utils.d.ts +9 -0
  413. package/vendor/ink/build/utils.js +19 -0
  414. package/vendor/ink/build/utils.js.map +1 -0
  415. package/vendor/ink/build/wrap-text.d.ts +3 -0
  416. package/vendor/ink/build/wrap-text.js +38 -0
  417. package/vendor/ink/build/wrap-text.js.map +1 -0
  418. package/vendor/ink/build/write-synchronized.d.ts +4 -0
  419. package/vendor/ink/build/write-synchronized.js +9 -0
  420. package/vendor/ink/build/write-synchronized.js.map +1 -0
  421. package/vendor/ink/license +10 -0
  422. package/vendor/ink/package.json +137 -0
  423. package/.claude-plugin/marketplace.json +0 -34
  424. package/.claude-plugin/plugin.json +0 -20
  425. package/.gitattributes +0 -34
  426. package/.mcp.json +0 -14
  427. package/ARCHITECTURE.md +0 -77
  428. package/CHANGELOG.md +0 -30
  429. package/CONTRIBUTING.md +0 -45
  430. package/DATA-FLOW.md +0 -79
  431. package/LICENSE +0 -21
  432. package/SECURITY.md +0 -138
  433. package/UNINSTALL.md +0 -115
  434. package/agents/maintenance.md +0 -5
  435. package/agents/memory-classification.md +0 -30
  436. package/agents/scheduler-task.md +0 -18
  437. package/agents/webhook-handler.md +0 -27
  438. package/agents/worker.md +0 -24
  439. package/bin/bridge +0 -133
  440. package/bin/statusline-launcher.mjs +0 -82
  441. package/bin/statusline-lib.mjs +0 -581
  442. package/bin/statusline-route.mjs +0 -273
  443. package/bin/statusline.mjs +0 -638
  444. package/bun.lock +0 -927
  445. package/commands/config.md +0 -16
  446. package/commands/doctor.md +0 -13
  447. package/commands/model.md +0 -61
  448. package/commands/setup.md +0 -17
  449. package/defaults/hidden-roles.json +0 -68
  450. package/defaults/memory-chunk-prompt.md +0 -63
  451. package/defaults/mixdog-config.template.json +0 -27
  452. package/defaults/user-workflow.json +0 -8
  453. package/defaults/user-workflow.md +0 -17
  454. package/hooks/hooks.json +0 -73
  455. package/hooks/lib/active-instance.cjs +0 -77
  456. package/hooks/lib/permission-evaluator.cjs +0 -411
  457. package/hooks/lib/permission-route.cjs +0 -63
  458. package/hooks/lib/settings-loader.cjs +0 -117
  459. package/hooks/post-tool-use.cjs +0 -84
  460. package/hooks/pre-mcp-sandbox.cjs +0 -158
  461. package/hooks/pre-tool-subagent.cjs +0 -258
  462. package/hooks/session-start.cjs +0 -1493
  463. package/hooks/shim-launcher.cjs +0 -65
  464. package/hooks/turn-timer.cjs +0 -82
  465. package/lib/claude-md-writer.cjs +0 -386
  466. package/lib/keychain-cjs.cjs +0 -290
  467. package/lib/plugin-paths.cjs +0 -69
  468. package/lib/rules-builder.cjs +0 -241
  469. package/native/README.md +0 -117
  470. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  471. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  472. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  473. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  474. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  475. package/prompts/code-review.txt +0 -16
  476. package/prompts/security-audit.txt +0 -17
  477. package/rules/bridge/00-common.md +0 -39
  478. package/rules/bridge/20-skip-protocol.md +0 -18
  479. package/rules/bridge/30-explorer.md +0 -33
  480. package/rules/bridge/40-cycle1-agent.md +0 -52
  481. package/rules/bridge/41-cycle2-agent.md +0 -62
  482. package/rules/lead/00-tool-lead.md +0 -61
  483. package/rules/lead/01-general.md +0 -26
  484. package/rules/lead/02-channels.md +0 -49
  485. package/rules/lead/03-team.md +0 -27
  486. package/rules/lead/04-workflow.md +0 -20
  487. package/rules/shared/00-language.md +0 -14
  488. package/rules/shared/01-tool.md +0 -138
  489. package/scripts/bootstrap.mjs +0 -130
  490. package/scripts/bridge-unify-smoke.mjs +0 -308
  491. package/scripts/build-runtime-linux.sh +0 -348
  492. package/scripts/build-runtime-macos.sh +0 -217
  493. package/scripts/build-runtime-windows.ps1 +0 -242
  494. package/scripts/builtin-utils-smoke.mjs +0 -398
  495. package/scripts/bump.mjs +0 -80
  496. package/scripts/check-json.mjs +0 -45
  497. package/scripts/check-syntax-changed.mjs +0 -102
  498. package/scripts/check-syntax.mjs +0 -58
  499. package/scripts/code-graph-batch.test.mjs +0 -33
  500. package/scripts/config-preserve-smoke.mjs +0 -180
  501. package/scripts/doctor.mjs +0 -489
  502. package/scripts/edit-normalize-fuzz.mjs +0 -130
  503. package/scripts/edit-normalize-smoke.mjs +0 -401
  504. package/scripts/edit-operation-smoke.mjs +0 -369
  505. package/scripts/edit2-smoke.mjs +0 -63
  506. package/scripts/ensure-deps.mjs +0 -259
  507. package/scripts/fuzzy-e2e.mjs +0 -28
  508. package/scripts/fuzzy-smoke.mjs +0 -26
  509. package/scripts/gateway-model.mjs +0 -596
  510. package/scripts/generate-runtime-manifest.mjs +0 -166
  511. package/scripts/guard-smoke.mjs +0 -66
  512. package/scripts/hidden-role-schema-smoke.mjs +0 -162
  513. package/scripts/hook-routing-smoke.mjs +0 -29
  514. package/scripts/inject-input.ps1 +0 -204
  515. package/scripts/io-complex-smoke.mjs +0 -667
  516. package/scripts/io-explore-bench.mjs +0 -424
  517. package/scripts/io-guardrails-smoke.mjs +0 -205
  518. package/scripts/io-mini-bench-baseline.json +0 -11
  519. package/scripts/io-mini-bench.mjs +0 -216
  520. package/scripts/io-route-harness.mjs +0 -933
  521. package/scripts/io-telemetry-report.mjs +0 -691
  522. package/scripts/lib/gateway-inventory.mjs +0 -178
  523. package/scripts/lib/gateway-settings.mjs +0 -78
  524. package/scripts/mutation-bench.mjs +0 -564
  525. package/scripts/mutation-io-smoke.mjs +0 -1097
  526. package/scripts/native-patch-bridge-smoke.mjs +0 -288
  527. package/scripts/native-patch-smoke.mjs +0 -304
  528. package/scripts/openai-oauth-catalog-smoke.mjs +0 -53
  529. package/scripts/patch-interior-context-smoke.mjs +0 -49
  530. package/scripts/patch-newline-utf8-smoke.mjs +0 -157
  531. package/scripts/perf-hook-smoke.mjs +0 -71
  532. package/scripts/permission-eval-smoke.mjs +0 -443
  533. package/scripts/prep-patch.mjs +0 -53
  534. package/scripts/prep-shim.mjs +0 -96
  535. package/scripts/provider-cache-smoke.mjs +0 -687
  536. package/scripts/report-runtime-health.mjs +0 -132
  537. package/scripts/resolve-bun.mjs +0 -60
  538. package/scripts/run-mcp.mjs +0 -1473
  539. package/scripts/salvage-v4a-shatter.test.mjs +0 -58
  540. package/scripts/scoped-cache-io-smoke.mjs +0 -103
  541. package/scripts/shell-policy-round3-smoke.mjs +0 -46
  542. package/scripts/smoke-runtime-negative.ps1 +0 -100
  543. package/scripts/smoke-runtime-negative.sh +0 -95
  544. package/scripts/stall-policy-smoke.mjs +0 -50
  545. package/scripts/start-memory-worker.mjs +0 -23
  546. package/scripts/statusline-launcher-smoke.mjs +0 -235
  547. package/scripts/stress-atomic-write.mjs +0 -1028
  548. package/scripts/test-fault-inject.mjs +0 -164
  549. package/scripts/test-large-file.mjs +0 -174
  550. package/scripts/tool-edge-smoke.mjs +0 -209
  551. package/scripts/uninstall.mjs +0 -238
  552. package/scripts/webhook-selfheal-smoke.mjs +0 -27
  553. package/scripts/write-overwrite-guard-smoke.mjs +0 -56
  554. package/server-main.mjs +0 -3350
  555. package/server.mjs +0 -468
  556. package/setup/config-merge.mjs +0 -246
  557. package/setup/install.mjs +0 -574
  558. package/setup/launch-core.mjs +0 -617
  559. package/setup/launch.mjs +0 -101
  560. package/setup/locate-claude.mjs +0 -56
  561. package/setup/mixdog-cli.mjs +0 -122
  562. package/setup/setup-server.mjs +0 -3305
  563. package/setup/setup.html +0 -3740
  564. package/setup/tui.mjs +0 -325
  565. package/skills/retro-skill-proposer/SKILL.md +0 -92
  566. package/skills/schedule-add/SKILL.md +0 -77
  567. package/skills/setup/SKILL.md +0 -356
  568. package/skills/webhook-add/SKILL.md +0 -81
  569. package/src/agent/bridge-stall-watchdog.mjs +0 -337
  570. package/src/agent/index.mjs +0 -2229
  571. package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +0 -1010
  572. package/src/agent/orchestrator/bridge-retry.mjs +0 -220
  573. package/src/agent/orchestrator/bridge-trace.mjs +0 -601
  574. package/src/agent/orchestrator/cache-mtime.mjs +0 -58
  575. package/src/agent/orchestrator/config.mjs +0 -405
  576. package/src/agent/orchestrator/context/collect.mjs +0 -651
  577. package/src/agent/orchestrator/dispatch-persist.mjs +0 -549
  578. package/src/agent/orchestrator/drain-registry.mjs +0 -50
  579. package/src/agent/orchestrator/explore-validator.mjs +0 -8
  580. package/src/agent/orchestrator/internal-roles.mjs +0 -118
  581. package/src/agent/orchestrator/internal-tools.mjs +0 -88
  582. package/src/agent/orchestrator/jobs.mjs +0 -116
  583. package/src/agent/orchestrator/mcp/client.mjs +0 -364
  584. package/src/agent/orchestrator/providers/anthropic-oauth.mjs +0 -1884
  585. package/src/agent/orchestrator/providers/anthropic.mjs +0 -598
  586. package/src/agent/orchestrator/providers/gemini.mjs +0 -1530
  587. package/src/agent/orchestrator/providers/grok-oauth.mjs +0 -779
  588. package/src/agent/orchestrator/providers/model-catalog.mjs +0 -374
  589. package/src/agent/orchestrator/providers/openai-compat-stream.mjs +0 -366
  590. package/src/agent/orchestrator/providers/openai-compat.mjs +0 -1511
  591. package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +0 -1891
  592. package/src/agent/orchestrator/providers/openai-oauth.mjs +0 -1456
  593. package/src/agent/orchestrator/providers/openai-ws.mjs +0 -127
  594. package/src/agent/orchestrator/providers/registry.mjs +0 -192
  595. package/src/agent/orchestrator/providers/retry-classifier.mjs +0 -325
  596. package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +0 -142
  597. package/src/agent/orchestrator/session/cache/read-cache.mjs +0 -319
  598. package/src/agent/orchestrator/session/cache/scoped-cache.mjs +0 -361
  599. package/src/agent/orchestrator/session/loop.mjs +0 -1619
  600. package/src/agent/orchestrator/session/manager.mjs +0 -1991
  601. package/src/agent/orchestrator/session/result-classification.mjs +0 -65
  602. package/src/agent/orchestrator/session/store.mjs +0 -632
  603. package/src/agent/orchestrator/session/stream-watchdog.mjs +0 -130
  604. package/src/agent/orchestrator/session/tool-result-offload.mjs +0 -166
  605. package/src/agent/orchestrator/session/trim.mjs +0 -491
  606. package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +0 -115
  607. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +0 -331
  608. package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +0 -150
  609. package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +0 -228
  610. package/src/agent/orchestrator/smart-bridge/index.mjs +0 -215
  611. package/src/agent/orchestrator/smart-bridge/profiles.mjs +0 -37
  612. package/src/agent/orchestrator/smart-bridge/registry.mjs +0 -348
  613. package/src/agent/orchestrator/stall-policy.mjs +0 -201
  614. package/src/agent/orchestrator/tool-loop-guard.mjs +0 -75
  615. package/src/agent/orchestrator/tools/bash-session.mjs +0 -722
  616. package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +0 -511
  617. package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -480
  618. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +0 -256
  619. package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +0 -58
  620. package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +0 -240
  621. package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +0 -113
  622. package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +0 -74
  623. package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +0 -242
  624. package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +0 -211
  625. package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +0 -1364
  626. package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +0 -126
  627. package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +0 -141
  628. package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +0 -194
  629. package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +0 -60
  630. package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +0 -168
  631. package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +0 -173
  632. package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +0 -48
  633. package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +0 -99
  634. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +0 -193
  635. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +0 -597
  636. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +0 -110
  637. package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +0 -300
  638. package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +0 -152
  639. package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +0 -118
  640. package/src/agent/orchestrator/tools/builtin/read-open.mjs +0 -190
  641. package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +0 -728
  642. package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +0 -173
  643. package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +0 -602
  644. package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +0 -196
  645. package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +0 -422
  646. package/src/agent/orchestrator/tools/builtin/search-builders.mjs +0 -158
  647. package/src/agent/orchestrator/tools/builtin/search-tool.mjs +0 -869
  648. package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +0 -962
  649. package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +0 -223
  650. package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +0 -206
  651. package/src/agent/orchestrator/tools/builtin/write-tool.mjs +0 -401
  652. package/src/agent/orchestrator/tools/builtin.mjs +0 -503
  653. package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +0 -24
  654. package/src/agent/orchestrator/tools/code-graph.mjs +0 -4095
  655. package/src/agent/orchestrator/tools/cwd-tool.mjs +0 -298
  656. package/src/agent/orchestrator/tools/destructive-warning.mjs +0 -323
  657. package/src/agent/orchestrator/tools/edit-normalize.mjs +0 -603
  658. package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +0 -154
  659. package/src/agent/orchestrator/tools/graph-manifest.json +0 -26
  660. package/src/agent/orchestrator/tools/host-input.mjs +0 -204
  661. package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +0 -143
  662. package/src/agent/orchestrator/tools/patch-manifest.json +0 -26
  663. package/src/agent/orchestrator/tools/patch-tool-defs.mjs +0 -20
  664. package/src/agent/orchestrator/tools/patch.mjs +0 -2754
  665. package/src/agent/orchestrator/tools/progress-message.mjs +0 -118
  666. package/src/agent/orchestrator/tools/shell-command.mjs +0 -865
  667. package/src/agent/orchestrator/tools/shell-policy-imports.mjs +0 -7
  668. package/src/agent/orchestrator/tools/shell-snapshot.mjs +0 -313
  669. package/src/agent/orchestrator/workflow-store.mjs +0 -93
  670. package/src/agent/tool-defs.mjs +0 -110
  671. package/src/channels/backends/discord.mjs +0 -784
  672. package/src/channels/data/voice-runtime-manifest.json +0 -138
  673. package/src/channels/index.mjs +0 -3268
  674. package/src/channels/lib/config.mjs +0 -292
  675. package/src/channels/lib/drop-trace.mjs +0 -71
  676. package/src/channels/lib/event-pipeline.mjs +0 -81
  677. package/src/channels/lib/holidays.mjs +0 -138
  678. package/src/channels/lib/hook-pipe-server.mjs +0 -822
  679. package/src/channels/lib/output-forwarder.mjs +0 -765
  680. package/src/channels/lib/runtime-paths.mjs +0 -552
  681. package/src/channels/lib/scheduler.mjs +0 -723
  682. package/src/channels/lib/session-discovery.mjs +0 -103
  683. package/src/channels/lib/state-file.mjs +0 -68
  684. package/src/channels/lib/status-snapshot.mjs +0 -219
  685. package/src/channels/lib/tool-format.mjs +0 -140
  686. package/src/channels/lib/transcript-discovery.mjs +0 -195
  687. package/src/channels/lib/voice-runtime-fetcher.mjs +0 -734
  688. package/src/channels/lib/webhook.mjs +0 -1318
  689. package/src/channels/tool-defs.mjs +0 -170
  690. package/src/daemon/host.mjs +0 -118
  691. package/src/daemon/mcp-transport.mjs +0 -47
  692. package/src/daemon/session.mjs +0 -100
  693. package/src/daemon/thin-client.mjs +0 -71
  694. package/src/daemon/transport.mjs +0 -163
  695. package/src/gateway/claude-current.mjs +0 -255
  696. package/src/gateway/oauth-usage.mjs +0 -598
  697. package/src/gateway/route-meta.mjs +0 -629
  698. package/src/gateway/server.mjs +0 -713
  699. package/src/memory/data/runtime-manifest.json +0 -40
  700. package/src/memory/index.mjs +0 -3332
  701. package/src/memory/lib/core-memory-store.mjs +0 -330
  702. package/src/memory/lib/embedding-provider.mjs +0 -269
  703. package/src/memory/lib/embedding-worker.mjs +0 -323
  704. package/src/memory/lib/memory-cycle1.mjs +0 -645
  705. package/src/memory/lib/memory-cycle2.mjs +0 -1284
  706. package/src/memory/lib/memory-cycle3.mjs +0 -540
  707. package/src/memory/lib/memory-embed.mjs +0 -299
  708. package/src/memory/lib/memory-ops-policy.mjs +0 -190
  709. package/src/memory/lib/memory-recall-store.mjs +0 -638
  710. package/src/memory/lib/memory.mjs +0 -412
  711. package/src/memory/lib/pg/adapter.mjs +0 -308
  712. package/src/memory/lib/pg/process.mjs +0 -360
  713. package/src/memory/lib/pg/supervisor.mjs +0 -396
  714. package/src/memory/lib/runtime-fetcher.mjs +0 -458
  715. package/src/memory/lib/trace-store.mjs +0 -728
  716. package/src/memory/tool-defs.mjs +0 -79
  717. package/src/search/index.mjs +0 -1173
  718. package/src/search/lib/backends/anthropic-oauth.mjs +0 -98
  719. package/src/search/lib/backends/exa.mjs +0 -50
  720. package/src/search/lib/backends/firecrawl.mjs +0 -61
  721. package/src/search/lib/backends/gemini-api.mjs +0 -83
  722. package/src/search/lib/backends/grok-oauth.mjs +0 -86
  723. package/src/search/lib/backends/index.mjs +0 -150
  724. package/src/search/lib/backends/openai-api.mjs +0 -144
  725. package/src/search/lib/backends/openai-oauth.mjs +0 -102
  726. package/src/search/lib/backends/openai-web-search.mjs +0 -76
  727. package/src/search/lib/backends/tavily.mjs +0 -55
  728. package/src/search/lib/backends/xai-api.mjs +0 -113
  729. package/src/search/lib/config.mjs +0 -192
  730. package/src/search/lib/provider-usage.mjs +0 -67
  731. package/src/search/lib/providers.mjs +0 -47
  732. package/src/search/lib/search-intent.mjs +0 -109
  733. package/src/search/lib/setup-handler.mjs +0 -261
  734. package/src/search/lib/web-tools.mjs +0 -1219
  735. package/src/search/tool-defs.mjs +0 -83
  736. package/src/setup/defender-exclusion.mjs +0 -183
  737. package/src/shared/atomic-file.mjs +0 -436
  738. package/src/shared/config.mjs +0 -372
  739. package/src/shared/daemon-recycle.mjs +0 -108
  740. package/src/shared/disable-claude-builtins.mjs +0 -91
  741. package/src/shared/err-text.mjs +0 -12
  742. package/src/shared/llm/http-agent.mjs +0 -123
  743. package/src/shared/open-url.mjs +0 -62
  744. package/src/shared/plugin-paths.mjs +0 -58
  745. package/src/shared/schedules-store.mjs +0 -70
  746. package/src/shared/seed.mjs +0 -161
  747. package/src/shared/user-cwd.mjs +0 -225
  748. package/src/shared/user-data-guard.mjs +0 -244
  749. package/src/status/aggregator.mjs +0 -584
  750. package/src/status/server.mjs +0 -413
  751. package/tools.json +0 -1671
  752. /package/{defaults → src/defaults}/cycle3-review-prompt.md +0 -0
  753. /package/{defaults → src/defaults}/memory-promote-prompt.md +0 -0
  754. /package/{hooks → src/hooks}/lib/permission-rules.cjs +0 -0
  755. /package/{lib → src/lib}/config-cjs.cjs +0 -0
  756. /package/{lib → src/lib}/hook-pipe-path.cjs +0 -0
  757. /package/{lib → src/lib}/mixdog-debug.cjs +0 -0
  758. /package/{lib → src/lib}/text-utils.cjs +0 -0
  759. /package/{rules → src/rules}/bridge/42-cycle3-agent.md +0 -0
  760. /package/src/{agent → runtime/agent}/orchestrator/activity-bus.mjs +0 -0
  761. /package/src/{agent → runtime/agent}/orchestrator/providers/anthropic-betas.mjs +0 -0
  762. /package/src/{agent → runtime/agent}/orchestrator/session/abort-lookup.mjs +0 -0
  763. /package/src/{agent → runtime/agent}/orchestrator/session/cache/post-edit-marks.mjs +0 -0
  764. /package/src/{agent → runtime/agent}/orchestrator/session/cache/scoped-cache-outcome.mjs +0 -0
  765. /package/src/{agent → runtime/agent}/orchestrator/session/cache/util.mjs +0 -0
  766. /package/src/{agent → runtime/agent}/orchestrator/session/read-dedup.mjs +0 -0
  767. /package/src/{agent → runtime/agent}/orchestrator/session/save-session-worker.mjs +0 -0
  768. /package/src/{agent → runtime/agent}/orchestrator/smart-bridge/session-builder.mjs +0 -0
  769. /package/src/{agent → runtime/agent}/orchestrator/tools/bash-policy-scan.mjs +0 -0
  770. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/advisory-lock.mjs +0 -0
  771. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/atomic-write.mjs +0 -0
  772. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/binary-file.mjs +0 -0
  773. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/cache-layers.mjs +0 -0
  774. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/cwd-utils.mjs +0 -0
  775. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/device-paths.mjs +0 -0
  776. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -0
  777. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/diff-utils.mjs +0 -0
  778. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/fs-reachability.mjs +0 -0
  779. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/grep-formatting.mjs +0 -0
  780. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/hash-utils.mjs +0 -0
  781. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/list-formatting.mjs +0 -0
  782. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/open-config-tool.mjs +0 -0
  783. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/path-locks.mjs +0 -0
  784. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/path-utils.mjs +0 -0
  785. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-args.mjs +0 -0
  786. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-batch.mjs +0 -0
  787. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-constants.mjs +0 -0
  788. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-image-resize.mjs +0 -0
  789. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-image.mjs +0 -0
  790. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-lines.mjs +0 -0
  791. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-mode-tool.mjs +0 -0
  792. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-range-index.mjs +0 -0
  793. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-ranges.mjs +0 -0
  794. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-special-files.mjs +0 -0
  795. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-tool.mjs +0 -0
  796. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/read-windows.mjs +0 -0
  797. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/shell-analysis.mjs +0 -0
  798. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/shell-output.mjs +0 -0
  799. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/snapshot-helpers.mjs +0 -0
  800. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/snapshot-validation.mjs +0 -0
  801. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/text-stats.mjs +0 -0
  802. /package/src/{agent → runtime/agent}/orchestrator/tools/builtin/windows-roots.mjs +0 -0
  803. /package/src/{agent → runtime/agent}/orchestrator/tools/code-graph-prewarm-worker.mjs +0 -0
  804. /package/src/{agent → runtime/agent}/orchestrator/tools/env-scrub.mjs +0 -0
  805. /package/src/{agent → runtime/agent}/orchestrator/tools/mutation-content-cache.mjs +0 -0
  806. /package/src/{agent → runtime/agent}/orchestrator/tools/mutation-planner.mjs +0 -0
  807. /package/src/{agent → runtime/agent}/orchestrator/tools/next-call-utils.mjs +0 -0
  808. /package/src/{agent → runtime/agent}/orchestrator/tools/result-compression.mjs +0 -0
  809. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-exec-policy.mjs +0 -0
  810. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-policy-danger-target.mjs +0 -0
  811. /package/src/{agent → runtime/agent}/orchestrator/tools/shell-policy.mjs +0 -0
  812. /package/src/{channels → runtime/channels}/lib/cli-worker-host.mjs +0 -0
  813. /package/src/{channels → runtime/channels}/lib/config-lock.mjs +0 -0
  814. /package/src/{channels → runtime/channels}/lib/event-queue.mjs +0 -0
  815. /package/src/{channels → runtime/channels}/lib/executor.mjs +0 -0
  816. /package/src/{channels → runtime/channels}/lib/format.mjs +0 -0
  817. /package/src/{channels → runtime/channels}/lib/interaction-workflows.mjs +0 -0
  818. /package/src/{channels → runtime/channels}/lib/memory-client.mjs +0 -0
  819. /package/src/{channels → runtime/channels}/lib/session-control.mjs +0 -0
  820. /package/src/{channels → runtime/channels}/lib/settings.mjs +0 -0
  821. /package/src/{channels → runtime/channels}/lib/whisper-server.mjs +0 -0
  822. /package/src/{memory → runtime/memory}/lib/agent-ipc.mjs +0 -0
  823. /package/src/{memory → runtime/memory}/lib/bridge-trace-queries.mjs +0 -0
  824. /package/src/{memory → runtime/memory}/lib/llm-worker-host.mjs +0 -0
  825. /package/src/{memory → runtime/memory}/lib/memory-cycle.mjs +0 -0
  826. /package/src/{memory → runtime/memory}/lib/memory-extraction.mjs +0 -0
  827. /package/src/{memory → runtime/memory}/lib/memory-maintenance-store.mjs +0 -0
  828. /package/src/{memory → runtime/memory}/lib/memory-recall-id-patch.mjs +0 -0
  829. /package/src/{memory → runtime/memory}/lib/memory-recall-read-query.mjs +0 -0
  830. /package/src/{memory → runtime/memory}/lib/memory-recall-scope-filter.mjs +0 -0
  831. /package/src/{memory → runtime/memory}/lib/memory-retrievers.mjs +0 -0
  832. /package/src/{memory → runtime/memory}/lib/memory-score.mjs +0 -0
  833. /package/src/{memory → runtime/memory}/lib/memory-text-utils.mjs +0 -0
  834. /package/src/{memory → runtime/memory}/lib/model-profile.mjs +0 -0
  835. /package/src/{memory → runtime/memory}/lib/project-id-resolver.mjs +0 -0
  836. /package/src/{search → runtime/search}/lib/cache.mjs +0 -0
  837. /package/src/{search → runtime/search}/lib/formatter.mjs +0 -0
  838. /package/src/{search → runtime/search}/lib/state.mjs +0 -0
  839. /package/src/{shared → runtime/shared}/abort-controller.mjs +0 -0
  840. /package/src/{shared → runtime/shared}/llm/cost.mjs +0 -0
  841. /package/src/{shared → runtime/shared}/llm/index.mjs +0 -0
  842. /package/src/{shared → runtime/shared}/llm/pid-cleanup.mjs +0 -0
  843. /package/src/{shared → runtime/shared}/llm/usage-log.mjs +0 -0
  844. /package/src/{shared → runtime/shared}/wsl.mjs +0 -0
@@ -1,1173 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js'
4
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'
5
- import { z } from 'zod'
6
- import { zodToJsonSchema } from 'zod-to-json-schema'
7
- import fs from 'fs'
8
- import path from 'path'
9
- import {
10
- ensureDataDir,
11
- getFirecrawlApiKey,
12
- getRequestTimeoutMs,
13
- getRawSearchMaxResults,
14
- getRawProviderCredentialSource,
15
- getRawProviderApiKey,
16
- loadConfig,
17
- PLUGIN_ROOT,
18
- } from './lib/config.mjs'
19
- import { normalizeErrorMessage } from '../agent/orchestrator/tools/builtin/path-diagnostics.mjs'
20
- import { getAgentApiKey } from '../shared/config.mjs'
21
-
22
- function readPluginVersion() {
23
- try {
24
- const manifestPath = path.join(PLUGIN_ROOT, '.claude-plugin', 'plugin.json')
25
- return JSON.parse(fs.readFileSync(manifestPath, 'utf8')).version || '0.0.1'
26
- } catch { return '0.0.1' }
27
- }
28
- const PLUGIN_VERSION = readPluginVersion()
29
- import {
30
- buildCacheKey,
31
- buildCacheMeta,
32
- flushCacheState,
33
- getCachedEntry,
34
- loadCacheState,
35
- setCachedEntry,
36
- } from './lib/cache.mjs'
37
- import { fetchProviderUsageSnapshot } from './lib/provider-usage.mjs'
38
- import {
39
- flushUsageState,
40
- loadUsageState,
41
- noteProviderFailure,
42
- classifyProviderError,
43
- noteProviderSuccess,
44
- saveUsageState,
45
- updateProviderState,
46
- } from './lib/state.mjs'
47
- import {
48
- getProvidersWithApiKeys,
49
- RAW_PROVIDER_CAPABILITIES,
50
- } from './lib/providers.mjs'
51
- import { dispatchSearchBackend, PROVIDER_CAPS } from './lib/backends/index.mjs'
52
- import { normalizeSearchIntent } from './lib/search-intent.mjs'
53
- import { assertPublicUrl, crawlSite, getScrapeCapabilities, pinnedFetch, scrapeUrls } from './lib/web-tools.mjs'
54
- import { formatResponse } from './lib/formatter.mjs'
55
- import { handleSetup } from './lib/setup-handler.mjs'
56
-
57
-
58
- ensureDataDir()
59
-
60
- const searchArgsSchema = z.object({
61
- keywords: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]).describe('Search query string or array of queries.'),
62
- site: z.string().optional().describe('Restrict results to a specific domain.'),
63
- type: z.enum(['web', 'news', 'images']).optional().describe('Search type. Default: web.'),
64
- maxResults: z.number().int().min(1).max(20).optional().describe('Maximum number of results to return (1-20).'),
65
- locale: z.union([
66
- z.string(),
67
- z.object({
68
- country: z.string().optional(),
69
- language: z.string().optional(),
70
- region: z.string().optional(),
71
- city: z.string().optional(),
72
- timezone: z.string().optional(),
73
- }),
74
- ]).optional().describe('Explicit search locale. String such as "ko-KR" or object with country/language/city/region/timezone.'),
75
- contextSize: z.enum(['low', 'medium', 'high']).optional().describe('Search context size for providers that support it. Default: low.'),
76
- })
77
-
78
- const searchUrlArgsSchema = z.object({
79
- url: z.union([z.string().url(), z.array(z.string().url()).min(1)]).describe('Single URL or array of URLs to fetch.'),
80
- startIndex: z.number().int().min(0).optional().describe('Character offset to start the slice from (default 0). For chunked reading of large pages, pass the previous response\'s nextStartIndex.'),
81
- maxLength: z.number().int().min(0).optional().describe('Max characters to return per call (default 50000). Pass 0 for unlimited.'),
82
- cwd: z.string().optional(),
83
- })
84
-
85
- const SEARCH_EMPTY_STRING_FIELDS = ['keywords', 'site', 'type', 'locale', 'contextSize']
86
-
87
- function normalizeSearchArgs(rawArgs) {
88
- if (!rawArgs || typeof rawArgs !== 'object' || Array.isArray(rawArgs)) return rawArgs
89
- const args = { ...rawArgs }
90
- for (const key of SEARCH_EMPTY_STRING_FIELDS) {
91
- const value = args[key]
92
- if (typeof value === 'string') {
93
- const trimmed = value.trim()
94
- if (!trimmed) delete args[key]
95
- else args[key] = trimmed
96
- }
97
- }
98
- if (Array.isArray(args.keywords)) {
99
- const keywords = args.keywords
100
- .map(value => typeof value === 'string' ? value.trim() : value)
101
- .filter(value => typeof value === 'string' ? value.length > 0 : Boolean(value))
102
- if (keywords.length > 0) args.keywords = keywords
103
- else delete args.keywords
104
- }
105
- return args
106
- }
107
-
108
- function normalizeSearchUrlArgs(rawArgs) {
109
- if (!rawArgs || typeof rawArgs !== 'object' || Array.isArray(rawArgs)) return rawArgs
110
- const args = { ...rawArgs }
111
- if (typeof args.url === 'string') args.url = args.url.trim()
112
- if (Array.isArray(args.url)) {
113
- const urls = args.url
114
- .map(value => typeof value === 'string' ? value.trim() : value)
115
- .filter(value => typeof value === 'string' ? value.length > 0 : Boolean(value))
116
- if (urls.length > 0) args.url = urls
117
- else delete args.url
118
- }
119
- return args
120
- }
121
-
122
- const crawlArgsSchema = z.object({
123
- url: z.string().url().describe('Starting URL to begin crawling from.'),
124
- maxPages: z.number().int().min(1).max(200).optional().describe('Maximum number of pages to visit (1-200).'),
125
- maxDepth: z.number().int().min(0).max(5).optional().describe('Maximum link depth to follow (0-5).'),
126
- sameDomainOnly: z.boolean().optional().describe('If true, only follow links on the same domain.'),
127
- })
128
-
129
- function jsonText(payload) {
130
- return {
131
- content: [
132
- {
133
- type: 'text',
134
- text: JSON.stringify(payload, null, 2),
135
- },
136
- ],
137
- }
138
- }
139
-
140
- function formattedText(tool, payload) {
141
- const text = formatResponse(tool, tool === 'search' ? dropInvalidSearchResults(payload) : payload)
142
- return {
143
- content: [{ type: 'text', text }],
144
- }
145
- }
146
-
147
- function isInvalidSearchResult(result) {
148
- const title = String(result?.title || '').trim()
149
- return /\bpage not found\b|\b404\b.*\bnot found\b/i.test(title)
150
- }
151
-
152
- function dropInvalidSearchResults(payload) {
153
- if (!payload || typeof payload !== 'object') return payload
154
- const response = payload.response
155
- if (!response || typeof response !== 'object' || !Array.isArray(response.results)) return payload
156
- const results = response.results.filter(result => !isInvalidSearchResult(result))
157
- if (results.length === response.results.length) return payload
158
- return {
159
- ...payload,
160
- response: {
161
- ...response,
162
- results,
163
- droppedInvalidResults: (response.droppedInvalidResults || 0) + (response.results.length - results.length),
164
- },
165
- }
166
- }
167
-
168
- function buildInputSchema(zodSchema) {
169
- const jsonSchema = zodToJsonSchema(zodSchema, { target: 'openApi3' })
170
- delete jsonSchema.$schema
171
- return jsonSchema
172
- }
173
-
174
- function getSearchCacheTtlMs(type = 'web') {
175
- switch (type) {
176
- case 'news':
177
- return 20 * 60 * 1000
178
- case 'images':
179
- return 60 * 60 * 1000
180
- case 'web':
181
- default:
182
- return 30 * 60 * 1000
183
- }
184
- }
185
-
186
- function getScrapeCacheTtlMs(isXRoute = false) {
187
- return isXRoute ? 10 * 60 * 1000 : 60 * 60 * 1000
188
- }
189
-
190
- function buildRuntimeEnv(config) {
191
- return {
192
- ...process.env,
193
- ...(getFirecrawlApiKey(config)
194
- ? { FIRECRAWL_API_KEY: getFirecrawlApiKey(config) }
195
- : {}),
196
- ...(getRawProviderApiKey(config, 'tavily')
197
- ? { TAVILY_API_KEY: getRawProviderApiKey(config, 'tavily') }
198
- : {}),
199
- ...(getRawProviderApiKey(config, 'exa')
200
- ? { EXA_API_KEY: getRawProviderApiKey(config, 'exa') }
201
- : {}),
202
- // xAI search runs through the xai-api backend, which reads the Agent xAI
203
- // credential (getAgentApiKey('xai')) — not a separate raw search key. Mirror
204
- // that source here so the startup snapshot discovers 'xai-api' iff the agent
205
- // key is present.
206
- ...(getAgentApiKey('xai')
207
- ? { XAI_API_KEY: process.env.XAI_API_KEY || getAgentApiKey('xai') }
208
- : {}),
209
- }
210
- }
211
-
212
- function normalizeCacheUrl(url) {
213
- try {
214
- return new URL(url).toString()
215
- } catch {
216
- return String(url)
217
- }
218
- }
219
-
220
- const DOC_INDEX_MAX_BYTES = 2 * 1024 * 1024
221
- const DOC_INDEX_MAX_FETCHES = 8
222
- const DOC_INDEX_COMMON_PATHS = ['docs', 'api', 'reference', 'api/reference']
223
- const DOC_INDEX_STOPWORDS = new Set([
224
- 'about', 'after', 'again', 'also', 'and', 'are', 'can', 'com', 'doc', 'docs',
225
- 'documentation', 'for', 'from', 'how', 'http', 'https', 'into', 'official',
226
- 'page', 'pages', 'site', 'the', 'this', 'title', 'url', 'use', 'using', 'what',
227
- 'when', 'where', 'which', 'with', 'www',
228
- ])
229
-
230
- function keywordsText(keywords) {
231
- return Array.isArray(keywords) ? keywords.join(' ') : String(keywords || '')
232
- }
233
-
234
- function queryTokens(keywords) {
235
- const tokens = keywordsText(keywords)
236
- .toLowerCase()
237
- .match(/[\p{L}\p{N}][\p{L}\p{N}._-]{1,}/gu) || []
238
- return [...new Set(tokens
239
- .filter(token => token.length >= 3 && !DOC_INDEX_STOPWORDS.has(token)))]
240
- }
241
-
242
- // Weighted scoring across title/path/url/snippet. Title hit is the strongest
243
- // signal (8) because llms.txt entries are hand-curated; path-segment hits
244
- // (5) and last-segment hits (3..10) catch /api/foo over /blog/foo. Url and
245
- // snippet (2 / 1) act as tiebreakers when title misses. .md penalty -2 so
246
- // raw markdown sources lose to rendered docs when both are listed.
247
- function docLinkScore(link, tokens) {
248
- if (!tokens.length) return 0
249
- const title = String(link.title || '').toLowerCase()
250
- const url = String(link.url || '').toLowerCase()
251
- const snippet = String(link.snippet || '').toLowerCase()
252
- let pathname = ''
253
- try {
254
- pathname = new URL(link.url).pathname.toLowerCase()
255
- } catch {}
256
- const segments = pathname.split('/').filter(Boolean)
257
- let score = 0
258
- for (const token of tokens) {
259
- if (title.includes(token)) score += 8
260
- if (segments.includes(token)) score += 5
261
- if (segments.at(-1) === token) score += 3 + Math.max(0, 7 - segments.length)
262
- if (url.includes(token)) score += 2
263
- if (snippet.includes(token)) score += 1
264
- }
265
- if (/\.md$/i.test(pathname)) score -= 2
266
- return score
267
- }
268
-
269
- function docIndexUrlCandidates(site, keywords) {
270
- if (!site) return []
271
- let parsed
272
- try {
273
- parsed = new URL(/^https?:\/\//i.test(site) ? site : `https://${site}`)
274
- } catch {
275
- return []
276
- }
277
- const candidates = []
278
- const add = (url) => {
279
- try {
280
- const normalized = new URL(url).toString()
281
- if (!candidates.includes(normalized)) candidates.push(normalized)
282
- } catch {}
283
- }
284
- const pathParts = parsed.pathname.split('/').filter(Boolean)
285
- for (let i = pathParts.length; i >= 0; i -= 1) {
286
- const prefix = pathParts.slice(0, i).join('/')
287
- add(`${parsed.origin}${prefix ? `/${prefix}` : ''}/llms.txt`)
288
- }
289
- // When the user asks an api/docs question on a bare-host site, also probe
290
- // the common doc-prefix llms.txt locations the host might publish under.
291
- const docsIntent = /\b(?:api|docs?|documentation|reference)\b/i.test(keywordsText(keywords))
292
- if (docsIntent && pathParts.length === 0) {
293
- for (const prefix of DOC_INDEX_COMMON_PATHS) {
294
- add(`${parsed.origin}/${prefix}/llms.txt`)
295
- }
296
- }
297
- return candidates
298
- }
299
-
300
-
301
- function docIndexAbortSignal(timeoutMs, parentSignal) {
302
- const ms = Math.min(Math.max(Number(timeoutMs) || 10_000, 1000), 10_000)
303
- if (typeof AbortSignal.any === 'function') {
304
- const parts = [AbortSignal.timeout(ms)]
305
- if (parentSignal) parts.push(parentSignal)
306
- return AbortSignal.any(parts)
307
- }
308
- const controller = new AbortController()
309
- let timer
310
- let onParentAbort
311
- const abortWith = reason => {
312
- if (timer !== undefined) {
313
- clearTimeout(timer)
314
- timer = undefined
315
- }
316
- if (parentSignal && onParentAbort) {
317
- parentSignal.removeEventListener('abort', onParentAbort)
318
- onParentAbort = undefined
319
- }
320
- if (!controller.signal.aborted) controller.abort(reason)
321
- }
322
- timer = setTimeout(
323
- () => abortWith(new DOMException('The operation was aborted due to timeout', 'TimeoutError')),
324
- ms,
325
- )
326
- if (parentSignal) {
327
- if (parentSignal.aborted) {
328
- abortWith(parentSignal.reason)
329
- return controller.signal
330
- }
331
- onParentAbort = () => abortWith(parentSignal.reason)
332
- parentSignal.addEventListener('abort', onParentAbort, { once: true })
333
- }
334
- return controller.signal
335
- }
336
-
337
- function searchArgsForCacheKey(args, config) {
338
- const caps = PROVIDER_CAPS[config.provider] || { searchTypes: ['web'], localeMode: 'tool' }
339
- let keywords = args.keywords
340
- if (Array.isArray(keywords)) {
341
- const items = keywords.map(k => String(k || '').trim()).filter(Boolean)
342
- keywords = items.length === 1 ? items[0] : items
343
- }
344
- const intent = normalizeSearchIntent(
345
- {
346
- keywords,
347
- site: args.site,
348
- type: args.type,
349
- maxResults: args.maxResults,
350
- locale: args.locale,
351
- contextSize: args.contextSize,
352
- },
353
- { caps, defaultMaxResults: getRawSearchMaxResults(config) },
354
- )
355
- return {
356
- keywords: intent.rawQuery,
357
- site: intent.site || null,
358
- type: intent.type,
359
- locale: intent.locale,
360
- contextSize: intent.contextSize,
361
- maxResults: intent.maxResults,
362
- }
363
- }
364
-
365
- async function fetchDocIndex(url, timeoutMs, parentSignal) {
366
- // SSRF: reuse the guarded web_fetch path's public-URL/private-IP check so
367
- // docs-index discovery cannot be steered into localhost / link-local /
368
- // cloud-metadata addresses by a hostile site override. Follow redirects
369
- // manually and re-validate each hop so a 30x Location can't steer us to
370
- // a private/loopback address after the initial check.
371
- const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])
372
- const MAX_REDIRECTS = 5
373
- const signal = docIndexAbortSignal(timeoutMs, parentSignal)
374
- let currentUrl = url
375
- let response
376
- for (let hops = 0; ; hops++) {
377
- assertPublicUrl(currentUrl)
378
- // pinnedFetch resolves+validates the host once and pins the connection
379
- // to the validated IP, closing the validate-then-fetch DNS-rebinding /
380
- // TOCTOU window that bare `fetch` left open.
381
- response = await pinnedFetch(currentUrl, {
382
- headers: { Accept: 'text/markdown,text/plain,text/*,*/*' },
383
- signal,
384
- redirect: 'manual',
385
- })
386
- if (!REDIRECT_STATUSES.has(response.status)) break
387
- try { await response.body?.cancel() } catch {}
388
- if (hops >= MAX_REDIRECTS) {
389
- throw new Error(`docs index too many redirects (max ${MAX_REDIRECTS})`)
390
- }
391
- const location = response.headers.get('location')
392
- if (!location) {
393
- throw new Error(`docs index redirect ${response.status} without Location header`)
394
- }
395
- currentUrl = new URL(location, currentUrl).toString()
396
- }
397
- if (!response.ok) {
398
- try { await response.body?.cancel() } catch {}
399
- throw new Error(`docs index fetch failed: ${response.status}`)
400
- }
401
- const contentLength = Number(response.headers.get('content-length') || 0)
402
- if (contentLength > DOC_INDEX_MAX_BYTES) {
403
- try { await response.body?.cancel() } catch {}
404
- throw new Error(`docs index too large: ${contentLength}`)
405
- }
406
- // Enforce DOC_INDEX_MAX_BYTES while streaming so chunked / missing-length
407
- // responses can't blow past the 2MB cap by deferring the check until after
408
- // the whole body is buffered.
409
- const reader = response.body?.getReader?.()
410
- let text
411
- if (!reader) {
412
- // Buffer as bytes and cap by byte length — string.length counts UTF-16
413
- // code units, which under-counts multi-byte characters and lets the
414
- // body blow past DOC_INDEX_MAX_BYTES.
415
- const buf = new Uint8Array(await response.arrayBuffer())
416
- const capped = buf.byteLength > DOC_INDEX_MAX_BYTES ? buf.subarray(0, DOC_INDEX_MAX_BYTES) : buf
417
- text = new TextDecoder('utf-8', { fatal: false }).decode(capped)
418
- } else {
419
- const chunks = []
420
- let total = 0
421
- let capped = false
422
- try {
423
- while (true) {
424
- const { done, value } = await reader.read()
425
- if (done) break
426
- total += value.byteLength
427
- chunks.push(value)
428
- if (total >= DOC_INDEX_MAX_BYTES) {
429
- capped = true
430
- try { await reader.cancel() } catch {}
431
- break
432
- }
433
- }
434
- } finally {
435
- try { reader.releaseLock() } catch {}
436
- }
437
- const decoder = new TextDecoder('utf-8', { fatal: false })
438
- let buf = ''
439
- for (const chunk of chunks) buf += decoder.decode(chunk, { stream: true })
440
- buf += decoder.decode()
441
- text = capped || buf.length > DOC_INDEX_MAX_BYTES ? buf.slice(0, DOC_INDEX_MAX_BYTES) : buf
442
- }
443
- return {
444
- text,
445
- url: response.url || url,
446
- }
447
- }
448
-
449
- function parseDocIndexLinks(text, sourceUrl) {
450
- const links = []
451
- const seen = new Set()
452
- const add = (title, rawUrl, snippet = '') => {
453
- if (!title || !rawUrl) return
454
- let url
455
- try {
456
- url = new URL(rawUrl, sourceUrl).toString()
457
- } catch {
458
- return
459
- }
460
- if (!/^https?:\/\//i.test(url) || seen.has(url)) return
461
- seen.add(url)
462
- links.push({
463
- title: String(title).trim(),
464
- url,
465
- snippet: String(snippet || '').trim(),
466
- sourceUrl,
467
- })
468
- }
469
-
470
- for (const line of String(text || '').split(/\r?\n/)) {
471
- const item = line.match(/^\s*[-*]\s+\[([^\]]{1,180})\]\(([^)\s]+)\)\s*:?\s*(.*)$/)
472
- if (item) add(item[1], item[2], item[3])
473
- }
474
- const inlineRe = /\[([^\]]{1,180})\]\((https?:\/\/[^)\s]+)\)/g
475
- let match
476
- while ((match = inlineRe.exec(String(text || '')))) {
477
- add(match[1], match[2])
478
- }
479
- return links
480
- }
481
-
482
-
483
- function isDocIndexLink(url) {
484
- try {
485
- return /\/llms(?:-full)?\.txt$/i.test(new URL(url).pathname)
486
- } catch {
487
- return false
488
- }
489
- }
490
-
491
- function hostFromUrl(url) {
492
- try {
493
- return new URL(/^https?:\/\//i.test(url) ? url : `https://${url}`).hostname.toLowerCase()
494
- } catch {
495
- return ''
496
- }
497
- }
498
-
499
- function isBaseHost(host) {
500
- return host.split('.').filter(Boolean).length <= 2
501
- }
502
-
503
- function hostMatchesScope(host, scopedHost) {
504
- if (!host || !scopedHost) return false
505
- if (host === scopedHost) return true
506
- return isBaseHost(scopedHost) && host.endsWith(`.${scopedHost}`)
507
- }
508
-
509
- function sameDocIndexScope(url, site, requestedIndexUrl) {
510
- const linkHost = hostFromUrl(url)
511
- if (!linkHost) return false
512
- // Always require the link to match the original requested site host.
513
- const siteHost = hostFromUrl(site)
514
- if (siteHost && !hostMatchesScope(linkHost, siteHost)) return false
515
- const scopes = [
516
- siteHost,
517
- hostFromUrl(requestedIndexUrl),
518
- ].filter(Boolean)
519
- return scopes.some(scope => hostMatchesScope(linkHost, scope))
520
- }
521
-
522
- async function discoverDocsIndexResults(args, timeoutMs, parentSignal) {
523
- if (!args?.site || (args.type && args.type !== 'web')) return []
524
- const tokens = queryTokens(args.keywords)
525
- if (!tokens.length) return []
526
-
527
- const queue = docIndexUrlCandidates(args.site, args.keywords)
528
- const seenIndexes = new Set()
529
- const candidates = []
530
-
531
- while (queue.length > 0 && seenIndexes.size < DOC_INDEX_MAX_FETCHES) {
532
- if (parentSignal?.aborted) return []
533
- const indexUrl = queue.shift()
534
- if (!indexUrl || seenIndexes.has(indexUrl)) continue
535
- seenIndexes.add(indexUrl)
536
- let index = null
537
- try {
538
- index = await fetchDocIndex(indexUrl, timeoutMs, parentSignal)
539
- } catch {
540
- continue
541
- }
542
- const sourceUrl = index.url || indexUrl
543
- const links = parseDocIndexLinks(index.text, sourceUrl)
544
- for (const link of links) {
545
- if (isDocIndexLink(link.url)) {
546
- if (!seenIndexes.has(link.url) && queue.length + seenIndexes.size < DOC_INDEX_MAX_FETCHES) queue.push(link.url)
547
- continue
548
- }
549
- if (!sameDocIndexScope(link.url, args.site, indexUrl)) continue
550
- const score = docLinkScore(link, tokens)
551
- if (score <= 0) continue
552
- candidates.push({
553
- ...link,
554
- score,
555
- })
556
- }
557
- }
558
-
559
- const seenUrls = new Set()
560
- return candidates
561
- .sort((a, b) => b.score - a.score)
562
- .filter((item) => {
563
- if (seenUrls.has(item.url)) return false
564
- seenUrls.add(item.url)
565
- return true
566
- })
567
- .slice(0, Math.min(Number(args.maxResults) || 5, 5))
568
- .map(item => ({
569
- title: item.title,
570
- url: item.url,
571
- snippet: item.snippet || `Matched docs index: ${item.sourceUrl}`,
572
- source: 'docs-index',
573
- provider: 'docs-index',
574
- publishedDate: null,
575
- meta: { score: item.score, sourceUrl: item.sourceUrl },
576
- }))
577
- }
578
-
579
- async function augmentSearchPayloadWithDocsIndex(payload, args, timeoutMs, parentSignal) {
580
- if (!payload || typeof payload !== 'object') return payload
581
- const response = payload.response
582
- if (!response || typeof response !== 'object' || !Array.isArray(response.results)) return payload
583
- const indexResults = await discoverDocsIndexResults(args, timeoutMs, parentSignal)
584
- if (!indexResults.length) return payload
585
- const seen = new Set()
586
- const results = []
587
- for (const result of [...indexResults, ...response.results]) {
588
- const url = String(result?.url || '')
589
- const key = url || `${result?.title || ''}\n${result?.snippet || ''}`
590
- if (seen.has(key)) continue
591
- seen.add(key)
592
- results.push(result)
593
- }
594
- return {
595
- ...payload,
596
- response: {
597
- ...response,
598
- results: results.slice(0, Math.max(Number(args.maxResults) || results.length, indexResults.length)),
599
- docsIndexAugmented: {
600
- added: indexResults.length,
601
- sources: [...new Set(indexResults.map(item => item.meta?.sourceUrl).filter(Boolean))],
602
- },
603
- },
604
- }
605
- }
606
-
607
- async function writeStartupSnapshot() {
608
- const config = loadConfig()
609
- const usageState = loadUsageState()
610
- const runtimeEnv = buildRuntimeEnv(config)
611
- const rawProviders = getProvidersWithApiKeys(runtimeEnv)
612
- const scrapeCapabilities = getScrapeCapabilities()
613
-
614
- for (const provider of rawProviders) {
615
- let usagePatch = null
616
- try {
617
- usagePatch = await fetchProviderUsageSnapshot(provider, runtimeEnv)
618
- } catch {
619
- usagePatch = null
620
- }
621
-
622
- updateProviderState(usageState, provider, {
623
- available: true,
624
- connection: 'api',
625
- source: getRawProviderCredentialSource(config, provider, process.env) || 'env',
626
- usageSupport: RAW_PROVIDER_CAPABILITIES[provider]?.usageSupport || null,
627
- ...(usagePatch || {}),
628
- })
629
- }
630
-
631
- updateProviderState(usageState, 'readability', {
632
- available: scrapeCapabilities.readability,
633
- connection: 'builtin',
634
- source: 'local',
635
- })
636
-
637
- updateProviderState(usageState, 'puppeteer', {
638
- available: scrapeCapabilities.puppeteer,
639
- connection: 'local-browser',
640
- source: 'local',
641
- })
642
-
643
- updateProviderState(usageState, 'firecrawl', {
644
- readability: scrapeCapabilities.readability,
645
- puppeteer: scrapeCapabilities.puppeteer,
646
- connection: 'api',
647
- source: getRawProviderCredentialSource(config, 'firecrawl', process.env) || 'env',
648
- })
649
- }
650
-
651
- // ── Core action implementations (shared by individual and batch handlers) ──
652
-
653
- const _searchInFlight = new Map()
654
-
655
- function backendResultToSearchResponse(result) {
656
- const maxResults = Math.max(1, Math.min(20, Number(result?.maxResults) || 10))
657
- const citations = Array.isArray(result?.citations) ? result.citations : []
658
- const results = citations.slice(0, maxResults).map((item) => ({
659
- title: item?.title || '',
660
- url: item?.url || '',
661
- snippet: item?.snippet || '',
662
- source: item?.source || result?.backend || '',
663
- provider: result?.backend || '',
664
- publishedDate: item?.publishedDate || item?.published_date || null,
665
- }))
666
- return {
667
- usedProvider: result?.backend || '',
668
- query: result?.rawQuery || result?.query || '',
669
- rawQuery: result?.rawQuery || result?.query || '',
670
- answer: result?.answer || '',
671
- model: result?.model || null,
672
- durationMs: result?.durationMs || 0,
673
- usage: result?.usage || null,
674
- results,
675
- warnings: Array.isArray(result?.warnings) ? result.warnings : [],
676
- type: result?.type || 'web',
677
- site: result?.site || null,
678
- locale: result?.locale || null,
679
- webSearchCalls: result?.webSearchCalls || [],
680
- }
681
- }
682
-
683
- async function _searchCore(args, { config, usageState, cacheState, timeoutMs, signal }) {
684
- // Hoisted so the outer finally can reference it even on early throw.
685
- let searchCacheKey
686
- // Only the owner of the in-flight entry may delete it in the outer finally.
687
- // Coalesced callers that early-return `existing` must leave the entry intact
688
- // so a third identical caller still hits coalescing.
689
- let ownsInFlight = false
690
- try {
691
- const provider = config.provider
692
- if (!provider) {
693
- throw new Error('No search provider configured. Set search.provider in mixdog-config.json.')
694
- }
695
-
696
- const cacheArgs = searchArgsForCacheKey(args, config)
697
- searchCacheKey = buildCacheKey('search', {
698
- keywords: cacheArgs.keywords,
699
- provider,
700
- site: cacheArgs.site,
701
- type: cacheArgs.type,
702
- locale: cacheArgs.locale,
703
- contextSize: cacheArgs.contextSize,
704
- docs_index: cacheArgs.site && cacheArgs.type === 'web' ? 4 : null,
705
- maxResults: cacheArgs.maxResults,
706
- })
707
- const cachedSearch = getCachedEntry(cacheState, searchCacheKey)
708
- if (cachedSearch) {
709
- // Cache hit: skip docs-index network discovery. The cached payload
710
- // already includes any docs-index augmentation captured at insert
711
- // time, so re-running the network probe here would burn external I/O
712
- // on every cached search.
713
- return { ...cachedSearch.payload, cache: buildCacheMeta(cachedSearch, true) }
714
- }
715
-
716
- // Coalesce identical concurrent requests to the same cache key
717
- const existing = _searchInFlight.get(searchCacheKey)
718
- if (existing) return existing
719
- let resolveCoalesce, rejectCoalesce
720
- const coalescePromise = new Promise((res, rej) => { resolveCoalesce = res; rejectCoalesce = rej })
721
- // The first caller owns the real await path; duplicate callers may await this.
722
- // Mark it handled so a first-call failure does not leak as unhandledRejection.
723
- coalescePromise.catch(() => {})
724
- _searchInFlight.set(searchCacheKey, coalescePromise)
725
- // Only the owner of the in-flight entry may delete it. Coalesced callers
726
- // return `existing` above, but `return` still runs the outer finally; without
727
- // this flag a coalesced caller would delete the owner's in-flight entry mid-
728
- // flight and a third identical caller would miss coalescing.
729
- ownsInFlight = true
730
-
731
- try {
732
- const backendResult = await dispatchSearchBackend({
733
- provider,
734
- query: args.keywords,
735
- site: args.site,
736
- type: args.type,
737
- locale: args.locale,
738
- contextSize: args.contextSize,
739
- maxResults: args.maxResults || getRawSearchMaxResults(config),
740
- config,
741
- signal,
742
- })
743
- const response = backendResultToSearchResponse(backendResult)
744
-
745
- noteProviderSuccess(usageState, response.usedProvider, {
746
- lastCostUsdTicks: response.usage?.cost_in_usd_ticks || null,
747
- })
748
-
749
- const payload = await augmentSearchPayloadWithDocsIndex(
750
- { tool: 'search', provider, response },
751
- { ...args, ...cacheArgs, keywords: cacheArgs.keywords },
752
- timeoutMs,
753
- signal,
754
- )
755
- const cachedEntry = setCachedEntry(
756
- cacheState,
757
- searchCacheKey,
758
- payload,
759
- getSearchCacheTtlMs(args.type || 'web'),
760
- )
761
- flushCacheState()
762
- flushUsageState()
763
- const result = { ...payload, cache: buildCacheMeta(cachedEntry, false) }
764
- if (ownsInFlight) _searchInFlight.delete(searchCacheKey)
765
- resolveCoalesce(result)
766
- return result
767
- } catch (error) {
768
- if (ownsInFlight) _searchInFlight.delete(searchCacheKey)
769
- rejectCoalesce(error)
770
- noteProviderFailure(
771
- usageState,
772
- provider,
773
- error instanceof Error ? error.message : String(error),
774
- classifyProviderError(error),
775
- )
776
-
777
- const err = error instanceof Error ? error : new Error(String(error))
778
- err.details = { tool: 'search', provider }
779
- throw err
780
- }
781
- } finally {
782
- // Resolve coalesce waiters if not already rejected. Only the owner may
783
- // delete the in-flight entry — a coalesced caller that returned `existing`
784
- // earlier must not evict the still-running owner's coalesce target.
785
- if (ownsInFlight && _searchInFlight.has(searchCacheKey)) {
786
- _searchInFlight.delete(searchCacheKey)
787
- }
788
- }
789
- }
790
-
791
- const DEFAULT_FETCH_MAX_LENGTH = 50000
792
-
793
- // Apply character-level pagination to a cached or fresh fetch payload. Mirrors
794
- // the mcp-server-fetch reference: caller passes startIndex/maxLength and
795
- // receives a slice plus pointers (nextStartIndex, hasMore) for the next chunk.
796
- // totalLength is preserved so the caller can decide whether to keep paging.
797
- function applyFetchPagination(payload, args) {
798
- const fullContent = String(payload?.content ?? '')
799
- const totalLength = fullContent.length
800
- const startIndex = Math.max(0, Number.isFinite(args?.startIndex) ? args.startIndex : 0)
801
- const rawLimit = args?.maxLength
802
- const limit = rawLimit === 0
803
- ? Infinity
804
- : (rawLimit == null ? DEFAULT_FETCH_MAX_LENGTH : Math.max(0, Number(rawLimit)))
805
- if (startIndex >= totalLength) {
806
- return {
807
- ...payload,
808
- content: '',
809
- bytes: 0,
810
- totalLength,
811
- range: { startIndex, endIndex: startIndex },
812
- hasMore: false,
813
- nextStartIndex: null,
814
- truncated: false,
815
- }
816
- }
817
- const endIndex = Math.min(totalLength, startIndex + (Number.isFinite(limit) ? limit : totalLength - startIndex))
818
- const slice = fullContent.slice(startIndex, endIndex)
819
- const hasMore = endIndex < totalLength
820
- return {
821
- ...payload,
822
- content: slice,
823
- bytes: Buffer.byteLength(slice, 'utf-8'),
824
- totalLength,
825
- range: { startIndex, endIndex },
826
- hasMore,
827
- nextStartIndex: hasMore ? endIndex : null,
828
- truncated: hasMore || startIndex > 0,
829
- }
830
- }
831
-
832
- async function _fetchCore(args, { usageState, cacheState, timeoutMs, signal }) {
833
- const FETCH_URL_CAP = Math.max(1, Number(process.env.FETCH_URL_CAP) || 10)
834
- // Bound how many URLs scrape concurrently. Each non-cached URL can launch a
835
- // Puppeteer browser; running all FETCH_URL_CAP (default 10) at once can spawn
836
- // up to 10 Chromium processes simultaneously and exhaust memory/file handles.
837
- const FETCH_CONCURRENCY = Math.max(1, Number(process.env.FETCH_CONCURRENCY) || 3)
838
- const allUrls = Array.isArray(args.url) ? args.url : [args.url]
839
- const urls = allUrls.slice(0, FETCH_URL_CAP)
840
-
841
- const runOne = async (url, index) => {
842
- const normalizedUrl = normalizeCacheUrl(url)
843
- const fetchCacheKey = buildCacheKey('fetch:url', { url: normalizedUrl })
844
- const cached = getCachedEntry(cacheState, fetchCacheKey)
845
- if (cached) {
846
- return {
847
- index: index + 1,
848
- status: 'success',
849
- ...applyFetchPagination(cached.payload, args),
850
- cache: buildCacheMeta(cached, true),
851
- }
852
- }
853
-
854
- try {
855
- const [page] = await scrapeUrls([url], timeoutMs, usageState, signal)
856
- if (page?.error) {
857
- return {
858
- index: index + 1,
859
- status: 'error',
860
- tool: 'web_fetch',
861
- url,
862
- error: page.error,
863
- }
864
- }
865
- const payload = { tool: 'web_fetch', ...page }
866
- const cachedEntry = setCachedEntry(cacheState, fetchCacheKey, payload, getScrapeCacheTtlMs(false))
867
- return {
868
- index: index + 1,
869
- status: 'success',
870
- ...applyFetchPagination(payload, args),
871
- cache: buildCacheMeta(cachedEntry, false),
872
- }
873
- } catch (error) {
874
- // Pre-extractor failures (e.g. assertPublicUrl in web-tools) throw
875
- // before scrapeUrls returns a page-shaped error. Surface the raw
876
- // message verbatim so the caller sees the actual cause rather than
877
- // a silenced/swallowed result.
878
- const message = error instanceof Error
879
- ? (error.message || error.name || 'fetch failed')
880
- : String(error)
881
- const code = error?.code || error?.name || null
882
- return {
883
- index: index + 1,
884
- status: 'error',
885
- tool: 'web_fetch',
886
- url,
887
- error: message,
888
- ...(code ? { errorCode: code } : {}),
889
- }
890
- }
891
- }
892
-
893
- // Bounded worker pool: at most FETCH_CONCURRENCY runOne() calls in flight.
894
- const results = new Array(urls.length)
895
- let next = 0
896
- const worker = async () => {
897
- while (next < urls.length) {
898
- const i = next++
899
- results[i] = await runOne(urls[i], i)
900
- }
901
- }
902
- await Promise.all(
903
- Array.from({ length: Math.min(FETCH_CONCURRENCY, urls.length) }, worker),
904
- )
905
-
906
- return { tool: 'web_fetch', results, urlsTruncated: allUrls.length > urls.length ? allUrls.length : 0 }
907
- }
908
-
909
- // `search` and `web_fetch` are the public surface. `crawl` / `setup`
910
- // remain `public: false`: still reachable via the module's
911
- // handleToolCall and advertised when this module runs as a standalone
912
- // MCP server, but excluded from the unified build-tools-manifest output
913
- // so the Lead only sees the high-level entry points.
914
- import { TOOL_DEFS as toolDefinitions } from './tool-defs.mjs'
915
-
916
- const SEARCH_INSTRUCTIONS = '';
917
-
918
- const server = new Server(
919
- {
920
- name: 'mixdog-search',
921
- version: PLUGIN_VERSION,
922
- },
923
- {
924
- capabilities: {
925
- tools: {},
926
- },
927
- instructions: SEARCH_INSTRUCTIONS,
928
- },
929
- )
930
-
931
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
932
- tools: toolDefinitions.filter(t => t.public !== false),
933
- }))
934
-
935
- async function handleToolCall(name, rawArgs, { signal } = {}) {
936
- const config = loadConfig()
937
- const usageState = loadUsageState()
938
- const cacheState = loadCacheState()
939
- const timeoutMs = getRequestTimeoutMs(config)
940
-
941
- switch (name) {
942
- case 'web_fetch': {
943
- let urlArgs
944
- try {
945
- urlArgs = searchUrlArgsSchema.parse(normalizeSearchUrlArgs(rawArgs || {}))
946
- } catch (e) {
947
- if (e instanceof z.ZodError) {
948
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'Invalid arguments', details: e.errors }) }], isError: true }
949
- }
950
- throw e
951
- }
952
- try {
953
- const result = await _fetchCore(urlArgs, { config, usageState, cacheState, timeoutMs, signal })
954
- flushCacheState()
955
- flushUsageState()
956
- return {
957
- ...formattedText('fetch', result),
958
- ...(result.results.some(item => item.status === 'success') ? {} : { isError: true }),
959
- }
960
- } catch (error) {
961
- flushUsageState()
962
- const _rawErr = error instanceof Error ? error.message : String(error)
963
- return { ...jsonText({ tool: 'web_fetch', url: urlArgs.url, error: normalizeErrorMessage(_rawErr) }), isError: true }
964
- }
965
- }
966
- case 'search': {
967
- let args
968
- if (rawArgs && rawArgs.pattern !== undefined && rawArgs.query === undefined && rawArgs.keywords === undefined) {
969
- return { content: [{ type: 'text', text: 'Error: web search requires query; use glob(pattern=...) for file paths.' }], isError: true }
970
- }
971
- // The public aiWrapped schema uses `query` (to match recall/explore style).
972
- // The direct zod schema expects `keywords`. Normalize so standalone callers
973
- // using the advertised schema don't get a validation error.
974
- if (rawArgs && rawArgs.query !== undefined && rawArgs.keywords === undefined) {
975
- rawArgs = { ...rawArgs, keywords: rawArgs.query }
976
- delete rawArgs.query
977
- }
978
- try {
979
- args = searchArgsSchema.parse(normalizeSearchArgs(rawArgs || {}))
980
- } catch (e) {
981
- if (e instanceof z.ZodError) {
982
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'Invalid arguments', details: e.errors }) }], isError: true }
983
- }
984
- throw e
985
- }
986
- // Fan-out: array `keywords` -> N parallel single-keyword calls,
987
- // grouped per-query with `### Query:` headers (mirrors recall fan-out).
988
- if (Array.isArray(args.keywords) && args.keywords.length > 1) {
989
- // Cap fan-out breadth: bounds both the parallel provider calls and the
990
- // aggregate result size. Env-overridable; extras dropped with a note.
991
- const SEARCH_FANOUT_CAP = Math.max(1, Number(process.env.SEARCH_FANOUT_CAP) || 10)
992
- const allKeywords = [...new Set(args.keywords.map(kw => String(kw || '').trim()).filter(Boolean))]
993
- const dedupedKeywords = allKeywords.slice(0, SEARCH_FANOUT_CAP)
994
- const FANOUT_CONCURRENCY = Math.max(1, Number(process.env.SEARCH_FANOUT_CONCURRENCY) || 10)
995
- const fanOutAbort = new AbortController()
996
- const deadlineSec = Math.max(1, Number(process.env.SEARCH_FANOUT_DEADLINE_S) || 180)
997
- const deadlineMs = deadlineSec * 1000
998
- let deadlineTimer
999
- let onToolCallAbort
1000
- if (signal) {
1001
- const abortFanoutFromToolCall = () => {
1002
- fanOutAbort.abort(signal.reason ?? new Error('search aborted'))
1003
- }
1004
- if (signal.aborted) {
1005
- abortFanoutFromToolCall()
1006
- } else {
1007
- onToolCallAbort = abortFanoutFromToolCall
1008
- signal.addEventListener('abort', onToolCallAbort, { once: true })
1009
- }
1010
- }
1011
- const deadlineRace = new Promise((_res, rej) => {
1012
- deadlineTimer = setTimeout(() => {
1013
- fanOutAbort.abort(new Error(`fan-out deadline exceeded (${deadlineSec}s)`))
1014
- rej(Object.assign(new Error(`fan-out deadline exceeded (${deadlineSec}s)`), { _deadline: true }))
1015
- }, deadlineMs)
1016
- })
1017
- // Track per-query results as they settle so a deadline hit preserves
1018
- // anything that already completed (Promise.allSettled would otherwise
1019
- // only assign `settled` after the whole batch finishes).
1020
- const partial = new Array(dedupedKeywords.length)
1021
- let fanoutActive = 0
1022
- const fanoutPending = []
1023
- const acquireFanoutSlot = () => {
1024
- if (fanOutAbort.signal.aborted) return Promise.reject(fanOutAbort.signal.reason)
1025
- if (fanoutActive < FANOUT_CONCURRENCY) {
1026
- fanoutActive++
1027
- return Promise.resolve()
1028
- }
1029
- return new Promise((resolve, reject) => {
1030
- const waiter = { resolve, reject }
1031
- const onAbort = () => {
1032
- const idx = fanoutPending.indexOf(waiter)
1033
- if (idx !== -1) fanoutPending.splice(idx, 1)
1034
- reject(fanOutAbort.signal.reason)
1035
- }
1036
- waiter.onAbort = onAbort
1037
- fanoutPending.push(waiter)
1038
- fanOutAbort.signal.addEventListener('abort', onAbort, { once: true })
1039
- })
1040
- }
1041
- const releaseFanoutSlot = () => {
1042
- while (fanoutPending.length > 0) {
1043
- const waiter = fanoutPending.shift()
1044
- if (fanOutAbort.signal.aborted) {
1045
- if (waiter.onAbort) fanOutAbort.signal.removeEventListener('abort', waiter.onAbort)
1046
- waiter.reject(fanOutAbort.signal.reason)
1047
- continue
1048
- }
1049
- if (waiter.onAbort) fanOutAbort.signal.removeEventListener('abort', waiter.onAbort)
1050
- waiter.resolve() // slot transferred; do NOT change fanoutActive
1051
- return
1052
- }
1053
- fanoutActive--
1054
- }
1055
- const queryPromises = dedupedKeywords.map((kw, i) => (async () => {
1056
- await acquireFanoutSlot()
1057
- try {
1058
- const sub = await handleToolCall('search', { ...rawArgs, keywords: kw }, { signal: fanOutAbort.signal })
1059
- if (fanOutAbort.signal.aborted) throw fanOutAbort.signal.reason
1060
- const text = (sub.content || []).filter(p => p.type === 'text').map(p => p.text).join('\n')
1061
- if (sub.isError) {
1062
- throw Object.assign(new Error(text || 'sub-search failed'), { _subError: true })
1063
- }
1064
- return `### Query: ${kw}\n\n${text}`
1065
- } finally {
1066
- releaseFanoutSlot()
1067
- }
1068
- })().then(
1069
- (value) => { partial[i] = { status: 'fulfilled', value }; return value },
1070
- (reason) => { partial[i] = { status: 'rejected', reason }; throw reason },
1071
- ))
1072
- let settled
1073
- try {
1074
- settled = await Promise.race([
1075
- Promise.allSettled(queryPromises),
1076
- deadlineRace,
1077
- ])
1078
- } catch (err) {
1079
- if (!err._deadline) throw err
1080
- // Deadline hit — preserve any completed partial results; mark the
1081
- // rest as rejected with the abort reason.
1082
- settled = dedupedKeywords.map((_kw, i) =>
1083
- partial[i] ?? { status: 'rejected', reason: fanOutAbort.signal.reason }
1084
- )
1085
- } finally {
1086
- clearTimeout(deadlineTimer)
1087
- if (signal && onToolCallAbort) {
1088
- signal.removeEventListener('abort', onToolCallAbort)
1089
- }
1090
- }
1091
- const anyFulfilled = settled.some(r => r.status === 'fulfilled')
1092
- const sections = settled.map((r, i) =>
1093
- r.status === 'fulfilled'
1094
- ? r.value
1095
- : `### Query: ${dedupedKeywords[i]}\n\n[error] ${normalizeErrorMessage(String(r.reason?.message || r.reason))}`
1096
- )
1097
- const fanoutNote = allKeywords.length > dedupedKeywords.length
1098
- ? `[fan-out capped at ${SEARCH_FANOUT_CAP} of ${allKeywords.length} keywords; raise SEARCH_FANOUT_CAP for more]\n\n`
1099
- : ''
1100
- return {
1101
- content: [{ type: 'text', text: fanoutNote + sections.join('\n\n---\n\n') }],
1102
- ...(anyFulfilled ? {} : { isError: true }),
1103
- }
1104
- }
1105
- try {
1106
- const result = await _searchCore(args, { config, usageState, cacheState, timeoutMs, signal })
1107
- flushUsageState()
1108
- return formattedText('search', result)
1109
- } catch (error) {
1110
- flushUsageState()
1111
- const details = error.details || { tool: 'search' }
1112
- const _rawErr = error instanceof Error ? error.message : String(error)
1113
- return { ...jsonText({ ...details, error: normalizeErrorMessage(_rawErr) }), isError: true }
1114
- }
1115
- }
1116
-
1117
- case 'crawl': {
1118
- let args
1119
- try {
1120
- args = crawlArgsSchema.parse(rawArgs || {})
1121
- } catch (e) {
1122
- if (e instanceof z.ZodError) {
1123
- return { content: [{ type: 'text', text: JSON.stringify({ error: 'Invalid arguments', details: e.errors }) }], isError: true }
1124
- }
1125
- throw e
1126
- }
1127
- try {
1128
- const pages = await crawlSite(
1129
- args.url,
1130
- {
1131
- maxPages: args.maxPages || config.crawl?.maxPages || 10,
1132
- maxDepth: args.maxDepth ?? config.crawl?.maxDepth ?? 1,
1133
- sameDomainOnly: args.sameDomainOnly ?? config.crawl?.sameDomainOnly ?? true,
1134
- },
1135
- timeoutMs,
1136
- usageState,
1137
- signal,
1138
- )
1139
- saveUsageState(usageState)
1140
- return formattedText('crawl', {
1141
- tool: 'crawl',
1142
- pages,
1143
- })
1144
- } catch (error) {
1145
- saveUsageState(usageState)
1146
- const _rawErr = error instanceof Error ? error.message : String(error)
1147
- return { ...jsonText({
1148
- tool: 'crawl',
1149
- url: args.url,
1150
- error: normalizeErrorMessage(_rawErr),
1151
- }), isError: true }
1152
- }
1153
- }
1154
-
1155
- case 'setup': {
1156
- return await handleSetup(server)
1157
- }
1158
- default:
1159
- throw new Error(`Unknown tool: ${name}`)
1160
- }
1161
- }
1162
-
1163
- server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
1164
- return handleToolCall(request.params.name, request.params.arguments, { signal: extra?.signal })
1165
- })
1166
-
1167
- /* ── Module exports (used when imported by mixdog-unified) ── */
1168
- export { toolDefinitions as TOOL_DEFS }
1169
- export { SEARCH_INSTRUCTIONS as instructions }
1170
-
1171
- export { handleToolCall }
1172
- export async function start() { await writeStartupSnapshot() }
1173
- export function stop() { flushUsageState(); flushCacheState() }