feat(webui): add tabbed pane workbench (#5322)
This commit is contained in:
@@ -339,7 +339,7 @@ function sortProjectSessions(
|
||||
});
|
||||
}
|
||||
|
||||
function sortSessions(
|
||||
export function sortSessions(
|
||||
sessions: ChatSummary[],
|
||||
sort: SidebarSortMode,
|
||||
titleOverrides: Record<string, string>,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user