feat(webui): add tabbed pane workbench (#5322)

This commit is contained in:
chengyongru
2026-08-12 14:45:12 +08:00
committed by GitHub
parent 1656664a47
commit 4b5319b760
38 changed files with 5706 additions and 527 deletions
+1 -1
View File
@@ -339,7 +339,7 @@ function sortProjectSessions(
});
}
function sortSessions(
export function sortSessions(
sessions: ChatSummary[],
sort: SidebarSortMode,
titleOverrides: Record<string, string>,
+20
View File
@@ -73,6 +73,7 @@ type SessionUpdateHandler = (
scope?: SessionUpdateScope,
workspaceScope?: WorkspaceScopePayload,
) => void;
type SidebarStateUpdateHandler = (state: SidebarStatePayload) => void;
type RunStatusHandler = (chatId: string, startedAt: number | null) => void;
/** Structured errors surfaced to the UI.
@@ -178,6 +179,7 @@ export class NanobotClient {
private statusHandlers = new Set<StatusHandler>();
private runtimeModelHandlers = new Set<RuntimeModelHandler>();
private sessionUpdateHandlers = new Set<SessionUpdateHandler>();
private sidebarStateUpdateHandlers = new Set<SidebarStateUpdateHandler>();
private runStatusHandlers = new Set<RunStatusHandler>();
private errorHandlers = new Set<ErrorHandler>();
// chat_id -> handlers listening on it
@@ -275,6 +277,13 @@ export class NanobotClient {
};
}
onSidebarStateUpdate(handler: SidebarStateUpdateHandler): Unsubscribe {
this.sidebarStateUpdateHandlers.add(handler);
return () => {
this.sidebarStateUpdateHandlers.delete(handler);
};
}
onRunStatus(handler: RunStatusHandler): Unsubscribe {
this.runStatusHandlers.add(handler);
for (const [chatId, startedAt] of this.runStartedAtByChatId) {
@@ -1149,6 +1158,11 @@ export class NanobotClient {
return;
}
if (parsed.event === "sidebar_state_updated") {
this.emitSidebarStateUpdate(parsed.state);
return;
}
if (parsed.event === "error" && parsed.detail === "workspace_scope_rejected") {
this.emitError({
kind: "workspace_scope_rejected",
@@ -1198,6 +1212,12 @@ export class NanobotClient {
}
}
private emitSidebarStateUpdate(state: SidebarStatePayload): void {
for (const handler of this.sidebarStateUpdateHandlers) {
handler(state);
}
}
private emitRunStatus(chatId: string, startedAt: number | null): void {
for (const handler of this.runStatusHandlers) {
handler(chatId, startedAt);
+20
View File
@@ -368,6 +368,21 @@ export interface WorkspacesPayload {
export type SidebarDensity = "comfortable" | "compact";
export type SidebarSortMode = "updated_desc" | "created_desc" | "title_asc" | "manual";
export type WorkbenchLayout = "columns" | "rows" | "grid" | "bsp" | "main-stack";
export interface WorkbenchTabState {
explicit: boolean;
title: string | null;
paneKeys: string[];
layoutPaneKeys: string[];
layout: WorkbenchLayout;
splitRatios: number[];
}
export interface WorkbenchState {
version: 1;
tabs: Record<string, WorkbenchTabState>;
}
export interface SidebarViewState {
density: SidebarDensity;
@@ -386,6 +401,7 @@ export interface SidebarStatePayload {
project_name_overrides: Record<string, string>;
tags_by_key: Record<string, string[]>;
collapsed_groups: Record<string, boolean>;
workbench: WorkbenchState;
view: SidebarViewState;
updated_at?: string | null;
}
@@ -1281,6 +1297,10 @@ export type InboundEvent =
scope?: "metadata" | "thread" | string;
workspace_scope?: WorkspaceScopePayload;
}
| {
event: "sidebar_state_updated";
state: SidebarStatePayload;
}
| { event: "transcription_result"; request_id: string; text: string }
| {
event: "transcription_error";