106 lines · 3.9 KB · TypeScript
RawDownload
import type {  OrchestrationV2ProjectedTurnItem,  OrchestrationV2ProviderCapabilities,  OrchestrationV2ThreadProjection,} from "@t3tools/contracts";import { copySorted } from "@t3tools/shared/Array"; type Projection = OrchestrationV2ThreadProjection;type Run = Projection["runs"][number];type ProviderSession = Projection["providerSessions"][number]; const ACTIVE_RUN_STATUSES = new Set<Run["status"]>(["preparing", "starting", "running", "waiting"]); export interface QueuedThreadRun {  readonly run: Run;  readonly text: string;} export interface ThreadQueueWorkflowState {  readonly activeRun: Run | null;  readonly queuedRuns: ReadonlyArray<QueuedThreadRun>;  readonly canReorder: boolean;  readonly canPromoteToSteer: boolean;} export function resolveActiveThreadRun(projection: Projection): Run | null {  return projection.runs.findLast((run) => ACTIVE_RUN_STATUSES.has(run.status)) ?? null;} export function resolveThreadProviderSession(projection: Projection): ProviderSession | null {  const activeRun = resolveActiveThreadRun(projection);  const providerThreadId = activeRun?.providerThreadId ?? projection.thread.activeProviderThreadId;  const activeProviderThread =    providerThreadId === null      ? null      : (projection.providerThreads.find((thread) => thread.id === providerThreadId) ?? null);  const attachedProviderThread =    activeProviderThread ??    projection.providerThreads.find(      (thread) => thread.appThreadId === projection.thread.id && thread.providerSessionId !== null,    ) ??    null;  const sessionId = attachedProviderThread?.providerSessionId ?? null;  if (sessionId !== null) {    return projection.providerSessions.find((session) => session.id === sessionId) ?? null;  }  return (    projection.providerSessions.findLast(      (session) => session.status !== "stopped" && session.status !== "error",    ) ?? null  );} export function deriveThreadQueueWorkflowState(projection: Projection): ThreadQueueWorkflowState {  const activeRun = resolveActiveThreadRun(projection);  const session = resolveThreadProviderSession(projection);  const capabilities = session?.capabilities.turns;  const queuedRuns = copySorted(    projection.runs.filter((run) => run.status === "queued"),    (left, right) =>      (left.queuePosition ?? left.ordinal) - (right.queuePosition ?? right.ordinal) ||      left.ordinal - right.ordinal,  ).map((run) => ({    run,    text:      projection.messages.find((message) => message.id === run.userMessageId)?.text ??      "Queued message",  }));   return {    activeRun,    queuedRuns,    canReorder: capabilities?.supportsQueuedMessages === true,    canPromoteToSteer:      activeRun !== null &&      (capabilities?.supportsActiveSteering === true ||        capabilities?.supportsSteeringByInterruptRestart === true),  };} export function canForkProjectedAssistantItem(input: {  readonly projectedItem: OrchestrationV2ProjectedTurnItem;  readonly capabilities?: OrchestrationV2ProviderCapabilities | undefined;}): boolean {  const item = input.projectedItem.item;  if (item.type !== "assistant_message" || item.runId === null || item.status !== "completed") {    return false;  }  if (input.capabilities === undefined) {    // Historical and inherited rows may outlive their provider-session record.    // Keep the portable server-side fallback available when capability evidence    // is absent; a known incapable provider is rejected below.    return true;  }  const capabilities = input.capabilities;  const canForkNatively =    capabilities.threads.canForkThread &&    capabilities.threads.canForkFromTurn &&    capabilities.identity.nativeThreadIds === "strong";  return canForkNatively || capabilities.context.supportsFullThreadHandoff;} export function canDetachThreadProviderSession(projection: Projection): boolean {  const session = resolveThreadProviderSession(projection);  return session !== null && session.status !== "stopped" && session.status !== "error";}