52 lines
3.7 KiB
TypeScript
52 lines
3.7 KiB
TypeScript
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<T> }[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<string, unknown> : {};
|
|
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";
|
|
}
|