@blockrun/franklin 3.6.8 → 3.6.10
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/commands.js +1 -1
- package/dist/agent/loop.js +2 -2
- package/dist/agent/types.d.ts +4 -2
- package/dist/commands/start.js +9 -1
- package/dist/ui/app.d.ts +1 -1
- package/dist/ui/app.js +11 -5
- package/dist/ui/mouse.d.ts +5 -0
- package/dist/ui/mouse.js +12 -0
- package/package.json +1 -1
package/dist/agent/commands.js
CHANGED
|
@@ -627,7 +627,7 @@ export async function handleSlashCommand(input, ctx) {
|
|
|
627
627
|
const newModel = resolveModel(input.slice(7).trim());
|
|
628
628
|
ctx.config.model = newModel;
|
|
629
629
|
ctx.config.baseModel = newModel; // Update recovery target so loop doesn't reset
|
|
630
|
-
ctx.config.onModelChange?.(newModel);
|
|
630
|
+
ctx.config.onModelChange?.(newModel, 'user');
|
|
631
631
|
ctx.onEvent({ kind: 'text_delta', text: `Model → **${newModel}**\n` });
|
|
632
632
|
}
|
|
633
633
|
emitDone(ctx);
|
package/dist/agent/loop.js
CHANGED
|
@@ -298,7 +298,7 @@ export async function interactiveSession(config, getUserInput, onEvent, onAbortR
|
|
|
298
298
|
const baseModel = config.baseModel ?? config.model;
|
|
299
299
|
if (config.model !== baseModel && !paymentFailedModels.has(baseModel)) {
|
|
300
300
|
config.model = baseModel;
|
|
301
|
-
config.onModelChange?.(baseModel);
|
|
301
|
+
config.onModelChange?.(baseModel, 'system');
|
|
302
302
|
}
|
|
303
303
|
turnFailedModels = new Set(); // Fresh slate for transient failures this turn
|
|
304
304
|
const abort = new AbortController();
|
|
@@ -589,7 +589,7 @@ export async function interactiveSession(config, getUserInput, onEvent, onAbortR
|
|
|
589
589
|
if (nextFree) {
|
|
590
590
|
const oldModel = config.model;
|
|
591
591
|
config.model = nextFree;
|
|
592
|
-
config.onModelChange?.(nextFree);
|
|
592
|
+
config.onModelChange?.(nextFree, 'system');
|
|
593
593
|
onEvent({ kind: 'text_delta', text: `\n*${oldModel} failed — switching to ${nextFree}*\n` });
|
|
594
594
|
continue; // Retry with next model
|
|
595
595
|
}
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -140,8 +140,10 @@ export interface AgentConfig {
|
|
|
140
140
|
permissionPromptFn?: (toolName: string, description: string) => Promise<'yes' | 'no' | 'always'>;
|
|
141
141
|
/** Routes AskUser questions through ink UI input to avoid raw-mode stdin conflict */
|
|
142
142
|
onAskUser?: (question: string, options?: string[]) => Promise<string>;
|
|
143
|
-
/** Notify UI when agent switches model
|
|
144
|
-
|
|
143
|
+
/** Notify UI when agent switches model. `reason` is 'user' for explicit /model
|
|
144
|
+
* commands and 'system' for payment fallbacks or recovery. User-initiated
|
|
145
|
+
* changes must also update `baseModel`. */
|
|
146
|
+
onModelChange?: (model: string, reason?: 'user' | 'system') => void;
|
|
145
147
|
/** The user's intended model — updated by /model command, used for turn recovery */
|
|
146
148
|
baseModel?: string;
|
|
147
149
|
}
|
package/dist/commands/start.js
CHANGED
|
@@ -184,8 +184,13 @@ async function runWithInkUI(agentConfig, model, workDir, version, walletInfo, on
|
|
|
184
184
|
walletAddress: walletInfo?.address,
|
|
185
185
|
walletBalance: walletInfo?.balance,
|
|
186
186
|
chain: walletInfo?.chain,
|
|
187
|
-
onModelChange: (newModel) => {
|
|
187
|
+
onModelChange: (newModel, reason) => {
|
|
188
188
|
agentConfig.model = newModel;
|
|
189
|
+
// User-initiated switch must also update baseModel so the agent loop
|
|
190
|
+
// doesn't revert to the previous model on the next turn.
|
|
191
|
+
if (reason === 'user') {
|
|
192
|
+
agentConfig.baseModel = newModel;
|
|
193
|
+
}
|
|
189
194
|
},
|
|
190
195
|
});
|
|
191
196
|
// Wire permission prompts through Ink UI to avoid stdin/readline conflict.
|
|
@@ -329,12 +334,14 @@ async function handleSlashCommand(cmd, config, ui) {
|
|
|
329
334
|
const newModel = parts[1];
|
|
330
335
|
if (newModel) {
|
|
331
336
|
config.model = resolveModel(newModel);
|
|
337
|
+
config.baseModel = config.model;
|
|
332
338
|
console.error(chalk.green(` Model → ${config.model}`));
|
|
333
339
|
return null;
|
|
334
340
|
}
|
|
335
341
|
const picked = await pickModel(config.model);
|
|
336
342
|
if (picked) {
|
|
337
343
|
config.model = picked;
|
|
344
|
+
config.baseModel = picked;
|
|
338
345
|
console.error(chalk.green(` Model → ${config.model}`));
|
|
339
346
|
}
|
|
340
347
|
return null;
|
|
@@ -343,6 +350,7 @@ async function handleSlashCommand(cmd, config, ui) {
|
|
|
343
350
|
const picked = await pickModel(config.model);
|
|
344
351
|
if (picked) {
|
|
345
352
|
config.model = picked;
|
|
353
|
+
config.baseModel = picked;
|
|
346
354
|
console.error(chalk.green(` Model → ${config.model}`));
|
|
347
355
|
}
|
|
348
356
|
return null;
|
package/dist/ui/app.d.ts
CHANGED
package/dist/ui/app.js
CHANGED
|
@@ -13,7 +13,7 @@ import { renderMarkdown } from './markdown.js';
|
|
|
13
13
|
import { resolveModel, PICKER_CATEGORIES, PICKER_MODELS_FLAT, } from './model-picker.js';
|
|
14
14
|
import { estimateCost } from '../pricing.js';
|
|
15
15
|
import { formatTokens, shortModelName } from '../stats/format.js';
|
|
16
|
-
import { mouse } from './mouse.js';
|
|
16
|
+
import { mouse, forceDisableMouseTracking } from './mouse.js';
|
|
17
17
|
// ─── Full-width input box ──────────────────────────────────────────────────
|
|
18
18
|
function InputBox({ input, setInput, onSubmit, model, balance, sessionCost, queued, queuedCount, focused, busy, contextPct, vimMode, onVimModeChange }) {
|
|
19
19
|
const { stdout } = useStdout();
|
|
@@ -219,7 +219,7 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
219
219
|
else if (key.return) {
|
|
220
220
|
const selected = PICKER_MODELS_FLAT[pickerIdx];
|
|
221
221
|
setCurrentModel(selected.id);
|
|
222
|
-
onModelChange(selected.id);
|
|
222
|
+
onModelChange(selected.id, 'user');
|
|
223
223
|
showStatus(`Model → ${selected.label}`, 'success', 3000);
|
|
224
224
|
setMode('input');
|
|
225
225
|
setReady(true);
|
|
@@ -290,7 +290,7 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
290
290
|
if (parts[1]) {
|
|
291
291
|
const resolved = resolveModel(parts[1]);
|
|
292
292
|
setCurrentModel(resolved);
|
|
293
|
-
onModelChange(resolved);
|
|
293
|
+
onModelChange(resolved, 'user');
|
|
294
294
|
showStatus(`Model → ${resolved}`, 'success', 3000);
|
|
295
295
|
}
|
|
296
296
|
else {
|
|
@@ -395,8 +395,14 @@ function RunCodeApp({ initialModel, workDir, walletAddress, walletBalance, chain
|
|
|
395
395
|
turnSavingsRef.current = undefined;
|
|
396
396
|
onSubmit(trimmed);
|
|
397
397
|
}, [ready, currentModel, totalCost, onSubmit, onModelChange, onAbort, onExit, exit, lastPrompt, inputHistory, showStatus]);
|
|
398
|
-
// Mouse support —
|
|
398
|
+
// Mouse support — OFF by default because Node stdin is shared: mouse escape
|
|
399
|
+
// sequences leak into Ink's input handler as typed text. Opt in with
|
|
400
|
+
// FRANKLIN_MOUSE=1 if you want click-to-expand-tool + drag-to-copy.
|
|
399
401
|
useEffect(() => {
|
|
402
|
+
// Always disable any leftover mouse tracking from a previous session
|
|
403
|
+
forceDisableMouseTracking();
|
|
404
|
+
if (process.env.FRANKLIN_MOUSE !== '1')
|
|
405
|
+
return;
|
|
400
406
|
const cleanup = mouse.enable();
|
|
401
407
|
const handleClick = (event) => {
|
|
402
408
|
// Ignore clicks in the input area (bottom 4 rows of the terminal)
|
|
@@ -679,7 +685,7 @@ export function launchInkUI(opts) {
|
|
|
679
685
|
// Agent loop hasn't called waitForInput yet — queue the input
|
|
680
686
|
pendingInput = value;
|
|
681
687
|
}
|
|
682
|
-
}, onModelChange: (model) => { opts.onModelChange?.(model); }, onAbort: () => { abortCallback?.(); }, onExit: () => {
|
|
688
|
+
}, onModelChange: (model, reason) => { opts.onModelChange?.(model, reason); }, onAbort: () => { abortCallback?.(); }, onExit: () => {
|
|
683
689
|
exiting = true;
|
|
684
690
|
if (resolveInput) {
|
|
685
691
|
resolveInput(null);
|
package/dist/ui/mouse.d.ts
CHANGED
|
@@ -40,4 +40,9 @@ declare class MouseManager extends EventEmitter {
|
|
|
40
40
|
}
|
|
41
41
|
/** Singleton mouse manager. */
|
|
42
42
|
export declare const mouse: MouseManager;
|
|
43
|
+
/**
|
|
44
|
+
* Force-disable any leftover mouse tracking from a previous session.
|
|
45
|
+
* Safe to call unconditionally — if tracking is off, it's a no-op at the terminal level.
|
|
46
|
+
*/
|
|
47
|
+
export declare function forceDisableMouseTracking(): void;
|
|
43
48
|
export {};
|
package/dist/ui/mouse.js
CHANGED
|
@@ -265,3 +265,15 @@ class MouseManager extends EventEmitter {
|
|
|
265
265
|
}
|
|
266
266
|
/** Singleton mouse manager. */
|
|
267
267
|
export const mouse = new MouseManager();
|
|
268
|
+
/**
|
|
269
|
+
* Force-disable any leftover mouse tracking from a previous session.
|
|
270
|
+
* Safe to call unconditionally — if tracking is off, it's a no-op at the terminal level.
|
|
271
|
+
*/
|
|
272
|
+
export function forceDisableMouseTracking() {
|
|
273
|
+
try {
|
|
274
|
+
process.stdout.write(DISABLE_MOUSE);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Ignore — stdout may not be writable in some contexts
|
|
278
|
+
}
|
|
279
|
+
}
|
package/package.json
CHANGED