dual-brain 3.0.0 → 3.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/hooks/cost-report.mjs
CHANGED
|
@@ -200,6 +200,8 @@ function allOpusCost(records, rateMap, datePrefix = null) {
|
|
|
200
200
|
// Formatting helpers
|
|
201
201
|
// ---------------------------------------------------------------------------
|
|
202
202
|
|
|
203
|
+
const W = 50;
|
|
204
|
+
|
|
203
205
|
const TIER_ORDER = ["search", "execute", "think"];
|
|
204
206
|
|
|
205
207
|
const TIER_LABELS = {
|
|
@@ -224,8 +226,6 @@ function renderTable(title, aggregated, allOpus, records = []) {
|
|
|
224
226
|
const savings = allOpus - totalCost;
|
|
225
227
|
const savingsPct = allOpus > 0 ? Math.round((savings / allOpus) * 100) : 0;
|
|
226
228
|
|
|
227
|
-
const W = 50; // total inner width (between ║ chars)
|
|
228
|
-
|
|
229
229
|
const line = (s) => `║ ${pad(s, W - 2)} ║`;
|
|
230
230
|
const border = (l, r, m) => l + "═".repeat(W) + r;
|
|
231
231
|
const sep = () => "╠" + "═".repeat(W) + "╣";
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { execSync, spawnSync } from 'child_process';
|
|
16
16
|
import { readFileSync } from 'fs';
|
|
17
|
-
import { dirname, resolve } from 'path';
|
|
17
|
+
import { dirname, join, resolve } from 'path';
|
|
18
18
|
import { fileURLToPath } from 'url';
|
|
19
19
|
|
|
20
20
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
package/hooks/setup-wizard.mjs
CHANGED
|
@@ -119,7 +119,7 @@ async function main() {
|
|
|
119
119
|
|
|
120
120
|
console.log(` ║ Quality gate: ${gateEnabled ? 'enabled' : 'disabled'}`.padEnd(53) + '║');
|
|
121
121
|
console.log(' ╠══════════════════════════════════════════════════╣');
|
|
122
|
-
console.log(' ║
|
|
122
|
+
console.log(' ║ Hooks are active — no restart needed ║');
|
|
123
123
|
console.log(' ╚══════════════════════════════════════════════════╝');
|
|
124
124
|
console.log('');
|
|
125
125
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{"timestamp":"2026-05-14T00:33:17.462Z","type":"tier_recommendation","detected_tier":"search","recommended_model":"haiku","actual_model":"opus","prompt_hash":"9990d6fd8943","followed":false}
|
|
2
|
+
{"timestamp":"2026-05-14T00:33:17.501Z","type":"tier_recommendation","detected_tier":"execute","recommended_model":"sonnet","actual_model":"sonnet","prompt_hash":"c636a5e74cdc","followed":true}
|
|
3
|
+
{"timestamp":"2026-05-14T00:33:17.536Z","type":"tier_recommendation","detected_tier":"think","recommended_model":"opus","actual_model":"haiku","prompt_hash":"bd666c33402c","followed":false}
|
|
4
|
+
{"timestamp":"2026-05-14T00:33:17.606Z","type":"tier_recommendation","detected_tier":"execute","recommended_model":"sonnet","actual_model":"unknown-model-xyz","prompt_hash":"913203af69f8","followed":false}
|
|
5
|
+
{"timestamp":"2026-05-14T00:33:17.746Z","type":"tier_recommendation","detected_tier":"think","recommended_model":"opus","actual_model":"gpt-4.1-mini","prompt_hash":"7196103e6569","followed":false}
|
package/install.mjs
CHANGED
|
@@ -24,6 +24,11 @@ const force = flag('--force');
|
|
|
24
24
|
const dryRun = flag('--dry-run');
|
|
25
25
|
const jsonOut = flag('--json');
|
|
26
26
|
|
|
27
|
+
if (flag('--version') || flag('-v')) {
|
|
28
|
+
console.log(`dual-brain v${VERSION}`);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
if (flag('--help') || flag('-h')) {
|
|
28
33
|
console.log(`
|
|
29
34
|
dual-brain v${VERSION} — Dual-provider orchestrator for Claude Code
|
|
@@ -240,7 +245,20 @@ function generateSettings(workspace) {
|
|
|
240
245
|
],
|
|
241
246
|
};
|
|
242
247
|
|
|
243
|
-
|
|
248
|
+
const DUAL_BRAIN_CMDS = [
|
|
249
|
+
'node .claude/hooks/enforce-tier.mjs',
|
|
250
|
+
'node .claude/hooks/cost-logger.mjs',
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
const merged = { ...(existing.hooks || {}) };
|
|
254
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
255
|
+
const existingEntries = (merged[event] || []).filter(e =>
|
|
256
|
+
!e.hooks?.some(h => DUAL_BRAIN_CMDS.includes(h.command))
|
|
257
|
+
);
|
|
258
|
+
merged[event] = [...existingEntries, ...entries];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return { ...existing, hooks: merged };
|
|
244
262
|
}
|
|
245
263
|
|
|
246
264
|
function generateClaudeMd(mode) {
|
|
@@ -322,7 +340,7 @@ function install(workspace, env, mode) {
|
|
|
322
340
|
if (needed.length > 0) {
|
|
323
341
|
writeFileSync(
|
|
324
342
|
join(workspace, '.gitignore'),
|
|
325
|
-
gi + '\n# Dual-Brain Orchestrator\n' + needed.join('\n') + '\n'
|
|
343
|
+
(gi && !gi.endsWith('\n') ? gi + '\n' : gi) + '\n# Dual-Brain Orchestrator\n' + needed.join('\n') + '\n'
|
|
326
344
|
);
|
|
327
345
|
actions.push('✓ .gitignore updated');
|
|
328
346
|
}
|
|
@@ -397,6 +415,29 @@ function printReport(env, mode, actions) {
|
|
|
397
415
|
console.log('');
|
|
398
416
|
for (const l of lines) console.log(` ${l}`);
|
|
399
417
|
console.log('');
|
|
418
|
+
|
|
419
|
+
if (actions) {
|
|
420
|
+
console.log(' What just happened:');
|
|
421
|
+
console.log(' Every Claude Code session in this project now auto-routes');
|
|
422
|
+
console.log(' agent work by complexity — cheap models for search, mid-tier');
|
|
423
|
+
console.log(' for execution, best models for thinking. Cost is tracked.');
|
|
424
|
+
if (mode.mode === 'dual') {
|
|
425
|
+
console.log(' Both Claude and GPT are available as work providers.');
|
|
426
|
+
}
|
|
427
|
+
console.log('');
|
|
428
|
+
console.log(' Try these in your next Claude Code session:');
|
|
429
|
+
console.log(' node .claude/hooks/health-check.mjs # verify setup');
|
|
430
|
+
console.log(' node .claude/hooks/cost-report.mjs # see activity');
|
|
431
|
+
console.log(' node .claude/hooks/budget-balancer.mjs # provider balance');
|
|
432
|
+
if (mode.openaiEnabled) {
|
|
433
|
+
console.log(' node .claude/hooks/dual-brain-review.mjs # GPT code review');
|
|
434
|
+
}
|
|
435
|
+
console.log('');
|
|
436
|
+
console.log(' Customize:');
|
|
437
|
+
console.log(' .claude/review-rules.md # your project\'s review rules');
|
|
438
|
+
console.log(' .claude/orchestrator.json # routing, budgets, tiers');
|
|
439
|
+
console.log('');
|
|
440
|
+
}
|
|
400
441
|
}
|
|
401
442
|
|
|
402
443
|
// ─── Main ───────────────────────────────────────────────────────────────────
|
package/package.json
CHANGED