mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-22 16:58:10 +00:00
fix(tui): show connection host in footer
This commit is contained in:
@@ -54,7 +54,7 @@ Notes:
|
||||
- Header: connection URL, current agent, current session.
|
||||
- Chat log: user messages, assistant replies, system notices, tool cards.
|
||||
- Status line: connection/run state (connecting, running, streaming, idle, error).
|
||||
- Footer: connection state + agent + session + model + goal state + think/fast/verbose/trace/reasoning + token counts + deliver.
|
||||
- Footer: connection host when available + agent + session + model + goal state + think/fast/verbose/trace/reasoning + token counts + deliver.
|
||||
- Input: text editor with autocomplete.
|
||||
|
||||
## Mental model: agents + sessions
|
||||
@@ -67,7 +67,7 @@ Notes:
|
||||
- Session scope:
|
||||
- `per-sender` (default): each agent has many sessions.
|
||||
- `global`: the TUI always uses the `global` session (the picker may be empty).
|
||||
- The current agent + session are always visible in the footer.
|
||||
- For URL-backed connections, the footer includes the connection host alongside the current agent and session.
|
||||
- If the session has a [goal](/tools/goal), the footer shows its compact state
|
||||
such as `Pursuing goal`, `Goal paused (/goal resume)`, or
|
||||
`Goal achieved`.
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
extractContentFromMessage,
|
||||
extractTextFromMessage,
|
||||
extractThinkingFromMessage,
|
||||
formatConnectionHostFooter,
|
||||
formatGoalFooter,
|
||||
isCommandMessage,
|
||||
sanitizeRenderableText,
|
||||
@@ -45,6 +46,19 @@ describe("formatGoalFooter", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatConnectionHostFooter", () => {
|
||||
it("renders only the connection hostname", () => {
|
||||
expect(formatConnectionHostFooter("ws://gateway-host:18789")).toBe("host gateway-host");
|
||||
expect(
|
||||
formatConnectionHostFooter("wss://user:secret@example.com:443/path?token=redacted"),
|
||||
).toBe("host example.com");
|
||||
});
|
||||
|
||||
it("skips non-url local connection labels", () => {
|
||||
expect(formatConnectionHostFooter("local embedded")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractTextFromMessage", () => {
|
||||
it("prefers final_answer text over commentary text for assistant messages", () => {
|
||||
const text = extractTextFromMessage({
|
||||
|
||||
@@ -443,6 +443,15 @@ export function formatTokens(total?: number | null, context?: number | null) {
|
||||
return `tokens ${totalLabel}/${formatTokenCount(context)}${pct !== null ? ` (${pct}%)` : ""}`;
|
||||
}
|
||||
|
||||
export function formatConnectionHostFooter(connectionUrl: string): string | null {
|
||||
try {
|
||||
const hostname = new URL(connectionUrl.trim()).hostname.trim();
|
||||
return hostname ? `host ${hostname}` : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function formatGoalUsage(goal: SessionGoal): string | null {
|
||||
if (goal.tokenBudget === undefined) {
|
||||
return goal.tokensUsed > 0 ? formatTokenCount(goal.tokensUsed) : null;
|
||||
|
||||
@@ -364,6 +364,7 @@ describe.sequential("TUI PTY harness", () => {
|
||||
|
||||
it("renders local ready on startup", () => {
|
||||
expect(fixture.run.output()).toContain("local ready");
|
||||
expect(fixture.run.output()).toContain("host local");
|
||||
});
|
||||
|
||||
it(
|
||||
|
||||
@@ -35,7 +35,7 @@ import { editorTheme, theme } from "./theme/theme.js";
|
||||
import type { TuiBackend } from "./tui-backend.js";
|
||||
import { createCommandHandlers } from "./tui-command-handlers.js";
|
||||
import { createEventHandlers } from "./tui-event-handlers.js";
|
||||
import { formatGoalFooter, formatTokens } from "./tui-formatters.js";
|
||||
import { formatConnectionHostFooter, formatGoalFooter, formatTokens } from "./tui-formatters.js";
|
||||
import {
|
||||
buildTuiLastSessionScopeKey,
|
||||
readTuiLastSessionKey,
|
||||
@@ -1199,7 +1199,9 @@ export async function runTui(opts: RunTuiOptions): Promise<TuiResult> {
|
||||
const reasoning = sessionInfo.reasoningLevel ?? "off";
|
||||
const reasoningLabel =
|
||||
reasoning === "on" ? "reasoning" : reasoning === "stream" ? "reasoning:stream" : null;
|
||||
const hostLabel = formatConnectionHostFooter(client.connection.url);
|
||||
const footerParts = [
|
||||
hostLabel,
|
||||
`agent ${agentLabel}`,
|
||||
`session ${sessionLabel}`,
|
||||
modelLabel,
|
||||
|
||||
Reference in New Issue
Block a user