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,176 @@
1
+ /**
2
+ * Minimal i18n for CLI commands (setup, config, etc.)
3
+ *
4
+ * TUI stays Japanese (Eva world-building).
5
+ * CLI setup/config supports ja/en.
6
+ */
7
+ let currentLocale = 'ja';
8
+ export function getLocale() {
9
+ return currentLocale;
10
+ }
11
+ export function setLocale(locale) {
12
+ currentLocale = locale;
13
+ }
14
+ /** Detect locale from environment or system settings. */
15
+ export function detectLocale() {
16
+ const lang = process.env.LANG ?? process.env.LC_ALL ?? process.env.LANGUAGE ?? '';
17
+ if (lang.startsWith('ja'))
18
+ return 'ja';
19
+ // Default to English for all non-Japanese locales
20
+ return 'en';
21
+ }
22
+ const ja = {
23
+ setup_title: 'MAGI System — 初期セットアップ',
24
+ setup_step_detect: 'AI CLIを検出',
25
+ setup_step_config: '構成を選択',
26
+ setup_step_settings: '動作設定',
27
+ setup_detecting: '利用可能なAI CLIをスキャン中...',
28
+ setup_installed: 'インストール済み',
29
+ setup_not_installed: '未インストール',
30
+ setup_no_cli: 'AI CLIが見つかりませんでした。',
31
+ setup_no_cli_hint: 'claude, codex, gemini のいずれかをインストールしてください。',
32
+ setup_select_config: '使用するAIの構成',
33
+ setup_select_config_hint: '検出されたCLIから構成を選びます',
34
+ setup_all_ai: '全AIで合議',
35
+ setup_two_ai: '2体で合議',
36
+ setup_single: '単体モード',
37
+ setup_recommended: '推奨',
38
+ setup_rounds: '最大ラウンド数',
39
+ setup_rounds_1: '最速 — 1回で終了',
40
+ setup_rounds_2: 'バランス型',
41
+ setup_rounds_3: '標準 — しっかり議論',
42
+ setup_rounds_5: '慎重 — 複雑な問題向け',
43
+ setup_early_exit: '意見一致で早期終了',
44
+ setup_early_exit_hint: 'AIの意見が一致したら残りのラウンドをスキップ',
45
+ setup_deadlock: '意見が割れた時',
46
+ setup_deadlock_melchior: 'MELCHIOR優先',
47
+ setup_deadlock_melchior_hint: 'MELCHIORの判断を採用',
48
+ setup_deadlock_confidence: '確信度で決定',
49
+ setup_deadlock_confidence_hint: '最も自信のある意見を採用',
50
+ setup_deadlock_escalate: 'エスカレーション',
51
+ setup_deadlock_escalate_hint: '決定を保留して報告',
52
+ setup_deadlock_human: '人間に聞く',
53
+ setup_deadlock_human_hint: 'ターミナルで判断を委ねる',
54
+ setup_tui: 'エヴァンゲリオン風UI (TUI)',
55
+ setup_tui_hint: 'フルスクリーンのアニメーション表示',
56
+ setup_file_access: 'ファイルアクセス',
57
+ setup_file_access_hint: 'CLIがプロジェクトファイルを読み取れるようにする',
58
+ setup_language: '言語',
59
+ setup_saved: '設定を保存しました',
60
+ setup_saved_path: '.magi/config.json',
61
+ setup_hint_config: '設定の確認: /config',
62
+ setup_hint_reset: '設定の初期化: /config reset',
63
+ setup_defaults_ok: 'デフォルトのままでOK',
64
+ setup_cancelled: 'セットアップを中断しました',
65
+ yes: 'はい',
66
+ no: 'いいえ',
67
+ config_title: 'MAGI 設定',
68
+ config_no_file: '設定ファイルがありません',
69
+ config_no_file_hint: '/setup で作成できます',
70
+ config_file: 'ファイル',
71
+ config_units: '有効なユニット',
72
+ config_max_rounds: '最大ラウンド数',
73
+ config_early_exit: '早期合意終了',
74
+ config_deadlock: 'デッドロック戦略',
75
+ config_quorum: '定足数',
76
+ config_phase_timeout: 'フェーズタイムアウト',
77
+ config_tui: 'TUI',
78
+ config_sound: 'サウンド',
79
+ config_log_level: 'ログレベル',
80
+ config_output_format: '出力形式',
81
+ config_cache: 'キャッシュ',
82
+ config_file_access: 'ファイルアクセス',
83
+ config_language: '言語',
84
+ config_change_hint: '変更: /config set <項目> <値>',
85
+ config_reset_hint: '初期化: /config reset',
86
+ config_set_ok: '設定を変更しました',
87
+ config_set_invalid: '無効な設定値です',
88
+ config_set_usage: '使い方: /config set <項目> <値>',
89
+ config_reset_ok: '設定を初期化しました',
90
+ config_reset_none: '設定ファイルがまだありません',
91
+ config_unknown_action: '不明な操作',
92
+ on: 'ON',
93
+ off: 'OFF',
94
+ nav_hint: '↑↓ 移動 Enter 決定',
95
+ needs_tty: 'インタラクティブターミナルが必要です',
96
+ };
97
+ const en = {
98
+ setup_title: 'MAGI System — Setup',
99
+ setup_step_detect: 'Detect AI CLIs',
100
+ setup_step_config: 'Choose configuration',
101
+ setup_step_settings: 'Settings',
102
+ setup_detecting: 'Scanning for available AI CLIs...',
103
+ setup_installed: 'installed',
104
+ setup_not_installed: 'not found',
105
+ setup_no_cli: 'No AI CLIs found.',
106
+ setup_no_cli_hint: 'Install at least one of: claude, codex, gemini',
107
+ setup_select_config: 'AI configuration',
108
+ setup_select_config_hint: 'Choose which AIs to use for deliberation',
109
+ setup_all_ai: 'All 3 AIs deliberate together',
110
+ setup_two_ai: '2 AIs deliberate together',
111
+ setup_single: 'Single AI mode',
112
+ setup_recommended: 'recommended',
113
+ setup_rounds: 'Max rounds',
114
+ setup_rounds_1: 'Fastest — one pass',
115
+ setup_rounds_2: 'Balanced',
116
+ setup_rounds_3: 'Standard — thorough deliberation',
117
+ setup_rounds_5: 'Careful — for complex problems',
118
+ setup_early_exit: 'Early consensus exit',
119
+ setup_early_exit_hint: 'Skip remaining rounds when AIs agree',
120
+ setup_deadlock: 'When AIs disagree',
121
+ setup_deadlock_melchior: 'MELCHIOR decides',
122
+ setup_deadlock_melchior_hint: 'Use MELCHIOR\'s judgment as tiebreaker',
123
+ setup_deadlock_confidence: 'Highest confidence',
124
+ setup_deadlock_confidence_hint: 'Pick the most confident opinion',
125
+ setup_deadlock_escalate: 'Escalate',
126
+ setup_deadlock_escalate_hint: 'Defer the decision',
127
+ setup_deadlock_human: 'Ask human',
128
+ setup_deadlock_human_hint: 'Prompt the user in terminal',
129
+ setup_tui: 'Evangelion-themed UI (TUI)',
130
+ setup_tui_hint: 'Full-screen animated display',
131
+ setup_file_access: 'File access',
132
+ setup_file_access_hint: 'Let CLIs read project files during deliberation',
133
+ setup_language: 'Language',
134
+ setup_saved: 'Configuration saved',
135
+ setup_saved_path: '.magi/config.json',
136
+ setup_hint_config: 'View config: /config',
137
+ setup_hint_reset: 'Reset config: /config reset',
138
+ setup_defaults_ok: 'Defaults are fine',
139
+ setup_cancelled: 'Setup cancelled',
140
+ yes: 'Yes',
141
+ no: 'No',
142
+ config_title: 'MAGI Configuration',
143
+ config_no_file: 'No configuration file found',
144
+ config_no_file_hint: 'Run /setup to create one',
145
+ config_file: 'File',
146
+ config_units: 'Enabled units',
147
+ config_max_rounds: 'Max rounds',
148
+ config_early_exit: 'Early consensus exit',
149
+ config_deadlock: 'Deadlock strategy',
150
+ config_quorum: 'Quorum',
151
+ config_phase_timeout: 'Phase timeout',
152
+ config_tui: 'TUI',
153
+ config_sound: 'Sound',
154
+ config_log_level: 'Log level',
155
+ config_output_format: 'Output format',
156
+ config_cache: 'Cache',
157
+ config_file_access: 'File access',
158
+ config_language: 'Language',
159
+ config_change_hint: 'Change: /config set <key> <value>',
160
+ config_reset_hint: 'Reset: /config reset',
161
+ config_set_ok: 'Configuration updated',
162
+ config_set_invalid: 'Invalid configuration value',
163
+ config_set_usage: 'Usage: /config set <key> <value>',
164
+ config_reset_ok: 'Configuration reset to defaults',
165
+ config_reset_none: 'No configuration file to reset',
166
+ config_unknown_action: 'Unknown action',
167
+ on: 'ON',
168
+ off: 'OFF',
169
+ nav_hint: '↑↓ move Enter select',
170
+ needs_tty: 'Requires an interactive terminal',
171
+ };
172
+ const catalogs = { ja, en };
173
+ /** Get localized message. */
174
+ export function t(key) {
175
+ return catalogs[currentLocale][key];
176
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Arrow-key interactive selector for terminal UI.
3
+ *
4
+ * @clack/prompts inspired box-drawing style.
5
+ * ↑/↓ to navigate, Enter to select, Ctrl+C to cancel.
6
+ */
7
+ export interface SelectOption {
8
+ label: string;
9
+ value: string;
10
+ hint?: string;
11
+ recommended?: boolean;
12
+ }
13
+ /** Thrown when user presses Ctrl+C during interactive selection. */
14
+ export declare class UserCancelledError extends Error {
15
+ constructor();
16
+ }
17
+ /**
18
+ * Display an interactive selection menu with box-drawing UI.
19
+ * Returns the selected index.
20
+ * Throws UserCancelledError if Ctrl+C is pressed.
21
+ */
22
+ export declare function interactiveSelect(title: string, options: SelectOption[], defaultIndex?: number): Promise<number>;
23
+ /**
24
+ * Yes/No selection with box-drawing UI.
25
+ * Throws UserCancelledError if Ctrl+C is pressed.
26
+ */
27
+ export declare function interactiveConfirm(message: string, defaultYes?: boolean): Promise<boolean>;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Arrow-key interactive selector for terminal UI.
3
+ *
4
+ * @clack/prompts inspired box-drawing style.
5
+ * ↑/↓ to navigate, Enter to select, Ctrl+C to cancel.
6
+ */
7
+ import chalk from 'chalk';
8
+ import { t } from './i18n.js';
9
+ // ── Box-drawing symbols (clack style) ────────────────────────────
10
+ const S = {
11
+ BAR: '│',
12
+ BAR_END: '└',
13
+ BAR_H: '─',
14
+ CORNER_TL: '┌',
15
+ RADIO_ON: '●',
16
+ RADIO_OFF: '○',
17
+ CHECK: '◼',
18
+ STEP_ACTIVE: '◆',
19
+ STEP_DONE: '◇',
20
+ };
21
+ /** Thrown when user presses Ctrl+C during interactive selection. */
22
+ export class UserCancelledError extends Error {
23
+ constructor() {
24
+ super('User cancelled');
25
+ this.name = 'UserCancelledError';
26
+ }
27
+ }
28
+ /**
29
+ * Display an interactive selection menu with box-drawing UI.
30
+ * Returns the selected index.
31
+ * Throws UserCancelledError if Ctrl+C is pressed.
32
+ */
33
+ export async function interactiveSelect(title, options, defaultIndex = 0) {
34
+ if (!process.stdin.isTTY)
35
+ return defaultIndex;
36
+ if (options.length === 0)
37
+ return -1;
38
+ if (options.length === 1) {
39
+ printSingleChoice(title, options[0]);
40
+ return 0;
41
+ }
42
+ let cursor = defaultIndex;
43
+ return new Promise((resolve, reject) => {
44
+ const wasRaw = process.stdin.isRaw;
45
+ const cleanup = () => {
46
+ process.stdin.removeListener('data', onData);
47
+ try {
48
+ process.stdin.setRawMode(wasRaw ?? false);
49
+ }
50
+ catch { /* ignore */ }
51
+ };
52
+ renderMenu(title, options, cursor);
53
+ process.stdin.setRawMode(true);
54
+ process.stdin.resume();
55
+ const onData = (data) => {
56
+ try {
57
+ const key = data.toString();
58
+ if (key === '\x1b[A' || key === 'k') {
59
+ cursor = (cursor - 1 + options.length) % options.length;
60
+ clearAndRender(title, options, cursor);
61
+ }
62
+ else if (key === '\x1b[B' || key === 'j') {
63
+ cursor = (cursor + 1) % options.length;
64
+ clearAndRender(title, options, cursor);
65
+ }
66
+ else if (key === '\r' || key === '\n') {
67
+ cleanup();
68
+ clearLines(options.length + 2);
69
+ printSelected(title, options[cursor]);
70
+ resolve(cursor);
71
+ }
72
+ else if (key === '\x03') {
73
+ cleanup();
74
+ clearLines(options.length + 2);
75
+ console.log(chalk.yellow(S.STEP_DONE) + chalk.dim(` ${title} `) + chalk.yellow('cancelled'));
76
+ reject(new UserCancelledError());
77
+ }
78
+ }
79
+ catch (err) {
80
+ cleanup();
81
+ reject(err);
82
+ }
83
+ };
84
+ process.stdin.on('data', onData);
85
+ });
86
+ }
87
+ // ── Rendering ────────────────────────────────────────────────────
88
+ function renderMenu(title, options, cursor) {
89
+ console.log(chalk.cyan(S.STEP_ACTIVE) + chalk.bold(` ${title}`));
90
+ for (let i = 0; i < options.length; i++) {
91
+ const opt = options[i];
92
+ const active = i === cursor;
93
+ const radio = active ? chalk.cyan(S.RADIO_ON) : chalk.dim(S.RADIO_OFF);
94
+ const label = active ? chalk.white(opt.label) : chalk.dim(opt.label);
95
+ const rec = opt.recommended ? chalk.cyan(` (${t('setup_recommended')})`) : '';
96
+ const hint = opt.hint ? chalk.dim(` ${opt.hint}`) : '';
97
+ console.log(chalk.gray(S.BAR) + ` ${radio} ${label}${rec}${hint}`);
98
+ }
99
+ console.log(chalk.gray(S.BAR_END) + chalk.dim(` ${t('nav_hint')}`));
100
+ }
101
+ function printSelected(title, option) {
102
+ const rec = option.recommended ? chalk.cyan(` (${t('setup_recommended')})`) : '';
103
+ console.log(chalk.cyan(S.STEP_DONE) + chalk.dim(` ${title} `) + chalk.white(option.label) + rec);
104
+ }
105
+ function printSingleChoice(title, option) {
106
+ console.log(chalk.cyan(S.STEP_DONE) + chalk.dim(` ${title} `) + chalk.white(option.label));
107
+ }
108
+ function clearLines(n) {
109
+ for (let i = 0; i < n; i++) {
110
+ process.stdout.write('\x1b[1A\x1b[2K');
111
+ }
112
+ }
113
+ function clearAndRender(title, options, cursor) {
114
+ clearLines(options.length + 2);
115
+ renderMenu(title, options, cursor);
116
+ }
117
+ /**
118
+ * Yes/No selection with box-drawing UI.
119
+ * Throws UserCancelledError if Ctrl+C is pressed.
120
+ */
121
+ export async function interactiveConfirm(message, defaultYes = true) {
122
+ if (!process.stdin.isTTY)
123
+ return defaultYes;
124
+ const options = [
125
+ { label: t('yes'), value: 'yes' },
126
+ { label: t('no'), value: 'no' },
127
+ ];
128
+ const idx = await interactiveSelect(message, options, defaultYes ? 0 : 1);
129
+ return idx === 0;
130
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * TUI initialization helper — extracted from deliberate/review/decide commands
3
+ * to eliminate 3x code duplication in bin/magi.ts.
4
+ *
5
+ * Handles:
6
+ * 1. Non-TUI mode: prints header + starts StreamingProgressReporter
7
+ * 2. TUI mode + capable terminal: creates and starts MagiTui instance
8
+ * 3. TUI mode + incapable terminal: graceful fallback to streaming mode
9
+ */
10
+ import type { MagiEventBus } from '../engine/events.js';
11
+ export interface TuiSetupResult {
12
+ tuiInstance?: {
13
+ dispose: () => void;
14
+ waitForDismiss: () => Promise<void>;
15
+ };
16
+ /** True when a StreamingProgressReporter is already subscribed as fallback. */
17
+ streamingActive?: boolean;
18
+ /** Dispose function for StreamingProgressReporter (removes all listeners). */
19
+ disposeStreaming?: () => void;
20
+ }
21
+ export interface TuiSetupOptions {
22
+ soundEnabled?: boolean;
23
+ }
24
+ export declare function initializeTui(eventBus: MagiEventBus, enableTui: boolean, options?: TuiSetupOptions): Promise<TuiSetupResult>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * TUI initialization helper — extracted from deliberate/review/decide commands
3
+ * to eliminate 3x code duplication in bin/magi.ts.
4
+ *
5
+ * Handles:
6
+ * 1. Non-TUI mode: prints header + starts StreamingProgressReporter
7
+ * 2. TUI mode + capable terminal: creates and starts MagiTui instance
8
+ * 3. TUI mode + incapable terminal: graceful fallback to streaming mode
9
+ */
10
+ import chalk from 'chalk';
11
+ import { StreamingProgressReporter } from '../reporters/streaming.js';
12
+ import { printHeader } from '../reporters/console.js';
13
+ import { setTuiMode } from '../utils/logger.js';
14
+ // ── Main function ───────────────────────────────────────────
15
+ export async function initializeTui(eventBus, enableTui, options = {}) {
16
+ if (!enableTui) {
17
+ printHeader();
18
+ const reporter = new StreamingProgressReporter(eventBus);
19
+ return { streamingActive: true, disposeStreaming: () => reporter.dispose() };
20
+ }
21
+ const { MagiTui, detectCapabilities, tuiCheckFailure } = await import('../tui/index.js');
22
+ const caps = detectCapabilities();
23
+ const failure = tuiCheckFailure(caps);
24
+ if (failure) {
25
+ console.error(chalk.yellow(` TUI unavailable: ${failure} — falling back to streaming mode`));
26
+ printHeader();
27
+ const reporter = new StreamingProgressReporter(eventBus);
28
+ return { streamingActive: true, disposeStreaming: () => reporter.dispose() };
29
+ }
30
+ const tui = new MagiTui({ eventBus, soundEnabled: options.soundEnabled });
31
+ await tui.start();
32
+ setTuiMode(true);
33
+ return {
34
+ tuiInstance: {
35
+ dispose: () => {
36
+ setTuiMode(false);
37
+ tui.dispose();
38
+ },
39
+ waitForDismiss: () => tui.waitForDismiss(),
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * CLI auto-detection and configuration suggestion.
3
+ *
4
+ * Detects which AI CLIs (claude, codex, gemini) are available
5
+ * and generates recommended unit configurations.
6
+ */
7
+ import type { BuiltinMagiUnit } from '../types/core.js';
8
+ export interface CliStatus {
9
+ available: boolean;
10
+ version?: string;
11
+ }
12
+ export interface CliDetectionResult {
13
+ claude: CliStatus;
14
+ codex: CliStatus;
15
+ gemini: CliStatus;
16
+ }
17
+ export interface ConfigSuggestion {
18
+ enabledUnits: BuiltinMagiUnit[];
19
+ unitCount: number;
20
+ description: string;
21
+ recommended: boolean;
22
+ }
23
+ /**
24
+ * Detect which AI CLIs are installed and available.
25
+ * Runs all checks in parallel using Promise.allSettled.
26
+ */
27
+ export declare function detectAvailableCLIs(): Promise<CliDetectionResult>;
28
+ /**
29
+ * Get the list of available units from detection result.
30
+ */
31
+ export declare function getAvailableUnits(detection: CliDetectionResult): BuiltinMagiUnit[];
32
+ /**
33
+ * Generate configuration suggestions based on detected CLIs.
34
+ * Returns suggestions sorted by unit count (descending), with the
35
+ * largest available configuration marked as recommended.
36
+ */
37
+ export declare function suggestConfigurations(detection: CliDetectionResult): ConfigSuggestion[];
@@ -0,0 +1,99 @@
1
+ /**
2
+ * CLI auto-detection and configuration suggestion.
3
+ *
4
+ * Detects which AI CLIs (claude, codex, gemini) are available
5
+ * and generates recommended unit configurations.
6
+ */
7
+ import { isBinaryAvailable } from '../utils/process.js';
8
+ import { logger } from '../utils/logger.js';
9
+ // ── CLI ↔ Unit mapping ──────────────────────────────────────────
10
+ const CLI_UNIT_MAP = {
11
+ claude: 'MELCHIOR',
12
+ codex: 'BALTHASAR',
13
+ gemini: 'CASPER',
14
+ };
15
+ // ── Detection ───────────────────────────────────────────────────
16
+ /**
17
+ * Detect which AI CLIs are installed and available.
18
+ * Runs all checks in parallel using Promise.allSettled.
19
+ */
20
+ export async function detectAvailableCLIs() {
21
+ const clis = ['claude', 'codex', 'gemini'];
22
+ const results = await Promise.allSettled(clis.map(async (cli) => {
23
+ const available = await isBinaryAvailable(cli);
24
+ return { cli, available };
25
+ }));
26
+ const detection = {
27
+ claude: { available: false },
28
+ codex: { available: false },
29
+ gemini: { available: false },
30
+ };
31
+ for (const result of results) {
32
+ if (result.status === 'fulfilled') {
33
+ detection[result.value.cli] = { available: result.value.available };
34
+ }
35
+ else {
36
+ logger.debug('CLI detection failed', { error: String(result.reason) });
37
+ }
38
+ }
39
+ return detection;
40
+ }
41
+ /**
42
+ * Get the list of available units from detection result.
43
+ */
44
+ export function getAvailableUnits(detection) {
45
+ const units = [];
46
+ for (const [cli, status] of Object.entries(detection)) {
47
+ if (status.available && cli in CLI_UNIT_MAP) {
48
+ units.push(CLI_UNIT_MAP[cli]);
49
+ }
50
+ }
51
+ return units;
52
+ }
53
+ /**
54
+ * Generate configuration suggestions based on detected CLIs.
55
+ * Returns suggestions sorted by unit count (descending), with the
56
+ * largest available configuration marked as recommended.
57
+ */
58
+ export function suggestConfigurations(detection) {
59
+ const available = getAvailableUnits(detection);
60
+ if (available.length === 0)
61
+ return [];
62
+ const suggestions = [];
63
+ const displayNames = {
64
+ MELCHIOR: 'MELCHIOR (Claude)',
65
+ BALTHASAR: 'BALTHASAR (Codex)',
66
+ CASPER: 'CASPER (Gemini)',
67
+ };
68
+ // Full configuration (all available)
69
+ if (available.length >= 2) {
70
+ suggestions.push({
71
+ enabledUnits: [...available],
72
+ unitCount: available.length,
73
+ description: `${available.length}体モード (${available.map(u => displayNames[u]).join(' + ')})`,
74
+ recommended: true,
75
+ });
76
+ }
77
+ // 2-unit combinations (only if 3 are available)
78
+ if (available.length === 3) {
79
+ for (let i = 0; i < available.length; i++) {
80
+ const pair = available.filter((_, idx) => idx !== i);
81
+ suggestions.push({
82
+ enabledUnits: pair,
83
+ unitCount: 2,
84
+ description: `2体モード (${pair.map(u => displayNames[u]).join(' + ')})`,
85
+ recommended: false,
86
+ });
87
+ }
88
+ }
89
+ // Single-unit options
90
+ for (const unit of available) {
91
+ suggestions.push({
92
+ enabledUnits: [unit],
93
+ unitCount: 1,
94
+ description: `1体モード (${displayNames[unit]} のみ)`,
95
+ recommended: available.length === 1,
96
+ });
97
+ }
98
+ return suggestions;
99
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * User configuration management for .magi/config.json
3
+ *
4
+ * Handles loading, saving, validating, and merging user-level
5
+ * settings with the immutable DEFAULT_CONFIG.
6
+ */
7
+ import { z } from 'zod/v4';
8
+ import type { MagiConfig } from '../types/config.js';
9
+ export declare const UserConfigSchema: z.ZodObject<{
10
+ enabledUnits: z.ZodOptional<z.ZodArray<z.ZodEnum<{
11
+ MELCHIOR: "MELCHIOR";
12
+ BALTHASAR: "BALTHASAR";
13
+ CASPER: "CASPER";
14
+ }>>>;
15
+ adapters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
16
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
17
+ maxRetries: z.ZodOptional<z.ZodNumber>;
18
+ model: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>>>;
20
+ defaultPipeline: z.ZodOptional<z.ZodObject<{
21
+ maxRounds: z.ZodOptional<z.ZodNumber>;
22
+ earlyConsensusExit: z.ZodOptional<z.ZodBoolean>;
23
+ consensus: z.ZodOptional<z.ZodObject<{
24
+ deadlockStrategy: z.ZodOptional<z.ZodEnum<{
25
+ escalate: "escalate";
26
+ "melchior-tiebreak": "melchior-tiebreak";
27
+ "highest-confidence": "highest-confidence";
28
+ "human-in-the-loop": "human-in-the-loop";
29
+ }>>;
30
+ quorum: z.ZodOptional<z.ZodNumber>;
31
+ }, z.core.$strip>>;
32
+ phaseTimeoutMs: z.ZodOptional<z.ZodNumber>;
33
+ }, z.core.$strip>>;
34
+ logLevel: z.ZodOptional<z.ZodEnum<{
35
+ error: "error";
36
+ debug: "debug";
37
+ info: "info";
38
+ warn: "warn";
39
+ }>>;
40
+ outputFormat: z.ZodOptional<z.ZodEnum<{
41
+ json: "json";
42
+ console: "console";
43
+ markdown: "markdown";
44
+ }>>;
45
+ tui: z.ZodOptional<z.ZodObject<{
46
+ enabled: z.ZodOptional<z.ZodBoolean>;
47
+ soundEnabled: z.ZodOptional<z.ZodBoolean>;
48
+ }, z.core.$strip>>;
49
+ cacheEnabled: z.ZodOptional<z.ZodBoolean>;
50
+ language: z.ZodOptional<z.ZodEnum<{
51
+ ja: "ja";
52
+ en: "en";
53
+ }>>;
54
+ fileAccess: z.ZodOptional<z.ZodObject<{
55
+ enabled: z.ZodOptional<z.ZodBoolean>;
56
+ allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
57
+ deniedPatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
+ }, z.core.$strip>>;
59
+ }, z.core.$strict>;
60
+ export type UserConfig = z.infer<typeof UserConfigSchema>;
61
+ export declare function getUserConfigPath(workspaceDir?: string): string;
62
+ /**
63
+ * Load user config from .magi/config.json.
64
+ * Returns undefined if file does not exist.
65
+ * Throws on invalid JSON or schema validation failure.
66
+ */
67
+ export declare function loadUserConfig(workspaceDir?: string): Promise<UserConfig | undefined>;
68
+ /**
69
+ * Load user config with graceful fallback.
70
+ * Logs a warning on error and returns undefined instead of throwing.
71
+ */
72
+ export declare function loadUserConfigSafe(workspaceDir?: string): Promise<UserConfig | undefined>;
73
+ /**
74
+ * Save user config to .magi/config.json using safePersist (0o600).
75
+ */
76
+ export declare function saveUserConfig(config: UserConfig, workspaceDir?: string): Promise<void>;
77
+ /**
78
+ * Merge user config with DEFAULT_CONFIG, producing a full MagiConfig.
79
+ * The `tui` and `language` fields are stripped (consumed by the CLI layer, not Magi core).
80
+ */
81
+ export declare function mergeWithDefaults(userConfig: UserConfig): Partial<MagiConfig>;