@blockrun/franklin 3.0.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/LICENSE +190 -0
- package/README.md +256 -0
- package/dist/agent/commands.d.ts +27 -0
- package/dist/agent/commands.js +659 -0
- package/dist/agent/compact.d.ts +31 -0
- package/dist/agent/compact.js +366 -0
- package/dist/agent/context.d.ts +11 -0
- package/dist/agent/context.js +184 -0
- package/dist/agent/error-classifier.d.ts +10 -0
- package/dist/agent/error-classifier.js +61 -0
- package/dist/agent/llm.d.ts +63 -0
- package/dist/agent/llm.js +448 -0
- package/dist/agent/loop.d.ts +12 -0
- package/dist/agent/loop.js +346 -0
- package/dist/agent/optimize.d.ts +53 -0
- package/dist/agent/optimize.js +262 -0
- package/dist/agent/permissions.d.ts +39 -0
- package/dist/agent/permissions.js +226 -0
- package/dist/agent/reduce.d.ts +49 -0
- package/dist/agent/reduce.js +317 -0
- package/dist/agent/streaming-executor.d.ts +36 -0
- package/dist/agent/streaming-executor.js +149 -0
- package/dist/agent/tokens.d.ts +53 -0
- package/dist/agent/tokens.js +185 -0
- package/dist/agent/types.d.ts +125 -0
- package/dist/agent/types.js +5 -0
- package/dist/banner.d.ts +1 -0
- package/dist/banner.js +27 -0
- package/dist/commands/balance.d.ts +1 -0
- package/dist/commands/balance.js +40 -0
- package/dist/commands/config.d.ts +14 -0
- package/dist/commands/config.js +107 -0
- package/dist/commands/daemon.d.ts +3 -0
- package/dist/commands/daemon.js +117 -0
- package/dist/commands/history.d.ts +5 -0
- package/dist/commands/history.js +31 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +92 -0
- package/dist/commands/logs.d.ts +5 -0
- package/dist/commands/logs.js +89 -0
- package/dist/commands/models.d.ts +1 -0
- package/dist/commands/models.js +56 -0
- package/dist/commands/plugin.d.ts +14 -0
- package/dist/commands/plugin.js +176 -0
- package/dist/commands/proxy.d.ts +13 -0
- package/dist/commands/proxy.js +106 -0
- package/dist/commands/setup.d.ts +1 -0
- package/dist/commands/setup.js +49 -0
- package/dist/commands/start.d.ts +8 -0
- package/dist/commands/start.js +292 -0
- package/dist/commands/stats.d.ts +10 -0
- package/dist/commands/stats.js +94 -0
- package/dist/commands/uninit.d.ts +1 -0
- package/dist/commands/uninit.js +63 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +41 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +179 -0
- package/dist/mcp/client.d.ts +44 -0
- package/dist/mcp/client.js +147 -0
- package/dist/mcp/config.d.ts +20 -0
- package/dist/mcp/config.js +138 -0
- package/dist/plugin-sdk/channel.d.ts +100 -0
- package/dist/plugin-sdk/channel.js +10 -0
- package/dist/plugin-sdk/index.d.ts +14 -0
- package/dist/plugin-sdk/index.js +9 -0
- package/dist/plugin-sdk/plugin.d.ts +87 -0
- package/dist/plugin-sdk/plugin.js +7 -0
- package/dist/plugin-sdk/search.d.ts +13 -0
- package/dist/plugin-sdk/search.js +4 -0
- package/dist/plugin-sdk/tracker.d.ts +27 -0
- package/dist/plugin-sdk/tracker.js +5 -0
- package/dist/plugin-sdk/workflow.d.ts +126 -0
- package/dist/plugin-sdk/workflow.js +11 -0
- package/dist/plugins/registry.d.ts +33 -0
- package/dist/plugins/registry.js +155 -0
- package/dist/plugins/runner.d.ts +21 -0
- package/dist/plugins/runner.js +453 -0
- package/dist/plugins-bundled/social/index.d.ts +10 -0
- package/dist/plugins-bundled/social/index.js +363 -0
- package/dist/plugins-bundled/social/plugin.json +14 -0
- package/dist/plugins-bundled/social/prompts.d.ts +19 -0
- package/dist/plugins-bundled/social/prompts.js +67 -0
- package/dist/plugins-bundled/social/types.d.ts +58 -0
- package/dist/plugins-bundled/social/types.js +16 -0
- package/dist/pricing.d.ts +21 -0
- package/dist/pricing.js +91 -0
- package/dist/proxy/fallback.d.ts +38 -0
- package/dist/proxy/fallback.js +144 -0
- package/dist/proxy/server.d.ts +18 -0
- package/dist/proxy/server.js +576 -0
- package/dist/proxy/sse-translator.d.ts +29 -0
- package/dist/proxy/sse-translator.js +270 -0
- package/dist/router/index.d.ts +22 -0
- package/dist/router/index.js +269 -0
- package/dist/session/search.d.ts +33 -0
- package/dist/session/search.js +229 -0
- package/dist/session/storage.d.ts +48 -0
- package/dist/session/storage.js +173 -0
- package/dist/stats/insights.d.ts +55 -0
- package/dist/stats/insights.js +195 -0
- package/dist/stats/tracker.d.ts +54 -0
- package/dist/stats/tracker.js +165 -0
- package/dist/tools/askuser.d.ts +6 -0
- package/dist/tools/askuser.js +76 -0
- package/dist/tools/bash.d.ts +5 -0
- package/dist/tools/bash.js +336 -0
- package/dist/tools/edit.d.ts +5 -0
- package/dist/tools/edit.js +148 -0
- package/dist/tools/glob.d.ts +5 -0
- package/dist/tools/glob.js +158 -0
- package/dist/tools/grep.d.ts +5 -0
- package/dist/tools/grep.js +194 -0
- package/dist/tools/imagegen.d.ts +6 -0
- package/dist/tools/imagegen.js +172 -0
- package/dist/tools/index.d.ts +17 -0
- package/dist/tools/index.js +30 -0
- package/dist/tools/read.d.ts +11 -0
- package/dist/tools/read.js +90 -0
- package/dist/tools/subagent.d.ts +5 -0
- package/dist/tools/subagent.js +116 -0
- package/dist/tools/task.d.ts +5 -0
- package/dist/tools/task.js +91 -0
- package/dist/tools/webfetch.d.ts +5 -0
- package/dist/tools/webfetch.js +166 -0
- package/dist/tools/websearch.d.ts +5 -0
- package/dist/tools/websearch.js +103 -0
- package/dist/tools/write.d.ts +5 -0
- package/dist/tools/write.js +114 -0
- package/dist/ui/app.d.ts +26 -0
- package/dist/ui/app.js +545 -0
- package/dist/ui/model-picker.d.ts +14 -0
- package/dist/ui/model-picker.js +161 -0
- package/dist/ui/terminal.d.ts +35 -0
- package/dist/ui/terminal.js +337 -0
- package/dist/wallet/manager.d.ts +10 -0
- package/dist/wallet/manager.js +23 -0
- package/package.json +79 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback chain for runcode
|
|
3
|
+
* Automatically switches to backup models when primary fails (429, 5xx, etc.)
|
|
4
|
+
*/
|
|
5
|
+
export interface FallbackConfig {
|
|
6
|
+
/** Models to try in order of priority */
|
|
7
|
+
chain: string[];
|
|
8
|
+
/** HTTP status codes that trigger fallback */
|
|
9
|
+
retryOn: number[];
|
|
10
|
+
/** Maximum retries across all models */
|
|
11
|
+
maxRetries: number;
|
|
12
|
+
/** Delay between retries in ms */
|
|
13
|
+
retryDelayMs: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_FALLBACK_CONFIG: FallbackConfig;
|
|
16
|
+
export interface FallbackResult {
|
|
17
|
+
response: Response;
|
|
18
|
+
modelUsed: string;
|
|
19
|
+
/** The request body with the successful model substituted in */
|
|
20
|
+
bodyUsed: string;
|
|
21
|
+
fallbackUsed: boolean;
|
|
22
|
+
attemptsCount: number;
|
|
23
|
+
failedModels: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch with automatic fallback to backup models
|
|
27
|
+
*/
|
|
28
|
+
export declare function fetchWithFallback(url: string, init: RequestInit, originalBody: string, config?: FallbackConfig, onFallback?: (model: string, statusCode: number, nextModel: string) => void): Promise<FallbackResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Get the current model from fallback chain based on parsed request
|
|
31
|
+
*/
|
|
32
|
+
export declare function getCurrentModelFromChain(requestedModel: string | undefined, config?: FallbackConfig): string;
|
|
33
|
+
/**
|
|
34
|
+
* Build fallback chain starting from a specific model.
|
|
35
|
+
* Filters out routing profiles (blockrun/auto etc.) since the backend
|
|
36
|
+
* doesn't recognize them — they must be resolved by the smart router first.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildFallbackChain(startModel: string, config?: FallbackConfig): string[];
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback chain for runcode
|
|
3
|
+
* Automatically switches to backup models when primary fails (429, 5xx, etc.)
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
const LOG_FILE = path.join(os.homedir(), '.blockrun', 'runcode-debug.log');
|
|
9
|
+
// eslint-disable-next-line no-control-regex
|
|
10
|
+
const ANSI_RE = /\x1B\[[0-9;]*[A-Za-z]|\x1B\][^\x07]*\x07|\x1B[()][A-B]|\r/g;
|
|
11
|
+
function appendLog(msg) {
|
|
12
|
+
try {
|
|
13
|
+
fs.mkdirSync(path.dirname(LOG_FILE), { recursive: true });
|
|
14
|
+
fs.appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg.replace(ANSI_RE, '')}\n`);
|
|
15
|
+
}
|
|
16
|
+
catch { /* ignore */ }
|
|
17
|
+
}
|
|
18
|
+
export const DEFAULT_FALLBACK_CONFIG = {
|
|
19
|
+
chain: [
|
|
20
|
+
'deepseek/deepseek-chat', // Direct fallback — cheap & reliable
|
|
21
|
+
'google/gemini-2.5-flash', // Fast & capable
|
|
22
|
+
'nvidia/nemotron-ultra-253b', // Free model as ultimate fallback
|
|
23
|
+
],
|
|
24
|
+
retryOn: [429, 500, 502, 503, 504, 529],
|
|
25
|
+
maxRetries: 5,
|
|
26
|
+
retryDelayMs: 1000,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Sleep helper
|
|
30
|
+
*/
|
|
31
|
+
function sleep(ms) {
|
|
32
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Replace model in request body
|
|
36
|
+
*/
|
|
37
|
+
function replaceModelInBody(body, newModel) {
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(body);
|
|
40
|
+
parsed.model = newModel;
|
|
41
|
+
return JSON.stringify(parsed);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return body;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Fetch with automatic fallback to backup models
|
|
49
|
+
*/
|
|
50
|
+
export async function fetchWithFallback(url, init, originalBody, config = DEFAULT_FALLBACK_CONFIG, onFallback) {
|
|
51
|
+
const failedModels = [];
|
|
52
|
+
let attempts = 0;
|
|
53
|
+
const FALLBACK_TIMEOUT_MS = 60_000; // 60s per attempt
|
|
54
|
+
for (let i = 0; i < config.chain.length && attempts < config.maxRetries; i++) {
|
|
55
|
+
const model = config.chain[i];
|
|
56
|
+
const body = replaceModelInBody(originalBody, model);
|
|
57
|
+
try {
|
|
58
|
+
attempts++;
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
const timeout = setTimeout(() => controller.abort(), FALLBACK_TIMEOUT_MS);
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
...init,
|
|
63
|
+
body,
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
});
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
// Success or non-retryable error
|
|
68
|
+
if (!config.retryOn.includes(response.status)) {
|
|
69
|
+
return {
|
|
70
|
+
response,
|
|
71
|
+
modelUsed: model,
|
|
72
|
+
bodyUsed: body,
|
|
73
|
+
fallbackUsed: i > 0,
|
|
74
|
+
attemptsCount: attempts,
|
|
75
|
+
failedModels,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Retryable error - log and try next
|
|
79
|
+
failedModels.push(model);
|
|
80
|
+
const nextModel = config.chain[i + 1];
|
|
81
|
+
if (nextModel && onFallback) {
|
|
82
|
+
onFallback(model, response.status, nextModel);
|
|
83
|
+
}
|
|
84
|
+
// Wait before trying next model (with exponential backoff for same model retries)
|
|
85
|
+
if (i < config.chain.length - 1) {
|
|
86
|
+
await sleep(config.retryDelayMs);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
// Network error - try next model
|
|
91
|
+
failedModels.push(model);
|
|
92
|
+
const nextModel = config.chain[i + 1];
|
|
93
|
+
if (nextModel && onFallback) {
|
|
94
|
+
const errMsg = err instanceof Error ? err.message : 'Network error';
|
|
95
|
+
onFallback(model, 0, nextModel);
|
|
96
|
+
appendLog(`[runcode] [fallback] ${model} network error: ${errMsg}`);
|
|
97
|
+
}
|
|
98
|
+
if (i < config.chain.length - 1) {
|
|
99
|
+
await sleep(config.retryDelayMs);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// All models failed - throw error
|
|
104
|
+
throw new Error(`All models in fallback chain failed: ${failedModels.join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the current model from fallback chain based on parsed request
|
|
108
|
+
*/
|
|
109
|
+
export function getCurrentModelFromChain(requestedModel, config = DEFAULT_FALLBACK_CONFIG) {
|
|
110
|
+
// If model is explicitly set and in chain, start from there
|
|
111
|
+
if (requestedModel) {
|
|
112
|
+
const index = config.chain.indexOf(requestedModel);
|
|
113
|
+
if (index >= 0) {
|
|
114
|
+
return requestedModel;
|
|
115
|
+
}
|
|
116
|
+
// Model not in chain, use as-is (user specified custom model)
|
|
117
|
+
return requestedModel;
|
|
118
|
+
}
|
|
119
|
+
// Default to first model in chain
|
|
120
|
+
return config.chain[0];
|
|
121
|
+
}
|
|
122
|
+
/** Routing profiles that must never be sent to the backend directly */
|
|
123
|
+
const ROUTING_PROFILES = new Set([
|
|
124
|
+
'blockrun/auto', 'blockrun/eco', 'blockrun/premium', 'blockrun/free',
|
|
125
|
+
]);
|
|
126
|
+
/**
|
|
127
|
+
* Build fallback chain starting from a specific model.
|
|
128
|
+
* Filters out routing profiles (blockrun/auto etc.) since the backend
|
|
129
|
+
* doesn't recognize them — they must be resolved by the smart router first.
|
|
130
|
+
*/
|
|
131
|
+
export function buildFallbackChain(startModel, config = DEFAULT_FALLBACK_CONFIG) {
|
|
132
|
+
// Never include routing profiles in the chain — they'd cause 400s
|
|
133
|
+
const safeChain = config.chain.filter(m => !ROUTING_PROFILES.has(m));
|
|
134
|
+
const index = safeChain.indexOf(startModel);
|
|
135
|
+
if (index >= 0) {
|
|
136
|
+
return safeChain.slice(index);
|
|
137
|
+
}
|
|
138
|
+
// If startModel is a routing profile, skip it and just use the safe chain
|
|
139
|
+
if (ROUTING_PROFILES.has(startModel)) {
|
|
140
|
+
return safeChain;
|
|
141
|
+
}
|
|
142
|
+
// Model not in default chain - prepend it
|
|
143
|
+
return [startModel, ...safeChain];
|
|
144
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import type { Chain } from '../config.js';
|
|
3
|
+
export interface ProxyOptions {
|
|
4
|
+
port: number;
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
chain?: Chain;
|
|
7
|
+
modelOverride?: string;
|
|
8
|
+
debug?: boolean;
|
|
9
|
+
fallbackEnabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function createProxy(options: ProxyOptions): http.Server;
|
|
12
|
+
type RequestCategory = 'simple' | 'code' | 'default';
|
|
13
|
+
interface ClassifiedRequest {
|
|
14
|
+
category: RequestCategory;
|
|
15
|
+
suggestedModel?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function classifyRequest(body: string): ClassifiedRequest;
|
|
18
|
+
export {};
|