122 lines · 4.0 KB · TypeScript
RawDownload
import type {  OrchestrationV2ProviderTurnTokenUsage,  OrchestrationV2TurnItem,  ThreadTokenUsageSnapshot,} from "@t3tools/contracts";import * as DateTime from "effect/DateTime"; function asFiniteNumber(value: unknown): number | null {  return typeof value === "number" && Number.isFinite(value) ? value : null;} type NullableContextWindowUsage = {  readonly [Key in keyof ThreadTokenUsageSnapshot]: undefined extends ThreadTokenUsageSnapshot[Key]    ? Exclude<ThreadTokenUsageSnapshot[Key], undefined> | null    : ThreadTokenUsageSnapshot[Key];}; export type ContextWindowSnapshot = NullableContextWindowUsage & {  readonly remainingTokens: number | null;  readonly usedPercentage: number | null;  readonly remainingPercentage: number | null;  readonly updatedAt: string;}; /** Prefers the provider's live usage report (#8144); falls back to the last compaction item. */export function deriveLatestContextWindowSnapshot(  entries: ReadonlyArray<{    readonly item: OrchestrationV2TurnItem;  }>,  liveUsage?: OrchestrationV2ProviderTurnTokenUsage | null,): ContextWindowSnapshot | null {  if (liveUsage != null) {    const usedTokens = Math.max(0, liveUsage.usedTokens);    const maxTokens = liveUsage.maxTokens ?? null;    const usedPercentage =      maxTokens !== null && maxTokens > 0 ? Math.min(100, (usedTokens / maxTokens) * 100) : null;    const remainingTokens =      maxTokens !== null ? Math.max(0, Math.round(maxTokens - usedTokens)) : null;    const remainingPercentage = usedPercentage !== null ? Math.max(0, 100 - usedPercentage) : null;    return {      usedTokens,      totalProcessedTokens: null,      maxTokens,      remainingTokens,      usedPercentage,      remainingPercentage,      inputTokens: liveUsage.inputTokens ?? null,      cachedInputTokens: liveUsage.cachedInputTokens ?? null,      outputTokens: liveUsage.outputTokens ?? null,      reasoningOutputTokens: liveUsage.reasoningOutputTokens ?? null,      lastUsedTokens: null,      lastInputTokens: null,      lastCachedInputTokens: null,      lastOutputTokens: null,      lastReasoningOutputTokens: null,      toolUses: null,      durationMs: null,      compactsAutomatically: true,      autoCompactThreshold: null,      updatedAt: liveUsage.updatedAt,    };  }  for (let index = entries.length - 1; index >= 0; index -= 1) {    const entry = entries[index];    if (!entry || entry.item.type !== "compaction") {      continue;    }    const payload = entry.item;    const usedTokens = asFiniteNumber(payload.afterTokenCount);    if (usedTokens === null || usedTokens < 0) {      continue;    }     const maxTokens = null;    const usedPercentage =      maxTokens !== null && maxTokens > 0 ? Math.min(100, (usedTokens / maxTokens) * 100) : null;    const remainingTokens =      maxTokens !== null ? Math.max(0, Math.round(maxTokens - usedTokens)) : null;    const remainingPercentage = usedPercentage !== null ? Math.max(0, 100 - usedPercentage) : null;     return {      usedTokens,      totalProcessedTokens: asFiniteNumber(payload.beforeTokenCount),      maxTokens,      remainingTokens,      usedPercentage,      remainingPercentage,      inputTokens: null,      cachedInputTokens: null,      outputTokens: null,      reasoningOutputTokens: null,      lastUsedTokens: null,      lastInputTokens: null,      lastCachedInputTokens: null,      lastOutputTokens: null,      lastReasoningOutputTokens: null,      toolUses: null,      durationMs: null,      compactsAutomatically: true,      autoCompactThreshold: null,      updatedAt: DateTime.formatIso(payload.startedAt ?? payload.updatedAt),    };  }   return null;} export function formatContextWindowTokens(value: number | null): string {  if (value === null || !Number.isFinite(value)) {    return "0";  }  if (value < 1_000) {    return `${Math.round(value)}`;  }  if (value < 10_000) {    return `${(value / 1_000).toFixed(1).replace(/\.0$/, "")}k`;  }  if (value < 1_000_000) {    return `${Math.round(value / 1_000)}k`;  }  return `${(value / 1_000_000).toFixed(1).replace(/\.0$/, "")}m`;}