234 lines · 6.5 KB · TypeScript
RawDownload
import {  type RuntimeEventRawSource,  RuntimeItemId,  type CanonicalRequestType,  type EventId,  type ProviderApprovalDecision,  type ProviderApprovalOption,  type ProviderDriverKind,  type ProviderRuntimeEvent,  type RuntimeRequestId,  type ThreadId,  type TurnId,} from "@t3tools/contracts"; import {  type AcpPermissionRequest,  type AcpPlanUpdate,  type AcpToolCallState,  canonicalItemTypeFromAcpToolKind,} from "./AcpRuntimeModel.ts"; type AcpAdapterRawSource = Extract<  RuntimeEventRawSource,  "acp.jsonrpc" | `acp.${string}.extension`>; interface AcpEventStamp {  readonly eventId: EventId;  readonly createdAt: string;} type AcpCanonicalRequestType = Extract<  CanonicalRequestType,  "exec_command_approval" | "file_read_approval" | "file_change_approval" | "dynamic_tool_call">; function canonicalRequestTypeFromAcpKind(kind: string | "unknown"): AcpCanonicalRequestType {  switch (kind) {    case "execute":      return "exec_command_approval";    case "read":      return "file_read_approval";    case "edit":    case "delete":    case "move":      return "file_change_approval";    default:      return "dynamic_tool_call";  }} function runtimeItemStatusFromAcpToolStatus(  status: AcpToolCallState["status"],): "inProgress" | "completed" | "failed" | undefined {  switch (status) {    case "pending":    case "inProgress":      return "inProgress";    case "completed":      return "completed";    case "failed":      return "failed";    default:      return undefined;  }} export function makeAcpRequestOpenedEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly requestId: RuntimeRequestId;  readonly permissionRequest: AcpPermissionRequest;  readonly approvalOptions?: ReadonlyArray<ProviderApprovalOption>;  readonly detail: string;  readonly args: unknown;  readonly source: AcpAdapterRawSource;  readonly method: string;  readonly rawPayload: unknown;}): ProviderRuntimeEvent {  return {    type: "request.opened",    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    requestId: input.requestId,    payload: {      requestType: canonicalRequestTypeFromAcpKind(input.permissionRequest.kind),      detail: input.detail,      args: input.args,      ...(input.approvalOptions !== undefined ? { options: input.approvalOptions } : {}),    },    raw: {      source: input.source,      method: input.method,      payload: input.rawPayload,    },  };} export function makeAcpRequestResolvedEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly requestId: RuntimeRequestId;  readonly permissionRequest: AcpPermissionRequest;  readonly decision: ProviderApprovalDecision;}): ProviderRuntimeEvent {  return {    type: "request.resolved",    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    requestId: input.requestId,    payload: {      requestType: canonicalRequestTypeFromAcpKind(input.permissionRequest.kind),      decision: input.decision,    },  };} export function makeAcpPlanUpdatedEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly payload: AcpPlanUpdate;  readonly source: AcpAdapterRawSource;  readonly method: string;  readonly rawPayload: unknown;}): ProviderRuntimeEvent {  return {    type: "turn.plan.updated",    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    payload: input.payload,    raw: {      source: input.source,      method: input.method,      payload: input.rawPayload,    },  };} export function makeAcpToolCallEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly toolCall: AcpToolCallState;  readonly rawPayload: unknown;}): ProviderRuntimeEvent {  const runtimeStatus = runtimeItemStatusFromAcpToolStatus(input.toolCall.status);  return {    type:      input.toolCall.status === "completed" || input.toolCall.status === "failed"        ? "item.completed"        : "item.updated",    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    itemId: RuntimeItemId.make(input.toolCall.toolCallId),    payload: {      itemType: canonicalItemTypeFromAcpToolKind(input.toolCall.kind),      ...(runtimeStatus ? { status: runtimeStatus } : {}),      ...(input.toolCall.title ? { title: input.toolCall.title } : {}),      ...(input.toolCall.detail ? { detail: input.toolCall.detail } : {}),      ...(Object.keys(input.toolCall.data).length > 0 ? { data: input.toolCall.data } : {}),    },    raw: {      source: "acp.jsonrpc",      method: "session/update",      payload: input.rawPayload,    },  };} export function makeAcpAssistantItemEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly itemId: string;  readonly lifecycle: "item.started" | "item.completed";}): ProviderRuntimeEvent {  return {    type: input.lifecycle,    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    itemId: RuntimeItemId.make(input.itemId),    payload: {      itemType: "assistant_message",      status: input.lifecycle === "item.completed" ? "completed" : "inProgress",    },  };} export function makeAcpContentDeltaEvent(input: {  readonly stamp: AcpEventStamp;  readonly provider: ProviderDriverKind;  readonly threadId: ThreadId;  readonly turnId: TurnId | undefined;  readonly itemId?: string;  readonly streamKind?: "assistant_text" | "reasoning_text";  readonly text: string;  readonly rawPayload: unknown;}): ProviderRuntimeEvent {  return {    type: "content.delta",    ...input.stamp,    provider: input.provider,    threadId: input.threadId,    turnId: input.turnId,    ...(input.itemId ? { itemId: RuntimeItemId.make(input.itemId) } : {}),    payload: {      streamKind: input.streamKind ?? "assistant_text",      delta: input.text,    },    raw: {      source: "acp.jsonrpc",      method: "session/update",      payload: input.rawPayload,    },  };}