refactor: extend media understanding

This commit is contained in:
Peter Steinberger
2026-01-17 07:17:09 +00:00
parent 86a46874da
commit 0c0e1e4226
16 changed files with 674 additions and 550 deletions

View File

@@ -24,6 +24,7 @@ import { VERSION } from "../version.js";
import { listChatCommands, listChatCommandsForConfig } from "./commands-registry.js";
import type { SkillCommandSpec } from "../agents/skills.js";
import type { ElevatedLevel, ReasoningLevel, ThinkLevel, VerboseLevel } from "./thinking.js";
import type { MediaUnderstandingDecision } from "../media-understanding/types.js";
type AgentConfig = Partial<NonNullable<NonNullable<ClawdbotConfig["agents"]>["defaults"]>>;
@@ -52,6 +53,7 @@ type StatusArgs = {
modelAuth?: string;
usageLine?: string;
queue?: QueueStatus;
mediaDecisions?: MediaUnderstandingDecision[];
includeTranscriptUsage?: boolean;
now?: number;
};
@@ -167,6 +169,42 @@ const formatUsagePair = (input?: number | null, output?: number | null) => {
return `🧮 Tokens: ${inputLabel} in / ${outputLabel} out`;
};
const formatMediaUnderstandingLine = (decisions?: MediaUnderstandingDecision[]) => {
if (!decisions || decisions.length === 0) return null;
const parts = decisions
.map((decision) => {
const count = decision.attachments.length;
const countLabel = count > 1 ? ` x${count}` : "";
if (decision.outcome === "success") {
const chosen = decision.attachments.find((entry) => entry.chosen)?.chosen;
const provider = chosen?.provider?.trim();
const model = chosen?.model?.trim();
const modelLabel = provider ? (model ? `${provider}/${model}` : provider) : null;
return `${decision.capability}${countLabel} ok${modelLabel ? ` (${modelLabel})` : ""}`;
}
if (decision.outcome === "no-attachment") {
return `${decision.capability} none`;
}
if (decision.outcome === "disabled") {
return `${decision.capability} off`;
}
if (decision.outcome === "scope-deny") {
return `${decision.capability} denied`;
}
if (decision.outcome === "skipped") {
const reason = decision.attachments
.flatMap((entry) => entry.attempts.map((attempt) => attempt.reason).filter(Boolean))
.find(Boolean);
const shortReason = reason ? reason.split(":")[0]?.trim() : undefined;
return `${decision.capability} skipped${shortReason ? ` (${shortReason})` : ""}`;
}
return null;
})
.filter(Boolean);
if (parts.length === 0) return null;
return `📎 Media: ${parts.join(" · ")}`;
};
export function buildStatusMessage(args: StatusArgs): string {
const now = args.now ?? Date.now();
const entry = args.sessionEntry;
@@ -320,12 +358,14 @@ export function buildStatusMessage(args: StatusArgs): string {
const costLine = costLabel ? `💵 Cost: ${costLabel}` : null;
const usageCostLine =
usagePair && costLine ? `${usagePair} · ${costLine}` : (usagePair ?? costLine);
const mediaLine = formatMediaUnderstandingLine(args.mediaDecisions);
return [
versionLine,
modelLine,
usageCostLine,
`📚 ${contextLine}`,
mediaLine,
args.usageLine,
`🧵 ${sessionLine}`,
`⚙️ ${optionsLine}`,