Skip to content
Merged
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
16 changes: 16 additions & 0 deletions src/tools/imagegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import type { ContentLibrary } from '../content/library.js';
import { checkImageBudget, recordImageAsset } from '../content/record-image.js';
import { ModelClient } from '../agent/llm.js';
import { analyzeMediaRequest, renderProposalForAskUser } from '../agent/media-router.js';
import { recordUsage } from '../stats/tracker.js';
import { findModel, estimateCostUsd } from '../gateway-models.js';

interface ImageGenInput {
prompt: string;
Expand Down Expand Up @@ -220,6 +222,20 @@ function buildExecute(deps: ImageGenDeps) {
const sizeKB = (fileSize / 1024).toFixed(1);
const revisedPrompt = imageData.revised_prompt ? `\nRevised prompt: ${imageData.revised_prompt}` : '';

// Stats: record this generation so it shows up in `franklin insights`
// alongside chat spend. Before this, media generations bypassed
// recordUsage entirely (only LLM chat calls were tracked), so the
// insights panel under-reported total spend and never surfaced
// image-generation models in its "top models" list. Fire-and-forget —
// stats write must not fail a user-visible generation.
void (async () => {
try {
const m = await findModel(imageModel);
const estCost = m ? estimateCostUsd(m, { quantity: 1 }) : 0;
recordUsage(imageModel, 0, 0, estCost, 0);
} catch { /* ignore stats errors */ }
})();

let contentSummary = '';
if (contentId && deps.library) {
const rec = recordImageAsset(deps.library, {
Expand Down
17 changes: 17 additions & 0 deletions src/tools/videogen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { loadChain, API_URLS, VERSION } from '../config.js';
import type { ContentLibrary } from '../content/library.js';
import { ModelClient } from '../agent/llm.js';
import { analyzeMediaRequest, renderProposalForAskUser } from '../agent/media-router.js';
import { recordUsage } from '../stats/tracker.js';
import { findModel, estimateCostUsd } from '../gateway-models.js';

interface VideoGenInput {
prompt: string;
Expand Down Expand Up @@ -290,6 +292,21 @@ function buildExecute(deps: VideoGenDeps) {
const sizeMB = (fileSize / 1_048_576).toFixed(1);
const dur = videoData.duration_seconds ?? duration;

// Stats: record this generation so it shows up in `franklin insights`
// alongside chat spend. Before this, media generations bypassed
// recordUsage entirely, so the insights panel under-reported total
// spend and never surfaced video models in its "top models" list.
// Prefer the live gateway price when the model is in the catalog;
// fall back to the legacy $0.05/s estimate otherwise. Fire-and-
// forget — stats write must not fail a user-visible generation.
void (async () => {
try {
const m = await findModel(videoModel);
const estCost = m ? estimateCostUsd(m, { duration_seconds: dur }) : estimateVideoCostUsd(dur);
recordUsage(videoModel, 0, 0, estCost, 0);
} catch { /* ignore stats errors */ }
})();

let contentSummary = '';
if (contentId && deps.library) {
const rec = deps.library.addAsset(contentId, {
Expand Down
Loading