fix(cli): les annonces MCP/inter-agent restent affichées pendant qu'un agent est busy — #232
This commit is contained in:
@ -31,6 +31,7 @@ import type {
|
||||
SlashCommand,
|
||||
} from "@/domain";
|
||||
import { useGateways } from "@/app/di";
|
||||
import { AnnouncementsPreview } from "@/features/announcements";
|
||||
import { usePluginRuntime } from "@/features/plugins/PluginRuntimeProvider";
|
||||
import {
|
||||
markProjectCliInteractionFinished,
|
||||
@ -127,6 +128,10 @@ interface ChatErrorState {
|
||||
openFailure: boolean;
|
||||
}
|
||||
|
||||
interface RequesterDelegationState {
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
function describe(e: unknown): string {
|
||||
if (e && typeof e === "object" && "message" in e) {
|
||||
return String((e as GatewayError).message);
|
||||
@ -842,7 +847,7 @@ export function CustomAgentChatView({
|
||||
onSessionId,
|
||||
onConversationId,
|
||||
}: CustomAgentChatViewProps) {
|
||||
const { agent, profile: profileGateway, system } = useGateways();
|
||||
const { agent, profile: profileGateway, system, workState } = useGateways();
|
||||
const pluginRuntime = usePluginRuntime();
|
||||
const initialConversationCacheKey = conversationCacheKey(
|
||||
projectId,
|
||||
@ -1013,6 +1018,33 @@ export function CustomAgentChatView({
|
||||
[agentId, conversationId, projectId],
|
||||
);
|
||||
const displayTurns = turns;
|
||||
const [requesterDelegation, setRequesterDelegation] =
|
||||
useState<RequesterDelegationState>({ active: false });
|
||||
|
||||
const refreshRequesterDelegation = useCallback(async () => {
|
||||
if (!workState) {
|
||||
setRequesterDelegation({ active: false });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const state = await workState.getProjectWorkState(projectId);
|
||||
const target = state.agents.find((row) =>
|
||||
row.tickets.some(
|
||||
(ticket) =>
|
||||
ticket.status === "inProgress" &&
|
||||
ticket.source.kind === "agent" &&
|
||||
ticket.source.agentId === agentId,
|
||||
),
|
||||
);
|
||||
setRequesterDelegation(
|
||||
target
|
||||
? { active: true }
|
||||
: { active: false },
|
||||
);
|
||||
} catch {
|
||||
setRequesterDelegation({ active: false });
|
||||
}
|
||||
}, [agentId, projectId, workState]);
|
||||
|
||||
const clearPersistedDraft = useCallback(async () => {
|
||||
if (!draftScope) return;
|
||||
@ -1034,6 +1066,36 @@ export function CustomAgentChatView({
|
||||
setDraft(text);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
void refreshRequesterDelegation();
|
||||
}, [refreshRequesterDelegation]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!system?.onDomainEvent) return;
|
||||
let unsubscribe: (() => void) | undefined;
|
||||
let cancelled = false;
|
||||
void system
|
||||
.onDomainEvent((event) => {
|
||||
if (
|
||||
event.type === "agentBusyChanged" ||
|
||||
event.type === "delegationReady" ||
|
||||
event.type === "orchestratorRequestProcessed" ||
|
||||
event.type === "agentInboxChanged" ||
|
||||
event.type === "agentWakeChanged"
|
||||
) {
|
||||
void refreshRequesterDelegation();
|
||||
}
|
||||
})
|
||||
.then((un) => {
|
||||
if (cancelled) un();
|
||||
else unsubscribe = un;
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
unsubscribe?.();
|
||||
};
|
||||
}, [refreshRequesterDelegation, system]);
|
||||
|
||||
useEffect(() => {
|
||||
mountedRef.current = true;
|
||||
return () => {
|
||||
@ -1914,7 +1976,7 @@ export function CustomAgentChatView({
|
||||
<div
|
||||
ref={chatRootRef}
|
||||
data-testid="custom-agent-chat-view"
|
||||
className="flex h-full min-h-0 flex-col overflow-hidden bg-surface text-content"
|
||||
className="relative z-0 flex h-full min-h-0 flex-col overflow-hidden bg-surface text-content"
|
||||
>
|
||||
<div
|
||||
role="toolbar"
|
||||
@ -2076,6 +2138,13 @@ export function CustomAgentChatView({
|
||||
data-testid="custom-agent-chat-scroll"
|
||||
className="flex min-h-0 flex-1 basis-0 flex-col gap-2 overflow-x-hidden overflow-y-auto px-3 py-3"
|
||||
>
|
||||
<div className="shrink-0">
|
||||
<AnnouncementsPreview
|
||||
requester={agentId}
|
||||
fallbackActive={requesterDelegation.active}
|
||||
fallbackText="Délégation en cours."
|
||||
/>
|
||||
</div>
|
||||
{opening && displayTurns.length === 0 ? (
|
||||
<div className="flex items-center gap-2 text-sm text-muted">
|
||||
<Spinner size={14} />
|
||||
|
||||
Reference in New Issue
Block a user