@blockrun/franklin 3.9.0 → 3.9.2
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/dist/agent/loop.js +12 -10
- package/dist/agent/optimize.js +6 -0
- package/dist/pricing.js +2 -0
- package/dist/proxy/server.js +3 -2
- package/dist/ui/app.js +3 -3
- package/dist/ui/model-picker.js +5 -3
- package/package.json +1 -1
package/dist/agent/loop.js
CHANGED
|
@@ -523,15 +523,17 @@ export async function interactiveSession(config, getUserInput, onEvent, onAbortR
|
|
|
523
523
|
// is treated as a typo and falls back to the safe default rather than
|
|
524
524
|
// silently removing the wallet guard.
|
|
525
525
|
//
|
|
526
|
-
// Default
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
|
|
526
|
+
// Default lineage: $0.25 (≤ v3.8.41) → $1.00 (v3.8.42) → $2.00 (v3.9.1).
|
|
527
|
+
// v3.8.42's $1.00 was tuned for "multi-stage dashboard scaffold" workloads
|
|
528
|
+
// landing in the $0.20–$0.80 range on a single prompt. Real coding turns
|
|
529
|
+
// since — full BTC-style dashboards, multi-file refactors that pull in
|
|
530
|
+
// sonnet/opus on a COMPLEX-tier route — routinely cross $1.00 in their
|
|
531
|
+
// first planning pass alone, leaving no headroom for the execution call
|
|
532
|
+
// and tripping the cap mid-task. $2.00 keeps the runaway-protection
|
|
533
|
+
// promise (catches the buggy-loop drain v3.8.41's retry-policy targets)
|
|
534
|
+
// while letting a legitimate complex coding task finish in one turn.
|
|
535
|
+
// Users who liked the old ceiling can pin it via the config.
|
|
536
|
+
const TURN_SPEND_DEFAULT_USD = 2.0;
|
|
535
537
|
const turnSpendCap = (() => {
|
|
536
538
|
const raw = loadConfig()['max-turn-spend-usd'];
|
|
537
539
|
if (raw == null)
|
|
@@ -1058,7 +1060,7 @@ export async function interactiveSession(config, getUserInput, onEvent, onAbortR
|
|
|
1058
1060
|
onEvent({
|
|
1059
1061
|
kind: 'text_delta',
|
|
1060
1062
|
text: `\n\n⚠️ Turn spend limit reached ($${turnSpend.toFixed(3)} > $${MAX_TURN_SPEND_USD}). Stopping to protect your wallet.\n` +
|
|
1061
|
-
`Raise the cap with \`franklin config set max-turn-spend-usd
|
|
1063
|
+
`Raise the cap with \`franklin config set max-turn-spend-usd 4.0\` (or \`0\` to disable), then \`/retry\`.\n`,
|
|
1062
1064
|
});
|
|
1063
1065
|
onEvent({ kind: 'turn_done', reason: 'budget' });
|
|
1064
1066
|
break;
|
package/dist/agent/optimize.js
CHANGED
|
@@ -35,6 +35,12 @@ const MODEL_MAX_OUTPUT = {
|
|
|
35
35
|
'google/gemini-2.5-pro': 65_536,
|
|
36
36
|
'google/gemini-2.5-flash': 65_536,
|
|
37
37
|
'deepseek/deepseek-chat': 8_192,
|
|
38
|
+
// Kimi K2.6 supports 65K output per the BlockRun gateway model entry
|
|
39
|
+
// (moonshot/kimi-k2.6 max_output: 65536). Without this entry the default
|
|
40
|
+
// 16K cap left users with 4× headroom on the table for long-form coding
|
|
41
|
+
// outputs and dashboard scaffolds the model can otherwise emit in a
|
|
42
|
+
// single response.
|
|
43
|
+
'moonshot/kimi-k2.6': 65_536,
|
|
38
44
|
};
|
|
39
45
|
/** Get max output tokens for a model */
|
|
40
46
|
export function getMaxOutputTokens(model) {
|
package/dist/pricing.js
CHANGED
|
@@ -73,6 +73,8 @@ export const MODEL_PRICING = {
|
|
|
73
73
|
'minimax/minimax-m2.5': { input: 0.3, output: 1.2 },
|
|
74
74
|
// Moonshot
|
|
75
75
|
'moonshot/kimi-k2.6': { input: 0.95, output: 4.0 },
|
|
76
|
+
// Retired (kept for legacy session-cost records; the gateway no longer
|
|
77
|
+
// serves these and the picker shortcuts now resolve to K2.6).
|
|
76
78
|
'moonshot/kimi-k2.5': { input: 0.6, output: 3.0 },
|
|
77
79
|
'nvidia/kimi-k2.5': { input: 0.55, output: 2.5 },
|
|
78
80
|
// PROMOTION (active ~2026-04): flat $0.001/call for all GLM models
|
package/dist/proxy/server.js
CHANGED
|
@@ -175,8 +175,9 @@ const MODEL_SHORTCUTS = {
|
|
|
175
175
|
'glm5': 'zai/glm-5.1',
|
|
176
176
|
kimi: 'moonshot/kimi-k2.6',
|
|
177
177
|
'k2.6': 'moonshot/kimi-k2.6',
|
|
178
|
-
|
|
179
|
-
'k2.5': 'moonshot/kimi-k2.
|
|
178
|
+
// K2.5 retired by the gateway — aliases resolve to K2.6 for muscle memory.
|
|
179
|
+
'kimi-k2.5': 'moonshot/kimi-k2.6',
|
|
180
|
+
'k2.5': 'moonshot/kimi-k2.6',
|
|
180
181
|
};
|
|
181
182
|
// Model pricing now uses shared source from src/pricing.ts
|
|
182
183
|
function detectModelSwitch(parsed) {
|
package/dist/ui/app.js
CHANGED
|
@@ -37,7 +37,7 @@ function useTerminalSize() {
|
|
|
37
37
|
}, [stdout]);
|
|
38
38
|
return size;
|
|
39
39
|
}
|
|
40
|
-
function InputBox({ input, setInput, onSubmit, model, balance, sessionCost, queued, queuedCount, focused, busy, contextPct, vimMode, onVimModeChange }) {
|
|
40
|
+
function InputBox({ input, setInput, onSubmit, model, balance, chain, walletTail, sessionCost, queued, queuedCount, focused, busy, contextPct, vimMode, onVimModeChange }) {
|
|
41
41
|
const { cols } = useTerminalSize();
|
|
42
42
|
// Avoid drawing right up to the terminal edge. Several terminals auto-wrap
|
|
43
43
|
// a full-width border glyph onto the next row, which leaves "ghost" top
|
|
@@ -48,7 +48,7 @@ function InputBox({ input, setInput, onSubmit, model, balance, sessionCost, queu
|
|
|
48
48
|
? `⏎ ${queuedCount ?? 1} queued: ${queued.slice(0, 40)}`
|
|
49
49
|
: 'Working...')
|
|
50
50
|
: 'Type a message...';
|
|
51
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { borderStyle: "round", borderDimColor: true, paddingX: 1, width: boxWidth, children: [busy && !input ? _jsxs(Text, { color: "yellow", children: [_jsx(Spinner, { type: "dots" }), " "] }) : null, _jsx(Box, { flexGrow: 1, children: vimMode ? (_jsx(VimInput, { value: input, onChange: setInput, onSubmit: onSubmit, placeholder: placeholder, focus: focused !== false, showMode: true, onModeChange: onVimModeChange })) : (_jsx(TextInput, { value: input, onChange: setInput, onSubmit: onSubmit, placeholder: placeholder, focus: focused !== false })) })] }), _jsx(Box, { marginLeft: 1, children: _jsxs(Text, { dimColor: true, children: [busy ? _jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }) : null, busy ? ' ' : '', shortModelName(model), " \u00B7 ", balance, sessionCost > 0.00001 ? _jsxs(Text, { color: "yellow", children: [" -$", sessionCost.toFixed(4)] }) : '', contextPct !== undefined && contextPct > 0 ? (() => {
|
|
51
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { borderStyle: "round", borderDimColor: true, paddingX: 1, width: boxWidth, children: [busy && !input ? _jsxs(Text, { color: "yellow", children: [_jsx(Spinner, { type: "dots" }), " "] }) : null, _jsx(Box, { flexGrow: 1, children: vimMode ? (_jsx(VimInput, { value: input, onChange: setInput, onSubmit: onSubmit, placeholder: placeholder, focus: focused !== false, showMode: true, onModeChange: onVimModeChange })) : (_jsx(TextInput, { value: input, onChange: setInput, onSubmit: onSubmit, placeholder: placeholder, focus: focused !== false })) })] }), _jsx(Box, { marginLeft: 1, children: _jsxs(Text, { dimColor: true, children: [busy ? _jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }) : null, busy ? ' ' : '', shortModelName(model), " \u00B7 ", balance, chain ? _jsxs(Text, { children: [" \u00B7 ", _jsx(Text, { color: "magenta", children: chain }), walletTail ? _jsxs(Text, { dimColor: true, children: [":", walletTail] }) : ''] }) : '', sessionCost > 0.00001 ? _jsxs(Text, { color: "yellow", children: [" -$", sessionCost.toFixed(4)] }) : '', contextPct !== undefined && contextPct > 0 ? (() => {
|
|
52
52
|
// Visual context bar: ▓▓▓▓▓▓░░░░ 75%
|
|
53
53
|
const filled = Math.round(contextPct / 10);
|
|
54
54
|
const empty = 10 - filled;
|
|
@@ -774,7 +774,7 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
774
774
|
const isHighlight = m.highlight === true;
|
|
775
775
|
return (_jsxs(Box, { marginLeft: 2, children: [_jsxs(Text, { inverse: isSelected, color: isSelected ? 'cyan' : isHighlight ? 'yellow' : undefined, bold: isSelected || isHighlight, children: [' ', m.label.padEnd(26), ' '] }), _jsxs(Text, { dimColor: true, children: [" ", m.shortcut.padEnd(14)] }), _jsx(Text, { color: m.price === 'FREE' ? 'green' : isHighlight ? 'yellow' : undefined, dimColor: !isHighlight && m.price !== 'FREE', children: m.price }), isCurrent && _jsx(Text, { color: "green", children: " \u2190" })] }, m.id));
|
|
776
776
|
})] }, cat.category))), _jsx(Box, { marginTop: 1, marginLeft: 2, children: _jsx(Text, { dimColor: true, children: "Your conversation stays above \u2014 picking a model keeps all history intact." }) })] }));
|
|
777
|
-
})(), !inPicker && (_jsx(InputBox, { input: (permissionRequest || askUserRequest) ? '' : input, setInput: (permissionRequest || askUserRequest) ? () => { } : setInput, onSubmit: (permissionRequest || askUserRequest) ? () => { } : handleSubmit, model: currentModel, balance: liveBalance, sessionCost: totalCost, queued: queuedInputs[0] || undefined, queuedCount: queuedInputs.length, focused: !permissionRequest && !askUserRequest, busy: !askUserRequest && (waiting || thinking || tools.size > 0), contextPct: contextPct, vimMode: vimEnabled, onVimModeChange: setCurrentVimMode }))] }));
|
|
777
|
+
})(), !inPicker && (_jsx(InputBox, { input: (permissionRequest || askUserRequest) ? '' : input, setInput: (permissionRequest || askUserRequest) ? () => { } : setInput, onSubmit: (permissionRequest || askUserRequest) ? () => { } : handleSubmit, model: currentModel, balance: liveBalance, chain: chain, walletTail: walletAddress && walletAddress.length >= 4 && !walletAddress.startsWith('not set') ? walletAddress.slice(-4) : undefined, sessionCost: totalCost, queued: queuedInputs[0] || undefined, queuedCount: queuedInputs.length, focused: !permissionRequest && !askUserRequest, busy: !askUserRequest && (waiting || thinking || tools.size > 0), contextPct: contextPct, vimMode: vimEnabled, onVimModeChange: setCurrentVimMode }))] }));
|
|
778
778
|
}
|
|
779
779
|
export function launchInkUI(opts) {
|
|
780
780
|
let resolveInput = null;
|
package/dist/ui/model-picker.js
CHANGED
|
@@ -79,8 +79,11 @@ export const MODEL_SHORTCUTS = {
|
|
|
79
79
|
'glm5': 'zai/glm-5.1',
|
|
80
80
|
kimi: 'moonshot/kimi-k2.6',
|
|
81
81
|
'k2.6': 'moonshot/kimi-k2.6',
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
// K2.5 was retired by the gateway in favor of K2.6 (256K ctx, vision +
|
|
83
|
+
// reasoning, $0.95 in / $4 out — strictly better in every dimension).
|
|
84
|
+
// The aliases stay so muscle memory keeps working but resolve to K2.6.
|
|
85
|
+
'kimi-k2.5': 'moonshot/kimi-k2.6',
|
|
86
|
+
'k2.5': 'moonshot/kimi-k2.6',
|
|
84
87
|
};
|
|
85
88
|
/**
|
|
86
89
|
* Resolve a model name — supports shortcuts.
|
|
@@ -149,7 +152,6 @@ export const PICKER_CATEGORIES = [
|
|
|
149
152
|
{ id: 'google/gemini-2.5-flash', shortcut: 'flash', label: 'Gemini 2.5 Flash', price: '$0.3/$2.5' },
|
|
150
153
|
{ id: 'deepseek/deepseek-chat', shortcut: 'deepseek', label: 'DeepSeek V3', price: '$0.28/$0.42' },
|
|
151
154
|
{ id: 'moonshot/kimi-k2.6', shortcut: 'kimi', label: 'Kimi K2.6', price: '$0.95/$4' },
|
|
152
|
-
{ id: 'moonshot/kimi-k2.5', shortcut: 'kimi-k2.5', label: 'Kimi K2.5 (legacy)', price: '$0.6/$3' },
|
|
153
155
|
{ id: 'minimax/minimax-m2.7', shortcut: 'minimax', label: 'Minimax M2.7', price: '$0.3/$1.2' },
|
|
154
156
|
],
|
|
155
157
|
},
|
package/package.json
CHANGED