From efe85ddfddad780e377cdea67574a316db55b59c Mon Sep 17 00:00:00 2001 From: 1bcMax <195689928+1bcMax@users.noreply.github.com> Date: Thu, 18 Jun 2026 09:52:17 -0400 Subject: [PATCH] feat(imagegen): pure price-math spend confirm + CHANGELOG for #86 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ImageGen had no spend confirmation after the media-router removal (#86) — the router proposal was its only AskUser path. Add a pure price-math, model-aware Generate/Cancel confirm (parity with VideoGen): interactive callers see the model + estimated cost before any USDC is spent; direct callers (desktop, no onAskUser) generate immediately. Also document #86 in the CHANGELOG (3.29.4), including the upgrade note that cloud sync is now opt-in (FRANKLIN_CLOUD_SYNC=on). --- CHANGELOG.md | 9 +++++++++ package-lock.json | 4 ++-- package.json | 2 +- src/tools/imagegen.ts | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) 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