Fix reasoning timeline UI and type errors

This commit is contained in:
Mohamed Boudra
2025-11-23 14:12:53 +01:00
parent 95bacf8fc7
commit 47a99f5668
23 changed files with 2569 additions and 1237 deletions
@@ -21,6 +21,7 @@ import type {
AgentPermissionRequest,
AgentMode,
AgentCapabilityFlags,
AgentModelDefinition,
AgentUsage,
AgentPersistenceHandle,
} from "@server/server/agent/agent-sdk-types";
@@ -78,6 +79,13 @@ export type MessageEntry =
status: "executing" | "completed" | "failed";
};
type ProviderModelState = {
models: AgentModelDefinition[] | null;
fetchedAt: Date | null;
error: string | null;
isLoading: boolean;
};
export interface Agent {
id: string;
provider: AgentProvider;
@@ -245,6 +253,9 @@ interface SessionContextValue {
requestFilePreview: (agentId: string, path: string) => void;
navigateExplorerBack: (agentId: string) => string | null;
providerModels: Map<AgentProvider, ProviderModelState>;
requestProviderModels: (provider: AgentProvider, options?: { cwd?: string }) => void;
// Helpers
restartServer: (reason?: string) => void;
initializeAgent: (params: { agentId: string; requestId?: string }) => void;
@@ -305,10 +316,12 @@ export function SessionProvider({ children, serverUrl }: SessionProviderProps) {
const [pendingPermissions, setPendingPermissions] = useState<Map<string, PendingPermission>>(new Map());
const [gitDiffs, setGitDiffs] = useState<Map<string, string>>(new Map());
const [fileExplorer, setFileExplorer] = useState<Map<string, AgentFileExplorerState>>(new Map());
const [providerModels, setProviderModels] = useState<Map<AgentProvider, ProviderModelState>>(new Map());
const [draftInputs, setDraftInputs] = useState<SessionContextValue["draftInputs"]>(new Map());
const [queuedMessages, setQueuedMessages] = useState<SessionContextValue["queuedMessages"]>(new Map());
const activeAudioGroupsRef = useRef<Set<string>>(new Set());
const previousAgentStatusRef = useRef<Map<string, AgentLifecycleStatus>>(new Map());
const providerModelRequestIdsRef = useRef<Map<AgentProvider, string>>(new Map());
// Buffer for streaming audio chunks
interface AudioChunk {
@@ -879,6 +892,33 @@ export function SessionProvider({ children, serverUrl }: SessionProviderProps) {
});
});
const unsubProviderModels = ws.on(
"list_provider_models_response",
(message) => {
if (message.type !== "list_provider_models_response") {
return;
}
const { provider, models, error, fetchedAt, requestId } = message.payload;
const latestRequestId = providerModelRequestIdsRef.current.get(provider);
if (latestRequestId && requestId && requestId !== latestRequestId) {
return;
}
if (requestId) {
providerModelRequestIdsRef.current.delete(provider);
}
setProviderModels((prev) => {
const next = new Map(prev);
next.set(provider, {
models: models ?? null,
error: error ?? null,
fetchedAt: new Date(fetchedAt),
isLoading: false,
});
return next;
});
}
);
const unsubAgentDeleted = ws.on("agent_deleted", (message) => {
if (message.type !== "agent_deleted") {
return;
@@ -958,6 +998,7 @@ export function SessionProvider({ children, serverUrl }: SessionProviderProps) {
unsubTranscription();
unsubGitDiff();
unsubFileExplorer();
unsubProviderModels();
unsubAgentDeleted();
};
}, [ws, audioPlayer, setIsPlayingAudio, updateExplorerState]);
@@ -1010,6 +1051,37 @@ export function SessionProvider({ children, serverUrl }: SessionProviderProps) {
ws.send(msg);
}, [ws]);
const requestProviderModels = useCallback((provider: AgentProvider, options?: { cwd?: string }) => {
const requestId = generateMessageId();
providerModelRequestIdsRef.current.set(provider, requestId);
setProviderModels((prev) => {
const next = new Map(prev);
const current =
prev.get(provider) ?? {
models: null,
fetchedAt: null,
error: null,
isLoading: false,
};
next.set(provider, {
...current,
isLoading: true,
error: null,
});
return next;
});
const msg: WSInboundMessage = {
type: "session",
message: {
type: "list_provider_models_request",
provider,
...(options?.cwd ? { cwd: options.cwd } : {}),
requestId,
},
};
ws.send(msg);
}, [ws]);
const sendAgentMessage = useCallback(async (agentId: string, message: string, imageUris?: string[]) => {
// Generate unique message ID for deduplication
const messageId = generateMessageId();
@@ -1333,6 +1405,8 @@ export function SessionProvider({ children, serverUrl }: SessionProviderProps) {
gitDiffs,
requestGitDiff,
fileExplorer,
providerModels,
requestProviderModels,
draftInputs,
setDraftInputs,
queuedMessages,