Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions builds/typescript/client_web/src/api/useGatewayChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ export function useGatewayChat(options: UseGatewayChatOptions = {}): {
conversationIdRef.current = restored.conversationId;
backgroundStates.delete(cacheKey);
} else {
setMessages(externalMessages);
// Always start empty when switching conversations — externalMessages may be stale
// from the previous project's history that hasn't cleared yet. The secondary effect
// (below) will apply the correct history once it arrives from the async fetch.
setMessages(EMPTY_MESSAGES);
setIsLoading(false);
setError(null);
setToolStatus(null);
Expand Down Expand Up @@ -234,9 +237,12 @@ export function useGatewayChat(options: UseGatewayChatOptions = {}): {
}

async function resolveApproval(requestId: string, decision: ApprovalDecision): Promise<void> {
// Capture the tool name before removing the approval so we can show
// a user-friendly status ("Writing to your library...") instead of "Approval approved"
const approvalToolName = pendingApprovals.find((a) => a.requestId === requestId)?.toolName;
await submitApprovalDecision(requestId, decision);
setPendingApprovals((current) => current.filter((approval) => approval.requestId !== requestId));
setToolStatus(`Approval ${decision}`);
setToolStatus(decision === "approved" && approvalToolName ? approvalToolName : null);
setActivity((current) =>
appendActivity(current, {
id: nextActivityId(),
Expand Down Expand Up @@ -509,9 +515,9 @@ export function useGatewayChat(options: UseGatewayChatOptions = {}): {
message: `Approval required for ${humanizeToolName(event.tool_name)}`,
});
if (isActive()) {
setToolStatus(`Approval required: ${event.tool_name}`);
setToolStatus(event.tool_name);
} else {
updateBackground(() => ({ toolStatus: `Approval required: ${event.tool_name}` }));
updateBackground(() => ({ toolStatus: event.tool_name }));
}
break;
case "approval-result":
Expand All @@ -521,11 +527,8 @@ export function useGatewayChat(options: UseGatewayChatOptions = {}): {
message: `Approval ${event.decision}`,
status: event.decision,
});
if (isActive()) {
setToolStatus(`Approval ${event.decision}`);
} else {
updateBackground(() => ({ toolStatus: `Approval ${event.decision}` }));
}
// Don't set toolStatus here — resolveApproval already set it to the
// tool name (so it shows "Writing to your library..." not "Approval approved")
break;
}
}
Expand Down
30 changes: 5 additions & 25 deletions builds/typescript/client_web/src/components/chat/ChatPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ export default function ChatPanel({
conversationId,
toolStatus,
pendingApprovals,
activity,
append,
resolveApproval,
stop
Expand Down Expand Up @@ -173,8 +172,9 @@ export default function ChatPanel({

const lastMessage = messages.length > 0 ? messages[messages.length - 1] : null;
const hasStartedAssistantReply = isLoading && lastMessage?.role === "assistant";
const isTyping = isLoading && !hasStartedAssistantReply;
const typingStatus = isTyping
const isWaitingForReply = isLoading && !hasStartedAssistantReply;
const showTypingFeedback = isLoading && pendingApprovals.length === 0;
const typingStatus = isLoading
? toolStatus
? formatToolStatus(toolStatus)
: "Thinking..."
Expand Down Expand Up @@ -272,7 +272,7 @@ export default function ChatPanel({
onRemoveAttachment: () => setAttachment(null),
fileError,
onClearFileError: () => setFileError(null),
isStreaming: isTyping,
isStreaming: isWaitingForReply,
onStop: stop
};

Expand Down Expand Up @@ -339,7 +339,7 @@ export default function ChatPanel({
) : (
<MessageList
messages={messages}
isTyping={isTyping}
isTyping={showTypingFeedback}
typingStatus={typingStatus}
>
{visibleChatError && (
Expand Down Expand Up @@ -415,26 +415,6 @@ export default function ChatPanel({
</div>
</section>
)}
{activity.length > 0 && (
<section className="rounded-xl border border-bd-border bg-bd-bg-secondary p-4">
<div className="mb-3 text-sm font-medium text-bd-text-secondary">
Action Timeline
</div>
<div className="space-y-2">
{activity.slice(-8).map((item) => (
<div
key={item.id}
className="flex items-center justify-between gap-3 rounded-md bg-bd-bg-tertiary px-3 py-2 text-xs"
>
<span className="text-bd-text-secondary">{item.message}</span>
<span className="shrink-0 uppercase tracking-wide text-bd-text-muted">
{item.type}
</span>
</div>
))}
</div>
</section>
)}
</MessageList>
)) : contentOverride}
</div>
Expand Down