mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
122 lines
5.6 KiB
TypeScript
122 lines
5.6 KiB
TypeScript
import { consume } from "@lit/context";
|
|
import { property } from "lit/decorators.js";
|
|
import type { UpdateAvailable } from "../api/types.ts";
|
|
import { DEFAULT_SIDEBAR_ENTRIES, type NavigationRouteId } from "../app-navigation.ts";
|
|
import type { RouteId } from "../app-route-paths.ts";
|
|
import { selectApplicationSession } from "../app/agent-selection.ts";
|
|
import {
|
|
applicationContext,
|
|
type ApplicationContext,
|
|
type ApplicationNavigationOptions,
|
|
} from "../app/context.ts";
|
|
import type { CatalogOpenTarget } from "../app/settings.ts";
|
|
import type { ThemeMode } from "../app/theme.ts";
|
|
import { readSessionMethodAccess, type SessionMethodAccess } from "../lib/session-method-access.ts";
|
|
import { prepareSessionNavigationHandoff } from "../lib/sessions/navigation-handoff.ts";
|
|
import { SESSION_NAVIGATION_KEY_PARAM } from "../lib/sessions/route-navigation.ts";
|
|
import { parseAgentSessionKey } from "../lib/sessions/session-key.ts";
|
|
import { OpenClawLightDomContentsElement } from "../lit/openclaw-element.ts";
|
|
import type { NewSessionTarget } from "../pages/new-session/location.ts";
|
|
import type { SidebarWorkboardBoard, SidebarWorkboardRenderers } from "./app-sidebar-workboard.ts";
|
|
|
|
/** Stable custom-element inputs. Behavior is layered in focused sidebar modules. */
|
|
export abstract class AppSidebarBase extends OpenClawLightDomContentsElement {
|
|
@property({ attribute: false }) basePath = "";
|
|
@property({ attribute: false }) activeRouteId?: NavigationRouteId;
|
|
@property({ attribute: false }) activePluginTabId = "";
|
|
@property({ attribute: false }) activeWorkboardBoardId = "";
|
|
@property({ attribute: false }) enabledRouteIds?: readonly NavigationRouteId[];
|
|
@property({ attribute: false }) connected = false;
|
|
@property({ attribute: false }) offline = false;
|
|
@property({ attribute: false }) outboxCountForSession: (sessionKey: string) => number = () => 0;
|
|
@property({ attribute: false }) terminalAvailable = false;
|
|
@property({ attribute: false }) catalogOpenTarget: CatalogOpenTarget = "viewer";
|
|
@property({ attribute: false }) canPairDevice = false;
|
|
@property({ attribute: false }) sessionKey = "";
|
|
@property({ attribute: false }) sidebarEntries: readonly string[] = DEFAULT_SIDEBAR_ENTRIES;
|
|
@property({ attribute: false }) workboardBoards: readonly SidebarWorkboardBoard[] = [];
|
|
@property({ attribute: false }) workboardBoardsReady = false;
|
|
@property({ attribute: false }) workboardRenderers?: SidebarWorkboardRenderers;
|
|
@property({ attribute: false }) sidebarLiveActivity = true;
|
|
/** Agents surfaced first in the chip quick switcher when many exist. */
|
|
@property({ attribute: false }) pinnedAgentIds: readonly string[] = [];
|
|
@property({ attribute: false }) themeMode: ThemeMode = "system";
|
|
@property({ attribute: false }) lobsterPetVisits = true;
|
|
@property({ attribute: false }) lobsterPetSounds = false;
|
|
@property({ attribute: false }) gatewayVersion: string | null = null;
|
|
@property({ attribute: false }) devGitBranch: string | null = null;
|
|
@property({ attribute: false }) updateAvailable: UpdateAvailable | null = null;
|
|
@property({ attribute: false }) updateRunning = false;
|
|
@property({ attribute: false }) onUpdate: () => void = () => undefined;
|
|
@property({ attribute: false }) onOpenApprovals?: () => void;
|
|
@property({ attribute: false }) onRetryConnect?: () => void;
|
|
@property({ attribute: false }) onOpenNewSession?: (
|
|
agentId: string,
|
|
target?: NewSessionTarget,
|
|
) => void;
|
|
/** Agent id of the in-flight new-session draft; renders the draft row. */
|
|
@property({ attribute: false }) draftSessionAgentId = "";
|
|
@property({ attribute: false }) onUpdateSidebarEntries?: (entries: string[]) => void;
|
|
@property({ attribute: false }) onPairMobile?: () => void;
|
|
@property({ attribute: false })
|
|
onNavigate?: (routeId: NavigationRouteId, options?: ApplicationNavigationOptions) => void;
|
|
@property({ attribute: false }) onPreloadRoute?: (routeId: NavigationRouteId) => Promise<void>;
|
|
|
|
@consume({ context: applicationContext, subscribe: true })
|
|
protected context?: ApplicationContext<RouteId>;
|
|
|
|
protected setApplicationSession(sessionKey: string, fallbackAgentId?: string): void {
|
|
const context = this.context;
|
|
if (!context) {
|
|
return;
|
|
}
|
|
selectApplicationSession({
|
|
selection: context.agentSelection,
|
|
gateway: context.gateway,
|
|
sessionKey,
|
|
agentId: parseAgentSessionKey(sessionKey)?.agentId ?? fallbackAgentId,
|
|
});
|
|
}
|
|
|
|
prepareSessionNavigation(sessionKey: string, pathname: string): void {
|
|
if (this.context) {
|
|
prepareSessionNavigationHandoff(this.context.gateway, pathname, sessionKey);
|
|
}
|
|
}
|
|
|
|
protected bindLiteralSession(
|
|
sessionKey: string,
|
|
fallbackAgentId: string,
|
|
options: ApplicationNavigationOptions,
|
|
): void {
|
|
if (!new URLSearchParams(options.search ?? "").has(SESSION_NAVIGATION_KEY_PARAM)) {
|
|
this.setApplicationSession(sessionKey, fallbackAgentId);
|
|
}
|
|
}
|
|
|
|
readNewSessionAccess(): SessionMethodAccess {
|
|
return readSessionMethodAccess(this.connected ? this.context?.gateway.snapshot : null, {
|
|
method: "sessions.create",
|
|
params: {},
|
|
});
|
|
}
|
|
|
|
readSessionMutationAccess(request: {
|
|
method: string;
|
|
params?: unknown;
|
|
requiredScope?: "operator.write" | "operator.admin";
|
|
}): SessionMethodAccess {
|
|
return readSessionMethodAccess(this.connected ? this.context?.gateway.snapshot : null, request);
|
|
}
|
|
|
|
requestOpenNewSession(agentId: string, target?: NewSessionTarget): void {
|
|
if (this.readNewSessionAccess().allowed) {
|
|
if (target) {
|
|
this.onOpenNewSession?.(agentId, target);
|
|
} else {
|
|
this.onOpenNewSession?.(agentId);
|
|
}
|
|
}
|
|
}
|
|
}
|