magi-ai 0.1.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 (300) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +377 -0
  3. package/README.md +377 -0
  4. package/dist/bin/magi-benchmark.d.ts +14 -0
  5. package/dist/bin/magi-benchmark.js +93 -0
  6. package/dist/bin/magi-mcp.d.ts +8 -0
  7. package/dist/bin/magi-mcp.js +28 -0
  8. package/dist/bin/magi.d.ts +2 -0
  9. package/dist/bin/magi.js +634 -0
  10. package/dist/src/adapters/base.d.ts +34 -0
  11. package/dist/src/adapters/base.js +149 -0
  12. package/dist/src/adapters/claude.d.ts +29 -0
  13. package/dist/src/adapters/claude.js +65 -0
  14. package/dist/src/adapters/codex.d.ts +21 -0
  15. package/dist/src/adapters/codex.js +41 -0
  16. package/dist/src/adapters/gemini.d.ts +18 -0
  17. package/dist/src/adapters/gemini.js +31 -0
  18. package/dist/src/adapters/registry.d.ts +19 -0
  19. package/dist/src/adapters/registry.js +59 -0
  20. package/dist/src/audit/hash-chain.d.ts +21 -0
  21. package/dist/src/audit/hash-chain.js +70 -0
  22. package/dist/src/audit/types.d.ts +25 -0
  23. package/dist/src/audit/types.js +1 -0
  24. package/dist/src/audit/writer.d.ts +18 -0
  25. package/dist/src/audit/writer.js +100 -0
  26. package/dist/src/benchmark/golden-tasks.d.ts +9 -0
  27. package/dist/src/benchmark/golden-tasks.js +476 -0
  28. package/dist/src/benchmark/reporter.d.ts +5 -0
  29. package/dist/src/benchmark/reporter.js +107 -0
  30. package/dist/src/benchmark/runner.d.ts +30 -0
  31. package/dist/src/benchmark/runner.js +224 -0
  32. package/dist/src/benchmark/scorer.d.ts +12 -0
  33. package/dist/src/benchmark/scorer.js +124 -0
  34. package/dist/src/benchmark/types.d.ts +54 -0
  35. package/dist/src/benchmark/types.js +1 -0
  36. package/dist/src/cache/deliberation-cache.d.ts +49 -0
  37. package/dist/src/cache/deliberation-cache.js +127 -0
  38. package/dist/src/cli/commands/config-cmd.d.ts +11 -0
  39. package/dist/src/cli/commands/config-cmd.js +190 -0
  40. package/dist/src/cli/commands/demo.d.ts +12 -0
  41. package/dist/src/cli/commands/demo.js +66 -0
  42. package/dist/src/cli/commands/setup.d.ts +7 -0
  43. package/dist/src/cli/commands/setup.js +182 -0
  44. package/dist/src/cli/i18n.d.ts +89 -0
  45. package/dist/src/cli/i18n.js +176 -0
  46. package/dist/src/cli/interactive-select.d.ts +27 -0
  47. package/dist/src/cli/interactive-select.js +130 -0
  48. package/dist/src/cli/tui-setup.d.ts +24 -0
  49. package/dist/src/cli/tui-setup.js +42 -0
  50. package/dist/src/config/cli-detector.d.ts +37 -0
  51. package/dist/src/config/cli-detector.js +99 -0
  52. package/dist/src/config/user-config.d.ts +81 -0
  53. package/dist/src/config/user-config.js +134 -0
  54. package/dist/src/context/auto-collector.d.ts +43 -0
  55. package/dist/src/context/auto-collector.js +337 -0
  56. package/dist/src/context/manager.d.ts +35 -0
  57. package/dist/src/context/manager.js +162 -0
  58. package/dist/src/context/serializer.d.ts +20 -0
  59. package/dist/src/context/serializer.js +52 -0
  60. package/dist/src/demo/recorded-deliberation.d.ts +13 -0
  61. package/dist/src/demo/recorded-deliberation.js +277 -0
  62. package/dist/src/engine/angel-detector.d.ts +83 -0
  63. package/dist/src/engine/angel-detector.js +334 -0
  64. package/dist/src/engine/at-field.d.ts +40 -0
  65. package/dist/src/engine/at-field.js +195 -0
  66. package/dist/src/engine/berserk-orchestrator.d.ts +66 -0
  67. package/dist/src/engine/berserk-orchestrator.js +378 -0
  68. package/dist/src/engine/change-metrics.d.ts +56 -0
  69. package/dist/src/engine/change-metrics.js +214 -0
  70. package/dist/src/engine/consensus.d.ts +20 -0
  71. package/dist/src/engine/consensus.js +146 -0
  72. package/dist/src/engine/dead-sea-scrolls.d.ts +132 -0
  73. package/dist/src/engine/dead-sea-scrolls.js +610 -0
  74. package/dist/src/engine/drift-detector.d.ts +39 -0
  75. package/dist/src/engine/drift-detector.js +225 -0
  76. package/dist/src/engine/dummy-plug.d.ts +44 -0
  77. package/dist/src/engine/dummy-plug.js +190 -0
  78. package/dist/src/engine/engram-manager.d.ts +55 -0
  79. package/dist/src/engine/engram-manager.js +306 -0
  80. package/dist/src/engine/events.d.ts +130 -0
  81. package/dist/src/engine/events.js +44 -0
  82. package/dist/src/engine/gospel.d.ts +30 -0
  83. package/dist/src/engine/gospel.js +129 -0
  84. package/dist/src/engine/hallucination-detector.d.ts +33 -0
  85. package/dist/src/engine/hallucination-detector.js +215 -0
  86. package/dist/src/engine/human-resolver.d.ts +19 -0
  87. package/dist/src/engine/human-resolver.js +89 -0
  88. package/dist/src/engine/instrumentality.d.ts +64 -0
  89. package/dist/src/engine/instrumentality.js +297 -0
  90. package/dist/src/engine/iruel-battle.d.ts +79 -0
  91. package/dist/src/engine/iruel-battle.js +319 -0
  92. package/dist/src/engine/kernel/deliberation-kernel.d.ts +12 -0
  93. package/dist/src/engine/kernel/deliberation-kernel.js +303 -0
  94. package/dist/src/engine/kernel/index.d.ts +8 -0
  95. package/dist/src/engine/kernel/index.js +7 -0
  96. package/dist/src/engine/kernel/phase-runner.d.ts +10 -0
  97. package/dist/src/engine/kernel/phase-runner.js +155 -0
  98. package/dist/src/engine/kernel/post-processor.d.ts +17 -0
  99. package/dist/src/engine/kernel/post-processor.js +131 -0
  100. package/dist/src/engine/kernel/types.d.ts +107 -0
  101. package/dist/src/engine/kernel/types.js +1 -0
  102. package/dist/src/engine/kernel/unit-executor.d.ts +6 -0
  103. package/dist/src/engine/kernel/unit-executor.js +132 -0
  104. package/dist/src/engine/lcl-manager.d.ts +44 -0
  105. package/dist/src/engine/lcl-manager.js +143 -0
  106. package/dist/src/engine/middleware/cache.d.ts +7 -0
  107. package/dist/src/engine/middleware/cache.js +29 -0
  108. package/dist/src/engine/middleware/chain.d.ts +18 -0
  109. package/dist/src/engine/middleware/chain.js +45 -0
  110. package/dist/src/engine/middleware/firewall.d.ts +8 -0
  111. package/dist/src/engine/middleware/firewall.js +24 -0
  112. package/dist/src/engine/middleware/index.d.ts +4 -0
  113. package/dist/src/engine/middleware/index.js +3 -0
  114. package/dist/src/engine/middleware/types.d.ts +43 -0
  115. package/dist/src/engine/middleware/types.js +1 -0
  116. package/dist/src/engine/nebuchadnezzar-key.d.ts +61 -0
  117. package/dist/src/engine/nebuchadnezzar-key.js +203 -0
  118. package/dist/src/engine/neon-genesis.d.ts +52 -0
  119. package/dist/src/engine/neon-genesis.js +203 -0
  120. package/dist/src/engine/objective-judge.d.ts +53 -0
  121. package/dist/src/engine/objective-judge.js +214 -0
  122. package/dist/src/engine/offline-mode.d.ts +18 -0
  123. package/dist/src/engine/offline-mode.js +46 -0
  124. package/dist/src/engine/orchestrator.d.ts +79 -0
  125. package/dist/src/engine/orchestrator.js +58 -0
  126. package/dist/src/engine/secret-cipher.d.ts +26 -0
  127. package/dist/src/engine/secret-cipher.js +114 -0
  128. package/dist/src/engine/seele-council.d.ts +90 -0
  129. package/dist/src/engine/seele-council.js +482 -0
  130. package/dist/src/engine/self-destruct.d.ts +61 -0
  131. package/dist/src/engine/self-destruct.js +231 -0
  132. package/dist/src/engine/self-evolution.d.ts +64 -0
  133. package/dist/src/engine/self-evolution.js +368 -0
  134. package/dist/src/engine/sync-rate.d.ts +45 -0
  135. package/dist/src/engine/sync-rate.js +151 -0
  136. package/dist/src/engine/type666-firewall.d.ts +76 -0
  137. package/dist/src/engine/type666-firewall.js +343 -0
  138. package/dist/src/engine/umbilical-cable.d.ts +41 -0
  139. package/dist/src/engine/umbilical-cable.js +192 -0
  140. package/dist/src/index.d.ts +106 -0
  141. package/dist/src/index.js +426 -0
  142. package/dist/src/mcp/server.d.ts +38 -0
  143. package/dist/src/mcp/server.js +196 -0
  144. package/dist/src/metrics/token-tracker.d.ts +38 -0
  145. package/dist/src/metrics/token-tracker.js +112 -0
  146. package/dist/src/parsers/json-extractor.d.ts +9 -0
  147. package/dist/src/parsers/json-extractor.js +239 -0
  148. package/dist/src/parsers/opinion-schema.d.ts +81 -0
  149. package/dist/src/parsers/opinion-schema.js +147 -0
  150. package/dist/src/parsers/unstructured-parser.d.ts +20 -0
  151. package/dist/src/parsers/unstructured-parser.js +122 -0
  152. package/dist/src/pipelines/architecture.d.ts +10 -0
  153. package/dist/src/pipelines/architecture.js +9 -0
  154. package/dist/src/pipelines/bug-analysis.d.ts +9 -0
  155. package/dist/src/pipelines/bug-analysis.js +8 -0
  156. package/dist/src/pipelines/code-review.d.ts +10 -0
  157. package/dist/src/pipelines/code-review.js +30 -0
  158. package/dist/src/pipelines/custom.d.ts +14 -0
  159. package/dist/src/pipelines/custom.js +29 -0
  160. package/dist/src/pipelines/registry.d.ts +9 -0
  161. package/dist/src/pipelines/registry.js +20 -0
  162. package/dist/src/prompts/personas.d.ts +6 -0
  163. package/dist/src/prompts/personas.js +44 -0
  164. package/dist/src/prompts/schemas.d.ts +4 -0
  165. package/dist/src/prompts/schemas.js +24 -0
  166. package/dist/src/prompts/templates.d.ts +6 -0
  167. package/dist/src/prompts/templates.js +91 -0
  168. package/dist/src/repl/accessibility.d.ts +23 -0
  169. package/dist/src/repl/accessibility.js +46 -0
  170. package/dist/src/repl/banner.d.ts +4 -0
  171. package/dist/src/repl/banner.js +28 -0
  172. package/dist/src/repl/boot-animation.d.ts +13 -0
  173. package/dist/src/repl/boot-animation.js +143 -0
  174. package/dist/src/repl/completer.d.ts +21 -0
  175. package/dist/src/repl/completer.js +168 -0
  176. package/dist/src/repl/context.d.ts +24 -0
  177. package/dist/src/repl/context.js +42 -0
  178. package/dist/src/repl/display-utils.d.ts +13 -0
  179. package/dist/src/repl/display-utils.js +65 -0
  180. package/dist/src/repl/event-listener.d.ts +18 -0
  181. package/dist/src/repl/event-listener.js +112 -0
  182. package/dist/src/repl/export-formatter.d.ts +8 -0
  183. package/dist/src/repl/export-formatter.js +73 -0
  184. package/dist/src/repl/ghost-text.d.ts +31 -0
  185. package/dist/src/repl/ghost-text.js +119 -0
  186. package/dist/src/repl/handoff-animation.d.ts +15 -0
  187. package/dist/src/repl/handoff-animation.js +65 -0
  188. package/dist/src/repl/history.d.ts +16 -0
  189. package/dist/src/repl/history.js +130 -0
  190. package/dist/src/repl/job-registry.d.ts +26 -0
  191. package/dist/src/repl/job-registry.js +80 -0
  192. package/dist/src/repl/magi-repl.d.ts +72 -0
  193. package/dist/src/repl/magi-repl.js +1008 -0
  194. package/dist/src/repl/multiline-input.d.ts +45 -0
  195. package/dist/src/repl/multiline-input.js +78 -0
  196. package/dist/src/repl/prompt-builder.d.ts +19 -0
  197. package/dist/src/repl/prompt-builder.js +36 -0
  198. package/dist/src/repl/repl-state.d.ts +5 -0
  199. package/dist/src/repl/repl-state.js +19 -0
  200. package/dist/src/repl/result-display.d.ts +8 -0
  201. package/dist/src/repl/result-display.js +195 -0
  202. package/dist/src/repl/session-stats.d.ts +26 -0
  203. package/dist/src/repl/session-stats.js +119 -0
  204. package/dist/src/repl/slash-commands.d.ts +60 -0
  205. package/dist/src/repl/slash-commands.js +725 -0
  206. package/dist/src/repl/terminal-sanitize.d.ts +14 -0
  207. package/dist/src/repl/terminal-sanitize.js +19 -0
  208. package/dist/src/reporters/console.d.ts +7 -0
  209. package/dist/src/reporters/console.js +78 -0
  210. package/dist/src/reporters/json.d.ts +2 -0
  211. package/dist/src/reporters/json.js +3 -0
  212. package/dist/src/reporters/markdown.d.ts +2 -0
  213. package/dist/src/reporters/markdown.js +65 -0
  214. package/dist/src/reporters/streaming.d.ts +20 -0
  215. package/dist/src/reporters/streaming.js +178 -0
  216. package/dist/src/tui/activity-log.d.ts +23 -0
  217. package/dist/src/tui/activity-log.js +67 -0
  218. package/dist/src/tui/animations.d.ts +39 -0
  219. package/dist/src/tui/animations.js +167 -0
  220. package/dist/src/tui/ansi.d.ts +28 -0
  221. package/dist/src/tui/ansi.js +51 -0
  222. package/dist/src/tui/boot-sequence.d.ts +11 -0
  223. package/dist/src/tui/boot-sequence.js +98 -0
  224. package/dist/src/tui/colors.d.ts +101 -0
  225. package/dist/src/tui/colors.js +71 -0
  226. package/dist/src/tui/header.d.ts +24 -0
  227. package/dist/src/tui/header.js +122 -0
  228. package/dist/src/tui/index.d.ts +3 -0
  229. package/dist/src/tui/index.js +3 -0
  230. package/dist/src/tui/keypress.d.ts +25 -0
  231. package/dist/src/tui/keypress.js +95 -0
  232. package/dist/src/tui/layout.d.ts +74 -0
  233. package/dist/src/tui/layout.js +171 -0
  234. package/dist/src/tui/magi-tui.d.ts +101 -0
  235. package/dist/src/tui/magi-tui.js +754 -0
  236. package/dist/src/tui/panel.d.ts +45 -0
  237. package/dist/src/tui/panel.js +292 -0
  238. package/dist/src/tui/screen-buffer.d.ts +54 -0
  239. package/dist/src/tui/screen-buffer.js +262 -0
  240. package/dist/src/tui/status-bar.d.ts +25 -0
  241. package/dist/src/tui/status-bar.js +124 -0
  242. package/dist/src/tui/terminal-detect.d.ts +26 -0
  243. package/dist/src/tui/terminal-detect.js +44 -0
  244. package/dist/src/tui/tui-helpers.d.ts +12 -0
  245. package/dist/src/tui/tui-helpers.js +37 -0
  246. package/dist/src/types/adapter.d.ts +75 -0
  247. package/dist/src/types/adapter.js +36 -0
  248. package/dist/src/types/config.d.ts +108 -0
  249. package/dist/src/types/config.js +85 -0
  250. package/dist/src/types/consensus.d.ts +55 -0
  251. package/dist/src/types/consensus.js +17 -0
  252. package/dist/src/types/core.d.ts +178 -0
  253. package/dist/src/types/core.js +85 -0
  254. package/dist/src/types/magi-api.d.ts +62 -0
  255. package/dist/src/types/magi-api.js +7 -0
  256. package/dist/src/types/phase-h.d.ts +142 -0
  257. package/dist/src/types/phase-h.js +7 -0
  258. package/dist/src/types/phase-i.d.ts +186 -0
  259. package/dist/src/types/phase-i.js +6 -0
  260. package/dist/src/types/phase-k.d.ts +259 -0
  261. package/dist/src/types/phase-k.js +6 -0
  262. package/dist/src/types/phase-l.d.ts +199 -0
  263. package/dist/src/types/phase-l.js +6 -0
  264. package/dist/src/types/pipeline.d.ts +37 -0
  265. package/dist/src/types/pipeline.js +2 -0
  266. package/dist/src/utils/abstain-factory.d.ts +2 -0
  267. package/dist/src/utils/abstain-factory.js +18 -0
  268. package/dist/src/utils/errors.d.ts +34 -0
  269. package/dist/src/utils/errors.js +59 -0
  270. package/dist/src/utils/file-validator.d.ts +50 -0
  271. package/dist/src/utils/file-validator.js +124 -0
  272. package/dist/src/utils/fire-and-forget.d.ts +5 -0
  273. package/dist/src/utils/fire-and-forget.js +10 -0
  274. package/dist/src/utils/flag-validator.d.ts +21 -0
  275. package/dist/src/utils/flag-validator.js +79 -0
  276. package/dist/src/utils/freeze.d.ts +8 -0
  277. package/dist/src/utils/freeze.js +16 -0
  278. package/dist/src/utils/language-detector.d.ts +16 -0
  279. package/dist/src/utils/language-detector.js +159 -0
  280. package/dist/src/utils/latency-tracker.d.ts +45 -0
  281. package/dist/src/utils/latency-tracker.js +100 -0
  282. package/dist/src/utils/logger.d.ts +33 -0
  283. package/dist/src/utils/logger.js +112 -0
  284. package/dist/src/utils/process.d.ts +40 -0
  285. package/dist/src/utils/process.js +253 -0
  286. package/dist/src/utils/retry.d.ts +12 -0
  287. package/dist/src/utils/retry.js +30 -0
  288. package/dist/src/utils/safe-fs.d.ts +38 -0
  289. package/dist/src/utils/safe-fs.js +56 -0
  290. package/dist/src/utils/safe-json-parse.d.ts +15 -0
  291. package/dist/src/utils/safe-json-parse.js +49 -0
  292. package/dist/src/utils/sanitize.d.ts +14 -0
  293. package/dist/src/utils/sanitize.js +186 -0
  294. package/dist/src/utils/semaphore.d.ts +22 -0
  295. package/dist/src/utils/semaphore.js +57 -0
  296. package/dist/src/utils/shutdown.d.ts +6 -0
  297. package/dist/src/utils/shutdown.js +51 -0
  298. package/dist/src/utils/tty.d.ts +5 -0
  299. package/dist/src/utils/tty.js +7 -0
  300. package/package.json +82 -0
@@ -0,0 +1,426 @@
1
+ /**
2
+ * MAGI System - Public API
3
+ *
4
+ * Usage:
5
+ * import { Magi } from 'magi-ai';
6
+ * const magi = new Magi();
7
+ * const result = await magi.deliberate({ type: 'code-review', ... });
8
+ */
9
+ import { DEFAULT_CONFIG } from './types/config.js';
10
+ import { AdapterRegistry } from './adapters/registry.js';
11
+ import { ClaudeAdapter } from './adapters/claude.js';
12
+ import { CodexAdapter } from './adapters/codex.js';
13
+ import { GeminiAdapter } from './adapters/gemini.js';
14
+ import { PipelineRegistry } from './pipelines/registry.js';
15
+ import { CodeReviewPipeline } from './pipelines/code-review.js';
16
+ import { ArchitecturePipeline } from './pipelines/architecture.js';
17
+ import { BugAnalysisPipeline } from './pipelines/bug-analysis.js';
18
+ import { CustomPipeline } from './pipelines/custom.js';
19
+ import { Orchestrator } from './engine/orchestrator.js';
20
+ import { ContextManager } from './context/manager.js';
21
+ import { DeliberationCache } from './cache/deliberation-cache.js';
22
+ import { MagiEventBus } from './engine/events.js';
23
+ import { TokenTracker } from './metrics/token-tracker.js';
24
+ import { ObjectiveJudge } from './engine/objective-judge.js';
25
+ import { setLogLevel, initAuditLog } from './utils/logger.js';
26
+ import { SyncRateTracker } from './engine/sync-rate.js';
27
+ import { ATField } from './engine/at-field.js';
28
+ import { GospelChronicle } from './engine/gospel.js';
29
+ import { SecretCipher } from './engine/secret-cipher.js';
30
+ import { UmbilicalCable } from './engine/umbilical-cable.js';
31
+ import { OfflineMode } from './engine/offline-mode.js';
32
+ import { DummyPlugSystem } from './engine/dummy-plug.js';
33
+ import { EngramManager } from './engine/engram-manager.js';
34
+ import { DriftDetector } from './engine/drift-detector.js';
35
+ import { LCLManager } from './engine/lcl-manager.js';
36
+ import { InstrumentalityEngine } from './engine/instrumentality.js';
37
+ import { BerserkOrchestrator } from './engine/berserk-orchestrator.js';
38
+ // Phase K modules
39
+ import { Type666Firewall } from './engine/type666-firewall.js';
40
+ import { NebuchadnezzarKey } from './engine/nebuchadnezzar-key.js';
41
+ import { AngelDetector } from './engine/angel-detector.js';
42
+ import { DeadSeaScrolls } from './engine/dead-sea-scrolls.js';
43
+ // Phase L modules
44
+ import { IruelBattleSystem } from './engine/iruel-battle.js';
45
+ import { NeonGenesis } from './engine/neon-genesis.js';
46
+ import { SelfEvolutionEngine } from './engine/self-evolution.js';
47
+ import { SeeleCouncil } from './engine/seele-council.js';
48
+ import { SelfDestructSequence } from './engine/self-destruct.js';
49
+ import { logger } from './utils/logger.js';
50
+ import { fireAndForget } from './utils/fire-and-forget.js';
51
+ export class Magi {
52
+ orchestrator;
53
+ berserkOrchestrator;
54
+ adapters;
55
+ pipelines;
56
+ contextManager;
57
+ config;
58
+ eventBus;
59
+ tokenTracker;
60
+ engramManager;
61
+ syncRateTracker;
62
+ umbilicalCable;
63
+ atField;
64
+ initPromise;
65
+ initialized = false;
66
+ // Promoted from constructor locals → private fields (for namespace API)
67
+ gospel;
68
+ driftDetector;
69
+ lclManager;
70
+ type666Firewall;
71
+ nebuchadnezzarKey;
72
+ secretCipher;
73
+ objectiveJudge;
74
+ dummyPlug;
75
+ offlineMode;
76
+ iruelBattle;
77
+ // Lazy-instantiated engines (only created when accessed via namespace)
78
+ _angelDetector;
79
+ _deadSeaScrolls;
80
+ _selfEvolution;
81
+ _seeleCouncil;
82
+ _selfDestruct;
83
+ _neonGenesis;
84
+ // Cached namespace objects
85
+ _runtime;
86
+ _diagnostics;
87
+ _admin;
88
+ constructor(config) {
89
+ this.config = { ...DEFAULT_CONFIG, ...config };
90
+ setLogLevel(this.config.logLevel);
91
+ this.adapters = new AdapterRegistry();
92
+ this.pipelines = new PipelineRegistry();
93
+ this.contextManager = new ContextManager(this.config.workspaceDir);
94
+ const pipelines = this.pipelines;
95
+ const context = this.contextManager;
96
+ this.eventBus = new MagiEventBus();
97
+ this.tokenTracker = new TokenTracker(this.config.workspaceDir);
98
+ // Register adapters — only enabled units (default: all 3)
99
+ const enabledUnits = this.config.enabledUnits ?? ['MELCHIOR', 'BALTHASAR', 'CASPER'];
100
+ const adapterFactories = {
101
+ MELCHIOR: () => new ClaudeAdapter(this.config.adapters.MELCHIOR),
102
+ BALTHASAR: () => new CodexAdapter(this.config.adapters.BALTHASAR),
103
+ CASPER: () => new GeminiAdapter(this.config.adapters.CASPER),
104
+ };
105
+ for (const unit of enabledUnits) {
106
+ const factory = adapterFactories[unit];
107
+ if (factory)
108
+ this.adapters.register(factory());
109
+ }
110
+ // Auto-adjust quorum and phases for reduced unit counts
111
+ if (enabledUnits.length === 1) {
112
+ this.config = {
113
+ ...this.config,
114
+ defaultPipeline: {
115
+ ...this.config.defaultPipeline,
116
+ phases: ['initial-opinion', 'final-vote'],
117
+ consensus: { ...this.config.defaultPipeline.consensus, quorum: 1 },
118
+ },
119
+ };
120
+ }
121
+ else if (enabledUnits.length === 2) {
122
+ const needsStrategyFix = this.config.defaultPipeline.consensus.deadlockStrategy === 'melchior-tiebreak'
123
+ && !enabledUnits.includes('MELCHIOR');
124
+ this.config = {
125
+ ...this.config,
126
+ defaultPipeline: {
127
+ ...this.config.defaultPipeline,
128
+ consensus: {
129
+ ...this.config.defaultPipeline.consensus,
130
+ quorum: 2,
131
+ ...(needsStrategyFix ? { deadlockStrategy: 'highest-confidence' } : {}),
132
+ },
133
+ },
134
+ };
135
+ }
136
+ // Register pipelines
137
+ pipelines.register(new CodeReviewPipeline());
138
+ pipelines.register(new ArchitecturePipeline());
139
+ pipelines.register(new BugAnalysisPipeline());
140
+ pipelines.register(new CustomPipeline());
141
+ const cache = this.config.cacheEnabled !== false
142
+ ? new DeliberationCache(this.config.cacheTtlMs)
143
+ : undefined;
144
+ this.objectiveJudge = new ObjectiveJudge(this.config.workspaceDir);
145
+ // Phase H modules (all optional, graceful degradation)
146
+ this.syncRateTracker = new SyncRateTracker(this.config.workspaceDir);
147
+ this.atField = new ATField();
148
+ this.gospel = new GospelChronicle(this.config.workspaceDir);
149
+ const allUnits = this.adapters.getAll().map(a => a.unit);
150
+ this.umbilicalCable = new UmbilicalCable(allUnits);
151
+ this.dummyPlug = new DummyPlugSystem(this.syncRateTracker);
152
+ this.offlineMode = new OfflineMode(cache);
153
+ // Secret cipher
154
+ this.secretCipher = new SecretCipher(this.config.workspaceDir);
155
+ // Phase I modules (all optional, graceful degradation)
156
+ this.engramManager = new EngramManager(this.config.workspaceDir, this.eventBus);
157
+ this.driftDetector = new DriftDetector();
158
+ this.lclManager = new LCLManager(undefined, this.eventBus);
159
+ const instrumentality = new InstrumentalityEngine(this.adapters, this.eventBus);
160
+ // Phase K modules (all optional, graceful degradation)
161
+ this.type666Firewall = new Type666Firewall(this.eventBus);
162
+ this.nebuchadnezzarKey = new NebuchadnezzarKey(this.config.workspaceDir, this.eventBus);
163
+ // Phase L modules (all optional, graceful degradation)
164
+ this.iruelBattle = new IruelBattleSystem(allUnits, this.eventBus, this.driftDetector);
165
+ this.orchestrator = new Orchestrator({
166
+ adapters: this.adapters,
167
+ pipelines,
168
+ contextManager: context,
169
+ maxConcurrentDeliberations: this.config.maxConcurrentDeliberations,
170
+ cache,
171
+ eventBus: this.eventBus,
172
+ tokenTracker: this.tokenTracker,
173
+ objectiveJudge: this.objectiveJudge,
174
+ syncRateTracker: this.syncRateTracker,
175
+ atField: this.atField,
176
+ gospel: this.gospel,
177
+ umbilicalCable: this.umbilicalCable,
178
+ dummyPlug: this.dummyPlug,
179
+ offlineMode: this.offlineMode,
180
+ engramManager: this.engramManager,
181
+ lclManager: this.lclManager,
182
+ instrumentality,
183
+ driftDetector: this.driftDetector,
184
+ type666Firewall: this.type666Firewall,
185
+ nebuchadnezzarKey: this.nebuchadnezzarKey,
186
+ iruelBattle: this.iruelBattle,
187
+ fileAccessEnabled: this.config.fileAccess?.enabled,
188
+ });
189
+ // Persistent BerserkOrchestrator — reused across calls for LatencyTracker accumulation
190
+ this.berserkOrchestrator = new BerserkOrchestrator(this.adapters, this.pipelines, this.contextManager, this.eventBus, undefined, this.type666Firewall, this.config.fileAccess?.enabled);
191
+ // Collect all async initializations into a single awaitable promise
192
+ // (replaces individual fire-and-forget .catch() calls — SAFE-03)
193
+ this.initPromise = Promise.allSettled([
194
+ this.syncRateTracker.load(),
195
+ this.gospel.initialize(),
196
+ this.secretCipher.autoInitialize(),
197
+ this.engramManager.load(),
198
+ this.nebuchadnezzarKey.load(),
199
+ this.config.auditLog ? initAuditLog(this.config.auditLog) : Promise.resolve(),
200
+ ]).then(results => {
201
+ for (const r of results) {
202
+ if (r.status === 'rejected') {
203
+ logger.debug(`Init module failed (non-fatal): ${String(r.reason)}`);
204
+ }
205
+ }
206
+ this.initialized = true;
207
+ });
208
+ }
209
+ async ensureInitialized() {
210
+ if (!this.initialized)
211
+ await this.initPromise;
212
+ }
213
+ // ── Lazy-instantiated engine accessors ──────────────────
214
+ get angelDetector() {
215
+ if (!this._angelDetector) {
216
+ this._angelDetector = new AngelDetector(undefined, this.eventBus);
217
+ }
218
+ return this._angelDetector;
219
+ }
220
+ get deadSeaScrolls() {
221
+ if (!this._deadSeaScrolls) {
222
+ this._deadSeaScrolls = new DeadSeaScrolls(this.config.workspaceDir, this.eventBus);
223
+ }
224
+ return this._deadSeaScrolls;
225
+ }
226
+ get selfEvolution() {
227
+ if (!this._selfEvolution) {
228
+ this._selfEvolution = new SelfEvolutionEngine(this.config.workspaceDir, '.', this.eventBus);
229
+ }
230
+ return this._selfEvolution;
231
+ }
232
+ get seeleCouncil() {
233
+ if (!this._seeleCouncil) {
234
+ this._seeleCouncil = new SeeleCouncil('MAGI-01', this.eventBus);
235
+ }
236
+ return this._seeleCouncil;
237
+ }
238
+ get selfDestructSequence() {
239
+ if (!this._selfDestruct) {
240
+ const allUnits = this.adapters.getAll().map(a => a.unit);
241
+ this._selfDestruct = new SelfDestructSequence(allUnits, this.eventBus, this.secretCipher);
242
+ }
243
+ return this._selfDestruct;
244
+ }
245
+ get neonGenesis() {
246
+ if (!this._neonGenesis) {
247
+ this._neonGenesis = new NeonGenesis(this.config.workspaceDir, this.eventBus);
248
+ }
249
+ return this._neonGenesis;
250
+ }
251
+ // ── Namespaced API getters ──────────────────────────────
252
+ get runtime() {
253
+ if (!this._runtime) {
254
+ const self = this;
255
+ this._runtime = Object.freeze({
256
+ startWatch(opts) {
257
+ if (opts?.pollIntervalMs) {
258
+ // Stop existing detector before re-creating with custom interval
259
+ self._angelDetector?.stopWatch();
260
+ self._angelDetector = new AngelDetector({ pollIntervalMs: opts.pollIntervalMs }, self.eventBus);
261
+ }
262
+ self.angelDetector.startWatch();
263
+ let stopped = false;
264
+ if (opts?.signal) {
265
+ opts.signal.addEventListener('abort', () => {
266
+ if (!stopped) {
267
+ self.angelDetector.stopWatch();
268
+ stopped = true;
269
+ }
270
+ }, { once: true });
271
+ }
272
+ return {
273
+ stop() {
274
+ if (!stopped) {
275
+ self.angelDetector.stopWatch();
276
+ stopped = true;
277
+ }
278
+ },
279
+ get running() { return !stopped; },
280
+ };
281
+ },
282
+ stopWatch() { self.angelDetector.stopWatch(); },
283
+ async detectFromCommit(hash) { await self.ensureInitialized(); return self.angelDetector.detectFromCommit(hash); },
284
+ getCochangeGraph() { return self.angelDetector.getCochangeGraph(); },
285
+ async analyzeFile(filePath) { await self.ensureInitialized(); return self.deadSeaScrolls.analyze(filePath); },
286
+ async analyzeAll(dirPath) { await self.ensureInitialized(); return self.deadSeaScrolls.analyzeAll(dirPath); },
287
+ getScrollsAccuracy() { return self.deadSeaScrolls.getAccuracy(); },
288
+ scanFirewall(input) { return self.type666Firewall.scan(input); },
289
+ getFirewallStats() {
290
+ return {
291
+ patternCount: self.type666Firewall.getStaticPatternCount(),
292
+ dynamicCount: self.type666Firewall.getPatternCount(),
293
+ };
294
+ },
295
+ });
296
+ }
297
+ return this._runtime;
298
+ }
299
+ get diagnostics() {
300
+ if (!this._diagnostics) {
301
+ const self = this;
302
+ this._diagnostics = Object.freeze({
303
+ async simulateIruelBattle() { await self.ensureInitialized(); return self.iruelBattle.simulateBattle(); },
304
+ getIruelPhase() { return self.iruelBattle.getPhase(); },
305
+ resetIruelBattle() { self.iruelBattle.resetBattle(); },
306
+ computeASI(unit) { return self.driftDetector.computeASI(unit); },
307
+ checkDrift(unit) { return self.driftDetector.checkDrift(unit, self.eventBus); },
308
+ async evolve(opts) { await self.ensureInitialized(); return self.selfEvolution.evolve(opts); },
309
+ async diagnose() { await self.ensureInitialized(); return self.selfEvolution.diagnose(); },
310
+ getChronicleEntryCount() { return self.gospel.getCount(); },
311
+ getLCLDensity(phase) {
312
+ return self.lclManager.getDensity(phase);
313
+ },
314
+ });
315
+ }
316
+ return this._diagnostics;
317
+ }
318
+ get admin() {
319
+ if (!this._admin) {
320
+ const self = this;
321
+ this._admin = Object.freeze({
322
+ async simulateSeele() {
323
+ await self.ensureInitialized();
324
+ return self.seeleCouncil.simulateSession();
325
+ },
326
+ async executeSeeleAttack(attackers, target) {
327
+ await self.ensureInitialized();
328
+ return self.seeleCouncil.executeAttack(attackers, target);
329
+ },
330
+ formatSeelePanel() { return self.seeleCouncil.formatSoundOnlyPanel(); },
331
+ fileDestructMotion(reason) {
332
+ return self.selfDestructSequence.fileMotion(reason, 'API');
333
+ },
334
+ castDestructVote(motionId, unit, vote) {
335
+ self.selfDestructSequence.castVote(motionId, unit, vote);
336
+ },
337
+ async executeDestruct(motionId) {
338
+ await self.ensureInitialized();
339
+ return self.selfDestructSequence.executeCountdown(motionId);
340
+ },
341
+ getDestructPhase() { return self.selfDestructSequence.getPhase(); },
342
+ resetDestruct() { self.selfDestructSequence.reset(); },
343
+ async executeGenesis(reason, force) {
344
+ await self.ensureInitialized();
345
+ return self.neonGenesis.execute(reason, 'API', force);
346
+ },
347
+ async loadGenesisLog() { await self.ensureInitialized(); return self.neonGenesis.loadGenesisLog(); },
348
+ getNebuchadnezzarState() { return self.nebuchadnezzarKey.getState(); },
349
+ });
350
+ }
351
+ return this._admin;
352
+ }
353
+ async deliberate(task, options) {
354
+ await this.ensureInitialized();
355
+ return this.orchestrator.deliberate(task, options?.signal);
356
+ }
357
+ async deliberateBerserk(task, options) {
358
+ await this.ensureInitialized();
359
+ const result = await this.berserkOrchestrator.deliberate(task, options?.signal);
360
+ // Record berserk results in engram memory (same as normal deliberation post-processor)
361
+ fireAndForget(this.engramManager.recordDeliberation(result), 'berserk.engram.record');
362
+ return result;
363
+ }
364
+ on(event, listener) {
365
+ this.eventBus.on(event, listener);
366
+ return this;
367
+ }
368
+ once(event, listener) {
369
+ this.eventBus.once(event, listener);
370
+ return this;
371
+ }
372
+ off(event, listener) {
373
+ this.eventBus.off(event, listener);
374
+ return this;
375
+ }
376
+ getTokenSummary(deliberationId) {
377
+ return this.tokenTracker.summarize(deliberationId);
378
+ }
379
+ async loadAllTokens() {
380
+ return this.tokenTracker.loadAll();
381
+ }
382
+ getEventBus() {
383
+ return this.eventBus;
384
+ }
385
+ getEngramManager() {
386
+ return this.engramManager;
387
+ }
388
+ async getSystemStatus() {
389
+ await this.ensureInitialized();
390
+ const health = await this.adapters.healthCheckAll();
391
+ const allUnits = this.adapters.getAll().map(a => a.unit);
392
+ return {
393
+ units: allUnits.map(unit => ({
394
+ unit,
395
+ health: health.get(unit) ?? new Error('unknown'),
396
+ cableStatus: this.umbilicalCable.getStatus(unit),
397
+ syncRate: this.syncRateTracker.getRate(unit),
398
+ })),
399
+ atFieldStreak: this.atField.getUnanimousStreak(),
400
+ };
401
+ }
402
+ async healthCheck() {
403
+ await this.ensureInitialized();
404
+ const cliResults = await this.adapters.healthCheckAll();
405
+ const results = new Map();
406
+ for (const [unit, result] of cliResults) {
407
+ results.set(unit, result);
408
+ }
409
+ return results;
410
+ }
411
+ }
412
+ export { getDecisionProps, isApproval, isRejection, isUnanimous, isMajority, isDeadlock, getMajorityVote, } from './types/consensus.js';
413
+ export { MagiEventBus } from './engine/events.js';
414
+ export { StreamingProgressReporter } from './reporters/streaming.js';
415
+ export { MagiTui } from './tui/index.js';
416
+ // Phase K exports
417
+ export { AngelDetector } from './engine/angel-detector.js';
418
+ export { DeadSeaScrolls } from './engine/dead-sea-scrolls.js';
419
+ export { NebuchadnezzarKey } from './engine/nebuchadnezzar-key.js';
420
+ export { SelfDestructSequence } from './engine/self-destruct.js';
421
+ export { Type666Firewall } from './engine/type666-firewall.js';
422
+ // Phase L exports
423
+ export { NeonGenesis } from './engine/neon-genesis.js';
424
+ export { IruelBattleSystem } from './engine/iruel-battle.js';
425
+ export { SelfEvolutionEngine } from './engine/self-evolution.js';
426
+ export { SeeleCouncil } from './engine/seele-council.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MAGI MCP Server
3
+ *
4
+ * Exposes the MAGI deliberation system as MCP tools:
5
+ * magi_deliberate, magi_review, magi_decide, magi_doctor
6
+ */
7
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ import type { MagiDeliberation } from '../types/core.js';
9
+ export interface McpDeliberationSummary {
10
+ id: string;
11
+ decision: string;
12
+ method: string;
13
+ confidence: number;
14
+ summary: string;
15
+ dissent: Array<{
16
+ unit: string;
17
+ vote: string;
18
+ reasoning: string;
19
+ }>;
20
+ votes: {
21
+ approve: string[];
22
+ reject: string[];
23
+ abstain: string[];
24
+ };
25
+ rounds: number;
26
+ totalDurationMs: number;
27
+ fromCache: boolean;
28
+ opinions?: Array<{
29
+ unit: string;
30
+ vote: string;
31
+ confidence: number;
32
+ reasoning: string;
33
+ keyPoints: string[];
34
+ suggestions?: string[];
35
+ }>;
36
+ }
37
+ export declare function formatDeliberationForMcp(result: MagiDeliberation): string;
38
+ export declare function createMagiMcpServer(): McpServer;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * MAGI MCP Server
3
+ *
4
+ * Exposes the MAGI deliberation system as MCP tools:
5
+ * magi_deliberate, magi_review, magi_decide, magi_doctor
6
+ */
7
+ import { z } from 'zod/v4';
8
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import { Magi } from '../index.js';
10
+ import { detectLanguage } from '../utils/language-detector.js';
11
+ import { collectProjectContext } from '../context/auto-collector.js';
12
+ // ---------------------------------------------------------------------------
13
+ // Error sanitization — strip file paths from MCP error responses
14
+ // ---------------------------------------------------------------------------
15
+ function sanitizeErrorMessage(error) {
16
+ const msg = error instanceof Error ? error.message : String(error);
17
+ return msg.replace(/(?:\/[\w.@-]+){2,}|(?:[A-Z]:\\[\w\\.-]+)+/g, '[path]');
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Magi instance management
21
+ // ---------------------------------------------------------------------------
22
+ const magiCached = new Magi({ logLevel: 'warn' });
23
+ let magiNoCache;
24
+ function getMagi(noCache) {
25
+ if (!noCache)
26
+ return magiCached;
27
+ magiNoCache ??= new Magi({ logLevel: 'warn', cacheEnabled: false });
28
+ return magiNoCache;
29
+ }
30
+ export function formatDeliberationForMcp(result) {
31
+ const lastRound = result.rounds[result.rounds.length - 1];
32
+ const summary = {
33
+ id: result.id,
34
+ decision: result.consensus.decision,
35
+ method: result.consensus.method,
36
+ confidence: result.consensus.confidence,
37
+ summary: result.consensus.summary,
38
+ dissent: (result.consensus.dissent ?? []).map((d) => ({
39
+ unit: d.unit,
40
+ vote: d.vote,
41
+ reasoning: d.reasoning,
42
+ })),
43
+ votes: {
44
+ approve: result.consensus.votes.approve,
45
+ reject: result.consensus.votes.reject,
46
+ abstain: result.consensus.votes.abstain,
47
+ },
48
+ rounds: result.rounds.length,
49
+ totalDurationMs: result.totalDurationMs,
50
+ fromCache: result.fromCache ?? false,
51
+ opinions: lastRound
52
+ ? lastRound.opinions.map((o) => ({
53
+ unit: o.unit,
54
+ vote: o.vote,
55
+ confidence: o.confidence,
56
+ reasoning: o.reasoning,
57
+ keyPoints: o.keyPoints,
58
+ suggestions: o.suggestions,
59
+ }))
60
+ : undefined,
61
+ };
62
+ return JSON.stringify(summary, null, 2);
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // MCP Server factory
66
+ // ---------------------------------------------------------------------------
67
+ export function createMagiMcpServer() {
68
+ const server = new McpServer({
69
+ name: 'magi-system',
70
+ version: '0.1.0',
71
+ });
72
+ // -----------------------------------------------------------------------
73
+ // magi_deliberate
74
+ // -----------------------------------------------------------------------
75
+ server.tool('magi_deliberate', 'Run a MAGI deliberation — 3 AI CLIs (Claude/Codex/Gemini) discuss and vote on a topic. Takes 30-120 seconds.', {
76
+ prompt: z.string().max(50_000).describe('The topic or question to deliberate on'),
77
+ type: z.enum([
78
+ 'code-review',
79
+ 'architecture-decision',
80
+ 'bug-analysis',
81
+ 'implementation-plan',
82
+ 'security-audit',
83
+ 'custom',
84
+ ]).optional().describe('Task type (default: custom)'),
85
+ maxRounds: z.number().int().min(1).max(5).optional().describe('Maximum deliberation rounds (default: 3)'),
86
+ skipCrossExam: z.boolean().optional().describe('Skip cross-examination phase'),
87
+ noCache: z.boolean().optional().describe('Bypass deliberation cache'),
88
+ }, async (args) => {
89
+ try {
90
+ const taskType = args.type ?? 'custom';
91
+ const magi = getMagi(args.noCache ?? false);
92
+ const task = {
93
+ type: taskType,
94
+ title: args.prompt.slice(0, 200),
95
+ description: args.prompt,
96
+ config: {
97
+ ...(args.maxRounds != null ? { maxRounds: args.maxRounds } : {}),
98
+ ...(args.skipCrossExam
99
+ ? { phases: ['initial-opinion', 'final-vote'] }
100
+ : {}),
101
+ },
102
+ };
103
+ const result = await magi.deliberate(task);
104
+ return { content: [{ type: 'text', text: formatDeliberationForMcp(result) }] };
105
+ }
106
+ catch (error) {
107
+ return { content: [{ type: 'text', text: `Deliberation failed: ${sanitizeErrorMessage(error)}` }], isError: true };
108
+ }
109
+ });
110
+ // -----------------------------------------------------------------------
111
+ // magi_review
112
+ // -----------------------------------------------------------------------
113
+ server.tool('magi_review', 'MAGI code review — 3 AIs independently review code and vote APPROVE/REJECT. Takes 30-120 seconds.', {
114
+ filePath: z.string().max(1_000).describe('File path being reviewed (for context)'),
115
+ content: z.string().max(200_000).describe('Code content to review'),
116
+ language: z.string().optional().describe('Programming language (auto-detected if omitted)'),
117
+ context: z.string().max(200_000).optional().describe('Additional context for the review'),
118
+ }, async (args) => {
119
+ try {
120
+ // Auto-detect language if not provided
121
+ const language = args.language ?? detectLanguage(args.filePath);
122
+ const task = {
123
+ type: 'code-review',
124
+ title: `Code review: ${args.filePath}`,
125
+ description: args.context
126
+ ? `Review the following code.\n\nContext: ${args.context}`
127
+ : 'Review the following code for correctness, security, and quality.',
128
+ artifacts: [
129
+ {
130
+ type: 'file',
131
+ path: args.filePath,
132
+ content: args.content,
133
+ language,
134
+ },
135
+ ],
136
+ };
137
+ const result = await getMagi(false).deliberate(task);
138
+ return { content: [{ type: 'text', text: formatDeliberationForMcp(result) }] };
139
+ }
140
+ catch (error) {
141
+ return { content: [{ type: 'text', text: `Code review failed: ${sanitizeErrorMessage(error)}` }], isError: true };
142
+ }
143
+ });
144
+ // -----------------------------------------------------------------------
145
+ // magi_decide
146
+ // -----------------------------------------------------------------------
147
+ server.tool('magi_decide', 'MAGI architecture decision — 3 AIs evaluate a design question and vote. Takes 30-120 seconds.', {
148
+ question: z.string().max(50_000).describe('The architecture/design question to decide on'),
149
+ context: z.string().max(200_000).optional().describe('Additional context (constraints, requirements, etc.)'),
150
+ }, async (args) => {
151
+ try {
152
+ // Inject project context automatically
153
+ let fullContext = args.context ?? '';
154
+ try {
155
+ const projectCtx = await collectProjectContext();
156
+ if (projectCtx.charCount > 0) {
157
+ fullContext = fullContext
158
+ ? `${fullContext}\n\n${projectCtx.text}`
159
+ : projectCtx.text;
160
+ }
161
+ }
162
+ catch { /* graceful degradation */ }
163
+ const task = {
164
+ type: 'architecture-decision',
165
+ title: args.question.slice(0, 200),
166
+ description: fullContext
167
+ ? `${args.question}\n\nContext: ${fullContext}`
168
+ : args.question,
169
+ };
170
+ const result = await getMagi(false).deliberate(task);
171
+ return { content: [{ type: 'text', text: formatDeliberationForMcp(result) }] };
172
+ }
173
+ catch (error) {
174
+ return { content: [{ type: 'text', text: `Architecture decision failed: ${sanitizeErrorMessage(error)}` }], isError: true };
175
+ }
176
+ });
177
+ // -----------------------------------------------------------------------
178
+ // magi_doctor
179
+ // -----------------------------------------------------------------------
180
+ server.tool('magi_doctor', 'Check MAGI system health — verifies claude, codex, and gemini CLI availability.', {}, async () => {
181
+ try {
182
+ const results = await magiCached.healthCheck();
183
+ const status = {};
184
+ for (const [tool, result] of results) {
185
+ status[tool] = result instanceof Error ? `ERROR: ${result.message}` : result;
186
+ }
187
+ return {
188
+ content: [{ type: 'text', text: JSON.stringify(status, null, 2) }],
189
+ };
190
+ }
191
+ catch (error) {
192
+ return { content: [{ type: 'text', text: `Doctor check failed: ${sanitizeErrorMessage(error)}` }], isError: true };
193
+ }
194
+ });
195
+ return server;
196
+ }