Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,85 @@
# Changelog

## Franklin Agent 3.40.0 — priced but unreachable: the catalog gets a front door

**3.39.0 taught Franklin what the new models cost. It never taught anyone how
to ask for them.** That release added eleven chat models to `src/pricing.ts`
and stopped there — no shortcut, no picker row, no router wiring. The models
were live on the gateway, correctly priced, and reachable only by typing the
full `provider/model` id from memory. This release finishes the job.

**38 new shortcuts (107 → 145), covering every model 3.39.0 priced:**

| family | now reachable as |
|---|---|
| GPT-5.6 pro reasoning tier | `sol-pro`, `terra-pro`, `luna-pro` |
| GPT-5.5 Pro / ChatGPT default | `gpt-5.5-pro`, `chatgpt` / `instant` |
| Gemini 3.6 Flash + the Flash Lite line | `flash` (now 3.6), `flash-lite`, `gemini-3.1-flash-lite` |
| Qwen3.7 Plus / Flash | `qwen-plus`, `qwen-flash` |
| Tencent, Xiaomi (new providers) | `hy3` / `tencent`, `mimo` / `xiaomi` |
| GPT-4o + 4.1 mini/nano, o3-mini | `4o`, `gpt-4o-mini`, `gpt-4.1-mini`, `o3-mini` |

Worth knowing about the pro tier: **Terra Pro ($1/$6) and Luna Pro
($0.1/$0.6) undercut their own base tiers** while adding pro reasoning mode.
Sol Pro matches Sol exactly. `gpt` stays pinned to Sol — bare aliases follow
the gateway's flagship, not the cheapest sibling.

**New arrivals since 3.39.0.** `zai/glm-5.3` is Z.AI's flagship (1M context,
always-on reasoning, priced at 5.2's $1.4/$4.4) — `glm` now follows it.
`xai/grok-imagine-video-1.5` joins VideoGen at $0.08/s.

**The router's LLM classifier has been dead since 2026-07-27, silently.**
Its default model was `nvidia/qwen3-next-80b-a3b-instruct` — the same id
NVIDIA EOL'd, which the gateway now rides on `nemotron-3-super-120b`. That
substitute opens with *"Okay, let's see. The user wants to…"* and never
reaches a verdict inside the classifier's 16-token budget, so every
classification failed the strict parse and fell through to keyword-only
routing. The fallback is invisible by design, which is exactly why this went
three weeks without anyone noticing. Re-probed the free pool on the real
classifier prompt:

| free model | reply to a classification prompt |
|---|---|
| `qwen3-next` (old default) | prose, served by `nemotron-3-super-120b` |
| `nemotron-nano-9b-v2` | prose — *"Okay, let's see…"* |
| `nemotron-3-nano-omni` | **`MEDIUM`** — one bare word, served by itself |

`nemotron-3-nano-omni` is the new classifier. The lesson worth keeping: "good
free chat model" and "answers in one bare word under a tight cap" are
different requirements, and the free default is not automatically both.

**The 30B omni model started serving itself again.** In August it came back
as `gpt-oss-120b` — the pooled-substitute trap — which is why it had no alias
and led no chain. Re-probed 2026-08-19 on both the streaming and non-streaming
paths, it now answers as itself. It gets a shortcut (`omni`), a free picker
row, and second place in every free chain; the still-degraded
`mistral-nemotron` slides to third but stays as a genuinely different family.
`nvidia/step-3.7-flash` remains deliberately unaliased — it is billed at $0
and listed in the catalog, but live probes come back served by
`nemotron-3-super-120b`, and an alias that promises a model you don't get is
worse than no alias.

**Picker stays at its 24-row cap — new models displaced old ones.** GLM-5.3
takes GLM-5.2's slot. GPT-5.6 Terra Pro takes the row
`grok-4-1-fast-reasoning` held, which the gateway hides and reconciliation
dropped on every live render anyway. Qwen3.7 Flash ($0.03/$0.13, 1M context,
the cheapest paid model on the gateway) takes GLM-5's budget slot. Gemini 2.5
Pro's row retires from directly under 3.1 Pro. Every retired row keeps its
shortcut, per the long-standing hide-the-row-keep-the-alias rule, and `gemini`
now tracks the 3.1 Pro flagship like `gpt`, `grok` and `glm` already did.

**Also:** the offline picker fallback had stale prices (deepseek at
$0.20/$0.40, corrected to $0.14/$0.28 — live renders were already right since
the gateway is the source of truth for price). Brand numbers re-synced: 95
models visible, 8 video, 5 free. Model-family guidance now recognises
`chat-latest` as a strong model and routes Tencent/Xiaomi to balanced
guidance.

All 646 local tests pass. The five hidden-but-resolvable ids Franklin still
pins (`opus-4.6`, `gpt-5-nano`, `grok-3`, `grok-4-0709`,
`grok-4-1-fast-reasoning`) were each re-probed and still return 402, not 400 —
they stay.

## Franklin Agent 3.39.0 — the gateway moved for three weeks and Franklin didn't

**Franklin's free default was a dead model, and the whole catalog had drifted.**
Expand Down
14 changes: 7 additions & 7 deletions brand-numbers.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
"version": 1,
"models": {
"chatVisible": 71,
"totalVisible": 93,
"free": 6,
"freeWithheld": 19,
"totalVisible": 95,
"free": 5,
"freeWithheld": 20,
"image": 9,
"video": 6,
"video": 8,
"music": 1,
"speech": 5,
"soundfx": 1,
"withFallback": 46,
"withFallbackAllEntries": 79
"withFallback": 44,
"withFallbackAllEntries": 78
},
"clawrouter": {
"dimensions": 15,
"tiers": 4,
"profiles": 4,
"aliases": 202
"aliases": 229
},
"mcp": {
"tools": 20
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@blockrun/franklin",
"version": "3.39.0",
"version": "3.40.0",
"description": "Franklin Agent — The AI agent with a wallet. Spends USDC autonomously to get real work done. Pay per action, no subscriptions.",
"type": "module",
"exports": {
Expand Down
11 changes: 7 additions & 4 deletions src/agent/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ You run on the BlockRun AI Gateway. When the user asks you to "test the BlockRun
- \`GET /.well-known/x402\` — x402 resource list with prices

**LLM (POST, x402-paid)**
- \`POST /v1/chat/completions\` — OpenAI-compatible. Body: \`{ model, messages, stream?, tools?, max_tokens?, temperature? }\`. \`model\` MUST come from \`GET /v1/models\` (real frontier examples on the gateway, verified live 2026-08-12: \`anthropic/claude-sonnet-5\`, \`anthropic/claude-opus-5\`, \`deepseek/deepseek-v4-pro\`, \`zai/glm-5.2\`, \`xai/grok-4.5\`, \`nvidia/nemotron-nano-9b-v2\` (free)). Do NOT invent versions like \`openai/gpt-5.1\` or \`xai/grok-5\` — those don't exist; the gateway 400s with the valid list in the error body, so when in doubt fetch \`GET /v1/models\` first.
- \`POST /v1/chat/completions\` — OpenAI-compatible. Body: \`{ model, messages, stream?, tools?, max_tokens?, temperature? }\`. \`model\` MUST come from \`GET /v1/models\` (real frontier examples on the gateway, verified live 2026-08-19: \`anthropic/claude-sonnet-5\`, \`anthropic/claude-opus-5\`, \`openai/gpt-5.6-sol\`, \`deepseek/deepseek-v4-pro\`, \`zai/glm-5.3\`, \`xai/grok-4.5\`, \`qwen/qwen3.7-flash\`, \`nvidia/nemotron-nano-9b-v2\` (free)). Do NOT invent versions like \`openai/gpt-5.1\` or \`xai/grok-5\` — those don't exist; the gateway 400s with the valid list in the error body, so when in doubt fetch \`GET /v1/models\` first.
- \`POST /v1/messages\` — Anthropic-compatible. Body: \`{ model, messages, max_tokens, system?, tools? }\`.

**Media (POST, x402-paid; GET to poll async jobs)**
Expand Down Expand Up @@ -560,10 +560,13 @@ export function getModelGuidance(model: string): string {
}

// Medium models: balanced guidance. The bare `qwen` match dates from when
// every qwen id on the gateway was a free NVIDIA SKU — qwen3.7-max is a paid
// 1M-context flagship and belongs in the strong branch below.
// every qwen id on the gateway was a free NVIDIA SKU. The paid Qwen line is
// now Max + Plus + Flash — all 1M-context with reasoning — so only the Max
// flagship graduates to the strong branch; Plus and Flash stay here, and the
// legacy free `nvidia/qwen*` ids keep matching as before.
if (m.includes('kimi') || m.includes('grok') || m.includes('flash') ||
m.includes('haiku') || m.includes('deepseek') ||
m.includes('hy3') || m.includes('mimo') ||
(m.includes('qwen') && !m.includes('qwen3.7-max'))) {
return `# Execution Guidance
- Use tools to verify facts before stating them. Do not answer from memory when a tool can confirm.
Expand All @@ -576,7 +579,7 @@ export function getModelGuidance(model: string): string {
if (m.includes('claude') || m.includes('gpt-5') || m.includes('opus') ||
m.includes('sonnet') || m.includes('gemini-2.5-pro') || m.includes('gemini-3') ||
m.includes('o3') || m.includes('o1') || m.includes('codex') ||
m.includes('qwen3.7-max')) {
m.includes('chat-latest') || m.includes('qwen3.7-max')) {
return `# Quality Standards (strong model)
- Keep calling tools until the task is complete AND the result is verified. Don't stop at "this should work" — prove it works.
- Before finalizing: check correctness, grounding in tool output, and formatting.
Expand Down
1 change: 1 addition & 0 deletions src/pricing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export const MODEL_PRICING: Record<string, { input: number; output: number; perC
'zai/glm-5': { input: 1.0, output: 3.2 }, // flat promo ended 2026-06-06; raised upstream 2026-08-07
'zai/glm-5.1': { input: 1.40, output: 4.40 }, // launch promo ended 2026-06-05 — per-token now
'zai/glm-5.2': { input: 1.40, output: 4.40 }, // new flagship 2026-06 — 1M context, same per-token price as 5.1
'zai/glm-5.3': { input: 1.40, output: 4.40 }, // flagship 2026-08 — 1M context, always-on reasoning, priced at 5.2
'zai/glm-5-turbo': { input: 1.2, output: 4.0 }, // flat promo ended 2026-06-06 — per-token now
'zai/glm-5.1-turbo': { input: 1.2, output: 4.0 }, // client alias for zai/glm-5-turbo
};
Expand Down
52 changes: 37 additions & 15 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,23 @@ function classicRouteRequest(
// that can't be async (proxy, LLM-client bootstrap) keep using the sync
// `routeRequest`, which silently does keyword-only routing.

// llama-4-maverick: clean one-word classification output. glm-4.7 + qwen-
// thinking emit reasoning into thinking blocks and leave text empty under
// tight max_tokens — fine for chat, wrong shape for single-word dispatch.
const CLASSIFIER_MODEL = process.env.FRANKLIN_ROUTER_MODEL || 'nvidia/qwen3-next-80b-a3b-instruct';
// The classifier needs a free model that answers with ONE BARE WORD under a
// tight max_tokens. That is a narrower requirement than "is a good free chat
// model", and most of the free pool fails it by streaming chain-of-thought
// into `content` (glm-4.7 and the qwen-thinking builds emit reasoning and
// leave text empty; nemotron-nano-9b-v2 opens with "Okay, let's see. The user
// wants to…" and never reaches a verdict inside the budget).
//
// 2026-08-19: the previous default, nvidia/qwen3-next-80b-a3b-instruct, was
// EOL'd by NVIDIA (410 on 2026-07-27) — the gateway now rides its calls on
// nemotron-3-super-120b, which leaks prose. Every classification has been
// failing the strict parse and falling through to keyword-only routing ever
// since, silently, because the fallback is by design invisible.
//
// nemotron-3-nano-omni is the replacement: live-probed on this exact prompt
// shape it returns "MEDIUM" and nothing else, and it verifiably serves itself
// rather than riding a pooled substitute.
const CLASSIFIER_MODEL = process.env.FRANKLIN_ROUTER_MODEL || 'nvidia/nemotron-3-nano-omni-30b-a3b-reasoning';
const CLASSIFIER_TIMEOUT_MS = 2_500;

const CLASSIFIER_SYSTEM = `You classify a user's message into ONE routing tier for a CLI agent. Reply with EXACTLY ONE WORD from the allowed set. No explanation, no punctuation, no quotes.
Expand Down Expand Up @@ -771,22 +784,31 @@ export function getFallbackChain(
// verifiably serves ITSELF on the streaming path Franklin uses (verified live
// through the binary today). mistral-nemotron is DEGRADED at NVIDIA — stream
// calls 400 ("DEGRADED function cannot be invoked") and non-stream calls ride
// the gateway's disclosed fallback — so it sits second: it still answers
// non-streaming turns, and it upgrades the chain automatically if NVIDIA
// restores it. step-3.7-flash leaks thinking prose into content, and the 30B
// omni model came back served as nvidia/gpt-oss-120b (the pooled-substitute
// trap this comment already warns about).
// the gateway's disclosed fallback.
// 2026-08-19: nvidia/nemotron-3-nano-omni-30b-a3b-reasoning promoted to
// second. When it was last probed it came back served as gpt-oss-120b — the
// pooled-substitute trap this comment warns about — but NVIDIA has since
// fixed it: it now answers as ITSELF on both the streaming and non-streaming
// paths, and it returns clean single-word output under tight max_tokens (it
// is also the router's classifier for that reason). mistral-nemotron drops to
// third: still DEGRADED at NVIDIA, kept as a genuinely different family for
// the case where both Nemotron nano builds are down. The catalog's fifth free
// id, step-3.7-flash, stays out of every chain — it leaks thinking prose into
// content AND comes back served by nemotron-3-super-120b.
const OMNI = 'nvidia/nemotron-3-nano-omni-30b-a3b-reasoning';

const FREE_MODELS_BY_CATEGORY: Record<Category, string[]> = {
coding: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
trading: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
research: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
reasoning: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
chat: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
creative: ['nvidia/nemotron-nano-9b-v2', 'nvidia/mistral-nemotron'],
coding: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
trading: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
research: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
reasoning: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
chat: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
creative: ['nvidia/nemotron-nano-9b-v2', OMNI, 'nvidia/mistral-nemotron'],
};

const DEFAULT_FREE_CHAIN: string[] = [
'nvidia/nemotron-nano-9b-v2',
OMNI,
'nvidia/mistral-nemotron',
];

Expand Down
3 changes: 2 additions & 1 deletion src/tools/videogen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,11 @@ export function createVideoGenCapability(deps: VideoGenDeps = {}): CapabilityHan
type: 'string',
description:
'Video model. Default: xai/grok-imagine-video ($0.05/s). Known-valid models on the BlockRun gateway as of 2026-08: ' +
'xai/grok-imagine-video, bytedance/seedance-1.5-pro ($0.070/s), bytedance/seedance-2.0-mini ($0.0797/s), ' +
'xai/grok-imagine-video, xai/grok-imagine-video-1.5 ($0.08/s), bytedance/seedance-1.5-pro ($0.070/s), bytedance/seedance-2.0-mini ($0.0797/s), ' +
'bytedance/seedance-2.0-fast ($0.165/s), bytedance/seedance-2.0 ($0.227/s), bytedance/seedance-2.5 ($0.315/s), azure/sora-2 ($0.10/s). ' +
'Pick from this list; the gateway rejects unknown names with HTTP 400 (no money charged on rejection). ' +
'Speak "Seedance" → bytedance/seedance-2.5 (newest flagship); "Seedance Pro" → bytedance/seedance-2.0; ' +
'"Grok video" → xai/grok-imagine-video-1.5 (newer Grok clip model, $0.08/s vs $0.05/s); ' +
'"Seedance fast" → bytedance/seedance-2.0-fast; "Seedance mini" → bytedance/seedance-2.0-mini (cheapest).',
},
image_url: { type: 'string', description: 'Optional seed image (image-to-video). Accepts http(s) URL, data: URI, or local file path — local paths get inlined as base64 data URIs automatically.' },
Expand Down
Loading
Loading