Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import type { AgentActivityInteraction } from "@tutti-os/agent-activity-core";
|
|
import type { AgentConversationPromptVM } from "../contracts/agentConversationVM";
|
|
import { normalizeAgentApprovalPurpose } from "../agentApprovalPurpose";
|
|
import { normalizeAskUserQuestions } from "../askUserQuestions";
|
|
import {
|
|
extractExitPlanKeepPlanningOptionId,
|
|
extractExitPlanModeOptions
|
|
} from "../exitPlanOptions";
|
|
import { normalizeAgentApprovalOptions } from "./agentApprovalProjection";
|
|
|
|
type ApprovalPrompt = Extract<AgentConversationPromptVM, { kind: "approval" }>;
|
|
type InteractivePrompt = Exclude<
|
|
AgentConversationPromptVM,
|
|
ApprovalPrompt | { kind: "plan-implementation" }
|
|
>;
|
|
|
|
export function projectAgentConversationPromptFromInteraction(
|
|
interaction: AgentActivityInteraction
|
|
): ApprovalPrompt | InteractivePrompt | null {
|
|
return interaction.kind === "approval"
|
|
? projectAgentApprovalPromptFromInteraction(interaction)
|
|
: projectAgentInteractivePromptFromInteraction(interaction);
|
|
}
|
|
|
|
export function projectAgentApprovalPromptFromInteraction(
|
|
interaction: AgentActivityInteraction | null
|
|
): ApprovalPrompt | null {
|
|
if (!interaction || interaction.kind !== "approval") return null;
|
|
const callId =
|
|
typeof interaction.input?.callId === "string" &&
|
|
interaction.input.callId.trim()
|
|
? interaction.input.callId.trim()
|
|
: interaction.requestId.trim();
|
|
const options = normalizeAgentApprovalOptions(interaction.input?.options);
|
|
if (!callId || options.length === 0) return null;
|
|
const approvalPurpose = normalizeAgentApprovalPurpose(
|
|
interaction.metadata?.approvalPurpose
|
|
);
|
|
return {
|
|
kind: "approval",
|
|
id: `approval:${callId}`,
|
|
agentSessionId: interaction.agentSessionId,
|
|
turnId: interaction.turnId,
|
|
requestId: interaction.requestId,
|
|
callId,
|
|
...(approvalPurpose ? { approvalPurpose } : {}),
|
|
title: interaction.toolName?.trim() || "",
|
|
status: "waiting_approval",
|
|
toolName: interaction.toolName?.trim() || null,
|
|
input: interaction.input ?? null,
|
|
options,
|
|
output: interaction.output ?? null,
|
|
occurredAtUnixMs: interaction.createdAtUnixMs
|
|
};
|
|
}
|
|
|
|
export function projectAgentInteractivePromptFromInteraction(
|
|
interaction: AgentActivityInteraction | null
|
|
): InteractivePrompt | null {
|
|
if (!interaction || interaction.kind === "approval") return null;
|
|
const toolName = normalizeInteractiveToolName(
|
|
interaction.toolName ?? undefined
|
|
);
|
|
if (interaction.kind === "plan" || toolName === "exitplanmode") {
|
|
const keepPlanningOptionId = extractExitPlanKeepPlanningOptionId(
|
|
interaction.input
|
|
);
|
|
return {
|
|
kind: "exit-plan",
|
|
agentSessionId: interaction.agentSessionId,
|
|
turnId: interaction.turnId,
|
|
requestId: interaction.requestId,
|
|
title: interaction.toolName?.trim() || "",
|
|
options: extractExitPlanModeOptions(interaction.input),
|
|
...(keepPlanningOptionId ? { keepPlanningOptionId } : {})
|
|
};
|
|
}
|
|
if (interaction.kind !== "question" || toolName !== "askuserquestion") {
|
|
return null;
|
|
}
|
|
const questions = normalizeAskUserQuestions(interaction.input?.questions, {
|
|
missingText: ""
|
|
});
|
|
return questions.length > 0
|
|
? {
|
|
kind: "ask-user",
|
|
agentSessionId: interaction.agentSessionId,
|
|
turnId: interaction.turnId,
|
|
requestId: interaction.requestId,
|
|
title: interaction.toolName?.trim() || "",
|
|
questions
|
|
}
|
|
: null;
|
|
}
|
|
|
|
function normalizeInteractiveToolName(toolName: string | undefined): string {
|
|
return (toolName?.trim() ?? "").replace(/[_\s-]+/g, "").toLowerCase();
|
|
}
|