Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

105 lines
3.1 KiB
TypeScript

import type { WorkspaceAgentSessionDetailToolCall } from "../../workspaceAgentSessionDetailViewModel";
import { extractAgentMcpToolTarget } from "../../agentMcpToolTarget";
import { normalizeAgentApprovalPurpose } from "../agentApprovalPurpose";
import type {
AgentApprovalItemVM,
AgentApprovalOptionVM
} from "../contracts/agentApprovalItemVM";
import { isExitPlanSwitchModeInput } from "../exitPlanOptions";
export function projectAgentApprovalItem(
call: WorkspaceAgentSessionDetailToolCall,
input: Record<string, unknown> | null,
output: Record<string, unknown> | null
): AgentApprovalItemVM | null {
const callType = normalizeToken(call.callType);
const toolName = normalizeToken(call.toolName);
if (callType !== "approval" && toolName !== "approval") {
return null;
}
const requestId =
stringValue(input?.requestId) ??
stringValue(call.payload?.requestId) ??
stringValue(output?.requestId);
if (!requestId) {
return null;
}
const options = normalizeAgentApprovalOptions(
input?.options ?? call.payload?.options
);
if (isExitPlanSwitchModeInput(input)) {
return null;
}
const mcpTarget = extractAgentMcpToolTarget({
input,
payload: call.payload,
toolName: call.toolName,
name: call.name
});
const approvalPurpose = normalizeAgentApprovalPurpose(
call.payload?.approvalPurpose
);
return {
kind: "approval",
id: call.id,
turnId: call.turnId ?? "turn:unknown",
requestId,
callId: call.id.replace(/^call:/, ""),
...(approvalPurpose ? { approvalPurpose } : {}),
title: mcpTarget?.displayName ?? (call.summary.trim() || call.name),
toolName: call.toolName,
status: stringValue(call.payload?.status) ?? call.status,
input,
options,
output,
occurredAtUnixMs: call.occurredAtUnixMs ?? null
};
}
export function normalizeAgentApprovalOptions(
value: unknown
): AgentApprovalOptionVM[] {
const values = arrayValue(value) ?? [];
return values.flatMap((value) => {
const option = objectValue(value);
const id = stringValue(option?.optionId) ?? stringValue(option?.id);
if (!id) {
return [];
}
const label =
stringValue(option?.name) ??
stringValue(option?.label) ??
stringValue(option?.title) ??
stringValue(option?.kind) ??
id;
return [
{
id,
label,
kind: stringValue(option?.kind) ?? "",
...(stringValue(option?.description)
? { description: stringValue(option?.description) as string }
: {})
}
];
});
}
function normalizeToken(value: string | null | undefined): string {
return (value ?? "").trim().toLowerCase();
}
function stringValue(value: unknown): string | null {
return typeof value === "string" && value.trim() ? value.trim() : null;
}
function objectValue(value: unknown): Record<string, unknown> | null {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: null;
}
function arrayValue(value: unknown): unknown[] | null {
return Array.isArray(value) ? value : null;
}