import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent"; import type { EventInput, HarnessEventType } from "@agent-studio/shared"; import { reportArtifactSchema } from "@agent-studio/shared"; import { redactValue } from "./errors.js"; export interface PiAdapterContext { runId: string; assistantMessageId: string } export type MappedEvent = { [T in HarnessEventType]: EventInput }[HarnessEventType]; export function mapPiEvent(event: AgentSessionEvent, context: PiAdapterContext): MappedEvent[] { switch (event.type) { case "message_update": if (event.assistantMessageEvent.type === "text_delta") return [{ type: "assistant.delta", runId: context.runId, payload: { messageId: context.assistantMessageId, delta: event.assistantMessageEvent.delta } }]; return []; case "message_end": if (event.message.role === "assistant") return [{ type: "assistant.completed", runId: context.runId, payload: { messageId: context.assistantMessageId } }]; return []; case "tool_execution_start": return [{ type: "tool.requested", runId: context.runId, payload: { toolCallId: event.toolCallId, toolName: event.toolName, arguments: event.toolName === "render_swads_daily_report" ? { status: "requested" } : redactValue(event.args) } }]; case "tool_execution_end": { if (!event.isError && event.toolName === "render_swads_daily_report") { const details = (event.result as { details?: unknown })?.details; const wrapped = details && typeof details === "object" && !Array.isArray(details) ? details as Record : {}; const artifact = reportArtifactSchema.safeParse(wrapped.artifact ?? details); const markdown = typeof wrapped.markdown === "string" ? wrapped.markdown.slice(0, 6_000) : undefined; if (artifact.success) return [ { type: "tool.completed", runId: context.runId, payload: { toolCallId: event.toolCallId, toolName: event.toolName, result: artifact.data } }, { type: "report.generated", runId: context.runId, payload: { assistantMessageId: context.assistantMessageId, artifact: artifact.data, ...(markdown ? { markdown } : {}) } }, ]; return [{ type: "tool.failed", runId: context.runId, payload: { toolCallId: event.toolCallId, toolName: event.toolName, error: "SWADS_INVALID_REPORT" } }]; } return event.isError ? [{ type: "tool.failed", runId: context.runId, payload: { toolCallId: event.toolCallId, toolName: event.toolName, error: toolFailure(event.result) } }] : [{ type: "tool.completed", runId: context.runId, payload: { toolCallId: event.toolCallId, toolName: event.toolName, result: summarizeToolResult(event.toolName, event.result) } }]; } default: return []; } } function summarizeToolResult(toolName: string, result: unknown): unknown { if (["read", "grep", "find", "ls"].includes(toolName)) return { status: "success" }; if (toolName === "swads_cli") return redactValue((result as { details?: unknown })?.details ?? { status: "success" }); return redactValue(result); } function toolFailure(result: unknown): string { const content = (result as { content?: Array<{ type?: string; text?: string }> } | null)?.content; const text = content?.filter((item) => item.type === "text").map((item) => item.text ?? "").join(" ") ?? ""; const codes = ["NO_DATA", "NOT_CONFIGURED", "INVALID_CONFIG", "INVALID_ARGUMENTS", "AUTH_FAILED", "FORBIDDEN", "TOOL_MISSING", "TOOL_DRIFT", "NOT_READ_ONLY", "CAPABILITY_MISSING", "INVALID_RESPONSE", "UPSTREAM_ERROR", "RESPONSE_TOO_LARGE", "TIMEOUT", "ABORTED", "UNAVAILABLE", "PREFLIGHT_REQUIRED", "INVALID_REPORT", "REPORT_FAILED"]; return codes.map((code) => `SWADS_${code}`).find((code) => text === code || text === `Error: ${code}`) ?? "Tool execution failed"; }