openclaw-freerouter 1.3.0 → 2.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 +1 -1
- package/README.md +123 -64
- package/openclaw.plugin.json +96 -12
- package/package.json +32 -20
- package/src/cli.ts +378 -0
- package/src/index.ts +144 -0
- package/src/models.ts +1 -1
- package/src/provider.ts +563 -676
- package/src/router/config.ts +34 -21
- package/src/router/index.ts +9 -12
- package/src/router/rules.ts +1 -1
- package/src/router/selector.ts +1 -1
- package/src/router/types.ts +1 -2
- package/src/service.ts +773 -0
- package/CHANGELOG.md +0 -26
- package/index.ts +0 -63
- package/src/auth.ts +0 -128
- package/src/config.ts +0 -220
- package/src/logger.ts +0 -32
- package/src/server.ts +0 -381
package/src/router/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Default Routing Config — Customized for Direct API Keys
|
|
3
|
-
*
|
|
3
|
+
* FreeRouter — Default Routing Config
|
|
4
4
|
*
|
|
5
5
|
* Tier models are mapped to providers YOU have API keys for.
|
|
6
6
|
* Edit the `tiers` section to match your configured providers.
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import type { RoutingConfig } from "./types.js";
|
|
16
|
-
import { getConfig } from "../config.js";
|
|
17
16
|
|
|
18
17
|
export const DEFAULT_ROUTING_CONFIG: RoutingConfig = {
|
|
19
18
|
version: "2.0-direct",
|
|
@@ -210,33 +209,47 @@ export const DEFAULT_ROUTING_CONFIG: RoutingConfig = {
|
|
|
210
209
|
},
|
|
211
210
|
};
|
|
212
211
|
|
|
213
|
-
|
|
214
212
|
/**
|
|
215
|
-
* Get the
|
|
216
|
-
* External config can override: tiers, agenticTiers, tierBoundaries.
|
|
217
|
-
* Scoring weights and keywords remain as coded defaults (advanced users edit source).
|
|
213
|
+
* Get the default routing config.
|
|
218
214
|
*/
|
|
219
215
|
export function getRoutingConfig(): RoutingConfig {
|
|
220
|
-
|
|
221
|
-
|
|
216
|
+
return DEFAULT_ROUTING_CONFIG;
|
|
217
|
+
}
|
|
222
218
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
219
|
+
/**
|
|
220
|
+
* Apply plugin config overrides to the routing config.
|
|
221
|
+
* Merges user-specified tiers, scoring, and defaultTier over defaults.
|
|
222
|
+
*/
|
|
223
|
+
export function applyConfigOverrides(base: RoutingConfig, pluginConfig: Record<string, unknown>): RoutingConfig {
|
|
224
|
+
const result = JSON.parse(JSON.stringify(base)) as RoutingConfig;
|
|
225
|
+
|
|
226
|
+
// Override tiers if provided
|
|
227
|
+
if (pluginConfig.tiers && typeof pluginConfig.tiers === "object") {
|
|
228
|
+
const userTiers = pluginConfig.tiers as Record<string, { primary: string; fallback?: string[] }>;
|
|
229
|
+
for (const [tier, cfg] of Object.entries(userTiers)) {
|
|
230
|
+
if (result.tiers[tier as keyof typeof result.tiers]) {
|
|
231
|
+
result.tiers[tier as keyof typeof result.tiers] = {
|
|
232
|
+
primary: cfg.primary,
|
|
233
|
+
fallback: cfg.fallback ?? [],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
}
|
|
226
237
|
}
|
|
227
238
|
|
|
228
|
-
// Override
|
|
229
|
-
if (
|
|
230
|
-
|
|
239
|
+
// Override scoring config if provided
|
|
240
|
+
if (pluginConfig.scoring && typeof pluginConfig.scoring === "object") {
|
|
241
|
+
const userScoring = pluginConfig.scoring as Record<string, unknown>;
|
|
242
|
+
for (const [key, val] of Object.entries(userScoring)) {
|
|
243
|
+
if (key in result.scoring) {
|
|
244
|
+
(result.scoring as any)[key] = val;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
231
247
|
}
|
|
232
248
|
|
|
233
|
-
// Override tier
|
|
234
|
-
if (
|
|
235
|
-
|
|
236
|
-
...config.scoring,
|
|
237
|
-
tierBoundaries: extCfg.tierBoundaries,
|
|
238
|
-
};
|
|
249
|
+
// Override default tier for ambiguous requests
|
|
250
|
+
if (pluginConfig.defaultTier && typeof pluginConfig.defaultTier === "string") {
|
|
251
|
+
result.overrides.ambiguousDefaultTier = pluginConfig.defaultTier as any;
|
|
239
252
|
}
|
|
240
253
|
|
|
241
|
-
return
|
|
254
|
+
return result;
|
|
242
255
|
}
|
package/src/router/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Smart Router Entry Point
|
|
3
|
-
*
|
|
3
|
+
* FreeRouter — Smart Router Entry Point
|
|
4
4
|
*
|
|
5
5
|
* Classifies requests and routes to the best model from YOUR configured providers.
|
|
6
6
|
* 100% local — rules-based scoring handles all requests in <1ms.
|
|
@@ -32,14 +32,12 @@ export function route(
|
|
|
32
32
|
): RoutingDecision {
|
|
33
33
|
const { config, modelPricing } = options;
|
|
34
34
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const estimatedUserTokens = Math.ceil(prompt.length / 4);
|
|
39
|
-
const estimatedTotalTokens = Math.ceil((`${systemPrompt ?? ""} ${prompt}`).length / 4);
|
|
35
|
+
// Estimate input tokens (~4 chars per token)
|
|
36
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
37
|
+
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
40
38
|
|
|
41
39
|
// --- Rule-based classification ---
|
|
42
|
-
const ruleResult = classifyByRules(prompt, systemPrompt,
|
|
40
|
+
const ruleResult = classifyByRules(prompt, systemPrompt, estimatedTokens, config.scoring);
|
|
43
41
|
|
|
44
42
|
// Determine if agentic tiers should be used
|
|
45
43
|
const agenticScore = ruleResult.agenticScore ?? 0;
|
|
@@ -49,7 +47,7 @@ export function route(
|
|
|
49
47
|
const tierConfigs = useAgenticTiers ? config.agenticTiers! : config.tiers;
|
|
50
48
|
|
|
51
49
|
// --- Override: large context → force COMPLEX ---
|
|
52
|
-
if (
|
|
50
|
+
if (estimatedTokens > config.overrides.maxTokensForceComplex) {
|
|
53
51
|
return selectModel(
|
|
54
52
|
"COMPLEX",
|
|
55
53
|
0.95,
|
|
@@ -57,14 +55,13 @@ export function route(
|
|
|
57
55
|
`Input exceeds ${config.overrides.maxTokensForceComplex} tokens${useAgenticTiers ? " | agentic" : ""}`,
|
|
58
56
|
tierConfigs,
|
|
59
57
|
modelPricing,
|
|
60
|
-
|
|
58
|
+
estimatedTokens,
|
|
61
59
|
maxOutputTokens,
|
|
62
60
|
);
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
// Structured output detection
|
|
66
|
-
|
|
67
|
-
const hasStructuredOutput = /json|structured|schema/i.test(prompt);
|
|
64
|
+
const hasStructuredOutput = systemPrompt ? /json|structured|schema/i.test(systemPrompt) : false;
|
|
68
65
|
|
|
69
66
|
let tier: Tier;
|
|
70
67
|
let confidence: number;
|
|
@@ -103,7 +100,7 @@ export function route(
|
|
|
103
100
|
reasoning,
|
|
104
101
|
tierConfigs,
|
|
105
102
|
modelPricing,
|
|
106
|
-
|
|
103
|
+
estimatedTokens,
|
|
107
104
|
maxOutputTokens,
|
|
108
105
|
);
|
|
109
106
|
}
|
package/src/router/rules.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rule-Based Classifier (v2 — Weighted Scoring)
|
|
3
|
-
*
|
|
3
|
+
* FreeRouter — Rule-Based Classifier (Weighted Scoring)
|
|
4
4
|
*
|
|
5
5
|
* Scores a request across 14 weighted dimensions and maps the aggregate
|
|
6
6
|
* score to a tier using configurable boundaries. Confidence is calibrated
|
package/src/router/selector.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tier → Model Selection
|
|
3
|
-
*
|
|
3
|
+
* FreeRouter — Tier to Model Selection
|
|
4
4
|
*
|
|
5
5
|
* Maps a classification tier to the best model from configured providers.
|
|
6
6
|
* Builds RoutingDecision metadata with cost estimates and savings.
|
package/src/router/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Smart Router Types
|
|
3
|
-
* Stripped of x402/BlockRun payment layer.
|
|
2
|
+
* FreeRouter — Smart Router Types
|
|
4
3
|
*
|
|
5
4
|
* Four classification tiers — REASONING is distinct from COMPLEX because
|
|
6
5
|
* reasoning tasks need different models (o3, deepseek-reasoner) than general
|