Compare commits
2 Commits
main
...
fix/tui-to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
504f2b0606 | ||
|
|
e10e81f579 |
@ -27,6 +27,7 @@
|
||||
- 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: 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.
|
||||
- Directory: unify `clawdbot directory` across channels and plugin channels.
|
||||
- UI: allow deleting sessions from the Control UI.
|
||||
|
||||
@ -26,11 +26,11 @@ const workspaceVersions = new Map<string, number>();
|
||||
const watchers = new Map<string, SkillsWatchState>();
|
||||
let globalVersion = 0;
|
||||
|
||||
export const DEFAULT_SKILLS_WATCH_IGNORED = [
|
||||
export const DEFAULT_SKILLS_WATCH_IGNORED: RegExp[] = [
|
||||
/(^|[\\/])\.git([\\/]|$)/,
|
||||
/(^|[\\/])node_modules([\\/]|$)/,
|
||||
/(^|[\\/])dist([\\/]|$)/,
|
||||
] as const;
|
||||
];
|
||||
|
||||
function bumpVersion(current: number): number {
|
||||
const now = Date.now();
|
||||
|
||||
@ -8,10 +8,11 @@ type EventHandlerContext = {
|
||||
tui: TUI;
|
||||
state: TuiStateAccess;
|
||||
setActivityStatus: (text: string) => void;
|
||||
refreshSessionInfo?: () => Promise<void>;
|
||||
};
|
||||
|
||||
export function createEventHandlers(context: EventHandlerContext) {
|
||||
const { chatLog, tui, state, setActivityStatus } = context;
|
||||
const { chatLog, tui, state, setActivityStatus, refreshSessionInfo } = context;
|
||||
const finalizedRuns = new Map<string, number>();
|
||||
|
||||
const noteFinalizedRun = (runId: string) => {
|
||||
@ -64,16 +65,20 @@ export function createEventHandlers(context: EventHandlerContext) {
|
||||
noteFinalizedRun(evt.runId);
|
||||
state.activeChatRunId = null;
|
||||
setActivityStatus(stopReason === "error" ? "error" : "idle");
|
||||
// Refresh session info to update token counts in footer
|
||||
void refreshSessionInfo?.();
|
||||
}
|
||||
if (evt.state === "aborted") {
|
||||
chatLog.addSystem("run aborted");
|
||||
state.activeChatRunId = null;
|
||||
setActivityStatus("aborted");
|
||||
void refreshSessionInfo?.();
|
||||
}
|
||||
if (evt.state === "error") {
|
||||
chatLog.addSystem(`run error: ${evt.errorMessage ?? "unknown"}`);
|
||||
state.activeChatRunId = null;
|
||||
setActivityStatus("error");
|
||||
void refreshSessionInfo?.();
|
||||
}
|
||||
tui.requestRender();
|
||||
};
|
||||
|
||||
@ -41,6 +41,7 @@ export function createSessionActions(context: SessionActionContext) {
|
||||
updateAutocompleteProvider,
|
||||
setActivityStatus,
|
||||
} = context;
|
||||
let refreshSessionInfoPromise: Promise<void> | null = null;
|
||||
|
||||
const applyAgentsResult = (result: GatewayAgentsList) => {
|
||||
state.agentDefaultId = normalizeAgentId(result.defaultId);
|
||||
@ -95,43 +96,51 @@ export function createSessionActions(context: SessionActionContext) {
|
||||
};
|
||||
|
||||
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 {
|
||||
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)}`);
|
||||
await refreshSessionInfoPromise;
|
||||
} finally {
|
||||
refreshSessionInfoPromise = null;
|
||||
}
|
||||
updateAutocompleteProvider();
|
||||
updateFooter();
|
||||
tui.requestRender();
|
||||
};
|
||||
|
||||
const loadHistory = async () => {
|
||||
|
||||
@ -399,6 +399,7 @@ export async function runTui(opts: TuiOptions) {
|
||||
tui,
|
||||
state,
|
||||
setActivityStatus,
|
||||
refreshSessionInfo,
|
||||
});
|
||||
|
||||
const { handleCommand, sendMessage, openModelSelector, openAgentSelector, openSessionSelector } =
|
||||
|
||||
Loading…
Reference in New Issue
Block a user