fix(chat): hide raw permission metadata
Build Push and Deploy / docker-image (push) Failing after 42s
Build Push and Deploy / deploy-fallback-log (push) Successful in 0s

This commit is contained in:
2026-06-08 20:12:08 +08:00
parent 7da0ed0e39
commit 968d798a2a
7 changed files with 11 additions and 52 deletions
@@ -27,32 +27,6 @@ import VerifiedUserRounded from "@mui/icons-material/VerifiedUserRounded";
import type { PermissionReply } from "@/lib/chatStream"; import type { PermissionReply } from "@/lib/chatStream";
import type { Message } from "./GlobalChatbox.types"; import type { Message } from "./GlobalChatbox.types";
const formatMetadataValue = (value: unknown) => {
if (typeof value === "string") {
return value;
}
try {
return JSON.stringify(value);
} catch {
return "[unserializable]";
}
};
const truncateText = (value: string, maxLength: number) =>
value.length > maxLength ? `${value.slice(0, maxLength - 3)}...` : value;
const formatMetadata = (metadata: Record<string, unknown>) => {
const entries = Object.entries(metadata)
.filter(([key]) => !["command", "path", "file", "directory"].includes(key))
.slice(0, 3);
if (!entries.length) {
return "";
}
return entries
.map(([key, value]) => `${key}: ${truncateText(formatMetadataValue(value), 64)}`)
.join("");
};
const getPermissionTitle = (permission: NonNullable<Message["permissions"]>[number]) => { const getPermissionTitle = (permission: NonNullable<Message["permissions"]>[number]) => {
if (permission.permission === "external_directory") return "访问工作区外目录"; if (permission.permission === "external_directory") return "访问工作区外目录";
if (permission.permission === "bash") return "执行终端命令"; if (permission.permission === "bash") return "执行终端命令";
@@ -63,15 +37,8 @@ const getPermissionTitle = (permission: NonNullable<Message["permissions"]>[numb
const getPermissionPrimaryValue = ( const getPermissionPrimaryValue = (
permission: NonNullable<Message["permissions"]>[number], permission: NonNullable<Message["permissions"]>[number],
) => { ) => {
const command = permission.metadata.command; if (typeof permission.target === "string" && permission.target.trim()) {
if (typeof command === "string" && command.trim()) { return permission.target.trim();
return command.trim();
}
for (const key of ["path", "file", "directory"]) {
const value = permission.metadata[key];
if (typeof value === "string" && value.trim()) {
return value.trim();
}
} }
return permission.patterns[0] ?? permission.permission; return permission.patterns[0] ?? permission.permission;
}; };
@@ -139,7 +106,6 @@ const PermissionRequestCard = ({
isRunning && (permission.status === "pending" || permission.status === "error"); isRunning && (permission.status === "pending" || permission.status === "error");
const isSubmitting = isRunning && permission.status === "submitting"; const isSubmitting = isRunning && permission.status === "submitting";
const primaryValue = getPermissionPrimaryValue(permission); const primaryValue = getPermissionPrimaryValue(permission);
const metadataText = formatMetadata(permission.metadata);
const accentColor = getPermissionStatusColor(permission.status, theme); const accentColor = getPermissionStatusColor(permission.status, theme);
const statusTextColor = getPermissionStatusTextColor(permission.status, theme); const statusTextColor = getPermissionStatusTextColor(permission.status, theme);
const statusLabel = getPermissionStatusLabel(permission.status); const statusLabel = getPermissionStatusLabel(permission.status);
@@ -237,12 +203,6 @@ const PermissionRequestCard = ({
{primaryValue} {primaryValue}
</Typography> </Typography>
</Box> </Box>
{metadataText ? (
<Typography variant="caption" color="text.secondary" sx={{ wordBreak: "break-word" }}>
{metadataText}
</Typography>
) : null}
</Stack> </Stack>
{permission.error ? ( {permission.error ? (
+1 -1
View File
@@ -41,7 +41,7 @@ export type AgentPermissionRequest = {
sessionId: string; sessionId: string;
permission: string; permission: string;
patterns: string[]; patterns: string[];
metadata: Record<string, unknown>; target?: string;
always: string[]; always: string[];
tool?: { tool?: {
messageID: string; messageID: string;
@@ -88,7 +88,6 @@ export const cloneMessage = (message: Message): Message => ({
? [...permission.patterns] ? [...permission.patterns]
: [], : [],
always: Array.isArray(permission.always) ? [...permission.always] : [], always: Array.isArray(permission.always) ? [...permission.always] : [],
metadata: permission.metadata ?? {},
})) }))
: undefined, : undefined,
questions: normalizeQuestionRequests(message.questions), questions: normalizeQuestionRequests(message.questions),
@@ -115,7 +115,7 @@ export const upsertPermission = (
sessionId: event.sessionId, sessionId: event.sessionId,
permission: event.permission, permission: event.permission,
patterns: event.patterns, patterns: event.patterns,
metadata: event.metadata, target: event.target,
always: event.always, always: event.always,
tool: event.tool, tool: event.tool,
createdAt: event.createdAt, createdAt: event.createdAt,
@@ -99,7 +99,7 @@ describe("useAgentChatSession actions", () => {
requestId: "perm-1", requestId: "perm-1",
permission: "bash", permission: "bash",
patterns: ["rm *"], patterns: ["rm *"],
metadata: { command: "rm tmp.txt" }, target: "rm tmp.txt",
always: ["rm *"], always: ["rm *"],
createdAt: 123, createdAt: 123,
}); });
@@ -163,7 +163,7 @@ describe("useAgentChatSession actions", () => {
requestId: "perm-abort", requestId: "perm-abort",
permission: "bash", permission: "bash",
patterns: ["npm test"], patterns: ["npm test"],
metadata: { command: "npm test" }, target: "npm test",
always: ["npm test"], always: ["npm test"],
createdAt: 1002, createdAt: 1002,
} satisfies StreamEvent); } satisfies StreamEvent);
+2 -2
View File
@@ -186,7 +186,7 @@ describe("streamAgentChat", () => {
apiFetch.mockResolvedValue({ apiFetch.mockResolvedValue({
ok: true, ok: true,
body: makeStream([ body: makeStream([
'event: permission_request\ndata: {"session_id":"s1","request_id":"perm-1","permission":"bash","patterns":["rm *"],"metadata":{"command":"rm tmp.txt"},"always":["rm *"],"created_at":123}\n\n', 'event: permission_request\ndata: {"session_id":"s1","request_id":"perm-1","permission":"bash","patterns":["rm *"],"target":"rm tmp.txt","always":["rm *"],"created_at":123}\n\n',
'event: permission_response\ndata: {"session_id":"s1","request_id":"perm-1","reply":"reject"}\n\n', 'event: permission_response\ndata: {"session_id":"s1","request_id":"perm-1","reply":"reject"}\n\n',
]), ]),
}); });
@@ -205,7 +205,7 @@ describe("streamAgentChat", () => {
requestId: "perm-1", requestId: "perm-1",
permission: "bash", permission: "bash",
patterns: ["rm *"], patterns: ["rm *"],
metadata: { command: "rm tmp.txt" }, target: "rm tmp.txt",
always: ["rm *"], always: ["rm *"],
tool: undefined, tool: undefined,
createdAt: 123, createdAt: 123,
+3 -3
View File
@@ -98,7 +98,7 @@ export type StreamEvent =
requestId: string; requestId: string;
permission: string; permission: string;
patterns: string[]; patterns: string[];
metadata: Record<string, unknown>; target?: string;
always: string[]; always: string[];
tool?: { tool?: {
messageID: string; messageID: string;
@@ -296,7 +296,7 @@ const emitParsedStreamEvent = (
request_id?: string; request_id?: string;
permission?: string; permission?: string;
patterns?: unknown; patterns?: unknown;
metadata?: unknown; target?: string;
always?: unknown; always?: unknown;
created_at?: number; created_at?: number;
reply?: PermissionReply; reply?: PermissionReply;
@@ -370,7 +370,7 @@ const emitParsedStreamEvent = (
patterns: Array.isArray(parsed.patterns) patterns: Array.isArray(parsed.patterns)
? parsed.patterns.filter((item): item is string => typeof item === "string") ? parsed.patterns.filter((item): item is string => typeof item === "string")
: [], : [],
metadata: isObjectRecord(parsed.metadata) ? parsed.metadata : {}, target: typeof parsed.target === "string" ? parsed.target : undefined,
always: Array.isArray(parsed.always) always: Array.isArray(parsed.always)
? parsed.always.filter((item): item is string => typeof item === "string") ? parsed.always.filter((item): item is string => typeof item === "string")
: [], : [],