@blockrun/franklin 3.7.6 → 3.7.8
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/optimize.js +1 -0
- package/dist/agent/tokens.js +1 -0
- package/dist/pricing.js +2 -1
- package/dist/router/index.js +4 -4
- package/dist/ui/app.js +35 -4
- package/dist/ui/model-picker.js +5 -2
- package/package.json +1 -1
package/dist/agent/optimize.js
CHANGED
|
@@ -21,6 +21,7 @@ export const CAPPED_MAX_TOKENS = 16_384;
|
|
|
21
21
|
export const ESCALATED_MAX_TOKENS = 65_536;
|
|
22
22
|
/** Per-model max output tokens — prevents requesting more than the model supports */
|
|
23
23
|
const MODEL_MAX_OUTPUT = {
|
|
24
|
+
'anthropic/claude-opus-4.7': 128_000,
|
|
24
25
|
'anthropic/claude-opus-4.6': 32_000,
|
|
25
26
|
'anthropic/claude-sonnet-4.6': 64_000,
|
|
26
27
|
'anthropic/claude-haiku-4.5-20251001': 16_384,
|
package/dist/agent/tokens.js
CHANGED
|
@@ -151,6 +151,7 @@ export function estimateHistoryTokens(history) {
|
|
|
151
151
|
*/
|
|
152
152
|
const MODEL_CONTEXT_WINDOWS = {
|
|
153
153
|
// Anthropic
|
|
154
|
+
'anthropic/claude-opus-4.7': 1_000_000,
|
|
154
155
|
'anthropic/claude-opus-4.6': 200_000,
|
|
155
156
|
'anthropic/claude-sonnet-4.6': 200_000,
|
|
156
157
|
'anthropic/claude-sonnet-4': 200_000,
|
package/dist/pricing.js
CHANGED
|
@@ -23,6 +23,7 @@ export const MODEL_PRICING = {
|
|
|
23
23
|
// Anthropic
|
|
24
24
|
'anthropic/claude-sonnet-4.6': { input: 3.0, output: 15.0 },
|
|
25
25
|
'anthropic/claude-opus-4.6': { input: 5.0, output: 25.0 },
|
|
26
|
+
'anthropic/claude-opus-4.7': { input: 5.0, output: 25.0 },
|
|
26
27
|
'anthropic/claude-haiku-4.5': { input: 1.0, output: 5.0 },
|
|
27
28
|
'anthropic/claude-haiku-4.5-20251001': { input: 1.0, output: 5.0 },
|
|
28
29
|
// OpenAI
|
|
@@ -76,7 +77,7 @@ export const MODEL_PRICING = {
|
|
|
76
77
|
'zai/glm-5.1-turbo': { input: 0, output: 0, perCall: 0.001 }, // client alias for zai/glm-5-turbo
|
|
77
78
|
};
|
|
78
79
|
/** Opus pricing for savings calculations */
|
|
79
|
-
export const OPUS_PRICING = MODEL_PRICING['anthropic/claude-opus-4.
|
|
80
|
+
export const OPUS_PRICING = MODEL_PRICING['anthropic/claude-opus-4.7'];
|
|
80
81
|
/**
|
|
81
82
|
* Estimate cost in USD for a request.
|
|
82
83
|
* Falls back to $2/$10 per 1M for unknown models.
|
package/dist/router/index.js
CHANGED
|
@@ -46,10 +46,10 @@ const AUTO_TIERS = {
|
|
|
46
46
|
},
|
|
47
47
|
COMPLEX: {
|
|
48
48
|
primary: 'anthropic/claude-sonnet-4.6',
|
|
49
|
-
fallback: ['openai/gpt-5.4', 'anthropic/claude-opus-4.
|
|
49
|
+
fallback: ['openai/gpt-5.4', 'anthropic/claude-opus-4.7'],
|
|
50
50
|
},
|
|
51
51
|
REASONING: {
|
|
52
|
-
primary: 'anthropic/claude-opus-4.
|
|
52
|
+
primary: 'anthropic/claude-opus-4.7',
|
|
53
53
|
fallback: ['openai/o3', 'xai/grok-4-1-fast-reasoning'],
|
|
54
54
|
},
|
|
55
55
|
};
|
|
@@ -81,12 +81,12 @@ const PREMIUM_TIERS = {
|
|
|
81
81
|
fallback: ['anthropic/claude-sonnet-4.6'],
|
|
82
82
|
},
|
|
83
83
|
COMPLEX: {
|
|
84
|
-
primary: 'anthropic/claude-opus-4.
|
|
84
|
+
primary: 'anthropic/claude-opus-4.7',
|
|
85
85
|
fallback: ['openai/gpt-5.4', 'anthropic/claude-sonnet-4.6'],
|
|
86
86
|
},
|
|
87
87
|
REASONING: {
|
|
88
88
|
primary: 'anthropic/claude-sonnet-4.6',
|
|
89
|
-
fallback: ['anthropic/claude-opus-4.
|
|
89
|
+
fallback: ['anthropic/claude-opus-4.7', 'openai/o3'],
|
|
90
90
|
},
|
|
91
91
|
};
|
|
92
92
|
// ─── Keywords for Classification ───
|
package/dist/ui/app.js
CHANGED
|
@@ -15,16 +15,36 @@ import { estimateCost } from '../pricing.js';
|
|
|
15
15
|
import { formatTokens, shortModelName } from '../stats/format.js';
|
|
16
16
|
import { mouse, forceDisableMouseTracking } from './mouse.js';
|
|
17
17
|
// ─── Full-width input box ──────────────────────────────────────────────────
|
|
18
|
-
|
|
18
|
+
// Subscribe to terminal resize so React re-renders with fresh dimensions.
|
|
19
|
+
// Without this, useStdout() returns a stable ref and children that read
|
|
20
|
+
// stdout.columns on each render still need React to re-execute them — which
|
|
21
|
+
// only happens if some state changes. stdout.on('resize') → setState does that.
|
|
22
|
+
function useTerminalSize() {
|
|
19
23
|
const { stdout } = useStdout();
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
const [size, setSize] = useState(() => ({
|
|
25
|
+
cols: stdout?.columns ?? 80,
|
|
26
|
+
rows: stdout?.rows ?? 24,
|
|
27
|
+
}));
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!stdout)
|
|
30
|
+
return;
|
|
31
|
+
const onResize = () => setSize({
|
|
32
|
+
cols: stdout.columns ?? 80,
|
|
33
|
+
rows: stdout.rows ?? 24,
|
|
34
|
+
});
|
|
35
|
+
stdout.on('resize', onResize);
|
|
36
|
+
return () => { stdout.off('resize', onResize); };
|
|
37
|
+
}, [stdout]);
|
|
38
|
+
return size;
|
|
39
|
+
}
|
|
40
|
+
function InputBox({ input, setInput, onSubmit, model, balance, sessionCost, queued, queuedCount, focused, busy, contextPct, vimMode, onVimModeChange }) {
|
|
41
|
+
const { cols } = useTerminalSize();
|
|
22
42
|
const placeholder = busy
|
|
23
43
|
? (queued
|
|
24
44
|
? `⏎ ${queuedCount ?? 1} queued: ${queued.slice(0, 40)}`
|
|
25
45
|
: 'Working...')
|
|
26
46
|
: 'Type a message...';
|
|
27
|
-
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
47
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { borderStyle: "round", borderDimColor: true, paddingX: 1, width: cols, 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 ? (() => {
|
|
28
48
|
// Visual context bar: ▓▓▓▓▓▓░░░░ 75%
|
|
29
49
|
const filled = Math.round(contextPct / 10);
|
|
30
50
|
const empty = 10 - filled;
|
|
@@ -221,10 +241,17 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
221
241
|
setCurrentModel(selected.id);
|
|
222
242
|
onModelChange(selected.id, 'user');
|
|
223
243
|
showStatus(`Model → ${selected.label}`, 'success', 3000);
|
|
244
|
+
// Clear any stale draft that was in the input when the picker opened —
|
|
245
|
+
// previously a paste/typed value could leak back into the chat box after
|
|
246
|
+
// the picker closed, which is both confusing and a privacy risk.
|
|
247
|
+
setInput('');
|
|
248
|
+
setHistoryIdx(-1);
|
|
224
249
|
setMode('input');
|
|
225
250
|
setReady(true);
|
|
226
251
|
}
|
|
227
252
|
else if (key.escape) {
|
|
253
|
+
setInput('');
|
|
254
|
+
setHistoryIdx(-1);
|
|
228
255
|
setMode('input');
|
|
229
256
|
setReady(true);
|
|
230
257
|
}
|
|
@@ -296,6 +323,10 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
296
323
|
else {
|
|
297
324
|
const idx = PICKER_MODELS_FLAT.findIndex(m => m.id === currentModel);
|
|
298
325
|
setPickerIdx(idx >= 0 ? idx : 0);
|
|
326
|
+
// Defensive: ensure no draft text survives into the picker —
|
|
327
|
+
// closing handlers clear input too, so both ends are covered.
|
|
328
|
+
setInput('');
|
|
329
|
+
setHistoryIdx(-1);
|
|
299
330
|
setMode('model-picker');
|
|
300
331
|
}
|
|
301
332
|
return;
|
package/dist/ui/model-picker.js
CHANGED
|
@@ -14,7 +14,9 @@ export const MODEL_SHORTCUTS = {
|
|
|
14
14
|
// Anthropic
|
|
15
15
|
sonnet: 'anthropic/claude-sonnet-4.6',
|
|
16
16
|
claude: 'anthropic/claude-sonnet-4.6',
|
|
17
|
-
opus: 'anthropic/claude-opus-4.
|
|
17
|
+
opus: 'anthropic/claude-opus-4.7',
|
|
18
|
+
'opus-4.7': 'anthropic/claude-opus-4.7',
|
|
19
|
+
'opus-4.6': 'anthropic/claude-opus-4.6',
|
|
18
20
|
haiku: 'anthropic/claude-haiku-4.5-20251001',
|
|
19
21
|
// OpenAI
|
|
20
22
|
gpt: 'openai/gpt-5.4',
|
|
@@ -93,8 +95,9 @@ export const PICKER_CATEGORIES = [
|
|
|
93
95
|
{
|
|
94
96
|
category: '✨ Premium frontier',
|
|
95
97
|
models: [
|
|
98
|
+
{ id: 'anthropic/claude-opus-4.7', shortcut: 'opus', label: 'Claude Opus 4.7', price: '$5/$25', highlight: true },
|
|
96
99
|
{ id: 'anthropic/claude-sonnet-4.6', shortcut: 'sonnet', label: 'Claude Sonnet 4.6', price: '$3/$15' },
|
|
97
|
-
{ id: 'anthropic/claude-opus-4.6', shortcut: 'opus', label: 'Claude Opus 4.6', price: '$5/$25' },
|
|
100
|
+
{ id: 'anthropic/claude-opus-4.6', shortcut: 'opus-4.6', label: 'Claude Opus 4.6', price: '$5/$25' },
|
|
98
101
|
{ id: 'openai/gpt-5.4', shortcut: 'gpt', label: 'GPT-5.4', price: '$2.5/$15' },
|
|
99
102
|
{ id: 'openai/gpt-5.4-pro', shortcut: 'gpt-5.4-pro', label: 'GPT-5.4 Pro', price: '$30/$180' },
|
|
100
103
|
{ id: 'google/gemini-2.5-pro', shortcut: 'gemini', label: 'Gemini 2.5 Pro', price: '$1.25/$10' },
|
package/package.json
CHANGED