@bahulam/code 0.1.17 → 0.1.19
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/package.json +1 -1
- package/src/config/model-defaults-default.json +9 -0
- package/src/config/model-defaults.mjs +42 -0
- package/src/config/settings.mjs +3 -2
- package/src/onboarding/preflight.mjs +1 -1
- package/src/terminal/repl.mjs +19 -8
- package/src/tools/agent.mjs +2 -1
- package/src/ui/commands.mjs +8 -5
- package/src/ui/input-dock.mjs +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shipped npm-side model defaults.
|
|
3
|
+
*
|
|
4
|
+
* Source of truth is backend `app/services/model_defaults.py`; release sync
|
|
5
|
+
* writes `model-defaults-default.json` next to the shipped catalog.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
export const FALLBACK_MODEL_DEFAULTS = Object.freeze({
|
|
13
|
+
reasoning: 'deepseek/deepseek-v4-flash',
|
|
14
|
+
fast: 'deepseek/deepseek-v4-flash',
|
|
15
|
+
planning: 'deepseek/deepseek-v4-pro',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const _dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const DEFAULTS_PATH = path.join(_dirname, 'model-defaults-default.json');
|
|
20
|
+
|
|
21
|
+
function clean(value) {
|
|
22
|
+
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function readShippedModelDefaults() {
|
|
26
|
+
try {
|
|
27
|
+
const data = JSON.parse(fs.readFileSync(DEFAULTS_PATH, 'utf-8'));
|
|
28
|
+
const defaults = data?.defaults && typeof data.defaults === 'object' ? data.defaults : {};
|
|
29
|
+
return {
|
|
30
|
+
reasoning: clean(defaults.reasoning) || FALLBACK_MODEL_DEFAULTS.reasoning,
|
|
31
|
+
fast: clean(defaults.fast) || FALLBACK_MODEL_DEFAULTS.fast,
|
|
32
|
+
planning: clean(defaults.planning) || FALLBACK_MODEL_DEFAULTS.planning,
|
|
33
|
+
};
|
|
34
|
+
} catch {
|
|
35
|
+
return { ...FALLBACK_MODEL_DEFAULTS };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const SHIPPED_MODEL_DEFAULTS = readShippedModelDefaults();
|
|
40
|
+
export const DEFAULT_REASONING_MODEL = SHIPPED_MODEL_DEFAULTS.reasoning;
|
|
41
|
+
export const DEFAULT_FAST_MODEL = SHIPPED_MODEL_DEFAULTS.fast;
|
|
42
|
+
export const DEFAULT_PLANNING_MODEL = SHIPPED_MODEL_DEFAULTS.planning;
|
package/src/config/settings.mjs
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import os from 'os';
|
|
10
|
+
import { DEFAULT_FAST_MODEL, DEFAULT_REASONING_MODEL } from './model-defaults.mjs';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Full settings schema with defaults.
|
|
@@ -30,9 +31,9 @@ export const SETTINGS_SCHEMA = {
|
|
|
30
31
|
Stop: [],
|
|
31
32
|
SessionStart: [],
|
|
32
33
|
},
|
|
33
|
-
model:
|
|
34
|
+
model: DEFAULT_REASONING_MODEL,
|
|
34
35
|
subagentModel: null,
|
|
35
|
-
fastModel:
|
|
36
|
+
fastModel: DEFAULT_FAST_MODEL,
|
|
36
37
|
fastMode: false,
|
|
37
38
|
alwaysThinkingEnabled: false,
|
|
38
39
|
autoCompactEnabled: true,
|
|
@@ -343,7 +343,7 @@ export async function runPreflight({ auth, cwd, version, silent = false } = {})
|
|
|
343
343
|
const t = term();
|
|
344
344
|
const write = (s) => { if (!silent) process.stderr.write(s); };
|
|
345
345
|
|
|
346
|
-
const header = `${icons.search} ${paint.bold(paint.brand.primary('Bahulam Code v' + (version || '?')))} ${paint.text.dim('·
|
|
346
|
+
const header = `${icons.search} ${paint.bold(paint.brand.primary('Bahulam Code v' + (version || '?')))} ${paint.text.dim('· starting session')}`;
|
|
347
347
|
write('\n' + header + '\n\n');
|
|
348
348
|
|
|
349
349
|
const checks = [];
|
package/src/terminal/repl.mjs
CHANGED
|
@@ -1335,8 +1335,8 @@ async function _checkForUpgradeAndAnnounce() {
|
|
|
1335
1335
|
const [x, y, z] = asTuple(current);
|
|
1336
1336
|
const newer = (a > x) || (a === x && b > y) || (a === x && b === y && c1 > z);
|
|
1337
1337
|
if (!newer) return;
|
|
1338
|
-
process.stderr.write(` ${c.brand('◆')} ${c.dim('
|
|
1339
|
-
process.stderr.write(` ${c.dim('
|
|
1338
|
+
process.stderr.write(` ${c.brand('◆')} ${c.dim('Update available:')} ${c.bold(c.green(`${pkgName}@${latest}`))} ${c.dim(`(installed ${current})`)}\n`);
|
|
1339
|
+
process.stderr.write(` ${c.dim(' Install:')} ${c.dim('npm install -g ' + pkgName + '@latest')}\n\n`);
|
|
1340
1340
|
}
|
|
1341
1341
|
|
|
1342
1342
|
// ── Prompt Chrome ──
|
|
@@ -1385,6 +1385,8 @@ function buildContextStrip() {
|
|
|
1385
1385
|
// volume + elapsed. Historical rate calc was double-counting the cache tokens
|
|
1386
1386
|
// vs OpenRouter's convention (see computeCacheTotals) which was misleading.
|
|
1387
1387
|
const parts = [];
|
|
1388
|
+
const model = compactDockModel(activeDockModel());
|
|
1389
|
+
if (model) parts.push(c.dim(`model ${model}`));
|
|
1388
1390
|
// ctx: last turn's cumulative input tokens — approximates the CURRENT
|
|
1389
1391
|
// prompt size. Only shown once we've completed at least one turn (so
|
|
1390
1392
|
// the initial banner doesn't read '0 ctx'). This is the number the
|
|
@@ -1397,13 +1399,27 @@ function buildContextStrip() {
|
|
|
1397
1399
|
return parts.join(c.dim(' · '));
|
|
1398
1400
|
}
|
|
1399
1401
|
|
|
1400
|
-
// ── Dock meta line (
|
|
1402
|
+
// ── Dock meta line (cwd ⎇ branch · turn N) ─────────────────────────────
|
|
1401
1403
|
//
|
|
1402
1404
|
// The dock's meta row shows durable session context. Git branch is cached
|
|
1403
1405
|
// so we don't shell out on every keystroke; refreshed at most every 5s.
|
|
1404
1406
|
|
|
1405
1407
|
const _dockGitCache = { branch: null, at: 0, cwd: null };
|
|
1406
1408
|
|
|
1409
|
+
function activeDockModel() {
|
|
1410
|
+
return session.modelOverrides?.reasoning
|
|
1411
|
+
|| session.model
|
|
1412
|
+
|| session.modelLimits?.coder?.model
|
|
1413
|
+
|| session.user?.default_reasoning_model
|
|
1414
|
+
|| null;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
function compactDockModel(model) {
|
|
1418
|
+
const value = String(model || '').trim();
|
|
1419
|
+
if (!value) return '';
|
|
1420
|
+
return value.replace(/^(anthropic|openai|google|deepseek|xai|meta)\//, '');
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1407
1423
|
function _probeGitBranch(cwd) {
|
|
1408
1424
|
const now = Date.now();
|
|
1409
1425
|
if (_dockGitCache.cwd === cwd && (now - _dockGitCache.at) < 5000) {
|
|
@@ -1434,11 +1450,6 @@ function buildDockMeta() {
|
|
|
1434
1450
|
parts.push(`turn ${session.turns}`);
|
|
1435
1451
|
}
|
|
1436
1452
|
|
|
1437
|
-
const totalTokens = session.inputTokens + session.outputTokens;
|
|
1438
|
-
if (totalTokens > 0) {
|
|
1439
|
-
parts.push(`${formatTokens(totalTokens)} tok`);
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
1453
|
return parts.join(' · ');
|
|
1443
1454
|
}
|
|
1444
1455
|
|
package/src/tools/agent.mjs
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { createAgentLoop } from '../core/agent-loop.mjs';
|
|
12
12
|
import { createToolRegistry } from './registry.mjs';
|
|
13
13
|
import { createPermissionChecker } from '../permissions/checker.mjs';
|
|
14
|
+
import { DEFAULT_REASONING_MODEL } from '../config/model-defaults.mjs';
|
|
14
15
|
|
|
15
16
|
export const AgentTool = {
|
|
16
17
|
name: 'Agent',
|
|
@@ -59,7 +60,7 @@ export const AgentTool = {
|
|
|
59
60
|
_nextBgId: 0,
|
|
60
61
|
|
|
61
62
|
async call(input, options = {}) {
|
|
62
|
-
const model = input.model || process.env.SUBAGENT_MODEL ||
|
|
63
|
+
const model = input.model || process.env.SUBAGENT_MODEL || DEFAULT_REASONING_MODEL;
|
|
63
64
|
const tools = createToolRegistry({
|
|
64
65
|
pluginRegistry: options.pluginRegistry || null,
|
|
65
66
|
stateEmit: options.stateEmit || null,
|
package/src/ui/commands.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { SessionManager } from '../core/session.mjs';
|
|
|
9
9
|
import { CheckpointManager } from '../core/checkpoints.mjs';
|
|
10
10
|
import { readEnv, listEnvVars } from '../config/env.mjs';
|
|
11
11
|
import * as telemetry from '../telemetry/index.mjs';
|
|
12
|
+
import { DEFAULT_FAST_MODEL, DEFAULT_REASONING_MODEL } from '../config/model-defaults.mjs';
|
|
12
13
|
|
|
13
14
|
const checkpoints = new CheckpointManager();
|
|
14
15
|
let sessionManager = null;
|
|
@@ -134,12 +135,14 @@ export const COMMANDS = {
|
|
|
134
135
|
'/fast': {
|
|
135
136
|
description: 'Toggle fast mode (uses faster, cheaper model)',
|
|
136
137
|
handler(args, state) {
|
|
137
|
-
if (state.
|
|
138
|
-
state.
|
|
139
|
-
|
|
138
|
+
if (state.fastMode) {
|
|
139
|
+
state.fastMode = false;
|
|
140
|
+
state.model = DEFAULT_REASONING_MODEL;
|
|
141
|
+
return `Fast mode OFF — using ${DEFAULT_REASONING_MODEL}`;
|
|
140
142
|
}
|
|
141
|
-
state.
|
|
142
|
-
|
|
143
|
+
state.fastMode = true;
|
|
144
|
+
state.model = DEFAULT_FAST_MODEL;
|
|
145
|
+
return `Fast mode ON — using ${DEFAULT_FAST_MODEL}`;
|
|
143
146
|
},
|
|
144
147
|
},
|
|
145
148
|
|
package/src/ui/input-dock.mjs
CHANGED
|
@@ -704,11 +704,12 @@ export function clearInputPrompt() {
|
|
|
704
704
|
export function renderDockInput(prefix, value, { context = '', tips = '', meta = '', cursor = null, fixedRows = null } = {}) {
|
|
705
705
|
if (!mounted) return false;
|
|
706
706
|
contentTrackingActive = false;
|
|
707
|
+
lastFrame = { ...lastFrame, context, tips, meta, prefix, value, cursor, overlayLines: null };
|
|
707
708
|
const requestedRows = fixedRows == null
|
|
708
709
|
? computeInputRowsForBuffer(prefix, value)
|
|
709
710
|
: Math.max(MIN_INPUT_ROWS, Math.min(inputRowsMax, Math.floor(Number(fixedRows) || MIN_INPUT_ROWS)));
|
|
710
711
|
setInputRowsTo(requestedRows);
|
|
711
|
-
renderFrame(
|
|
712
|
+
renderFrame(lastFrame);
|
|
712
713
|
const layout = layoutInput(prefix, value);
|
|
713
714
|
drawInputLines(layout.lines);
|
|
714
715
|
focusDockInput(prefix, value, cursor);
|