dual-brain 3.0.1 → 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
|
}
|
package/package.json
CHANGED