diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a02ecb..51367c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## Franklin Agent 3.29.4 — pure media tools, image spend confirm, local-first by default + +ImageGen and VideoGen no longer make a second LLM call to a free "media router" that rewrote the prompt and picked a model — that call ran on a free NVIDIA model and hit the gateway's 120s provider timeout, which is why *video generation appeared broken* to customers (the Seedance → token360 pipeline itself was fine). The tools now use exactly the model + prompt the caller gives. + +- **Pure image/video tools.** Deleted `src/agent/media-router.ts` and its tests. No more LLM prompt-rewriting or model "routing" inside the tools — the UI / agent decides those upstream. +- **VideoGen keeps a pure price-math cost confirm** (no LLM) when an `onAskUser` bridge exists (CLI / agent); direct callers (desktop) generate immediately. The estimate is now **model-aware** (`findModel` + `estimateCostUsd`) so the quoted price matches the model named in the prompt, falling back to the flat per-second rate only for unknown models. +- **ImageGen now confirms spend too.** Same pure price-math, model-aware Generate/Cancel confirm (parity with video): interactive callers see the model + estimated cost before any USDC is spent; direct callers generate straight away (the explicit "generate" action is consent). +- **Cloud sync is now opt-in** (`FRANKLIN_CLOUD_SYNC=on`) instead of default-on, so the desktop is local-first like Claude Code / Codex — conversation history stays on disk and is not uploaded to franklin.run unless you opt in. **Upgrade note:** users who relied on cross-device sync must set `FRANKLIN_CLOUD_SYNC=on` to keep it; `=off` is no longer needed to stay local. + ## Franklin Agent 3.29.3 — promote GLM flagship 5.1 → 5.2 (1M context) Z.AI shipped GLM-5.2 and the gateway now serves it (verified live on `GET /v1/models`). 5.2 is the new flagship: 1M-token context (up from 200K on 5.1), top open-source on long-horizon coding, same per-token price as 5.1 ($1.4/$4.4). diff --git a/package-lock.json b/package-lock.json index 9fda7fa..809cc26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@blockrun/franklin", - "version": "3.29.2", + "version": "3.29.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@blockrun/franklin", - "version": "3.29.2", + "version": "3.29.4", "license": "Apache-2.0", "dependencies": { "@blockrun/llm": "^2.0.0", diff --git a/package.json b/package.json index add40d6..f1b21c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@blockrun/franklin", - "version": "3.29.3", + "version": "3.29.4", "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": { diff --git a/src/tools/imagegen.ts b/src/tools/imagegen.ts index ab27f98..e1dd28a 100644 --- a/src/tools/imagegen.ts +++ b/src/tools/imagegen.ts @@ -309,6 +309,25 @@ function buildExecute(deps: ImageGenDeps) { } } + // Confirm the spend before the paid call (parity with VideoGen). Pure price + // math — no LLM. Interactive callers (CLI / agent) get a prompt via + // onAskUser; direct callers (e.g. the desktop media path) pass no onAskUser + // and generate straight away — the explicit "generate" action is consent. + const autoApprove = process.env.FRANKLIN_MEDIA_AUTO_APPROVE_ALL === '1'; + if (!autoApprove && ctx.onAskUser) { + const m = await findModel(imageModel); + const est = m ? estimateCostUsd(m, { quantity: n }) : 0; + const priceNote = est > 0 ? ` for ~$${est.toFixed(2)}` : ''; + const countNote = n > 1 ? `${n} images` : 'an image'; + const answer = await ctx.onAskUser( + `Generate ${countNote} with ${imageModel}${priceNote}? No USDC is spent if you cancel.`, + ['Generate', 'Cancel'], + ); + if (answer !== 'Generate') { + return { output: `## Image generation cancelled\n\nNo USDC was spent.` }; + } + } + // Resolve all reference images + the mask into base64 data URIs now, right // before the paid call. Done after the cheap validations so bad paths / // oversize attachments / unsupported combinations fail without any network