import type { OrchestrationV2ThreadProjection, ProviderRequestKind, RuntimeRequestId, } from "@t3tools/contracts"; import * as DateTime from "effect/DateTime"; export interface ThreadPendingApproval { readonly requestId: RuntimeRequestId; readonly requestKind: ProviderRequestKind; readonly createdAt: string; readonly detail?: string; readonly responseCapability: "live" | "not_resumable"; } export interface ThreadUserInputQuestion { readonly id: string; readonly header: string; readonly question: string; readonly options: ReadonlyArray<{ readonly label: string; readonly description: string; }>; readonly multiSelect: boolean; } export interface ThreadPendingUserInput { readonly requestId: RuntimeRequestId; readonly createdAt: string; readonly questions: ReadonlyArray; readonly responseCapability: "live" | "not_resumable"; } export interface PendingThreadRequests { readonly approvals: ReadonlyArray; readonly userInputs: ReadonlyArray; } /** Joins pending request entities to the request items that carry display data. */ export function derivePendingThreadRequests( projection: OrchestrationV2ThreadProjection, ): PendingThreadRequests { const approvals: ThreadPendingApproval[] = []; const userInputs: ThreadPendingUserInput[] = []; for (const request of projection.runtimeRequests) { if (request.status !== "pending") continue; const responseCapability = request.responseCapability.type; if (request.kind === "user_input") { const item = projection.turnItems.findLast( (candidate) => candidate.type === "user_input_request" && candidate.requestId === request.id, ); if (item === undefined || item.type !== "user_input_request") continue; userInputs.push({ requestId: request.id, createdAt: DateTime.formatIso(request.createdAt), questions: item.questions.map((question) => ({ ...question, multiSelect: false })), responseCapability, }); continue; } if (request.kind === "auth_refresh" || request.kind === "dynamic_tool_call") continue; const item = projection.turnItems.findLast( (candidate) => candidate.type === "approval_request" && candidate.requestId === request.id, ); approvals.push({ requestId: request.id, requestKind: request.kind, createdAt: DateTime.formatIso(request.createdAt), ...(item?.type === "approval_request" && item.prompt ? { detail: item.prompt } : {}), responseCapability, }); } return { approvals, userInputs }; }