Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879import type { ModelInfo, SessionMessageAssistant, SessionMessageInfo } from "@opencode/client"import { Locale } from "./locale"
type SessionNode = { id: string parentID?: string | null}
export function sessionFamily<T extends SessionNode>(sessions: readonly T[], sessionID: string) { const byID = new Map(sessions.map((session) => [session.id, session])) const current = byID.get(sessionID) if (!current) return []
const children = new Map<string, T[]>() sessions.forEach((session) => { if (!session.parentID) return const group = children.get(session.parentID) if (group) group.push(session) else children.set(session.parentID, [session]) })
function root(session: T): T { const parent = session.parentID ? byID.get(session.parentID) : undefined return parent ? root(parent) : session }
function walk(parentID: string, ancestors: boolean[]): Array<{ session: T; prefix: string }> { const group = children.get(parentID) ?? [] return group.flatMap((session, index) => { const last = index === group.length - 1 const prefix = ancestors.length === 0 ? "" : ancestors .slice(1) .map((ancestor) => (ancestor ? " " : "│ ")) .join("") + (last ? "└─ " : "├─ ") return [{ session, prefix }, ...walk(session.id, [...ancestors, last])] }) }
return walk(root(current).id, [])}
export function lastAssistantWithUsage(messages: ReadonlyArray<SessionMessageInfo>, boundary?: string) { const boundaryIndex = boundary ? messages.findIndex((message) => message.id === boundary) : -1 if (boundary && boundaryIndex === -1) return undefined const end = boundaryIndex === -1 ? messages.length : boundaryIndex const compactionIndex = messages.findLastIndex( (message, index) => message.type === "compaction" && message.status === "completed" && index < end, ) return messages.findLast( (message, index): message is SessionMessageAssistant & { tokens: NonNullable<SessionMessageAssistant["tokens"]> } => message.type === "assistant" && message.tokens !== undefined && index > compactionIndex && index < end, )}
export function contextUsage( messages: ReadonlyArray<SessionMessageInfo>, models: ReadonlyArray<ModelInfo> | undefined, boundary?: string,) { const last = lastAssistantWithUsage(messages, boundary) if (!last) return const tokens = last.tokens.input + last.tokens.output + last.tokens.reasoning + last.tokens.cache.read + last.tokens.cache.write if (tokens <= 0) return const model = models?.find((model) => model.providerID === last.model.providerID && model.id === last.model.id) return { tokens, percent: model?.limit.context ? Math.round((tokens / model.limit.context) * 100) : undefined, }}
export function formatContextUsage(tokens: number, percent?: number) { const value = Locale.number(tokens) return percent === undefined ? value : `${value} (${percent}%)`}