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.
- package/LICENSE +21 -0
- package/README.ja.md +377 -0
- package/README.md +377 -0
- package/dist/bin/magi-benchmark.d.ts +14 -0
- package/dist/bin/magi-benchmark.js +93 -0
- package/dist/bin/magi-mcp.d.ts +8 -0
- package/dist/bin/magi-mcp.js +28 -0
- package/dist/bin/magi.d.ts +2 -0
- package/dist/bin/magi.js +634 -0
- package/dist/src/adapters/base.d.ts +34 -0
- package/dist/src/adapters/base.js +149 -0
- package/dist/src/adapters/claude.d.ts +29 -0
- package/dist/src/adapters/claude.js +65 -0
- package/dist/src/adapters/codex.d.ts +21 -0
- package/dist/src/adapters/codex.js +41 -0
- package/dist/src/adapters/gemini.d.ts +18 -0
- package/dist/src/adapters/gemini.js +31 -0
- package/dist/src/adapters/registry.d.ts +19 -0
- package/dist/src/adapters/registry.js +59 -0
- package/dist/src/audit/hash-chain.d.ts +21 -0
- package/dist/src/audit/hash-chain.js +70 -0
- package/dist/src/audit/types.d.ts +25 -0
- package/dist/src/audit/types.js +1 -0
- package/dist/src/audit/writer.d.ts +18 -0
- package/dist/src/audit/writer.js +100 -0
- package/dist/src/benchmark/golden-tasks.d.ts +9 -0
- package/dist/src/benchmark/golden-tasks.js +476 -0
- package/dist/src/benchmark/reporter.d.ts +5 -0
- package/dist/src/benchmark/reporter.js +107 -0
- package/dist/src/benchmark/runner.d.ts +30 -0
- package/dist/src/benchmark/runner.js +224 -0
- package/dist/src/benchmark/scorer.d.ts +12 -0
- package/dist/src/benchmark/scorer.js +124 -0
- package/dist/src/benchmark/types.d.ts +54 -0
- package/dist/src/benchmark/types.js +1 -0
- package/dist/src/cache/deliberation-cache.d.ts +49 -0
- package/dist/src/cache/deliberation-cache.js +127 -0
- package/dist/src/cli/commands/config-cmd.d.ts +11 -0
- package/dist/src/cli/commands/config-cmd.js +190 -0
- package/dist/src/cli/commands/demo.d.ts +12 -0
- package/dist/src/cli/commands/demo.js +66 -0
- package/dist/src/cli/commands/setup.d.ts +7 -0
- package/dist/src/cli/commands/setup.js +182 -0
- package/dist/src/cli/i18n.d.ts +89 -0
- package/dist/src/cli/i18n.js +176 -0
- package/dist/src/cli/interactive-select.d.ts +27 -0
- package/dist/src/cli/interactive-select.js +130 -0
- package/dist/src/cli/tui-setup.d.ts +24 -0
- package/dist/src/cli/tui-setup.js +42 -0
- package/dist/src/config/cli-detector.d.ts +37 -0
- package/dist/src/config/cli-detector.js +99 -0
- package/dist/src/config/user-config.d.ts +81 -0
- package/dist/src/config/user-config.js +134 -0
- package/dist/src/context/auto-collector.d.ts +43 -0
- package/dist/src/context/auto-collector.js +337 -0
- package/dist/src/context/manager.d.ts +35 -0
- package/dist/src/context/manager.js +162 -0
- package/dist/src/context/serializer.d.ts +20 -0
- package/dist/src/context/serializer.js +52 -0
- package/dist/src/demo/recorded-deliberation.d.ts +13 -0
- package/dist/src/demo/recorded-deliberation.js +277 -0
- package/dist/src/engine/angel-detector.d.ts +83 -0
- package/dist/src/engine/angel-detector.js +334 -0
- package/dist/src/engine/at-field.d.ts +40 -0
- package/dist/src/engine/at-field.js +195 -0
- package/dist/src/engine/berserk-orchestrator.d.ts +66 -0
- package/dist/src/engine/berserk-orchestrator.js +378 -0
- package/dist/src/engine/change-metrics.d.ts +56 -0
- package/dist/src/engine/change-metrics.js +214 -0
- package/dist/src/engine/consensus.d.ts +20 -0
- package/dist/src/engine/consensus.js +146 -0
- package/dist/src/engine/dead-sea-scrolls.d.ts +132 -0
- package/dist/src/engine/dead-sea-scrolls.js +610 -0
- package/dist/src/engine/drift-detector.d.ts +39 -0
- package/dist/src/engine/drift-detector.js +225 -0
- package/dist/src/engine/dummy-plug.d.ts +44 -0
- package/dist/src/engine/dummy-plug.js +190 -0
- package/dist/src/engine/engram-manager.d.ts +55 -0
- package/dist/src/engine/engram-manager.js +306 -0
- package/dist/src/engine/events.d.ts +130 -0
- package/dist/src/engine/events.js +44 -0
- package/dist/src/engine/gospel.d.ts +30 -0
- package/dist/src/engine/gospel.js +129 -0
- package/dist/src/engine/hallucination-detector.d.ts +33 -0
- package/dist/src/engine/hallucination-detector.js +215 -0
- package/dist/src/engine/human-resolver.d.ts +19 -0
- package/dist/src/engine/human-resolver.js +89 -0
- package/dist/src/engine/instrumentality.d.ts +64 -0
- package/dist/src/engine/instrumentality.js +297 -0
- package/dist/src/engine/iruel-battle.d.ts +79 -0
- package/dist/src/engine/iruel-battle.js +319 -0
- package/dist/src/engine/kernel/deliberation-kernel.d.ts +12 -0
- package/dist/src/engine/kernel/deliberation-kernel.js +303 -0
- package/dist/src/engine/kernel/index.d.ts +8 -0
- package/dist/src/engine/kernel/index.js +7 -0
- package/dist/src/engine/kernel/phase-runner.d.ts +10 -0
- package/dist/src/engine/kernel/phase-runner.js +155 -0
- package/dist/src/engine/kernel/post-processor.d.ts +17 -0
- package/dist/src/engine/kernel/post-processor.js +131 -0
- package/dist/src/engine/kernel/types.d.ts +107 -0
- package/dist/src/engine/kernel/types.js +1 -0
- package/dist/src/engine/kernel/unit-executor.d.ts +6 -0
- package/dist/src/engine/kernel/unit-executor.js +132 -0
- package/dist/src/engine/lcl-manager.d.ts +44 -0
- package/dist/src/engine/lcl-manager.js +143 -0
- package/dist/src/engine/middleware/cache.d.ts +7 -0
- package/dist/src/engine/middleware/cache.js +29 -0
- package/dist/src/engine/middleware/chain.d.ts +18 -0
- package/dist/src/engine/middleware/chain.js +45 -0
- package/dist/src/engine/middleware/firewall.d.ts +8 -0
- package/dist/src/engine/middleware/firewall.js +24 -0
- package/dist/src/engine/middleware/index.d.ts +4 -0
- package/dist/src/engine/middleware/index.js +3 -0
- package/dist/src/engine/middleware/types.d.ts +43 -0
- package/dist/src/engine/middleware/types.js +1 -0
- package/dist/src/engine/nebuchadnezzar-key.d.ts +61 -0
- package/dist/src/engine/nebuchadnezzar-key.js +203 -0
- package/dist/src/engine/neon-genesis.d.ts +52 -0
- package/dist/src/engine/neon-genesis.js +203 -0
- package/dist/src/engine/objective-judge.d.ts +53 -0
- package/dist/src/engine/objective-judge.js +214 -0
- package/dist/src/engine/offline-mode.d.ts +18 -0
- package/dist/src/engine/offline-mode.js +46 -0
- package/dist/src/engine/orchestrator.d.ts +79 -0
- package/dist/src/engine/orchestrator.js +58 -0
- package/dist/src/engine/secret-cipher.d.ts +26 -0
- package/dist/src/engine/secret-cipher.js +114 -0
- package/dist/src/engine/seele-council.d.ts +90 -0
- package/dist/src/engine/seele-council.js +482 -0
- package/dist/src/engine/self-destruct.d.ts +61 -0
- package/dist/src/engine/self-destruct.js +231 -0
- package/dist/src/engine/self-evolution.d.ts +64 -0
- package/dist/src/engine/self-evolution.js +368 -0
- package/dist/src/engine/sync-rate.d.ts +45 -0
- package/dist/src/engine/sync-rate.js +151 -0
- package/dist/src/engine/type666-firewall.d.ts +76 -0
- package/dist/src/engine/type666-firewall.js +343 -0
- package/dist/src/engine/umbilical-cable.d.ts +41 -0
- package/dist/src/engine/umbilical-cable.js +192 -0
- package/dist/src/index.d.ts +106 -0
- package/dist/src/index.js +426 -0
- package/dist/src/mcp/server.d.ts +38 -0
- package/dist/src/mcp/server.js +196 -0
- package/dist/src/metrics/token-tracker.d.ts +38 -0
- package/dist/src/metrics/token-tracker.js +112 -0
- package/dist/src/parsers/json-extractor.d.ts +9 -0
- package/dist/src/parsers/json-extractor.js +239 -0
- package/dist/src/parsers/opinion-schema.d.ts +81 -0
- package/dist/src/parsers/opinion-schema.js +147 -0
- package/dist/src/parsers/unstructured-parser.d.ts +20 -0
- package/dist/src/parsers/unstructured-parser.js +122 -0
- package/dist/src/pipelines/architecture.d.ts +10 -0
- package/dist/src/pipelines/architecture.js +9 -0
- package/dist/src/pipelines/bug-analysis.d.ts +9 -0
- package/dist/src/pipelines/bug-analysis.js +8 -0
- package/dist/src/pipelines/code-review.d.ts +10 -0
- package/dist/src/pipelines/code-review.js +30 -0
- package/dist/src/pipelines/custom.d.ts +14 -0
- package/dist/src/pipelines/custom.js +29 -0
- package/dist/src/pipelines/registry.d.ts +9 -0
- package/dist/src/pipelines/registry.js +20 -0
- package/dist/src/prompts/personas.d.ts +6 -0
- package/dist/src/prompts/personas.js +44 -0
- package/dist/src/prompts/schemas.d.ts +4 -0
- package/dist/src/prompts/schemas.js +24 -0
- package/dist/src/prompts/templates.d.ts +6 -0
- package/dist/src/prompts/templates.js +91 -0
- package/dist/src/repl/accessibility.d.ts +23 -0
- package/dist/src/repl/accessibility.js +46 -0
- package/dist/src/repl/banner.d.ts +4 -0
- package/dist/src/repl/banner.js +28 -0
- package/dist/src/repl/boot-animation.d.ts +13 -0
- package/dist/src/repl/boot-animation.js +143 -0
- package/dist/src/repl/completer.d.ts +21 -0
- package/dist/src/repl/completer.js +168 -0
- package/dist/src/repl/context.d.ts +24 -0
- package/dist/src/repl/context.js +42 -0
- package/dist/src/repl/display-utils.d.ts +13 -0
- package/dist/src/repl/display-utils.js +65 -0
- package/dist/src/repl/event-listener.d.ts +18 -0
- package/dist/src/repl/event-listener.js +112 -0
- package/dist/src/repl/export-formatter.d.ts +8 -0
- package/dist/src/repl/export-formatter.js +73 -0
- package/dist/src/repl/ghost-text.d.ts +31 -0
- package/dist/src/repl/ghost-text.js +119 -0
- package/dist/src/repl/handoff-animation.d.ts +15 -0
- package/dist/src/repl/handoff-animation.js +65 -0
- package/dist/src/repl/history.d.ts +16 -0
- package/dist/src/repl/history.js +130 -0
- package/dist/src/repl/job-registry.d.ts +26 -0
- package/dist/src/repl/job-registry.js +80 -0
- package/dist/src/repl/magi-repl.d.ts +72 -0
- package/dist/src/repl/magi-repl.js +1008 -0
- package/dist/src/repl/multiline-input.d.ts +45 -0
- package/dist/src/repl/multiline-input.js +78 -0
- package/dist/src/repl/prompt-builder.d.ts +19 -0
- package/dist/src/repl/prompt-builder.js +36 -0
- package/dist/src/repl/repl-state.d.ts +5 -0
- package/dist/src/repl/repl-state.js +19 -0
- package/dist/src/repl/result-display.d.ts +8 -0
- package/dist/src/repl/result-display.js +195 -0
- package/dist/src/repl/session-stats.d.ts +26 -0
- package/dist/src/repl/session-stats.js +119 -0
- package/dist/src/repl/slash-commands.d.ts +60 -0
- package/dist/src/repl/slash-commands.js +725 -0
- package/dist/src/repl/terminal-sanitize.d.ts +14 -0
- package/dist/src/repl/terminal-sanitize.js +19 -0
- package/dist/src/reporters/console.d.ts +7 -0
- package/dist/src/reporters/console.js +78 -0
- package/dist/src/reporters/json.d.ts +2 -0
- package/dist/src/reporters/json.js +3 -0
- package/dist/src/reporters/markdown.d.ts +2 -0
- package/dist/src/reporters/markdown.js +65 -0
- package/dist/src/reporters/streaming.d.ts +20 -0
- package/dist/src/reporters/streaming.js +178 -0
- package/dist/src/tui/activity-log.d.ts +23 -0
- package/dist/src/tui/activity-log.js +67 -0
- package/dist/src/tui/animations.d.ts +39 -0
- package/dist/src/tui/animations.js +167 -0
- package/dist/src/tui/ansi.d.ts +28 -0
- package/dist/src/tui/ansi.js +51 -0
- package/dist/src/tui/boot-sequence.d.ts +11 -0
- package/dist/src/tui/boot-sequence.js +98 -0
- package/dist/src/tui/colors.d.ts +101 -0
- package/dist/src/tui/colors.js +71 -0
- package/dist/src/tui/header.d.ts +24 -0
- package/dist/src/tui/header.js +122 -0
- package/dist/src/tui/index.d.ts +3 -0
- package/dist/src/tui/index.js +3 -0
- package/dist/src/tui/keypress.d.ts +25 -0
- package/dist/src/tui/keypress.js +95 -0
- package/dist/src/tui/layout.d.ts +74 -0
- package/dist/src/tui/layout.js +171 -0
- package/dist/src/tui/magi-tui.d.ts +101 -0
- package/dist/src/tui/magi-tui.js +754 -0
- package/dist/src/tui/panel.d.ts +45 -0
- package/dist/src/tui/panel.js +292 -0
- package/dist/src/tui/screen-buffer.d.ts +54 -0
- package/dist/src/tui/screen-buffer.js +262 -0
- package/dist/src/tui/status-bar.d.ts +25 -0
- package/dist/src/tui/status-bar.js +124 -0
- package/dist/src/tui/terminal-detect.d.ts +26 -0
- package/dist/src/tui/terminal-detect.js +44 -0
- package/dist/src/tui/tui-helpers.d.ts +12 -0
- package/dist/src/tui/tui-helpers.js +37 -0
- package/dist/src/types/adapter.d.ts +75 -0
- package/dist/src/types/adapter.js +36 -0
- package/dist/src/types/config.d.ts +108 -0
- package/dist/src/types/config.js +85 -0
- package/dist/src/types/consensus.d.ts +55 -0
- package/dist/src/types/consensus.js +17 -0
- package/dist/src/types/core.d.ts +178 -0
- package/dist/src/types/core.js +85 -0
- package/dist/src/types/magi-api.d.ts +62 -0
- package/dist/src/types/magi-api.js +7 -0
- package/dist/src/types/phase-h.d.ts +142 -0
- package/dist/src/types/phase-h.js +7 -0
- package/dist/src/types/phase-i.d.ts +186 -0
- package/dist/src/types/phase-i.js +6 -0
- package/dist/src/types/phase-k.d.ts +259 -0
- package/dist/src/types/phase-k.js +6 -0
- package/dist/src/types/phase-l.d.ts +199 -0
- package/dist/src/types/phase-l.js +6 -0
- package/dist/src/types/pipeline.d.ts +37 -0
- package/dist/src/types/pipeline.js +2 -0
- package/dist/src/utils/abstain-factory.d.ts +2 -0
- package/dist/src/utils/abstain-factory.js +18 -0
- package/dist/src/utils/errors.d.ts +34 -0
- package/dist/src/utils/errors.js +59 -0
- package/dist/src/utils/file-validator.d.ts +50 -0
- package/dist/src/utils/file-validator.js +124 -0
- package/dist/src/utils/fire-and-forget.d.ts +5 -0
- package/dist/src/utils/fire-and-forget.js +10 -0
- package/dist/src/utils/flag-validator.d.ts +21 -0
- package/dist/src/utils/flag-validator.js +79 -0
- package/dist/src/utils/freeze.d.ts +8 -0
- package/dist/src/utils/freeze.js +16 -0
- package/dist/src/utils/language-detector.d.ts +16 -0
- package/dist/src/utils/language-detector.js +159 -0
- package/dist/src/utils/latency-tracker.d.ts +45 -0
- package/dist/src/utils/latency-tracker.js +100 -0
- package/dist/src/utils/logger.d.ts +33 -0
- package/dist/src/utils/logger.js +112 -0
- package/dist/src/utils/process.d.ts +40 -0
- package/dist/src/utils/process.js +253 -0
- package/dist/src/utils/retry.d.ts +12 -0
- package/dist/src/utils/retry.js +30 -0
- package/dist/src/utils/safe-fs.d.ts +38 -0
- package/dist/src/utils/safe-fs.js +56 -0
- package/dist/src/utils/safe-json-parse.d.ts +15 -0
- package/dist/src/utils/safe-json-parse.js +49 -0
- package/dist/src/utils/sanitize.d.ts +14 -0
- package/dist/src/utils/sanitize.js +186 -0
- package/dist/src/utils/semaphore.d.ts +22 -0
- package/dist/src/utils/semaphore.js +57 -0
- package/dist/src/utils/shutdown.d.ts +6 -0
- package/dist/src/utils/shutdown.js +51 -0
- package/dist/src/utils/tty.d.ts +5 -0
- package/dist/src/utils/tty.js +7 -0
- package/package.json +82 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bottom status bar renderer.
|
|
3
|
+
* Shows phase, round, elapsed time, and system indicators.
|
|
4
|
+
*/
|
|
5
|
+
import { BOX } from './layout.js';
|
|
6
|
+
import { isApproval, isRejection } from '../types/consensus.js';
|
|
7
|
+
import { EVA_PALETTE } from './colors.js';
|
|
8
|
+
import { ATTR_BOLD, stringDisplayWidth, truncateToDisplayWidth } from './screen-buffer.js';
|
|
9
|
+
import { phaseCode, formatElapsedMmSs } from './tui-helpers.js';
|
|
10
|
+
// ── Status Bar Renderer ─────────────────────────────────────
|
|
11
|
+
export class StatusBarRenderer {
|
|
12
|
+
drawStatusBar(buf, rect, data) {
|
|
13
|
+
const fc = EVA_PALETTE.frame;
|
|
14
|
+
const tc = EVA_PALETTE.textPrimary;
|
|
15
|
+
const tw = EVA_PALETTE.textSecondary;
|
|
16
|
+
const { row, col, width } = rect;
|
|
17
|
+
// Top separator line
|
|
18
|
+
buf.writeAt(row, col, BOX.lT, fc.r, fc.g, fc.b);
|
|
19
|
+
for (let x = col + 1; x < col + width - 1; x++) {
|
|
20
|
+
buf.writeAt(row, x, BOX.h, fc.r, fc.g, fc.b);
|
|
21
|
+
}
|
|
22
|
+
buf.writeAt(row, col + width - 1, BOX.rT, fc.r, fc.g, fc.b);
|
|
23
|
+
// Status content (row + 1)
|
|
24
|
+
const contentRow = row + 1;
|
|
25
|
+
// Clear content area
|
|
26
|
+
for (let x = col + 1; x < col + width - 1; x++) {
|
|
27
|
+
buf.writeAt(contentRow, x, ' ');
|
|
28
|
+
}
|
|
29
|
+
if (data.decision) {
|
|
30
|
+
// Final result
|
|
31
|
+
const decColor = isApproval(data.decision) ? EVA_PALETTE.approve
|
|
32
|
+
: isRejection(data.decision) ? EVA_PALETTE.reject
|
|
33
|
+
: EVA_PALETTE.textSecondary;
|
|
34
|
+
if (data.showPrompt) {
|
|
35
|
+
// Decision + prompt on same line
|
|
36
|
+
const prompt = 'ANY KEY // 1-3 DETAIL';
|
|
37
|
+
const label = data.fromCache ? `${data.decision} (cached)` : data.decision;
|
|
38
|
+
const combined = `${label} ${prompt}`;
|
|
39
|
+
const centered = Math.max(1, Math.floor((width - stringDisplayWidth(combined)) / 2));
|
|
40
|
+
buf.writeAt(contentRow, col + centered, label, decColor.r, decColor.g, decColor.b, 0, 0, 0, ATTR_BOLD);
|
|
41
|
+
const promptCol = col + centered + stringDisplayWidth(label) + 2;
|
|
42
|
+
const pc = EVA_PALETTE.frame;
|
|
43
|
+
buf.writeAt(contentRow, promptCol, prompt, pc.r, pc.g, pc.b);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const label = data.fromCache ? `${data.decision} (cached)` : data.decision;
|
|
47
|
+
const centered = Math.max(1, Math.floor((width - stringDisplayWidth(label)) / 2));
|
|
48
|
+
buf.writeAt(contentRow, col + centered, label, decColor.r, decColor.g, decColor.b, 0, 0, 0, ATTR_BOLD);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Progress info
|
|
53
|
+
const elapsed = formatElapsedMmSs(data.elapsedMs);
|
|
54
|
+
const { left, middle, right } = buildProgressSegments(width, {
|
|
55
|
+
phase: data.phase,
|
|
56
|
+
roundNumber: data.roundNumber,
|
|
57
|
+
maxRounds: data.maxRounds,
|
|
58
|
+
elapsed,
|
|
59
|
+
atFieldLevel: data.atFieldLevel,
|
|
60
|
+
syncSummary: data.syncSummary,
|
|
61
|
+
modeLabel: data.modeLabel,
|
|
62
|
+
umbilicalStatus: data.umbilicalStatus,
|
|
63
|
+
alertCode: data.alertCode ?? data.warning ?? 'ALERT:NONE',
|
|
64
|
+
});
|
|
65
|
+
buf.writeAt(contentRow, col + 2, left, tc.r, tc.g, tc.b);
|
|
66
|
+
const middleCol = col + 2 + stringDisplayWidth(left) + 2;
|
|
67
|
+
if (middle) {
|
|
68
|
+
buf.writeAt(contentRow, middleCol, middle, tw.r, tw.g, tw.b);
|
|
69
|
+
}
|
|
70
|
+
const rightColor = right === 'ALERT NONE' || right === 'ALERT:NONE' ? tc : EVA_PALETTE.warning;
|
|
71
|
+
const rightCol = Math.max(col + 2, col + width - stringDisplayWidth(right) - 2);
|
|
72
|
+
buf.writeAt(contentRow, rightCol, right, rightColor.r, rightColor.g, rightColor.b, 0, 0, 0, ATTR_BOLD);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function buildProgressSegments(width, data) {
|
|
77
|
+
const phase = phaseCode(data.phase, 'STBY');
|
|
78
|
+
const atf = data.atFieldLevel !== undefined
|
|
79
|
+
? data.atFieldLevel === 'MAX' ? 'AT MAX' : `AT L${data.atFieldLevel}`
|
|
80
|
+
: 'AT STB';
|
|
81
|
+
const sync = data.syncSummary ? `SYNC ${data.syncSummary}` : 'SYNC --';
|
|
82
|
+
const mode = data.modeLabel ? `MODE ${data.modeLabel}` : 'MODE NORMAL';
|
|
83
|
+
const cable = data.umbilicalStatus ? `UMB ${data.umbilicalStatus}` : 'UMB CONNECTED';
|
|
84
|
+
const alert = normalizeAlert(data.alertCode);
|
|
85
|
+
const leftVariants = [
|
|
86
|
+
`PHASE ${phase} ROUND ${data.roundNumber}/${data.maxRounds} ELAPSED ${data.elapsed}`,
|
|
87
|
+
`PH ${phase} R ${data.roundNumber}/${data.maxRounds} T ${data.elapsed}`,
|
|
88
|
+
];
|
|
89
|
+
const middleVariants = [
|
|
90
|
+
`${mode} ${sync}`,
|
|
91
|
+
`${mode}`,
|
|
92
|
+
'',
|
|
93
|
+
];
|
|
94
|
+
const rightVariants = [
|
|
95
|
+
`${atf} ${cable} ${alert}`,
|
|
96
|
+
`${atf} ${alert}`,
|
|
97
|
+
`${alert}`,
|
|
98
|
+
];
|
|
99
|
+
for (const leftCandidate of leftVariants) {
|
|
100
|
+
for (const middleCandidate of middleVariants) {
|
|
101
|
+
for (const rightCandidate of rightVariants) {
|
|
102
|
+
const totalWidth = stringDisplayWidth(leftCandidate)
|
|
103
|
+
+ stringDisplayWidth(middleCandidate || '')
|
|
104
|
+
+ stringDisplayWidth(rightCandidate)
|
|
105
|
+
+ (middleCandidate ? 4 : 2);
|
|
106
|
+
if (totalWidth <= Math.max(10, width - 4)) {
|
|
107
|
+
return {
|
|
108
|
+
left: leftCandidate,
|
|
109
|
+
middle: middleCandidate,
|
|
110
|
+
right: rightCandidate,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
left: truncateToDisplayWidth(leftVariants[leftVariants.length - 1], Math.max(12, Math.floor(width * 0.45))),
|
|
118
|
+
middle: '',
|
|
119
|
+
right: truncateToDisplayWidth(rightVariants[rightVariants.length - 1], Math.max(10, Math.floor(width * 0.3))),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function normalizeAlert(alertCode) {
|
|
123
|
+
return alertCode.replace(/:/g, ' ').replace(/\s+/g, ' ').trim();
|
|
124
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal capability detection for TUI mode.
|
|
3
|
+
*/
|
|
4
|
+
import { type TuiProfile } from './layout.js';
|
|
5
|
+
export declare const MIN_COLS = 80;
|
|
6
|
+
export declare const MIN_ROWS = 24;
|
|
7
|
+
export interface TerminalCapabilities {
|
|
8
|
+
readonly cols: number;
|
|
9
|
+
readonly rows: number;
|
|
10
|
+
readonly trueColor: boolean;
|
|
11
|
+
readonly color256: boolean;
|
|
12
|
+
readonly unicode: boolean;
|
|
13
|
+
readonly isTTY: boolean;
|
|
14
|
+
readonly profile: TuiProfile;
|
|
15
|
+
}
|
|
16
|
+
export declare function getTerminalSize(): {
|
|
17
|
+
cols: number;
|
|
18
|
+
rows: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function detectCapabilities(): TerminalCapabilities;
|
|
21
|
+
/**
|
|
22
|
+
* Check if the terminal meets minimum TUI requirements.
|
|
23
|
+
* Returns a failure reason string, or null if capable.
|
|
24
|
+
*/
|
|
25
|
+
export declare function tuiCheckFailure(caps: TerminalCapabilities): string | null;
|
|
26
|
+
export declare function isTuiCapable(caps: TerminalCapabilities): boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal capability detection for TUI mode.
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { getTuiProfile } from './layout.js';
|
|
6
|
+
// ── Minimum requirements ────────────────────────────────────
|
|
7
|
+
export const MIN_COLS = 80;
|
|
8
|
+
export const MIN_ROWS = 24;
|
|
9
|
+
// ── Detection ───────────────────────────────────────────────
|
|
10
|
+
export function getTerminalSize() {
|
|
11
|
+
return {
|
|
12
|
+
cols: process.stdout.columns ?? 80,
|
|
13
|
+
rows: process.stdout.rows ?? 24,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function detectCapabilities() {
|
|
17
|
+
const { cols, rows } = getTerminalSize();
|
|
18
|
+
const lang = process.env['LC_ALL'] ?? process.env['LC_CTYPE'] ?? process.env['LANG'] ?? '';
|
|
19
|
+
return {
|
|
20
|
+
cols,
|
|
21
|
+
rows,
|
|
22
|
+
trueColor: chalk.level >= 3,
|
|
23
|
+
color256: chalk.level >= 2,
|
|
24
|
+
unicode: /utf-?8/i.test(lang),
|
|
25
|
+
isTTY: process.stdout.isTTY === true,
|
|
26
|
+
profile: getTuiProfile(cols, rows),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if the terminal meets minimum TUI requirements.
|
|
31
|
+
* Returns a failure reason string, or null if capable.
|
|
32
|
+
*/
|
|
33
|
+
export function tuiCheckFailure(caps) {
|
|
34
|
+
if (!caps.isTTY) {
|
|
35
|
+
return 'stdout is not a TTY';
|
|
36
|
+
}
|
|
37
|
+
if (caps.cols < MIN_COLS || caps.rows < MIN_ROWS) {
|
|
38
|
+
return `Terminal too small (${caps.cols}x${caps.rows}, need ${MIN_COLS}x${MIN_ROWS})`;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
export function isTuiCapable(caps) {
|
|
43
|
+
return tuiCheckFailure(caps) === null;
|
|
44
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper functions for TUI renderers.
|
|
3
|
+
* Single source of truth for logic previously duplicated across magi-tui.ts, header.ts, status-bar.ts, panel.ts.
|
|
4
|
+
*/
|
|
5
|
+
/** Derive a compact source label for the header display. */
|
|
6
|
+
export declare function deriveSourceLabel(taskType: string, taskTitle: string): string;
|
|
7
|
+
/** Derive a priority label from task type. */
|
|
8
|
+
export declare function derivePriorityLabel(taskType: string): string;
|
|
9
|
+
/** Convert phase name to compact 3-4 char code. */
|
|
10
|
+
export declare function phaseCode(phase: string, defaultCode?: string): string;
|
|
11
|
+
/** Format milliseconds as MM:SS. */
|
|
12
|
+
export declare function formatElapsedMmSs(ms: number): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper functions for TUI renderers.
|
|
3
|
+
* Single source of truth for logic previously duplicated across magi-tui.ts, header.ts, status-bar.ts, panel.ts.
|
|
4
|
+
*/
|
|
5
|
+
/** Derive a compact source label for the header display. */
|
|
6
|
+
export function deriveSourceLabel(taskType, taskTitle) {
|
|
7
|
+
if (taskType === 'code-review' && taskTitle.startsWith('Code Review: ')) {
|
|
8
|
+
return taskTitle.slice('Code Review: '.length);
|
|
9
|
+
}
|
|
10
|
+
return `NERV://${taskType}`;
|
|
11
|
+
}
|
|
12
|
+
/** Derive a priority label from task type. */
|
|
13
|
+
export function derivePriorityLabel(taskType) {
|
|
14
|
+
switch (taskType) {
|
|
15
|
+
case 'security-audit': return 'AAA';
|
|
16
|
+
case 'code-review': return 'AA';
|
|
17
|
+
case 'bug-analysis': return 'A+';
|
|
18
|
+
case 'architecture-decision': return 'A';
|
|
19
|
+
default: return 'B';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Convert phase name to compact 3-4 char code. */
|
|
23
|
+
export function phaseCode(phase, defaultCode = 'MAGI') {
|
|
24
|
+
switch (phase) {
|
|
25
|
+
case 'initial-opinion': return 'IOP';
|
|
26
|
+
case 'cross-examination': return 'XAM';
|
|
27
|
+
case 'final-vote': return 'VOTE';
|
|
28
|
+
default: return phase ? phase.toUpperCase().slice(0, 4) : defaultCode;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Format milliseconds as MM:SS. */
|
|
32
|
+
export function formatElapsedMmSs(ms) {
|
|
33
|
+
const totalSec = Math.floor(ms / 1000);
|
|
34
|
+
const min = Math.floor(totalSec / 60);
|
|
35
|
+
const sec = totalSec % 60;
|
|
36
|
+
return `${String(min).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
|
|
37
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { MagiUnit, CliTool, ExecutionMeta } from './core.js';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
3
|
+
/** Zod schema for binaryPath validation — rejects ".." segments and unknown basenames */
|
|
4
|
+
export declare const binaryPathSchema: z.ZodString;
|
|
5
|
+
/** Zod schema for adapter configuration validation */
|
|
6
|
+
export declare const AdapterConfigSchema: z.ZodObject<{
|
|
7
|
+
binaryPath: z.ZodOptional<z.ZodString>;
|
|
8
|
+
timeoutMs: z.ZodNumber;
|
|
9
|
+
maxRetries: z.ZodNumber;
|
|
10
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
11
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
12
|
+
model: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
/** Configuration for a CLI adapter */
|
|
15
|
+
export interface AdapterConfig {
|
|
16
|
+
binaryPath?: string;
|
|
17
|
+
timeoutMs: number;
|
|
18
|
+
maxRetries: number;
|
|
19
|
+
cwd?: string;
|
|
20
|
+
env?: Record<string, string>;
|
|
21
|
+
model?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Request to send to a CLI adapter */
|
|
24
|
+
export interface AdapterRequest {
|
|
25
|
+
prompt: string;
|
|
26
|
+
systemPrompt?: string;
|
|
27
|
+
jsonSchema?: Record<string, unknown>;
|
|
28
|
+
maxBudgetUsd?: number;
|
|
29
|
+
timeoutMs?: number;
|
|
30
|
+
cwd?: string;
|
|
31
|
+
contextFiles?: string[];
|
|
32
|
+
onStdoutChunk?: (chunk: string) => void;
|
|
33
|
+
onStderrChunk?: (chunk: string) => void;
|
|
34
|
+
signal?: AbortSignal;
|
|
35
|
+
/** When true, adapters may enable file-reading tools/flags */
|
|
36
|
+
fileAccessEnabled?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** Response from a CLI adapter */
|
|
39
|
+
export interface AdapterResponse {
|
|
40
|
+
structured: Record<string, unknown> | null;
|
|
41
|
+
raw: string;
|
|
42
|
+
meta: ExecutionMeta;
|
|
43
|
+
parsed: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Known error codes from CLI adapters */
|
|
46
|
+
export type AdapterErrorCode = 'TIMEOUT' | 'CRASH' | 'PARSE_ERROR' | 'BINARY_NOT_FOUND' | 'UNKNOWN';
|
|
47
|
+
/** Error from a CLI adapter */
|
|
48
|
+
export declare class AdapterError extends Error {
|
|
49
|
+
readonly unit: MagiUnit;
|
|
50
|
+
readonly tool: CliTool;
|
|
51
|
+
readonly code: AdapterErrorCode;
|
|
52
|
+
readonly stderr?: string;
|
|
53
|
+
readonly exitCode?: number;
|
|
54
|
+
readonly partialOutput?: string;
|
|
55
|
+
constructor(opts: {
|
|
56
|
+
unit: MagiUnit;
|
|
57
|
+
tool: CliTool;
|
|
58
|
+
code: AdapterErrorCode;
|
|
59
|
+
message: string;
|
|
60
|
+
stderr?: string;
|
|
61
|
+
exitCode?: number;
|
|
62
|
+
partialOutput?: string;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Abstract interface for CLI adapters */
|
|
66
|
+
export interface ICliAdapter {
|
|
67
|
+
readonly unit: MagiUnit;
|
|
68
|
+
readonly tool: CliTool;
|
|
69
|
+
readonly displayName: string;
|
|
70
|
+
healthCheck(): Promise<string>;
|
|
71
|
+
execute(request: AdapterRequest): Promise<AdapterResponse>;
|
|
72
|
+
supportsStructuredOutput(): boolean;
|
|
73
|
+
supportsSystemPrompt(): boolean;
|
|
74
|
+
buildCommand(request: AdapterRequest): string[];
|
|
75
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
/** Known binary basenames for MAGI adapters */
|
|
3
|
+
const KNOWN_BINARIES = new Set(['claude', 'codex', 'gemini']);
|
|
4
|
+
/** Zod schema for binaryPath validation — rejects ".." segments and unknown basenames */
|
|
5
|
+
export const binaryPathSchema = z.string()
|
|
6
|
+
.refine(p => !p.split('/').includes('..'), 'binaryPath must not contain ".." segments')
|
|
7
|
+
.refine(p => KNOWN_BINARIES.has(p.split('/').pop() ?? ''), 'binaryPath basename must be claude, codex, or gemini');
|
|
8
|
+
/** Zod schema for adapter configuration validation */
|
|
9
|
+
export const AdapterConfigSchema = z.object({
|
|
10
|
+
binaryPath: binaryPathSchema.optional(),
|
|
11
|
+
timeoutMs: z.number().int().min(1_000).max(600_000),
|
|
12
|
+
maxRetries: z.number().int().min(0).max(5),
|
|
13
|
+
cwd: z.string().optional(),
|
|
14
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
15
|
+
model: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
/** Error from a CLI adapter */
|
|
18
|
+
export class AdapterError extends Error {
|
|
19
|
+
unit;
|
|
20
|
+
tool;
|
|
21
|
+
code;
|
|
22
|
+
stderr;
|
|
23
|
+
exitCode;
|
|
24
|
+
partialOutput;
|
|
25
|
+
constructor(opts) {
|
|
26
|
+
super(opts.message);
|
|
27
|
+
this.name = 'AdapterError';
|
|
28
|
+
this.unit = opts.unit;
|
|
29
|
+
this.tool = opts.tool;
|
|
30
|
+
this.code = opts.code;
|
|
31
|
+
this.stderr = opts.stderr;
|
|
32
|
+
this.exitCode = opts.exitCode;
|
|
33
|
+
this.partialOutput = opts.partialOutput;
|
|
34
|
+
Error.captureStackTrace?.(this, AdapterError);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import type { BuiltinMagiUnit } from './core.js';
|
|
3
|
+
import type { AdapterConfig } from './adapter.js';
|
|
4
|
+
import type { PipelineConfig } from './pipeline.js';
|
|
5
|
+
import type { AuditLogConfig } from '../audit/types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Adapter map: built-in units are guaranteed present, additional custom units allowed.
|
|
8
|
+
* This ensures `config.adapters.MELCHIOR` etc. are non-undefined while supporting N-body.
|
|
9
|
+
*/
|
|
10
|
+
export type AdapterMap = Record<BuiltinMagiUnit, AdapterConfig> & Record<string, AdapterConfig>;
|
|
11
|
+
/** Configuration for CLI file access during deliberation */
|
|
12
|
+
export interface FileAccessConfig {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
/** Glob patterns for allowed paths (default: all in cwd) */
|
|
15
|
+
allowedPaths?: string[];
|
|
16
|
+
/** Glob patterns to deny (default: .env, *.key, credentials*, etc.) */
|
|
17
|
+
deniedPatterns?: string[];
|
|
18
|
+
}
|
|
19
|
+
/** Top-level MAGI system configuration */
|
|
20
|
+
export interface MagiConfig {
|
|
21
|
+
adapters: AdapterMap;
|
|
22
|
+
defaultPipeline: PipelineConfig;
|
|
23
|
+
workspaceDir: string;
|
|
24
|
+
logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
25
|
+
outputFormat: 'console' | 'json' | 'markdown';
|
|
26
|
+
preserveWorkspace: boolean;
|
|
27
|
+
maxConcurrentDeliberations: number;
|
|
28
|
+
cacheEnabled?: boolean;
|
|
29
|
+
cacheTtlMs?: number;
|
|
30
|
+
auditLog?: AuditLogConfig;
|
|
31
|
+
/** Which units to enable. undefined = all 3 built-in units. */
|
|
32
|
+
enabledUnits?: BuiltinMagiUnit[];
|
|
33
|
+
/** CLI file access during deliberation. Default: disabled. */
|
|
34
|
+
fileAccess?: FileAccessConfig;
|
|
35
|
+
}
|
|
36
|
+
/** Zod schema for MagiConfig validation */
|
|
37
|
+
export declare const MagiConfigSchema: z.ZodObject<{
|
|
38
|
+
adapters: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
39
|
+
binaryPath: z.ZodOptional<z.ZodString>;
|
|
40
|
+
timeoutMs: z.ZodNumber;
|
|
41
|
+
maxRetries: z.ZodNumber;
|
|
42
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
43
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
44
|
+
model: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, z.core.$strip>>;
|
|
46
|
+
defaultPipeline: z.ZodObject<{
|
|
47
|
+
phases: z.ZodArray<z.ZodEnum<{
|
|
48
|
+
"initial-opinion": "initial-opinion";
|
|
49
|
+
"cross-examination": "cross-examination";
|
|
50
|
+
"final-vote": "final-vote";
|
|
51
|
+
}>>;
|
|
52
|
+
maxRounds: z.ZodNumber;
|
|
53
|
+
parallelInitialOpinions: z.ZodBoolean;
|
|
54
|
+
earlyConsensusExit: z.ZodBoolean;
|
|
55
|
+
earlyExitThresholds: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
unanimous: z.ZodNumber;
|
|
57
|
+
majority: z.ZodNumber;
|
|
58
|
+
}, z.core.$strip>>;
|
|
59
|
+
consensus: z.ZodObject<{
|
|
60
|
+
minConfidenceThreshold: z.ZodNumber;
|
|
61
|
+
useWeightedVoting: z.ZodBoolean;
|
|
62
|
+
unitWeights: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
63
|
+
deadlockStrategy: z.ZodEnum<{
|
|
64
|
+
escalate: "escalate";
|
|
65
|
+
"melchior-tiebreak": "melchior-tiebreak";
|
|
66
|
+
"highest-confidence": "highest-confidence";
|
|
67
|
+
"human-in-the-loop": "human-in-the-loop";
|
|
68
|
+
}>;
|
|
69
|
+
quorum: z.ZodNumber;
|
|
70
|
+
}, z.core.$strip>;
|
|
71
|
+
phaseTimeoutMs: z.ZodNumber;
|
|
72
|
+
adapterTimeoutMs: z.ZodNumber;
|
|
73
|
+
deliberationTimeoutMs: z.ZodNumber;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
workspaceDir: z.ZodString;
|
|
76
|
+
logLevel: z.ZodEnum<{
|
|
77
|
+
error: "error";
|
|
78
|
+
debug: "debug";
|
|
79
|
+
info: "info";
|
|
80
|
+
warn: "warn";
|
|
81
|
+
}>;
|
|
82
|
+
outputFormat: z.ZodEnum<{
|
|
83
|
+
json: "json";
|
|
84
|
+
console: "console";
|
|
85
|
+
markdown: "markdown";
|
|
86
|
+
}>;
|
|
87
|
+
preserveWorkspace: z.ZodBoolean;
|
|
88
|
+
maxConcurrentDeliberations: z.ZodNumber;
|
|
89
|
+
cacheEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
90
|
+
cacheTtlMs: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
enabledUnits: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
92
|
+
MELCHIOR: "MELCHIOR";
|
|
93
|
+
BALTHASAR: "BALTHASAR";
|
|
94
|
+
CASPER: "CASPER";
|
|
95
|
+
}>>>;
|
|
96
|
+
fileAccess: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
enabled: z.ZodBoolean;
|
|
98
|
+
allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
99
|
+
deniedPatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
100
|
+
}, z.core.$strip>>;
|
|
101
|
+
auditLog: z.ZodOptional<z.ZodObject<{
|
|
102
|
+
logDir: z.ZodString;
|
|
103
|
+
maxFileSize: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
maxFiles: z.ZodOptional<z.ZodNumber>;
|
|
105
|
+
}, z.core.$strip>>;
|
|
106
|
+
}, z.core.$strip>;
|
|
107
|
+
/** Default configuration */
|
|
108
|
+
export declare const DEFAULT_CONFIG: Readonly<MagiConfig>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { binaryPathSchema } from './adapter.js';
|
|
3
|
+
import { deepFreeze } from '../utils/freeze.js';
|
|
4
|
+
/** Zod schema for MagiConfig validation */
|
|
5
|
+
export const MagiConfigSchema = z.object({
|
|
6
|
+
adapters: z.record(z.string(), z.object({
|
|
7
|
+
binaryPath: binaryPathSchema.optional(),
|
|
8
|
+
timeoutMs: z.number().int().min(1_000).max(600_000),
|
|
9
|
+
maxRetries: z.number().int().min(0).max(5),
|
|
10
|
+
cwd: z.string().optional(),
|
|
11
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
12
|
+
model: z.string().optional(),
|
|
13
|
+
})),
|
|
14
|
+
defaultPipeline: z.object({
|
|
15
|
+
phases: z.array(z.enum(['initial-opinion', 'cross-examination', 'final-vote'])).min(1),
|
|
16
|
+
maxRounds: z.number().int().min(1).max(10),
|
|
17
|
+
parallelInitialOpinions: z.boolean(),
|
|
18
|
+
earlyConsensusExit: z.boolean(),
|
|
19
|
+
earlyExitThresholds: z.object({
|
|
20
|
+
unanimous: z.number().min(0).max(1),
|
|
21
|
+
majority: z.number().min(0).max(1),
|
|
22
|
+
}).optional(),
|
|
23
|
+
consensus: z.object({
|
|
24
|
+
minConfidenceThreshold: z.number().min(0).max(1),
|
|
25
|
+
useWeightedVoting: z.boolean(),
|
|
26
|
+
unitWeights: z.record(z.string(), z.number()).optional(),
|
|
27
|
+
deadlockStrategy: z.enum(['escalate', 'melchior-tiebreak', 'highest-confidence', 'human-in-the-loop']),
|
|
28
|
+
quorum: z.number().int().min(1).max(7),
|
|
29
|
+
}),
|
|
30
|
+
phaseTimeoutMs: z.number().int().min(1_000).max(3_600_000),
|
|
31
|
+
adapterTimeoutMs: z.number().int().min(1_000).max(600_000),
|
|
32
|
+
deliberationTimeoutMs: z.number().int().min(10_000).max(7_200_000),
|
|
33
|
+
}),
|
|
34
|
+
workspaceDir: z.string().min(1),
|
|
35
|
+
logLevel: z.enum(['debug', 'info', 'warn', 'error']),
|
|
36
|
+
outputFormat: z.enum(['console', 'json', 'markdown']),
|
|
37
|
+
preserveWorkspace: z.boolean(),
|
|
38
|
+
maxConcurrentDeliberations: z.number().int().min(1).max(10),
|
|
39
|
+
cacheEnabled: z.boolean().optional(),
|
|
40
|
+
cacheTtlMs: z.number().int().min(0).max(86_400_000).optional(),
|
|
41
|
+
enabledUnits: z.array(z.enum(['MELCHIOR', 'BALTHASAR', 'CASPER'])).min(1).max(3).optional(),
|
|
42
|
+
fileAccess: z.object({
|
|
43
|
+
enabled: z.boolean(),
|
|
44
|
+
allowedPaths: z.array(z.string()).optional(),
|
|
45
|
+
deniedPatterns: z.array(z.string()).optional(),
|
|
46
|
+
}).optional(),
|
|
47
|
+
auditLog: z.object({
|
|
48
|
+
logDir: z.string().min(1),
|
|
49
|
+
maxFileSize: z.number().int().min(1024).optional(),
|
|
50
|
+
maxFiles: z.number().int().min(1).max(100).optional(),
|
|
51
|
+
}).optional(),
|
|
52
|
+
});
|
|
53
|
+
/** Default configuration */
|
|
54
|
+
export const DEFAULT_CONFIG = deepFreeze({
|
|
55
|
+
adapters: {
|
|
56
|
+
MELCHIOR: { timeoutMs: 120_000, maxRetries: 2 },
|
|
57
|
+
BALTHASAR: { timeoutMs: 120_000, maxRetries: 2 },
|
|
58
|
+
CASPER: { timeoutMs: 120_000, maxRetries: 2 },
|
|
59
|
+
},
|
|
60
|
+
defaultPipeline: {
|
|
61
|
+
phases: ['initial-opinion', 'cross-examination', 'final-vote'],
|
|
62
|
+
maxRounds: 3,
|
|
63
|
+
parallelInitialOpinions: true,
|
|
64
|
+
earlyConsensusExit: true,
|
|
65
|
+
earlyExitThresholds: { unanimous: 0.7, majority: 0.85 },
|
|
66
|
+
consensus: {
|
|
67
|
+
minConfidenceThreshold: 0.3,
|
|
68
|
+
useWeightedVoting: false,
|
|
69
|
+
deadlockStrategy: 'melchior-tiebreak',
|
|
70
|
+
quorum: 2,
|
|
71
|
+
},
|
|
72
|
+
phaseTimeoutMs: 300_000,
|
|
73
|
+
adapterTimeoutMs: 120_000,
|
|
74
|
+
deliberationTimeoutMs: 1_800_000,
|
|
75
|
+
},
|
|
76
|
+
workspaceDir: '.magi',
|
|
77
|
+
logLevel: 'info',
|
|
78
|
+
outputFormat: 'console',
|
|
79
|
+
preserveWorkspace: false,
|
|
80
|
+
maxConcurrentDeliberations: 3,
|
|
81
|
+
fileAccess: { enabled: false },
|
|
82
|
+
auditLog: {
|
|
83
|
+
logDir: '.magi/audit',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { MagiUnit, Vote, Confidence } from './core.js';
|
|
2
|
+
/** Result of consensus calculation */
|
|
3
|
+
export interface ConsensusResult {
|
|
4
|
+
decision: ConsensusDecision;
|
|
5
|
+
method: ConsensusMethod;
|
|
6
|
+
votes: VoteSummary;
|
|
7
|
+
confidence: Confidence;
|
|
8
|
+
summary: string;
|
|
9
|
+
dissent?: DissentRecord[];
|
|
10
|
+
}
|
|
11
|
+
/** Possible consensus outcomes */
|
|
12
|
+
export type ConsensusDecision = 'UNANIMOUS_APPROVE' | 'MAJORITY_APPROVE' | 'UNANIMOUS_REJECT' | 'MAJORITY_REJECT' | 'DEADLOCK' | 'INSUFFICIENT';
|
|
13
|
+
/** Type-safe decision property helpers */
|
|
14
|
+
export interface DecisionProperties {
|
|
15
|
+
readonly isApproval: boolean;
|
|
16
|
+
readonly isRejection: boolean;
|
|
17
|
+
readonly isUnanimous: boolean;
|
|
18
|
+
readonly isMajority: boolean;
|
|
19
|
+
readonly isDeadlock: boolean;
|
|
20
|
+
readonly isInsufficient: boolean;
|
|
21
|
+
readonly majorityVote: 'APPROVE' | 'REJECT' | 'ABSTAIN';
|
|
22
|
+
}
|
|
23
|
+
export declare function getDecisionProps(decision: ConsensusDecision): DecisionProperties;
|
|
24
|
+
export declare function isApproval(d: ConsensusDecision): boolean;
|
|
25
|
+
export declare function isRejection(d: ConsensusDecision): boolean;
|
|
26
|
+
export declare function isUnanimous(d: ConsensusDecision): boolean;
|
|
27
|
+
export declare function isMajority(d: ConsensusDecision): boolean;
|
|
28
|
+
export declare function isDeadlock(d: ConsensusDecision): boolean;
|
|
29
|
+
export declare function getMajorityVote(d: ConsensusDecision): 'APPROVE' | 'REJECT' | 'ABSTAIN';
|
|
30
|
+
/** How the consensus was reached */
|
|
31
|
+
export type ConsensusMethod = 'unanimous' | 'majority' | 'weighted' | 'tiebreak' | 'escalated' | 'human';
|
|
32
|
+
/** Vote breakdown */
|
|
33
|
+
export interface VoteSummary {
|
|
34
|
+
approve: MagiUnit[];
|
|
35
|
+
reject: MagiUnit[];
|
|
36
|
+
abstain: MagiUnit[];
|
|
37
|
+
weightedApprove: number;
|
|
38
|
+
weightedReject: number;
|
|
39
|
+
}
|
|
40
|
+
/** Record of a dissenting opinion */
|
|
41
|
+
export interface DissentRecord {
|
|
42
|
+
unit: MagiUnit;
|
|
43
|
+
vote: Vote;
|
|
44
|
+
reasoning: string;
|
|
45
|
+
}
|
|
46
|
+
/** Configuration for the consensus engine */
|
|
47
|
+
export interface ConsensusConfig {
|
|
48
|
+
minConfidenceThreshold: Confidence;
|
|
49
|
+
useWeightedVoting: boolean;
|
|
50
|
+
unitWeights?: Partial<Record<MagiUnit, number>>;
|
|
51
|
+
deadlockStrategy: 'escalate' | 'melchior-tiebreak' | 'highest-confidence' | 'human-in-the-loop';
|
|
52
|
+
quorum: number;
|
|
53
|
+
/** Units to exclude from UNANIMOUS judgment (e.g., dummy plug units) */
|
|
54
|
+
excludeFromUnanimous?: MagiUnit[];
|
|
55
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const DECISION_PROPERTIES = {
|
|
2
|
+
UNANIMOUS_APPROVE: { isApproval: true, isRejection: false, isUnanimous: true, isMajority: false, isDeadlock: false, isInsufficient: false, majorityVote: 'APPROVE' },
|
|
3
|
+
MAJORITY_APPROVE: { isApproval: true, isRejection: false, isUnanimous: false, isMajority: true, isDeadlock: false, isInsufficient: false, majorityVote: 'APPROVE' },
|
|
4
|
+
UNANIMOUS_REJECT: { isApproval: false, isRejection: true, isUnanimous: true, isMajority: false, isDeadlock: false, isInsufficient: false, majorityVote: 'REJECT' },
|
|
5
|
+
MAJORITY_REJECT: { isApproval: false, isRejection: true, isUnanimous: false, isMajority: true, isDeadlock: false, isInsufficient: false, majorityVote: 'REJECT' },
|
|
6
|
+
DEADLOCK: { isApproval: false, isRejection: false, isUnanimous: false, isMajority: false, isDeadlock: true, isInsufficient: false, majorityVote: 'ABSTAIN' },
|
|
7
|
+
INSUFFICIENT: { isApproval: false, isRejection: false, isUnanimous: false, isMajority: false, isDeadlock: false, isInsufficient: true, majorityVote: 'ABSTAIN' },
|
|
8
|
+
};
|
|
9
|
+
export function getDecisionProps(decision) {
|
|
10
|
+
return DECISION_PROPERTIES[decision];
|
|
11
|
+
}
|
|
12
|
+
export function isApproval(d) { return DECISION_PROPERTIES[d].isApproval; }
|
|
13
|
+
export function isRejection(d) { return DECISION_PROPERTIES[d].isRejection; }
|
|
14
|
+
export function isUnanimous(d) { return DECISION_PROPERTIES[d].isUnanimous; }
|
|
15
|
+
export function isMajority(d) { return DECISION_PROPERTIES[d].isMajority; }
|
|
16
|
+
export function isDeadlock(d) { return DECISION_PROPERTIES[d].isDeadlock; }
|
|
17
|
+
export function getMajorityVote(d) { return DECISION_PROPERTIES[d].majorityVote; }
|