fix: refresh TUI session info after runs

This commit is contained in:
Peter Steinberger
2026-01-17 08:22:32 +00:00
parent 55622bac06
commit 837eea4ebd
3 changed files with 47 additions and 35 deletions

View File

@@ -27,6 +27,7 @@
- Tools: add tmux-style `process send-keys` and bracketed paste helpers for PTY sessions. - Tools: add tmux-style `process send-keys` and bracketed paste helpers for PTY sessions.
- Tools: add `process submit` helper to send CR for PTY sessions. - Tools: add `process submit` helper to send CR for PTY sessions.
- Tools: respond to PTY cursor position queries to unblock interactive TUIs. - Tools: respond to PTY cursor position queries to unblock interactive TUIs.
- TUI: refresh session token counts after runs complete or fail. (#1079) — thanks @d-ploutarchos.
- Status: trim `/status` to current-provider usage only and drop the OAuth/token block. - Status: trim `/status` to current-provider usage only and drop the OAuth/token block.
- Directory: unify `clawdbot directory` across channels and plugin channels. - Directory: unify `clawdbot directory` across channels and plugin channels.
- UI: allow deleting sessions from the Control UI. - UI: allow deleting sessions from the Control UI.

View File

@@ -72,11 +72,13 @@ export function createEventHandlers(context: EventHandlerContext) {
chatLog.addSystem("run aborted"); chatLog.addSystem("run aborted");
state.activeChatRunId = null; state.activeChatRunId = null;
setActivityStatus("aborted"); setActivityStatus("aborted");
void refreshSessionInfo?.();
} }
if (evt.state === "error") { if (evt.state === "error") {
chatLog.addSystem(`run error: ${evt.errorMessage ?? "unknown"}`); chatLog.addSystem(`run error: ${evt.errorMessage ?? "unknown"}`);
state.activeChatRunId = null; state.activeChatRunId = null;
setActivityStatus("error"); setActivityStatus("error");
void refreshSessionInfo?.();
} }
tui.requestRender(); tui.requestRender();
}; };

View File

@@ -41,6 +41,7 @@ export function createSessionActions(context: SessionActionContext) {
updateAutocompleteProvider, updateAutocompleteProvider,
setActivityStatus, setActivityStatus,
} = context; } = context;
let refreshSessionInfoPromise: Promise<void> | null = null;
const applyAgentsResult = (result: GatewayAgentsList) => { const applyAgentsResult = (result: GatewayAgentsList) => {
state.agentDefaultId = normalizeAgentId(result.defaultId); state.agentDefaultId = normalizeAgentId(result.defaultId);
@@ -95,43 +96,51 @@ export function createSessionActions(context: SessionActionContext) {
}; };
const refreshSessionInfo = async () => { const refreshSessionInfo = async () => {
if (refreshSessionInfoPromise) return refreshSessionInfoPromise;
refreshSessionInfoPromise = (async () => {
try {
const listAgentId =
state.currentSessionKey === "global" || state.currentSessionKey === "unknown"
? undefined
: state.currentAgentId;
const result = await client.listSessions({
includeGlobal: false,
includeUnknown: false,
agentId: listAgentId,
});
const entry = result.sessions.find((row) => {
// Exact match
if (row.key === state.currentSessionKey) return true;
// Also match canonical keys like "agent:default:main" against "main"
const parsed = parseAgentSessionKey(row.key);
return parsed?.rest === state.currentSessionKey;
});
state.sessionInfo = {
thinkingLevel: entry?.thinkingLevel,
verboseLevel: entry?.verboseLevel,
reasoningLevel: entry?.reasoningLevel,
model: entry?.model ?? result.defaults?.model ?? undefined,
modelProvider: entry?.modelProvider ?? result.defaults?.modelProvider ?? undefined,
contextTokens: entry?.contextTokens ?? result.defaults?.contextTokens,
inputTokens: entry?.inputTokens ?? null,
outputTokens: entry?.outputTokens ?? null,
totalTokens: entry?.totalTokens ?? null,
responseUsage: entry?.responseUsage,
updatedAt: entry?.updatedAt ?? null,
displayName: entry?.displayName,
};
} catch (err) {
chatLog.addSystem(`sessions list failed: ${String(err)}`);
}
updateAutocompleteProvider();
updateFooter();
tui.requestRender();
})();
try { try {
const listAgentId = await refreshSessionInfoPromise;
state.currentSessionKey === "global" || state.currentSessionKey === "unknown" } finally {
? undefined refreshSessionInfoPromise = null;
: state.currentAgentId;
const result = await client.listSessions({
includeGlobal: false,
includeUnknown: false,
agentId: listAgentId,
});
const entry = result.sessions.find((row) => {
// Exact match
if (row.key === state.currentSessionKey) return true;
// Also match canonical keys like "agent:default:main" against "main"
const parsed = parseAgentSessionKey(row.key);
return parsed?.rest === state.currentSessionKey;
});
state.sessionInfo = {
thinkingLevel: entry?.thinkingLevel,
verboseLevel: entry?.verboseLevel,
reasoningLevel: entry?.reasoningLevel,
model: entry?.model ?? result.defaults?.model ?? undefined,
modelProvider: entry?.modelProvider ?? result.defaults?.modelProvider ?? undefined,
contextTokens: entry?.contextTokens ?? result.defaults?.contextTokens,
inputTokens: entry?.inputTokens ?? null,
outputTokens: entry?.outputTokens ?? null,
totalTokens: entry?.totalTokens ?? null,
responseUsage: entry?.responseUsage,
updatedAt: entry?.updatedAt ?? null,
displayName: entry?.displayName,
};
} catch (err) {
chatLog.addSystem(`sessions list failed: ${String(err)}`);
} }
updateAutocompleteProvider();
updateFooter();
tui.requestRender();
}; };
const loadHistory = async () => { const loadHistory = async () => {