fix(chat): mark aborted permissions
This commit is contained in:
@@ -94,6 +94,7 @@ const getPermissionStatusLabel = (status: NonNullable<Message["permissions"]>[nu
|
|||||||
if (status === "approved_always") return "已始终允许";
|
if (status === "approved_always") return "已始终允许";
|
||||||
if (status === "approved_once") return "已允许一次";
|
if (status === "approved_once") return "已允许一次";
|
||||||
if (status === "rejected") return "已拒绝";
|
if (status === "rejected") return "已拒绝";
|
||||||
|
if (status === "aborted") return "已中断";
|
||||||
if (status === "error") return "提交失败";
|
if (status === "error") return "提交失败";
|
||||||
if (status === "submitting") return "提交中";
|
if (status === "submitting") return "提交中";
|
||||||
return "等待确认";
|
return "等待确认";
|
||||||
@@ -109,6 +110,7 @@ const getPermissionStatusColor = (
|
|||||||
if (status === "approved_once") return approvedOncePermissionColor;
|
if (status === "approved_once") return approvedOncePermissionColor;
|
||||||
if (status === "approved_always") return theme.palette.success.main;
|
if (status === "approved_always") return theme.palette.success.main;
|
||||||
if (status === "rejected" || status === "error") return theme.palette.error.main;
|
if (status === "rejected" || status === "error") return theme.palette.error.main;
|
||||||
|
if (status === "aborted") return theme.palette.text.secondary;
|
||||||
return pendingPermissionColor;
|
return pendingPermissionColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,19 +121,23 @@ const getPermissionStatusTextColor = (
|
|||||||
if (status === "approved_once") return "#006c78";
|
if (status === "approved_once") return "#006c78";
|
||||||
if (status === "approved_always") return theme.palette.success.dark;
|
if (status === "approved_always") return theme.palette.success.dark;
|
||||||
if (status === "rejected" || status === "error") return theme.palette.error.main;
|
if (status === "rejected" || status === "error") return theme.palette.error.main;
|
||||||
|
if (status === "aborted") return theme.palette.text.secondary;
|
||||||
return "#8a5a00";
|
return "#8a5a00";
|
||||||
};
|
};
|
||||||
|
|
||||||
const PermissionRequestCard = ({
|
const PermissionRequestCard = ({
|
||||||
permission,
|
permission,
|
||||||
|
isRunning,
|
||||||
onReply,
|
onReply,
|
||||||
}: {
|
}: {
|
||||||
permission: NonNullable<Message["permissions"]>[number];
|
permission: NonNullable<Message["permissions"]>[number];
|
||||||
|
isRunning: boolean;
|
||||||
onReply: (requestId: string, reply: PermissionReply) => void;
|
onReply: (requestId: string, reply: PermissionReply) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isPending = permission.status === "pending" || permission.status === "error";
|
const isPending =
|
||||||
const isSubmitting = permission.status === "submitting";
|
isRunning && (permission.status === "pending" || permission.status === "error");
|
||||||
|
const isSubmitting = isRunning && permission.status === "submitting";
|
||||||
const primaryValue = getPermissionPrimaryValue(permission);
|
const primaryValue = getPermissionPrimaryValue(permission);
|
||||||
const metadataText = formatMetadata(permission.metadata);
|
const metadataText = formatMetadata(permission.metadata);
|
||||||
const accentColor = getPermissionStatusColor(permission.status, theme);
|
const accentColor = getPermissionStatusColor(permission.status, theme);
|
||||||
@@ -363,7 +369,13 @@ export const PermissionRequestGroup = ({
|
|||||||
const onceCount = permissions.filter((permission) => permission.status === "approved_once").length;
|
const onceCount = permissions.filter((permission) => permission.status === "approved_once").length;
|
||||||
const alwaysCount = permissions.filter((permission) => permission.status === "approved_always").length;
|
const alwaysCount = permissions.filter((permission) => permission.status === "approved_always").length;
|
||||||
const rejectedCount = permissions.filter((permission) => permission.status === "rejected").length;
|
const rejectedCount = permissions.filter((permission) => permission.status === "rejected").length;
|
||||||
const pendingCount = permissions.length - onceCount - alwaysCount - rejectedCount;
|
const abortedCount = permissions.filter((permission) => permission.status === "aborted").length;
|
||||||
|
const pendingCount = permissions.filter(
|
||||||
|
(permission) =>
|
||||||
|
permission.status === "pending" ||
|
||||||
|
permission.status === "submitting" ||
|
||||||
|
permission.status === "error",
|
||||||
|
).length;
|
||||||
const hasPendingPermissions = pendingCount > 0;
|
const hasPendingPermissions = pendingCount > 0;
|
||||||
const [expanded, setExpanded] = React.useState(false);
|
const [expanded, setExpanded] = React.useState(false);
|
||||||
const latestPermissions = permissions.slice(-3);
|
const latestPermissions = permissions.slice(-3);
|
||||||
@@ -378,9 +390,24 @@ export const PermissionRequestGroup = ({
|
|||||||
{ label: "允许一次", value: onceCount, color: getPermissionStatusColor("approved_once", theme), textColor: getPermissionStatusTextColor("approved_once", theme) },
|
{ label: "允许一次", value: onceCount, color: getPermissionStatusColor("approved_once", theme), textColor: getPermissionStatusTextColor("approved_once", theme) },
|
||||||
{ label: "始终允许", value: alwaysCount, color: getPermissionStatusColor("approved_always", theme), textColor: getPermissionStatusTextColor("approved_always", theme) },
|
{ label: "始终允许", value: alwaysCount, color: getPermissionStatusColor("approved_always", theme), textColor: getPermissionStatusTextColor("approved_always", theme) },
|
||||||
{ label: "拒绝", value: rejectedCount, color: getPermissionStatusColor("rejected", theme), textColor: getPermissionStatusTextColor("rejected", theme) },
|
{ label: "拒绝", value: rejectedCount, color: getPermissionStatusColor("rejected", theme), textColor: getPermissionStatusTextColor("rejected", theme) },
|
||||||
|
{ label: "中断", value: abortedCount, color: getPermissionStatusColor("aborted", theme), textColor: getPermissionStatusTextColor("aborted", theme) },
|
||||||
];
|
];
|
||||||
const chipColor = pendingCount > 0 ? getPermissionStatusColor("pending", theme) : rejectedCount > 0 ? getPermissionStatusColor("rejected", theme) : getPermissionStatusColor("approved_always", theme);
|
const chipColor =
|
||||||
const chipTextColor = pendingCount > 0 ? getPermissionStatusTextColor("pending", theme) : rejectedCount > 0 ? getPermissionStatusTextColor("rejected", theme) : getPermissionStatusTextColor("approved_always", theme);
|
pendingCount > 0
|
||||||
|
? getPermissionStatusColor("pending", theme)
|
||||||
|
: abortedCount > 0
|
||||||
|
? getPermissionStatusColor("aborted", theme)
|
||||||
|
: rejectedCount > 0
|
||||||
|
? getPermissionStatusColor("rejected", theme)
|
||||||
|
: getPermissionStatusColor("approved_always", theme);
|
||||||
|
const chipTextColor =
|
||||||
|
pendingCount > 0
|
||||||
|
? getPermissionStatusTextColor("pending", theme)
|
||||||
|
: abortedCount > 0
|
||||||
|
? getPermissionStatusTextColor("aborted", theme)
|
||||||
|
: rejectedCount > 0
|
||||||
|
? getPermissionStatusTextColor("rejected", theme)
|
||||||
|
: getPermissionStatusTextColor("approved_always", theme);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -591,6 +618,7 @@ export const PermissionRequestGroup = ({
|
|||||||
<PermissionRequestCard
|
<PermissionRequestCard
|
||||||
key={permission.requestId}
|
key={permission.requestId}
|
||||||
permission={permission}
|
permission={permission}
|
||||||
|
isRunning={isRunning}
|
||||||
onReply={onReply}
|
onReply={onReply}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -605,6 +633,7 @@ export const PermissionRequestGroup = ({
|
|||||||
<PermissionRequestCard
|
<PermissionRequestCard
|
||||||
key={permission.requestId}
|
key={permission.requestId}
|
||||||
permission={permission}
|
permission={permission}
|
||||||
|
isRunning={isRunning}
|
||||||
onReply={onReply}
|
onReply={onReply}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -613,5 +642,3 @@ export const PermissionRequestGroup = ({
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export type AgentPermissionStatus =
|
|||||||
| "approved_once"
|
| "approved_once"
|
||||||
| "approved_always"
|
| "approved_always"
|
||||||
| "rejected"
|
| "rejected"
|
||||||
|
| "aborted"
|
||||||
| "error";
|
| "error";
|
||||||
|
|
||||||
export type AgentPermissionRequest = {
|
export type AgentPermissionRequest = {
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ export const normalizeSessionTodos = (
|
|||||||
return changed ? nextMessages : messages;
|
return changed ? nextMessages : messages;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const rejectOpenPermissionsAfterAbort = (
|
export const abortOpenPermissionsAfterAbort = (
|
||||||
permissions: AgentPermissionRequest[] | undefined,
|
permissions: AgentPermissionRequest[] | undefined,
|
||||||
) => {
|
) => {
|
||||||
if (!permissions?.length) return permissions;
|
if (!permissions?.length) return permissions;
|
||||||
@@ -380,7 +380,7 @@ export const rejectOpenPermissionsAfterAbort = (
|
|||||||
changed = true;
|
changed = true;
|
||||||
return {
|
return {
|
||||||
...permission,
|
...permission,
|
||||||
status: "rejected" as const,
|
status: "aborted" as const,
|
||||||
repliedAt: Date.now(),
|
repliedAt: Date.now(),
|
||||||
error: undefined,
|
error: undefined,
|
||||||
};
|
};
|
||||||
@@ -415,12 +415,12 @@ export const rejectOpenQuestionsAfterAbort = (
|
|||||||
export const finalizeAssistantMessageAfterAbort = (message: Message): Message => {
|
export const finalizeAssistantMessageAfterAbort = (message: Message): Message => {
|
||||||
const completedProgress = completeRunningProgress(message.progress);
|
const completedProgress = completeRunningProgress(message.progress);
|
||||||
const cancelledTodos = cancelRunningTodos(message.todos);
|
const cancelledTodos = cancelRunningTodos(message.todos);
|
||||||
const rejectedPermissions = rejectOpenPermissionsAfterAbort(message.permissions);
|
const abortedPermissions = abortOpenPermissionsAfterAbort(message.permissions);
|
||||||
const rejectedQuestions = rejectOpenQuestionsAfterAbort(message.questions);
|
const rejectedQuestions = rejectOpenQuestionsAfterAbort(message.questions);
|
||||||
const hasVisibleOutput =
|
const hasVisibleOutput =
|
||||||
message.content.trim().length > 0 ||
|
message.content.trim().length > 0 ||
|
||||||
Boolean(message.artifacts?.length) ||
|
Boolean(message.artifacts?.length) ||
|
||||||
Boolean(rejectedPermissions?.length) ||
|
Boolean(abortedPermissions?.length) ||
|
||||||
Boolean(rejectedQuestions?.length) ||
|
Boolean(rejectedQuestions?.length) ||
|
||||||
Boolean(completedProgress?.length) ||
|
Boolean(completedProgress?.length) ||
|
||||||
Boolean(cancelledTodos);
|
Boolean(cancelledTodos);
|
||||||
@@ -434,7 +434,7 @@ export const finalizeAssistantMessageAfterAbort = (message: Message): Message =>
|
|||||||
content: message.content || "⚠️ **请求已中断**",
|
content: message.content || "⚠️ **请求已中断**",
|
||||||
isError: true,
|
isError: true,
|
||||||
progress: completedProgress,
|
progress: completedProgress,
|
||||||
permissions: rejectedPermissions,
|
permissions: abortedPermissions,
|
||||||
questions: rejectedQuestions,
|
questions: rejectedQuestions,
|
||||||
todos: cancelledTodos,
|
todos: cancelledTodos,
|
||||||
};
|
};
|
||||||
@@ -454,4 +454,3 @@ export const createAssistantMessage = (): Message => ({
|
|||||||
role: "assistant",
|
role: "assistant",
|
||||||
content: "",
|
content: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ describe("useAgentChatSession actions", () => {
|
|||||||
permissions: [
|
permissions: [
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
requestId: "perm-abort",
|
requestId: "perm-abort",
|
||||||
status: "rejected",
|
status: "aborted",
|
||||||
repliedAt: expect.any(Number),
|
repliedAt: expect.any(Number),
|
||||||
error: undefined,
|
error: undefined,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user