mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 23:24:33 +00:00
TUI/Gateway: fix pi streaming + tool routing + model display + msg updating (#8432)
* TUI/Gateway: fix pi streaming + tool routing * Tests: clarify verbose tool output expectation * fix: avoid seq gaps for targeted tool events (#8432) (thanks @gumadeiras)
This commit is contained in:
committed by
GitHub
parent
a42e3cb78a
commit
38e6da1fe0
@@ -10,10 +10,24 @@ type EventHandlerContext = {
|
||||
state: TuiStateAccess;
|
||||
setActivityStatus: (text: string) => void;
|
||||
refreshSessionInfo?: () => Promise<void>;
|
||||
loadHistory?: () => Promise<void>;
|
||||
isLocalRunId?: (runId: string) => boolean;
|
||||
forgetLocalRunId?: (runId: string) => void;
|
||||
clearLocalRunIds?: () => void;
|
||||
};
|
||||
|
||||
export function createEventHandlers(context: EventHandlerContext) {
|
||||
const { chatLog, tui, state, setActivityStatus, refreshSessionInfo } = context;
|
||||
const {
|
||||
chatLog,
|
||||
tui,
|
||||
state,
|
||||
setActivityStatus,
|
||||
refreshSessionInfo,
|
||||
loadHistory,
|
||||
isLocalRunId,
|
||||
forgetLocalRunId,
|
||||
clearLocalRunIds,
|
||||
} = context;
|
||||
const finalizedRuns = new Map<string, number>();
|
||||
const sessionRuns = new Map<string, number>();
|
||||
let streamAssembler = new TuiStreamAssembler();
|
||||
@@ -50,6 +64,7 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
finalizedRuns.clear();
|
||||
sessionRuns.clear();
|
||||
streamAssembler = new TuiStreamAssembler();
|
||||
clearLocalRunIds?.();
|
||||
};
|
||||
|
||||
const noteSessionRun = (runId: string) => {
|
||||
@@ -95,6 +110,11 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
}
|
||||
if (evt.state === "final") {
|
||||
if (isCommandMessage(evt.message)) {
|
||||
if (isLocalRunId?.(evt.runId)) {
|
||||
forgetLocalRunId?.(evt.runId);
|
||||
} else {
|
||||
void loadHistory?.();
|
||||
}
|
||||
const text = extractTextFromMessage(evt.message);
|
||||
if (text) {
|
||||
chatLog.addSystem(text);
|
||||
@@ -107,6 +127,11 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
tui.requestRender();
|
||||
return;
|
||||
}
|
||||
if (isLocalRunId?.(evt.runId)) {
|
||||
forgetLocalRunId?.(evt.runId);
|
||||
} else {
|
||||
void loadHistory?.();
|
||||
}
|
||||
const stopReason =
|
||||
evt.message && typeof evt.message === "object" && !Array.isArray(evt.message)
|
||||
? typeof (evt.message as Record<string, unknown>).stopReason === "string"
|
||||
@@ -129,6 +154,11 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
state.activeChatRunId = null;
|
||||
setActivityStatus("aborted");
|
||||
void refreshSessionInfo?.();
|
||||
if (isLocalRunId?.(evt.runId)) {
|
||||
forgetLocalRunId?.(evt.runId);
|
||||
} else {
|
||||
void loadHistory?.();
|
||||
}
|
||||
}
|
||||
if (evt.state === "error") {
|
||||
chatLog.addSystem(`run error: ${evt.errorMessage ?? "unknown"}`);
|
||||
@@ -137,6 +167,11 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
state.activeChatRunId = null;
|
||||
setActivityStatus("error");
|
||||
void refreshSessionInfo?.();
|
||||
if (isLocalRunId?.(evt.runId)) {
|
||||
forgetLocalRunId?.(evt.runId);
|
||||
} else {
|
||||
void loadHistory?.();
|
||||
}
|
||||
}
|
||||
tui.requestRender();
|
||||
};
|
||||
@@ -148,12 +183,20 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
const evt = payload as AgentEvent;
|
||||
syncSessionKey();
|
||||
// Agent events (tool streaming, lifecycle) are emitted per-run. Filter against the
|
||||
// active chat run id, not the session id.
|
||||
// active chat run id, not the session id. Tool results can arrive after the chat
|
||||
// final event, so accept finalized runs for tool updates.
|
||||
const isActiveRun = evt.runId === state.activeChatRunId;
|
||||
if (!isActiveRun && !sessionRuns.has(evt.runId)) {
|
||||
const isKnownRun = isActiveRun || sessionRuns.has(evt.runId) || finalizedRuns.has(evt.runId);
|
||||
if (!isKnownRun) {
|
||||
return;
|
||||
}
|
||||
if (evt.stream === "tool") {
|
||||
const verbose = state.sessionInfo.verboseLevel ?? "off";
|
||||
const allowToolEvents = verbose !== "off";
|
||||
const allowToolOutput = verbose === "full";
|
||||
if (!allowToolEvents) {
|
||||
return;
|
||||
}
|
||||
const data = evt.data ?? {};
|
||||
const phase = asString(data.phase, "");
|
||||
const toolCallId = asString(data.toolCallId, "");
|
||||
@@ -164,13 +207,20 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
if (phase === "start") {
|
||||
chatLog.startTool(toolCallId, toolName, data.args);
|
||||
} else if (phase === "update") {
|
||||
if (!allowToolOutput) {
|
||||
return;
|
||||
}
|
||||
chatLog.updateToolResult(toolCallId, data.partialResult, {
|
||||
partial: true,
|
||||
});
|
||||
} else if (phase === "result") {
|
||||
chatLog.updateToolResult(toolCallId, data.result, {
|
||||
isError: Boolean(data.isError),
|
||||
});
|
||||
if (allowToolOutput) {
|
||||
chatLog.updateToolResult(toolCallId, data.result, {
|
||||
isError: Boolean(data.isError),
|
||||
});
|
||||
} else {
|
||||
chatLog.updateToolResult(toolCallId, { content: [] }, { isError: Boolean(data.isError) });
|
||||
}
|
||||
}
|
||||
tui.requestRender();
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user