diff --git a/packages/ui/src/components/chat/PermissionCard.tsx b/packages/ui/src/components/chat/PermissionCard.tsx index c882f48f..5e9cefce 100644 --- a/packages/ui/src/components/chat/PermissionCard.tsx +++ b/packages/ui/src/components/chat/PermissionCard.tsx @@ -329,7 +329,26 @@ export const PermissionCard: React.FC = ({ {}
- {} + {/* Show patterns being requested */} + {(permission.patterns as string[]) && (permission.patterns as string[]).length > 0 && ( +
+
Patterns:
+ + {(permission.patterns as string[]).join(", ")} + +
+ )} + + {!((permission.patterns as string[]) && (permission.patterns as string[]).length > 0) && + (permission.pattern as string | string[]) && +
+
Pattern:
+ + {Array.isArray(permission.pattern) ? permission.pattern.join(", ") : permission.pattern} + +
+ } + {(() => { let primaryContent = ''; @@ -441,27 +460,58 @@ export const PermissionCard: React.FC = ({ Allow Once - + {(permission.always as string[]) && (permission.always as string[]).length > 0 ? ( + + ) : ( + + )} + )} + {hasOutput ? ( -
0 && 'pt-1')} +
0 || sessionId) && 'pt-1')} > - {isOutputExpanded ? (
@@ -895,6 +916,14 @@ const ToolPart: React.FC = ({ part, isExpanded, onToggle, syntaxT const effectiveTimeStart = isTaskTool ? (pinnedTaskTimeRef.current.start ?? time?.start) : time?.start; const effectiveTimeEnd = isTaskTool ? (pinnedTaskTimeRef.current.end ?? time?.end) : time?.end; + const taskSessionId = React.useMemo(() => { + if (!isTaskTool) { + return undefined; + } + const candidate = metadata as { sessionId?: string } | undefined; + return typeof candidate?.sessionId === 'string' ? candidate.sessionId : undefined; + }, [isTaskTool, metadata]); + const taskSummaryEntries = React.useMemo(() => { if (!isTaskTool) { return []; @@ -1023,13 +1052,14 @@ const ToolPart: React.FC = ({ part, isExpanded, onToggle, syntaxT
{} - {isTaskTool && (taskSummaryEntries.length > 0 || isActive || isFinalized) ? ( + {isTaskTool && (taskSummaryEntries.length > 0 || isActive || isFinalized || taskSessionId) ? ( ) : null} diff --git a/packages/ui/src/hooks/useEventStream.ts b/packages/ui/src/hooks/useEventStream.ts index e6d596fc..545961af 100644 --- a/packages/ui/src/hooks/useEventStream.ts +++ b/packages/ui/src/hooks/useEventStream.ts @@ -955,8 +955,44 @@ export const useEventStream = () => { } break; - case 'permission.replied': + case 'permission.asked': + // New permission system from OpenCode's PermissionNext + if ('sessionID' in props && props.sessionID === currentSessionId) { + const askedProps = props as { + id: string; + permission: string; + sessionID: string; + patterns?: string[]; + always?: string[]; + metadata: Record; + tool?: { + messageID: string; + callID: string; + }; + }; + // Convert new permission.asked event format to Permission type + const permission = { + id: askedProps.id, + type: askedProps.permission, + pattern: askedProps.patterns, // Map patterns to pattern field for compatibility + sessionID: askedProps.sessionID, + messageID: askedProps.tool?.messageID || askedProps.sessionID, + callID: askedProps.tool?.callID, + title: `${askedProps.permission} permission required`, + metadata: { + ...askedProps.metadata, + always: askedProps.always, // Store always in metadata for UI access + patterns: askedProps.patterns, + }, + time: { created: Date.now() }, + } as unknown as Permission; + addPermission(permission); + } + break; + + case 'permission.replied': + // Permission was responded to - UI will update via permissionStore break; case 'todo.updated': { diff --git a/packages/ui/src/types/permission.ts b/packages/ui/src/types/permission.ts index 9d2a650a..1f157cb6 100644 --- a/packages/ui/src/types/permission.ts +++ b/packages/ui/src/types/permission.ts @@ -2,6 +2,8 @@ export interface Permission { id: string; type: string; pattern?: string | string[]; + patterns?: string[]; // New system: array of specific patterns requesting approval + always?: string[]; // New system: what will be auto-approved on "always" click sessionID: string; messageID: string; callID?: string; @@ -10,6 +12,10 @@ export interface Permission { time: { created: number; }; + tool?: { + messageID: string; + callID: string; + }; } export interface PermissionEvent {