dual-brain 0.2.29 → 0.3.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/.dual-brain/docs/claude-code-extension-points.md +32 -0
- package/.dual-brain/docs/data-tools-capabilities.md +181 -0
- package/.dual-brain/docs/ecosystem-tools.md +91 -0
- package/.dual-brain/docs/panel-handoff.md +124 -0
- package/.dual-brain/docs/ruflo-analysis.md +48 -0
- package/bin/dual-brain.mjs +122 -51
- package/dist/mcp-server/index.d.ts +27 -0
- package/dist/mcp-server/index.js +359 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/src/agent-protocol.d.ts +163 -0
- package/dist/src/agent-protocol.js +368 -0
- package/dist/src/agent-protocol.js.map +1 -0
- package/dist/src/agents/registry.d.ts +52 -0
- package/dist/src/agents/registry.js +393 -0
- package/dist/src/agents/registry.js.map +1 -0
- package/dist/src/awareness.d.ts +93 -0
- package/dist/src/awareness.js +406 -0
- package/dist/src/awareness.js.map +1 -0
- package/dist/src/brief.d.ts +48 -0
- package/dist/src/brief.js +179 -0
- package/dist/src/brief.js.map +1 -0
- package/dist/src/calibration.d.ts +32 -0
- package/dist/src/calibration.js +133 -0
- package/dist/src/calibration.js.map +1 -0
- package/dist/src/checkpoint.d.ts +33 -0
- package/dist/src/checkpoint.js +99 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/ci-triage.d.ts +33 -0
- package/dist/src/ci-triage.js +193 -0
- package/dist/src/ci-triage.js.map +1 -0
- package/dist/src/cognitive-loop.d.ts +56 -0
- package/dist/src/cognitive-loop.js +495 -0
- package/dist/src/cognitive-loop.js.map +1 -0
- package/dist/src/collaboration.d.ts +147 -0
- package/dist/src/collaboration.js +438 -0
- package/dist/src/collaboration.js.map +1 -0
- package/dist/src/context-intel.d.ts +47 -0
- package/dist/src/context-intel.js +156 -0
- package/dist/src/context-intel.js.map +1 -0
- package/dist/src/context.d.ts +53 -0
- package/dist/src/context.js +332 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/continuity.d.ts +89 -0
- package/dist/src/continuity.js +230 -0
- package/dist/src/continuity.js.map +1 -0
- package/dist/src/cost-tracker.d.ts +47 -0
- package/dist/src/cost-tracker.js +170 -0
- package/dist/src/cost-tracker.js.map +1 -0
- package/dist/src/debrief.d.ts +53 -0
- package/dist/src/debrief.js +222 -0
- package/dist/src/debrief.js.map +1 -0
- package/dist/src/decide.d.ts +96 -0
- package/dist/src/decide.js +744 -0
- package/dist/src/decide.js.map +1 -0
- package/dist/src/decompose.d.ts +39 -0
- package/dist/src/decompose.js +218 -0
- package/dist/src/decompose.js.map +1 -0
- package/dist/src/detect.d.ts +91 -0
- package/dist/src/detect.js +544 -0
- package/dist/src/detect.js.map +1 -0
- package/dist/src/dispatch.d.ts +154 -0
- package/dist/src/dispatch.js +1306 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +421 -0
- package/dist/src/doctor.js +1689 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/engine.d.ts +70 -0
- package/dist/src/engine.js +155 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/envelope.d.ts +36 -0
- package/dist/src/envelope.js +80 -0
- package/dist/src/envelope.js.map +1 -0
- package/dist/src/failure-memory.d.ts +55 -0
- package/dist/src/failure-memory.js +175 -0
- package/dist/src/failure-memory.js.map +1 -0
- package/dist/src/fx.d.ts +87 -0
- package/dist/src/fx.js +272 -0
- package/dist/src/fx.js.map +1 -0
- package/dist/src/governance.d.ts +93 -0
- package/dist/src/governance.js +261 -0
- package/dist/src/governance.js.map +1 -0
- package/dist/src/handoff.d.ts +11 -0
- package/dist/src/handoff.js +90 -0
- package/dist/src/handoff.js.map +1 -0
- package/dist/src/head-protocol.d.ts +76 -0
- package/dist/src/head-protocol.js +109 -0
- package/dist/src/head-protocol.js.map +1 -0
- package/dist/src/head.d.ts +222 -0
- package/dist/src/head.js +765 -0
- package/dist/src/head.js.map +1 -0
- package/dist/src/health.d.ts +132 -0
- package/dist/src/health.js +435 -0
- package/dist/src/health.js.map +1 -0
- package/dist/src/inbox.d.ts +70 -0
- package/dist/src/inbox.js +218 -0
- package/dist/src/inbox.js.map +1 -0
- package/dist/src/index.d.ts +33 -0
- package/dist/src/index.js +38 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/install-hooks.d.ts +13 -0
- package/dist/src/install-hooks.js +88 -0
- package/dist/src/install-hooks.js.map +1 -0
- package/dist/src/integrity.d.ts +59 -0
- package/dist/src/integrity.js +206 -0
- package/dist/src/integrity.js.map +1 -0
- package/dist/src/intelligence.d.ts +104 -0
- package/dist/src/intelligence.js +391 -0
- package/dist/src/intelligence.js.map +1 -0
- package/dist/src/ledger.d.ts +54 -0
- package/dist/src/ledger.js +179 -0
- package/dist/src/ledger.js.map +1 -0
- package/dist/src/living-docs.d.ts +14 -0
- package/dist/src/living-docs.js +197 -0
- package/dist/src/living-docs.js.map +1 -0
- package/dist/src/memory-tiers.d.ts +37 -0
- package/dist/src/memory-tiers.js +160 -0
- package/dist/src/memory-tiers.js.map +1 -0
- package/dist/src/model-profiles.d.ts +65 -0
- package/dist/src/model-profiles.js +568 -0
- package/dist/src/model-profiles.js.map +1 -0
- package/dist/src/models.d.ts +58 -0
- package/dist/src/models.js +327 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/narrative.d.ts +54 -0
- package/dist/src/narrative.js +163 -0
- package/dist/src/narrative.js.map +1 -0
- package/dist/src/nextstep.d.ts +16 -0
- package/dist/src/nextstep.js +103 -0
- package/dist/src/nextstep.js.map +1 -0
- package/dist/src/observer.d.ts +18 -0
- package/dist/src/observer.js +251 -0
- package/dist/src/observer.js.map +1 -0
- package/dist/src/outcome.d.ts +110 -0
- package/dist/src/outcome.js +377 -0
- package/dist/src/outcome.js.map +1 -0
- package/dist/src/pipeline.d.ts +167 -0
- package/dist/src/pipeline.js +1503 -0
- package/dist/src/pipeline.js.map +1 -0
- package/dist/src/playbook.d.ts +59 -0
- package/dist/src/playbook.js +238 -0
- package/dist/src/playbook.js.map +1 -0
- package/dist/src/pr-agent.d.ts +97 -0
- package/dist/src/pr-agent.js +195 -0
- package/dist/src/pr-agent.js.map +1 -0
- package/dist/src/predictive.d.ts +57 -0
- package/dist/src/predictive.js +230 -0
- package/dist/src/predictive.js.map +1 -0
- package/dist/src/profile.d.ts +294 -0
- package/dist/src/profile.js +1347 -0
- package/dist/src/profile.js.map +1 -0
- package/dist/src/prompt-audit.d.ts +22 -0
- package/dist/src/prompt-audit.js +194 -0
- package/dist/src/prompt-audit.js.map +1 -0
- package/dist/src/prompt-intel.d.ts +12 -0
- package/dist/src/prompt-intel.js +321 -0
- package/dist/src/prompt-intel.js.map +1 -0
- package/dist/src/provider-context.d.ts +121 -0
- package/dist/src/provider-context.js +222 -0
- package/dist/src/provider-context.js.map +1 -0
- package/dist/src/provider-manager.d.ts +92 -0
- package/dist/src/provider-manager.js +428 -0
- package/dist/src/provider-manager.js.map +1 -0
- package/dist/src/receipt.d.ts +87 -0
- package/dist/src/receipt.js +326 -0
- package/dist/src/receipt.js.map +1 -0
- package/dist/src/recommendations.d.ts +13 -0
- package/dist/src/recommendations.js +291 -0
- package/dist/src/recommendations.js.map +1 -0
- package/dist/src/redact.d.ts +15 -0
- package/dist/src/redact.js +129 -0
- package/dist/src/redact.js.map +1 -0
- package/dist/src/replit.d.ts +397 -0
- package/dist/src/replit.js +1160 -0
- package/dist/src/replit.js.map +1 -0
- package/dist/src/repo.d.ts +149 -0
- package/dist/src/repo.js +416 -0
- package/dist/src/repo.js.map +1 -0
- package/dist/src/revert.d.ts +30 -0
- package/dist/src/revert.js +166 -0
- package/dist/src/revert.js.map +1 -0
- package/dist/src/room.d.ts +102 -0
- package/dist/src/room.js +212 -0
- package/dist/src/room.js.map +1 -0
- package/dist/src/routing-advisor.d.ts +57 -0
- package/dist/src/routing-advisor.js +221 -0
- package/dist/src/routing-advisor.js.map +1 -0
- package/dist/src/self-correct.d.ts +40 -0
- package/dist/src/self-correct.js +137 -0
- package/dist/src/self-correct.js.map +1 -0
- package/dist/src/session-lock.d.ts +35 -0
- package/dist/src/session-lock.js +134 -0
- package/dist/src/session-lock.js.map +1 -0
- package/dist/src/session.d.ts +267 -0
- package/dist/src/session.js +1660 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/settings-tui.d.ts +5 -0
- package/dist/src/settings-tui.js +422 -0
- package/dist/src/settings-tui.js.map +1 -0
- package/dist/src/setup-flow.d.ts +63 -0
- package/dist/src/setup-flow.js +233 -0
- package/dist/src/setup-flow.js.map +1 -0
- package/dist/src/signal.d.ts +19 -0
- package/dist/src/signal.js +122 -0
- package/dist/src/signal.js.map +1 -0
- package/dist/src/simmer.d.ts +85 -0
- package/dist/src/simmer.js +224 -0
- package/dist/src/simmer.js.map +1 -0
- package/dist/src/state-export.d.ts +129 -0
- package/dist/src/state-export.js +233 -0
- package/dist/src/state-export.js.map +1 -0
- package/dist/src/strategy.d.ts +54 -0
- package/dist/src/strategy.js +95 -0
- package/dist/src/strategy.js.map +1 -0
- package/dist/src/subscription.d.ts +40 -0
- package/dist/src/subscription.js +189 -0
- package/dist/src/subscription.js.map +1 -0
- package/dist/src/templates.d.ts +208 -0
- package/dist/src/templates.js +238 -0
- package/dist/src/templates.js.map +1 -0
- package/dist/src/test.d.ts +9 -0
- package/dist/src/test.js +1173 -0
- package/dist/src/test.js.map +1 -0
- package/dist/src/think-engine.d.ts +67 -0
- package/dist/src/think-engine.js +412 -0
- package/dist/src/think-engine.js.map +1 -0
- package/dist/src/tui.d.ts +71 -0
- package/dist/src/tui.js +242 -0
- package/dist/src/tui.js.map +1 -0
- package/dist/src/types.d.ts +177 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/update-check.d.ts +7 -0
- package/dist/src/update-check.js +36 -0
- package/dist/src/update-check.js.map +1 -0
- package/dist/src/wave-planner.d.ts +30 -0
- package/dist/src/wave-planner.js +281 -0
- package/dist/src/wave-planner.js.map +1 -0
- package/hooks/head-guard.sh +41 -0
- package/hooks/task-classifier.mjs +328 -0
- package/hooks/vibe-router.mjs +387 -0
- package/package.json +29 -153
- package/src/agents/registry.mjs +0 -405
- package/src/awareness.mjs +0 -425
- package/src/brief.mjs +0 -266
- package/src/calibration.mjs +0 -148
- package/src/checkpoint.mjs +0 -109
- package/src/ci-triage.mjs +0 -191
- package/src/cognitive-loop.mjs +0 -562
- package/src/collaboration.mjs +0 -545
- package/src/context-intel.mjs +0 -158
- package/src/context.mjs +0 -389
- package/src/continuity.mjs +0 -298
- package/src/cost-tracker.mjs +0 -184
- package/src/debrief.mjs +0 -228
- package/src/decide.mjs +0 -1099
- package/src/decompose.mjs +0 -331
- package/src/detect.mjs +0 -702
- package/src/dispatch.mjs +0 -1447
- package/src/doctor.mjs +0 -1607
- package/src/envelope.mjs +0 -139
- package/src/failure-memory.mjs +0 -178
- package/src/fx.mjs +0 -276
- package/src/governance.mjs +0 -279
- package/src/handoff.mjs +0 -85
- package/src/head-protocol.mjs +0 -128
- package/src/head.mjs +0 -952
- package/src/health.mjs +0 -528
- package/src/inbox.mjs +0 -195
- package/src/index.mjs +0 -44
- package/src/install-hooks.mjs +0 -100
- package/src/integrity.mjs +0 -245
- package/src/intelligence.mjs +0 -447
- package/src/ledger.mjs +0 -196
- package/src/living-docs.mjs +0 -210
- package/src/memory-tiers.mjs +0 -193
- package/src/models.mjs +0 -363
- package/src/narrative.mjs +0 -169
- package/src/nextstep.mjs +0 -100
- package/src/observer.mjs +0 -241
- package/src/outcome.mjs +0 -386
- package/src/pipeline.mjs +0 -1689
- package/src/playbook.mjs +0 -257
- package/src/pr-agent.mjs +0 -214
- package/src/predictive.mjs +0 -250
- package/src/profile.mjs +0 -1411
- package/src/prompt-audit.mjs +0 -231
- package/src/prompt-intel.mjs +0 -325
- package/src/provider-context.mjs +0 -257
- package/src/receipt.mjs +0 -344
- package/src/recommendations.mjs +0 -291
- package/src/redact.mjs +0 -192
- package/src/replit.mjs +0 -1210
- package/src/repo.mjs +0 -445
- package/src/revert.mjs +0 -149
- package/src/routing-advisor.mjs +0 -200
- package/src/self-correct.mjs +0 -146
- package/src/session-lock.mjs +0 -160
- package/src/session.mjs +0 -1655
- package/src/settings-tui.mjs +0 -373
- package/src/setup-flow.mjs +0 -215
- package/src/signal.mjs +0 -114
- package/src/simmer.mjs +0 -241
- package/src/strategy.mjs +0 -235
- package/src/subscription.mjs +0 -212
- package/src/templates.mjs +0 -260
- package/src/think-engine.mjs +0 -428
- package/src/tui.mjs +0 -276
- package/src/update-check.mjs +0 -35
- package/src/wave-planner.mjs +0 -294
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mcp-server/index.ts — TypeScript MCP server for dual-brain orchestration.
|
|
4
|
+
*
|
|
5
|
+
* Exposes dual-brain orchestration as tools via JSON-RPC 2.0 over stdio
|
|
6
|
+
* using the MCP protocol (Content-Length framing).
|
|
7
|
+
*
|
|
8
|
+
* Tools:
|
|
9
|
+
* dual_brain_status — Provider health, routing stats, active rooms
|
|
10
|
+
* dual_brain_dispatch — Route a prompt to best provider/model/tier
|
|
11
|
+
* dual_brain_history — Recent routing decisions and outcomes
|
|
12
|
+
* dual_brain_health — Per-provider health scores and cooldown status
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* node dist/mcp-server/index.js
|
|
16
|
+
*
|
|
17
|
+
* MCP client config:
|
|
18
|
+
* {
|
|
19
|
+
* "mcpServers": {
|
|
20
|
+
* "dual-brain": {
|
|
21
|
+
* "command": "node",
|
|
22
|
+
* "args": ["node_modules/dual-brain/mcp-server/index.mjs"]
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
// Static imports — resolve to compiled siblings in dist/src/ after tsc.
|
|
28
|
+
// @ts-ignore — these modules use dynamic exports
|
|
29
|
+
import { detectTask } from '../src/detect.js';
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
import { decideRoute } from '../src/decide.js';
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
import { loadProfile } from '../src/profile.js';
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
import { getHealth, getProviderScore, getSessionStats, checkCooldown } from '../src/health.js';
|
|
36
|
+
// ─── Tool definitions ────────────────────────────────────────────────────────
|
|
37
|
+
const TOOLS = [
|
|
38
|
+
{
|
|
39
|
+
name: 'dual_brain_status',
|
|
40
|
+
description: 'Get current provider health, routing stats, active rooms, and session overview. Returns which providers are enabled, their plan tier, health states, and active routing preferences.',
|
|
41
|
+
inputSchema: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'dual_brain_dispatch',
|
|
48
|
+
description: 'Accept a prompt and options, detect task type, and return the routing decision: which provider, model, tier, and explanation of why.',
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
properties: {
|
|
52
|
+
prompt: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'The task description or prompt to route.',
|
|
55
|
+
},
|
|
56
|
+
files: {
|
|
57
|
+
type: 'array',
|
|
58
|
+
items: { type: 'string' },
|
|
59
|
+
description: 'Optional file paths involved in the task (for risk classification).',
|
|
60
|
+
},
|
|
61
|
+
profile: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
enum: ['auto', 'balanced', 'cost-saver', 'quality-first'],
|
|
64
|
+
description: 'Optional profile mode override.',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
required: ['prompt'],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'dual_brain_history',
|
|
72
|
+
description: 'Return recent routing decisions and outcomes from the current session. Shows dispatches made, providers used, and token consumption.',
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: 'object',
|
|
75
|
+
properties: {
|
|
76
|
+
limit: {
|
|
77
|
+
type: 'number',
|
|
78
|
+
description: 'Maximum number of recent entries to return (default 10).',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'dual_brain_health',
|
|
85
|
+
description: 'Return per-provider health scores and cooldown status. Shows whether each provider/model is healthy, degraded, hot, or in cooldown.',
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: {
|
|
89
|
+
provider: {
|
|
90
|
+
type: 'string',
|
|
91
|
+
enum: ['claude', 'openai'],
|
|
92
|
+
description: 'Optional: filter to a specific provider.',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
// ─── Tool handlers ───────────────────────────────────────────────────────────
|
|
99
|
+
function handleStatus() {
|
|
100
|
+
const cwd = process.cwd();
|
|
101
|
+
const profile = loadProfile(cwd);
|
|
102
|
+
const health = getHealth(cwd);
|
|
103
|
+
const providers = {};
|
|
104
|
+
for (const prov of ['claude', 'openai']) {
|
|
105
|
+
const cfg = profile?.providers?.[prov];
|
|
106
|
+
if (!cfg) {
|
|
107
|
+
providers[prov] = { enabled: false };
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const models = {
|
|
111
|
+
search: prov === 'claude' ? 'haiku' : 'gpt-4.1-mini',
|
|
112
|
+
execute: prov === 'claude' ? 'sonnet' : 'gpt-5.4',
|
|
113
|
+
think: prov === 'claude' ? 'opus' : 'gpt-5.5',
|
|
114
|
+
};
|
|
115
|
+
const scores = {};
|
|
116
|
+
const states = {};
|
|
117
|
+
for (const [tier, modelClass] of Object.entries(models)) {
|
|
118
|
+
scores[tier] = getProviderScore(prov, modelClass, cwd);
|
|
119
|
+
const key = `${prov}:${modelClass}`;
|
|
120
|
+
states[modelClass] = health.states[key] ?? { status: 'healthy' };
|
|
121
|
+
}
|
|
122
|
+
providers[prov] = {
|
|
123
|
+
enabled: cfg.enabled ?? false,
|
|
124
|
+
plan: cfg.plan ?? null,
|
|
125
|
+
scores,
|
|
126
|
+
states,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const session = getSessionStats(cwd);
|
|
130
|
+
return {
|
|
131
|
+
providers,
|
|
132
|
+
session,
|
|
133
|
+
profile: {
|
|
134
|
+
mode: profile?.mode || 'auto',
|
|
135
|
+
preferences: (profile?.preferences || [])
|
|
136
|
+
.filter((p) => p.enabled)
|
|
137
|
+
.map((p) => p.text),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function handleDispatch(args) {
|
|
142
|
+
const prompt = args.prompt;
|
|
143
|
+
const files = args.files || [];
|
|
144
|
+
const profileOverride = args.profile;
|
|
145
|
+
const cwd = process.cwd();
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
147
|
+
let profile = loadProfile(cwd);
|
|
148
|
+
if (profileOverride) {
|
|
149
|
+
profile = { ...profile, mode: profileOverride };
|
|
150
|
+
}
|
|
151
|
+
const detection = detectTask({ prompt, files });
|
|
152
|
+
const decision = decideRoute({ profile, detection, cwd });
|
|
153
|
+
return {
|
|
154
|
+
provider: decision.provider,
|
|
155
|
+
model: decision.model,
|
|
156
|
+
effort: decision.effort,
|
|
157
|
+
tier: decision.tier,
|
|
158
|
+
dualBrain: decision.dualBrain,
|
|
159
|
+
modes: decision.modes,
|
|
160
|
+
sandbox: decision.sandbox,
|
|
161
|
+
explanation: decision.explanation,
|
|
162
|
+
detection: {
|
|
163
|
+
intent: detection.intent,
|
|
164
|
+
risk: detection.risk,
|
|
165
|
+
complexity: detection.complexity,
|
|
166
|
+
tier: detection.tier,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function handleHistory(args) {
|
|
171
|
+
const limit = args.limit || 10;
|
|
172
|
+
const cwd = process.cwd();
|
|
173
|
+
const health = getHealth(cwd);
|
|
174
|
+
const session = health.session;
|
|
175
|
+
if (!session || !session.dispatches || session.dispatches.length === 0) {
|
|
176
|
+
return { dispatches: [], count: 0, message: 'No dispatches recorded in current session.' };
|
|
177
|
+
}
|
|
178
|
+
const dispatches = session.dispatches.slice(-limit);
|
|
179
|
+
const stats = getSessionStats(cwd);
|
|
180
|
+
return {
|
|
181
|
+
dispatches,
|
|
182
|
+
count: dispatches.length,
|
|
183
|
+
total: session.dispatches.length,
|
|
184
|
+
startedAt: session.startedAt ?? null,
|
|
185
|
+
aggregated: stats,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function handleHealth(args) {
|
|
189
|
+
const providerFilter = args.provider;
|
|
190
|
+
const cwd = process.cwd();
|
|
191
|
+
const health = getHealth(cwd);
|
|
192
|
+
const result = {};
|
|
193
|
+
for (const [key, state] of Object.entries(health.states)) {
|
|
194
|
+
const [prov] = key.split(':');
|
|
195
|
+
if (providerFilter && prov !== providerFilter)
|
|
196
|
+
continue;
|
|
197
|
+
const modelClass = key.split(':')[1];
|
|
198
|
+
const cooldownExpired = checkCooldown(prov, modelClass, cwd);
|
|
199
|
+
result[key] = {
|
|
200
|
+
...state,
|
|
201
|
+
cooldownExpired,
|
|
202
|
+
score: getProviderScore(prov, modelClass, cwd),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
states: result,
|
|
207
|
+
filter: providerFilter ?? 'all',
|
|
208
|
+
stateCount: Object.keys(result).length,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
// ─── JSON-RPC dispatch ───────────────────────────────────────────────────────
|
|
212
|
+
function dispatchTool(name, args) {
|
|
213
|
+
let result;
|
|
214
|
+
switch (name) {
|
|
215
|
+
case 'dual_brain_status':
|
|
216
|
+
result = handleStatus();
|
|
217
|
+
break;
|
|
218
|
+
case 'dual_brain_dispatch':
|
|
219
|
+
result = handleDispatch(args);
|
|
220
|
+
break;
|
|
221
|
+
case 'dual_brain_history':
|
|
222
|
+
result = handleHistory(args);
|
|
223
|
+
break;
|
|
224
|
+
case 'dual_brain_health':
|
|
225
|
+
result = handleHealth(args);
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
return {
|
|
229
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
230
|
+
isError: true,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// ─── MCP protocol handlers ───────────────────────────────────────────────────
|
|
238
|
+
function makeResponse(id, result) {
|
|
239
|
+
return { jsonrpc: '2.0', id, result };
|
|
240
|
+
}
|
|
241
|
+
function makeError(id, code, message, data) {
|
|
242
|
+
const error = { code, message };
|
|
243
|
+
if (data !== undefined)
|
|
244
|
+
error.data = data;
|
|
245
|
+
return { jsonrpc: '2.0', id, error };
|
|
246
|
+
}
|
|
247
|
+
function handleMessage(msg) {
|
|
248
|
+
const { id, method, params } = msg;
|
|
249
|
+
try {
|
|
250
|
+
switch (method) {
|
|
251
|
+
case 'initialize':
|
|
252
|
+
return makeResponse(id ?? null, {
|
|
253
|
+
protocolVersion: '2024-11-05',
|
|
254
|
+
capabilities: { tools: {} },
|
|
255
|
+
serverInfo: { name: 'dual-brain', version: '0.2.30' },
|
|
256
|
+
});
|
|
257
|
+
case 'initialized':
|
|
258
|
+
case 'notifications/initialized':
|
|
259
|
+
// Notifications — no response
|
|
260
|
+
return null;
|
|
261
|
+
case 'tools/list':
|
|
262
|
+
return makeResponse(id ?? null, { tools: TOOLS });
|
|
263
|
+
case 'tools/call': {
|
|
264
|
+
const toolName = params?.name;
|
|
265
|
+
const toolArgs = (params?.arguments) ?? {};
|
|
266
|
+
if (!toolName) {
|
|
267
|
+
return makeError(id ?? null, -32602, 'Missing tool name in params');
|
|
268
|
+
}
|
|
269
|
+
const result = dispatchTool(toolName, toolArgs);
|
|
270
|
+
return makeResponse(id ?? null, result);
|
|
271
|
+
}
|
|
272
|
+
case 'ping':
|
|
273
|
+
return makeResponse(id ?? null, {});
|
|
274
|
+
default:
|
|
275
|
+
return makeError(id ?? null, -32601, `Method not found: ${method}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
const message = err instanceof Error ? err.message : 'Internal error';
|
|
280
|
+
return makeError(id ?? null, -32000, message);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// ─── MCP stdio transport (Content-Length framing) ────────────────────────────
|
|
284
|
+
function sendMessage(response) {
|
|
285
|
+
const body = JSON.stringify(response);
|
|
286
|
+
const header = `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n`;
|
|
287
|
+
process.stdout.write(header + body);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Reads Content-Length framed messages from stdin.
|
|
291
|
+
* Also supports bare newline-delimited JSON for compatibility.
|
|
292
|
+
*/
|
|
293
|
+
function startTransport() {
|
|
294
|
+
let buffer = '';
|
|
295
|
+
process.stdin.setEncoding('utf8');
|
|
296
|
+
process.stdin.on('data', (chunk) => {
|
|
297
|
+
buffer += chunk;
|
|
298
|
+
processBuffer();
|
|
299
|
+
});
|
|
300
|
+
process.stdin.on('end', () => {
|
|
301
|
+
if (buffer.trim()) {
|
|
302
|
+
processLine(buffer.trim());
|
|
303
|
+
}
|
|
304
|
+
process.exit(0);
|
|
305
|
+
});
|
|
306
|
+
function processBuffer() {
|
|
307
|
+
while (true) {
|
|
308
|
+
const headerEnd = buffer.indexOf('\r\n\r\n');
|
|
309
|
+
if (headerEnd === -1) {
|
|
310
|
+
// Fall back to newline-delimited mode
|
|
311
|
+
processNewlineDelimited();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const headerSection = buffer.slice(0, headerEnd);
|
|
315
|
+
const match = headerSection.match(/Content-Length:\s*(\d+)/i);
|
|
316
|
+
if (!match) {
|
|
317
|
+
processNewlineDelimited();
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const contentLength = parseInt(match[1], 10);
|
|
321
|
+
const bodyStart = headerEnd + 4;
|
|
322
|
+
const available = Buffer.byteLength(buffer.slice(bodyStart), 'utf8');
|
|
323
|
+
if (available < contentLength) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const bodyBuf = Buffer.from(buffer.slice(bodyStart));
|
|
327
|
+
const body = bodyBuf.slice(0, contentLength).toString('utf8');
|
|
328
|
+
const consumed = bodyStart + body.length;
|
|
329
|
+
buffer = buffer.slice(consumed);
|
|
330
|
+
processLine(body);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function processNewlineDelimited() {
|
|
334
|
+
let newlineIdx;
|
|
335
|
+
while ((newlineIdx = buffer.indexOf('\n')) !== -1) {
|
|
336
|
+
const line = buffer.slice(0, newlineIdx).trim();
|
|
337
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
338
|
+
if (line)
|
|
339
|
+
processLine(line);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function processLine(raw) {
|
|
343
|
+
let msg;
|
|
344
|
+
try {
|
|
345
|
+
msg = JSON.parse(raw);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
sendMessage(makeError(null, -32700, 'Parse error'));
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const response = handleMessage(msg);
|
|
352
|
+
if (response !== null) {
|
|
353
|
+
sendMessage(response);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
// ─── Entry point ─────────────────────────────────────────────────────────────
|
|
358
|
+
startTransport();
|
|
359
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../mcp-server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent-protocol.ts — Typed contract system for the dual-brain agent hierarchy.
|
|
3
|
+
*
|
|
4
|
+
* Defines how HEAD, Managers, Supervisors, and Workers communicate:
|
|
5
|
+
* what they receive, what they produce, how they escalate, and how they report.
|
|
6
|
+
*
|
|
7
|
+
* Hierarchy:
|
|
8
|
+
* HEAD (user's session, lightest context)
|
|
9
|
+
* → Manager (project-level, persistent across sessions)
|
|
10
|
+
* → Supervisor (wave-level, deploys and monitors workers)
|
|
11
|
+
* → Worker (task-level, executes and reports)
|
|
12
|
+
*/
|
|
13
|
+
import type { RoomSummary, RoomInsight, RoomDecision, RoomPlan, WaveTask, WorkerAssignment, WorkerResult, UserInput } from './room.ts';
|
|
14
|
+
export type { RoomSummary, RoomInsight, RoomDecision, RoomPlan, WaveTask, WorkerAssignment, WorkerResult, UserInput, };
|
|
15
|
+
export type AgentLevel = 'head' | 'manager' | 'supervisor' | 'worker';
|
|
16
|
+
export interface HeadInput {
|
|
17
|
+
userMessage: string;
|
|
18
|
+
roomSummaries: RoomSummary[];
|
|
19
|
+
providerHealth: ProviderHealth[];
|
|
20
|
+
recentInsights: RoomInsight[];
|
|
21
|
+
}
|
|
22
|
+
export interface ManagerInput {
|
|
23
|
+
roomId: string;
|
|
24
|
+
taskDescription: string;
|
|
25
|
+
userInputs: UserInput[];
|
|
26
|
+
decisions: RoomDecision[];
|
|
27
|
+
waveResults: WaveResult[];
|
|
28
|
+
modelProfiles: ModelProfileSummary[];
|
|
29
|
+
providerHealth: ProviderHealth[];
|
|
30
|
+
}
|
|
31
|
+
export interface SupervisorInput {
|
|
32
|
+
roomId: string;
|
|
33
|
+
waveId: string;
|
|
34
|
+
tasks: WaveTask[];
|
|
35
|
+
modelProfiles: ModelProfileSummary[];
|
|
36
|
+
budget: BudgetConstraint;
|
|
37
|
+
providerHealth: ProviderHealth[];
|
|
38
|
+
}
|
|
39
|
+
export interface WorkerInput {
|
|
40
|
+
roomId: string;
|
|
41
|
+
taskId: string;
|
|
42
|
+
assignment: WorkerAssignment;
|
|
43
|
+
contextFiles: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
export interface HeadOutput {
|
|
46
|
+
userResponse: string;
|
|
47
|
+
roomActions: RoomAction[];
|
|
48
|
+
escalationNeeded: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface ManagerOutput {
|
|
51
|
+
plan?: RoomPlan;
|
|
52
|
+
insights: RoomInsight[];
|
|
53
|
+
supervisorDeployments: SupervisorDeployment[];
|
|
54
|
+
status: 'planning' | 'executing' | 'reviewing' | 'completed' | 'blocked';
|
|
55
|
+
blockedReason?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface SupervisorOutput {
|
|
58
|
+
workerDeployments: WorkerDeployment[];
|
|
59
|
+
qualityChecks: QualityCheck[];
|
|
60
|
+
waveStatus: 'running' | 'completed' | 'failed' | 'needs-replan';
|
|
61
|
+
replanReason?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface WorkerOutput {
|
|
64
|
+
result: WorkerResult;
|
|
65
|
+
selfAssessment: number;
|
|
66
|
+
issues: string[];
|
|
67
|
+
}
|
|
68
|
+
export interface SupervisorDeployment {
|
|
69
|
+
waveId: string;
|
|
70
|
+
tasks: WaveTask[];
|
|
71
|
+
model: string;
|
|
72
|
+
budget: BudgetConstraint;
|
|
73
|
+
}
|
|
74
|
+
export interface WorkerDeployment {
|
|
75
|
+
taskId: string;
|
|
76
|
+
assignment: WorkerAssignment;
|
|
77
|
+
model: string;
|
|
78
|
+
timeout: number;
|
|
79
|
+
}
|
|
80
|
+
export interface BudgetConstraint {
|
|
81
|
+
maxWorkers: number;
|
|
82
|
+
maxTotalTokens: number;
|
|
83
|
+
maxRetries: number;
|
|
84
|
+
costTier: 'frugal' | 'balanced' | 'quality' | 'maximum';
|
|
85
|
+
}
|
|
86
|
+
export interface QualityCheck {
|
|
87
|
+
taskId: string;
|
|
88
|
+
passed: boolean;
|
|
89
|
+
findings: string[];
|
|
90
|
+
recommendation: 'accept' | 'retry' | 'escalate' | 'reject';
|
|
91
|
+
}
|
|
92
|
+
export interface RoomAction {
|
|
93
|
+
type: 'create' | 'close' | 'decide' | 'escalate';
|
|
94
|
+
roomId?: string;
|
|
95
|
+
taskDescription?: string;
|
|
96
|
+
decision?: RoomDecision;
|
|
97
|
+
}
|
|
98
|
+
export interface ModelProfileSummary {
|
|
99
|
+
id: string;
|
|
100
|
+
name: string;
|
|
101
|
+
provider: string;
|
|
102
|
+
tier: number;
|
|
103
|
+
available: boolean;
|
|
104
|
+
strengths: string[];
|
|
105
|
+
}
|
|
106
|
+
export interface ProviderHealth {
|
|
107
|
+
provider: string;
|
|
108
|
+
status: 'healthy' | 'degraded' | 'down' | 'rate-limited';
|
|
109
|
+
remainingCapacity?: number;
|
|
110
|
+
cooldownUntil?: string;
|
|
111
|
+
}
|
|
112
|
+
export interface WaveResult {
|
|
113
|
+
waveId: string;
|
|
114
|
+
status: 'completed' | 'partial' | 'failed';
|
|
115
|
+
workerResults: WorkerResult[];
|
|
116
|
+
qualityScore: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Determine how deep the hierarchy should go for this task.
|
|
120
|
+
* Simple tasks return 'worker' (HEAD dispatches directly).
|
|
121
|
+
* Medium returns 'supervisor'. Complex returns 'manager'.
|
|
122
|
+
*/
|
|
123
|
+
export declare function classifyDepth(taskDescription: string, complexity?: number): AgentLevel;
|
|
124
|
+
/**
|
|
125
|
+
* Assemble HEAD's input from room files and provider state.
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildHeadInput(cwd?: string): HeadInput;
|
|
128
|
+
/**
|
|
129
|
+
* Assemble Manager's input from room files.
|
|
130
|
+
*/
|
|
131
|
+
export declare function buildManagerInput(roomId: string, cwd?: string): ManagerInput;
|
|
132
|
+
/**
|
|
133
|
+
* Assemble Supervisor's input for a specific wave.
|
|
134
|
+
*/
|
|
135
|
+
export declare function buildSupervisorInput(roomId: string, waveId: string, cwd?: string): SupervisorInput;
|
|
136
|
+
/**
|
|
137
|
+
* Assemble Worker's input with file contents.
|
|
138
|
+
*/
|
|
139
|
+
export declare function buildWorkerInput(roomId: string, taskId: string, cwd?: string): WorkerInput;
|
|
140
|
+
/**
|
|
141
|
+
* Type-check agent output before accepting.
|
|
142
|
+
* Returns true if the output matches the expected shape for the given level.
|
|
143
|
+
*/
|
|
144
|
+
export declare function validateOutput(level: AgentLevel, output: unknown): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Estimate token cost for a set of worker deployments.
|
|
147
|
+
* Returns estimated total tokens.
|
|
148
|
+
*/
|
|
149
|
+
export declare function estimateCost(deployments: WorkerDeployment[], profiles: ModelProfileSummary[]): number;
|
|
150
|
+
/**
|
|
151
|
+
* Pick the best available model for a task given budget constraints.
|
|
152
|
+
* Matches task tier to model tier, filtered by availability and budget.
|
|
153
|
+
*/
|
|
154
|
+
export declare function selectModel(task: WaveTask, profiles: ModelProfileSummary[], budget: BudgetConstraint): string;
|
|
155
|
+
/**
|
|
156
|
+
* Determine if results are bad enough to escalate to a higher level.
|
|
157
|
+
* Checks failure rate and quality against threshold.
|
|
158
|
+
*/
|
|
159
|
+
export declare function shouldEscalate(results: WorkerResult[], qualityThreshold?: number): boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Create budget constraints from the user's dial setting and task count.
|
|
162
|
+
*/
|
|
163
|
+
export declare function buildBudget(costTier: string, taskCount: number): BudgetConstraint;
|