|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function readBasePath(): string {
|
| if (typeof window === "undefined") return "";
|
| const raw = window.__HERMES_BASE_PATH__ ?? "";
|
| if (!raw) return "";
|
|
|
| const withLead = raw.startsWith("/") ? raw : `/${raw}`;
|
| return withLead.replace(/\/+$/, "");
|
| }
|
|
|
| export const HERMES_BASE_PATH = readBasePath();
|
| const BASE = HERMES_BASE_PATH;
|
|
|
| import type { DashboardTheme } from "@/themes/types";
|
|
|
|
|
|
|
| declare global {
|
| interface Window {
|
| __HERMES_SESSION_TOKEN__?: string;
|
| __HERMES_BASE_PATH__?: string;
|
| |
| |
| |
|
|
| __HERMES_AUTH_REQUIRED__?: boolean;
|
| }
|
| }
|
| let _sessionToken: string | null = null;
|
| const SESSION_HEADER = "X-Hermes-Session-Token";
|
|
|
| function setSessionHeader(headers: Headers, token: string): void {
|
| if (!headers.has(SESSION_HEADER)) {
|
| headers.set(SESSION_HEADER, token);
|
| }
|
| }
|
|
|
| export async function fetchJSON<T>(url: string, init?: RequestInit): Promise<T> {
|
|
|
| const headers = new Headers(init?.headers);
|
| const token = window.__HERMES_SESSION_TOKEN__;
|
| if (token) {
|
| setSessionHeader(headers, token);
|
| }
|
| const res = await fetch(`${BASE}${url}`, {
|
| ...init,
|
| headers,
|
|
|
|
|
|
|
|
|
| credentials: init?.credentials ?? "include",
|
| });
|
| if (res.status === 401) {
|
|
|
|
|
|
|
|
|
|
|
| let body: { error?: string; login_url?: string } = {};
|
| try {
|
| body = await res.clone().json();
|
| } catch {
|
|
|
| }
|
| if (
|
| (body.error === "unauthenticated" || body.error === "session_expired") &&
|
| body.login_url
|
| ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| try {
|
| sessionStorage.setItem(
|
| "hermes.lastLocation",
|
| window.location.pathname + window.location.search,
|
| );
|
| } catch {
|
|
|
| }
|
| window.location.assign(body.login_url);
|
|
|
| return new Promise<T>(() => {});
|
| }
|
| }
|
| if (!res.ok) {
|
| const text = await res.text().catch(() => res.statusText);
|
| throw new Error(`${res.status}: ${text}`);
|
| }
|
| return res.json();
|
| }
|
|
|
|
|
| function pluginPath(name: string): string {
|
| return name.split("/").map(encodeURIComponent).join("/");
|
| }
|
|
|
| async function getSessionToken(): Promise<string> {
|
| if (_sessionToken) return _sessionToken;
|
| const injected = window.__HERMES_SESSION_TOKEN__;
|
| if (injected) {
|
| _sessionToken = injected;
|
| return _sessionToken;
|
| }
|
| throw new Error("Session token not available β page must be served by the Hermes dashboard server");
|
| }
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| export async function getWsTicket(): Promise<{ ticket: string; ttl_seconds: number }> {
|
| const res = await fetch(`${BASE}/api/auth/ws-ticket`, {
|
| method: "POST",
|
| credentials: "include",
|
| });
|
| if (!res.ok) {
|
| throw new Error(`/api/auth/ws-ticket: HTTP ${res.status}`);
|
| }
|
| return res.json();
|
| }
|
|
|
| |
| |
| |
| |
|
|
| export async function buildWsAuthParam(): Promise<[string, string]> {
|
| if (window.__HERMES_AUTH_REQUIRED__) {
|
| const { ticket } = await getWsTicket();
|
| return ["ticket", ticket];
|
| }
|
| const token = window.__HERMES_SESSION_TOKEN__ ?? "";
|
| return ["token", token];
|
| }
|
|
|
| export const api = {
|
| getStatus: () => fetchJSON<StatusResponse>("/api/status"),
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| getAuthMe: () => fetchJSON<AuthMeResponse>("/api/auth/me"),
|
| logout: () =>
|
| fetch(`${BASE}/auth/logout`, {
|
| method: "POST",
|
| credentials: "include",
|
| }).then((r) => {
|
|
|
|
|
|
|
| window.location.assign("/login");
|
| return r;
|
| }),
|
| getSessions: (limit = 20, offset = 0) =>
|
| fetchJSON<PaginatedSessions>(`/api/sessions?limit=${limit}&offset=${offset}`),
|
| getSessionMessages: (id: string) =>
|
| fetchJSON<SessionMessagesResponse>(`/api/sessions/${encodeURIComponent(id)}/messages`),
|
| getSessionLatestDescendant: (id: string) =>
|
| fetchJSON<SessionLatestDescendantResponse>(
|
| `/api/sessions/${encodeURIComponent(id)}/latest-descendant`,
|
| ),
|
| deleteSession: (id: string) =>
|
| fetchJSON<{ ok: boolean }>(`/api/sessions/${encodeURIComponent(id)}`, {
|
| method: "DELETE",
|
| }),
|
| getLogs: (params: { file?: string; lines?: number; level?: string; component?: string }) => {
|
| const qs = new URLSearchParams();
|
| if (params.file) qs.set("file", params.file);
|
| if (params.lines) qs.set("lines", String(params.lines));
|
| if (params.level && params.level !== "ALL") qs.set("level", params.level);
|
| if (params.component && params.component !== "all") qs.set("component", params.component);
|
| return fetchJSON<LogsResponse>(`/api/logs?${qs.toString()}`);
|
| },
|
| getAnalytics: (days: number) =>
|
| fetchJSON<AnalyticsResponse>(`/api/analytics/usage?days=${days}`),
|
| getModelsAnalytics: (days: number) =>
|
| fetchJSON<ModelsAnalyticsResponse>(`/api/analytics/models?days=${days}`),
|
| getConfig: () => fetchJSON<Record<string, unknown>>("/api/config"),
|
| getDefaults: () => fetchJSON<Record<string, unknown>>("/api/config/defaults"),
|
| getSchema: () => fetchJSON<{ fields: Record<string, unknown>; category_order: string[] }>("/api/config/schema"),
|
| getModelInfo: () => fetchJSON<ModelInfoResponse>("/api/model/info"),
|
| getModelOptions: () => fetchJSON<ModelOptionsResponse>("/api/model/options"),
|
| getAuxiliaryModels: () => fetchJSON<AuxiliaryModelsResponse>("/api/model/auxiliary"),
|
| setModelAssignment: (body: ModelAssignmentRequest) =>
|
| fetchJSON<ModelAssignmentResponse>("/api/model/set", {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify(body),
|
| }),
|
| saveConfig: (config: Record<string, unknown>) =>
|
| fetchJSON<{ ok: boolean }>("/api/config", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ config }),
|
| }),
|
| getConfigRaw: () => fetchJSON<{ yaml: string }>("/api/config/raw"),
|
| saveConfigRaw: (yaml_text: string) =>
|
| fetchJSON<{ ok: boolean }>("/api/config/raw", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ yaml_text }),
|
| }),
|
| getEnvVars: () => fetchJSON<Record<string, EnvVarInfo>>("/api/env"),
|
| setEnvVar: (key: string, value: string) =>
|
| fetchJSON<{ ok: boolean }>("/api/env", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ key, value }),
|
| }),
|
| deleteEnvVar: (key: string) =>
|
| fetchJSON<{ ok: boolean }>("/api/env", {
|
| method: "DELETE",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ key }),
|
| }),
|
| revealEnvVar: async (key: string) => {
|
| const token = await getSessionToken();
|
| return fetchJSON<{ key: string; value: string }>("/api/env/reveal", {
|
| method: "POST",
|
| headers: {
|
| "Content-Type": "application/json",
|
| [SESSION_HEADER]: token,
|
| },
|
| body: JSON.stringify({ key }),
|
| });
|
| },
|
|
|
|
|
| getCronJobs: (profile = "all") =>
|
| fetchJSON<CronJob[]>(`/api/cron/jobs?profile=${encodeURIComponent(profile)}`),
|
| createCronJob: (job: { prompt: string; schedule: string; name?: string; deliver?: string }, profile = "default") =>
|
| fetchJSON<CronJob>(`/api/cron/jobs?profile=${encodeURIComponent(profile)}`, {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify(job),
|
| }),
|
| pauseCronJob: (id: string, profile = "default") =>
|
| fetchJSON<CronJob>(`/api/cron/jobs/${encodeURIComponent(id)}/pause?profile=${encodeURIComponent(profile)}`, { method: "POST" }),
|
| resumeCronJob: (id: string, profile = "default") =>
|
| fetchJSON<CronJob>(`/api/cron/jobs/${encodeURIComponent(id)}/resume?profile=${encodeURIComponent(profile)}`, { method: "POST" }),
|
| triggerCronJob: (id: string, profile = "default") =>
|
| fetchJSON<CronJob>(`/api/cron/jobs/${encodeURIComponent(id)}/trigger?profile=${encodeURIComponent(profile)}`, { method: "POST" }),
|
| deleteCronJob: (id: string, profile = "default") =>
|
| fetchJSON<{ ok: boolean }>(`/api/cron/jobs/${encodeURIComponent(id)}?profile=${encodeURIComponent(profile)}`, { method: "DELETE" }),
|
|
|
|
|
| getProfiles: () =>
|
| fetchJSON<{ profiles: ProfileInfo[] }>("/api/profiles"),
|
| createProfile: (body: { name: string; clone_from_default: boolean }) =>
|
| fetchJSON<{ ok: boolean; name: string; path: string }>("/api/profiles", {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify(body),
|
| }),
|
| renameProfile: (name: string, newName: string) =>
|
| fetchJSON<{ ok: boolean; name: string; path: string }>(
|
| `/api/profiles/${encodeURIComponent(name)}`,
|
| {
|
| method: "PATCH",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ new_name: newName }),
|
| },
|
| ),
|
| deleteProfile: (name: string) =>
|
| fetchJSON<{ ok: boolean }>(
|
| `/api/profiles/${encodeURIComponent(name)}`,
|
| { method: "DELETE" },
|
| ),
|
| getProfileSetupCommand: (name: string) =>
|
| fetchJSON<{ command: string }>(
|
| `/api/profiles/${encodeURIComponent(name)}/setup-command`,
|
| ),
|
| getProfileSoul: (name: string) =>
|
| fetchJSON<{ content: string; exists: boolean }>(
|
| `/api/profiles/${encodeURIComponent(name)}/soul`,
|
| ),
|
| updateProfileSoul: (name: string, content: string) =>
|
| fetchJSON<{ ok: boolean }>(
|
| `/api/profiles/${encodeURIComponent(name)}/soul`,
|
| {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ content }),
|
| },
|
| ),
|
|
|
|
|
| getSkills: () => fetchJSON<SkillInfo[]>("/api/skills"),
|
| toggleSkill: (name: string, enabled: boolean) =>
|
| fetchJSON<{ ok: boolean }>("/api/skills/toggle", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ name, enabled }),
|
| }),
|
| getToolsets: () => fetchJSON<ToolsetInfo[]>("/api/tools/toolsets"),
|
|
|
|
|
| searchSessions: (q: string) =>
|
| fetchJSON<SessionSearchResponse>(`/api/sessions/search?q=${encodeURIComponent(q)}`),
|
|
|
|
|
| getOAuthProviders: () =>
|
| fetchJSON<OAuthProvidersResponse>("/api/providers/oauth"),
|
| disconnectOAuthProvider: async (providerId: string) => {
|
| const token = await getSessionToken();
|
| return fetchJSON<{ ok: boolean; provider: string }>(
|
| `/api/providers/oauth/${encodeURIComponent(providerId)}`,
|
| {
|
| method: "DELETE",
|
| headers: { [SESSION_HEADER]: token },
|
| },
|
| );
|
| },
|
| startOAuthLogin: async (providerId: string) => {
|
| const token = await getSessionToken();
|
| return fetchJSON<OAuthStartResponse>(
|
| `/api/providers/oauth/${encodeURIComponent(providerId)}/start`,
|
| {
|
| method: "POST",
|
| headers: {
|
| "Content-Type": "application/json",
|
| [SESSION_HEADER]: token,
|
| },
|
| body: "{}",
|
| },
|
| );
|
| },
|
| submitOAuthCode: async (providerId: string, sessionId: string, code: string) => {
|
| const token = await getSessionToken();
|
| return fetchJSON<OAuthSubmitResponse>(
|
| `/api/providers/oauth/${encodeURIComponent(providerId)}/submit`,
|
| {
|
| method: "POST",
|
| headers: {
|
| "Content-Type": "application/json",
|
| [SESSION_HEADER]: token,
|
| },
|
| body: JSON.stringify({ session_id: sessionId, code }),
|
| },
|
| );
|
| },
|
| pollOAuthSession: (providerId: string, sessionId: string) =>
|
| fetchJSON<OAuthPollResponse>(
|
| `/api/providers/oauth/${encodeURIComponent(providerId)}/poll/${encodeURIComponent(sessionId)}`,
|
| ),
|
| cancelOAuthSession: async (sessionId: string) => {
|
| const token = await getSessionToken();
|
| return fetchJSON<{ ok: boolean }>(
|
| `/api/providers/oauth/sessions/${encodeURIComponent(sessionId)}`,
|
| {
|
| method: "DELETE",
|
| headers: { [SESSION_HEADER]: token },
|
| },
|
| );
|
| },
|
|
|
|
|
| restartGateway: () =>
|
| fetchJSON<ActionResponse>("/api/gateway/restart", { method: "POST" }),
|
| updateHermes: () =>
|
| fetchJSON<ActionResponse>("/api/hermes/update", { method: "POST" }),
|
| getActionStatus: (name: string, lines = 200) =>
|
| fetchJSON<ActionStatusResponse>(
|
| `/api/actions/${encodeURIComponent(name)}/status?lines=${lines}`,
|
| ),
|
|
|
|
|
| getPlugins: () =>
|
| fetchJSON<PluginManifestResponse[]>("/api/dashboard/plugins"),
|
| rescanPlugins: () =>
|
| fetchJSON<{ ok: boolean; count: number }>("/api/dashboard/plugins/rescan"),
|
|
|
| getPluginsHub: () => fetchJSON<PluginsHubResponse>("/api/dashboard/plugins/hub"),
|
|
|
| installAgentPlugin: (body: AgentPluginInstallRequest) =>
|
| fetchJSON<AgentPluginInstallResponse>("/api/dashboard/agent-plugins/install", {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ ...body }),
|
| }),
|
|
|
| enableAgentPlugin: (name: string) =>
|
| fetchJSON<{ ok: boolean; name: string; unchanged?: boolean }>(
|
| `/api/dashboard/agent-plugins/${pluginPath(name)}/enable`,
|
| { method: "POST" },
|
| ),
|
|
|
| disableAgentPlugin: (name: string) =>
|
| fetchJSON<{ ok: boolean; name: string; unchanged?: boolean }>(
|
| `/api/dashboard/agent-plugins/${pluginPath(name)}/disable`,
|
| { method: "POST" },
|
| ),
|
|
|
| updateAgentPlugin: (name: string) =>
|
| fetchJSON<AgentPluginUpdateResponse>(
|
| `/api/dashboard/agent-plugins/${pluginPath(name)}/update`,
|
| { method: "POST" },
|
| ),
|
|
|
| removeAgentPlugin: (name: string) =>
|
| fetchJSON<{ ok: boolean; name: string }>(
|
| `/api/dashboard/agent-plugins/${pluginPath(name)}`,
|
| { method: "DELETE" },
|
| ),
|
|
|
| savePluginProviders: (body: PluginProvidersPutRequest) =>
|
| fetchJSON<{ ok: boolean }>("/api/dashboard/plugin-providers", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify(body),
|
| }),
|
|
|
| setPluginVisibility: (name: string, hidden: boolean) =>
|
| fetchJSON<{ ok: boolean; name: string; hidden: boolean }>(
|
| `/api/dashboard/plugins/${pluginPath(name)}/visibility`,
|
| {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ hidden }),
|
| },
|
| ),
|
|
|
|
|
| getThemes: () =>
|
| fetchJSON<DashboardThemesResponse>("/api/dashboard/themes"),
|
| setTheme: (name: string) =>
|
| fetchJSON<{ ok: boolean; theme: string }>("/api/dashboard/theme", {
|
| method: "PUT",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify({ name }),
|
| }),
|
| };
|
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| export interface AuthMeResponse {
|
| user_id: string;
|
| email: string;
|
| display_name: string;
|
| org_id: string;
|
| provider: string;
|
| expires_at: number;
|
| }
|
|
|
| export interface ActionResponse {
|
| name: string;
|
| ok: boolean;
|
| pid: number;
|
| }
|
|
|
| export interface ActionStatusResponse {
|
| exit_code: number | null;
|
| lines: string[];
|
| name: string;
|
| pid: number | null;
|
| running: boolean;
|
| }
|
|
|
| export interface PlatformStatus {
|
| error_code?: string;
|
| error_message?: string;
|
| state: string;
|
| updated_at: string;
|
| }
|
|
|
| export interface StatusResponse {
|
| active_sessions: number;
|
| |
| |
|
|
| auth_required?: boolean;
|
| |
| |
|
|
| auth_providers?: string[];
|
| config_path: string;
|
| config_version: number;
|
| env_path: string;
|
| gateway_exit_reason: string | null;
|
| gateway_health_url: string | null;
|
| gateway_pid: number | null;
|
| gateway_platforms: Record<string, PlatformStatus>;
|
| gateway_running: boolean;
|
| gateway_state: string | null;
|
| gateway_updated_at: string | null;
|
| hermes_home: string;
|
| latest_config_version: number;
|
| release_date: string;
|
| version: string;
|
| }
|
|
|
| export interface SessionInfo {
|
| id: string;
|
| source: string | null;
|
| model: string | null;
|
| title: string | null;
|
| started_at: number;
|
| ended_at: number | null;
|
| last_active: number;
|
| is_active: boolean;
|
| message_count: number;
|
| tool_call_count: number;
|
| input_tokens: number;
|
| output_tokens: number;
|
| preview: string | null;
|
| parent_session_id?: string | null;
|
| }
|
|
|
| export interface SessionLatestDescendantResponse {
|
| requested_session_id: string;
|
| session_id: string;
|
| path: string[];
|
| changed: boolean;
|
| }
|
|
|
| export interface PaginatedSessions {
|
| sessions: SessionInfo[];
|
| total: number;
|
| limit: number;
|
| offset: number;
|
| }
|
|
|
| export interface EnvVarInfo {
|
| is_set: boolean;
|
| redacted_value: string | null;
|
| description: string;
|
| url: string | null;
|
| category: string;
|
| is_password: boolean;
|
| tools: string[];
|
| advanced: boolean;
|
| }
|
|
|
| export interface SessionMessage {
|
| role: "user" | "assistant" | "system" | "tool";
|
| content: string | null;
|
| tool_calls?: Array<{
|
| id: string;
|
| function: { name: string; arguments: string };
|
| }>;
|
| tool_name?: string;
|
| tool_call_id?: string;
|
| timestamp?: number;
|
| }
|
|
|
| export interface SessionMessagesResponse {
|
| session_id: string;
|
| messages: SessionMessage[];
|
| }
|
|
|
| export interface LogsResponse {
|
| file: string;
|
| lines: string[];
|
| }
|
|
|
| export interface AnalyticsDailyEntry {
|
| day: string;
|
| input_tokens: number;
|
| output_tokens: number;
|
| cache_read_tokens: number;
|
| reasoning_tokens: number;
|
| estimated_cost: number;
|
| actual_cost: number;
|
| sessions: number;
|
| api_calls: number;
|
| }
|
|
|
| export interface AnalyticsModelEntry {
|
| model: string;
|
| input_tokens: number;
|
| output_tokens: number;
|
| estimated_cost: number;
|
| sessions: number;
|
| api_calls: number;
|
| }
|
|
|
| export interface AnalyticsSkillEntry {
|
| skill: string;
|
| view_count: number;
|
| manage_count: number;
|
| total_count: number;
|
| percentage: number;
|
| last_used_at: number | null;
|
| }
|
|
|
| export interface AnalyticsSkillsSummary {
|
| total_skill_loads: number;
|
| total_skill_edits: number;
|
| total_skill_actions: number;
|
| distinct_skills_used: number;
|
| }
|
|
|
| export interface AnalyticsResponse {
|
| daily: AnalyticsDailyEntry[];
|
| by_model: AnalyticsModelEntry[];
|
| totals: {
|
| total_input: number;
|
| total_output: number;
|
| total_cache_read: number;
|
| total_reasoning: number;
|
| total_estimated_cost: number;
|
| total_actual_cost: number;
|
| total_sessions: number;
|
| total_api_calls: number;
|
| };
|
| skills: {
|
| summary: AnalyticsSkillsSummary;
|
| top_skills: AnalyticsSkillEntry[];
|
| };
|
| }
|
|
|
| export interface ProfileInfo {
|
| name: string;
|
| path: string;
|
| is_default: boolean;
|
| model: string | null;
|
| provider: string | null;
|
| has_env: boolean;
|
| skill_count: number;
|
| }
|
|
|
| export interface ModelsAnalyticsModelEntry {
|
| model: string;
|
| provider: string;
|
| input_tokens: number;
|
| output_tokens: number;
|
| cache_read_tokens: number;
|
| reasoning_tokens: number;
|
| estimated_cost: number;
|
| actual_cost: number;
|
| sessions: number;
|
| api_calls: number;
|
| tool_calls: number;
|
| last_used_at: number;
|
| avg_tokens_per_session: number;
|
| capabilities: {
|
| supports_tools?: boolean;
|
| supports_vision?: boolean;
|
| supports_reasoning?: boolean;
|
| context_window?: number;
|
| max_output_tokens?: number;
|
| model_family?: string;
|
| };
|
| }
|
|
|
| export interface ModelsAnalyticsResponse {
|
| models: ModelsAnalyticsModelEntry[];
|
| totals: {
|
| distinct_models: number;
|
| total_input: number;
|
| total_output: number;
|
| total_cache_read: number;
|
| total_reasoning: number;
|
| total_estimated_cost: number;
|
| total_actual_cost: number;
|
| total_sessions: number;
|
| total_api_calls: number;
|
| };
|
| period_days: number;
|
| }
|
|
|
| export interface CronJob {
|
| id: string;
|
| profile?: string | null;
|
| profile_name?: string | null;
|
| hermes_home?: string | null;
|
| is_default_profile?: boolean;
|
| name?: string | null;
|
| prompt?: string | null;
|
| script?: string | null;
|
| schedule?: { kind?: string; expr?: string; display?: string };
|
| schedule_display?: string | null;
|
| enabled: boolean;
|
| state?: string | null;
|
| deliver?: string | null;
|
| last_run_at?: string | null;
|
| next_run_at?: string | null;
|
| last_error?: string | null;
|
| }
|
|
|
| export interface SkillInfo {
|
| name: string;
|
| description: string;
|
| category: string;
|
| enabled: boolean;
|
| }
|
|
|
| export interface ToolsetInfo {
|
| name: string;
|
| label: string;
|
| description: string;
|
| enabled: boolean;
|
| configured: boolean;
|
| tools: string[];
|
| }
|
|
|
| export interface SessionSearchResult {
|
| session_id: string;
|
| snippet: string;
|
| role: string | null;
|
| source: string | null;
|
| model: string | null;
|
| session_started: number | null;
|
| }
|
|
|
| export interface SessionSearchResponse {
|
| results: SessionSearchResult[];
|
| }
|
|
|
|
|
|
|
| export interface ModelInfoResponse {
|
| model: string;
|
| provider: string;
|
| auto_context_length: number;
|
| config_context_length: number;
|
| effective_context_length: number;
|
| capabilities: {
|
| supports_tools?: boolean;
|
| supports_vision?: boolean;
|
| supports_reasoning?: boolean;
|
| context_window?: number;
|
| max_output_tokens?: number;
|
| model_family?: string;
|
| };
|
| }
|
|
|
|
|
|
|
| export interface ModelOptionProvider {
|
| name: string;
|
| slug: string;
|
| models?: string[];
|
| total_models?: number;
|
| is_current?: boolean;
|
| is_user_defined?: boolean;
|
| source?: string;
|
| warning?: string;
|
| }
|
|
|
| export interface ModelOptionsResponse {
|
| model?: string;
|
| provider?: string;
|
| providers?: ModelOptionProvider[];
|
| }
|
|
|
| export interface AuxiliaryTaskAssignment {
|
| task: string;
|
| provider: string;
|
| model: string;
|
| base_url: string;
|
| }
|
|
|
| export interface AuxiliaryModelsResponse {
|
| tasks: AuxiliaryTaskAssignment[];
|
| main: { provider: string; model: string };
|
| }
|
|
|
| export interface ModelAssignmentRequest {
|
| scope: "main" | "auxiliary";
|
| provider: string;
|
| model: string;
|
|
|
| task?: string;
|
| }
|
|
|
| export interface ModelAssignmentResponse {
|
| ok: boolean;
|
| scope?: string;
|
| provider?: string;
|
| model?: string;
|
| tasks?: string[];
|
| reset?: boolean;
|
| }
|
|
|
|
|
|
|
| export interface OAuthProviderStatus {
|
| logged_in: boolean;
|
| source?: string | null;
|
| source_label?: string | null;
|
| token_preview?: string | null;
|
| expires_at?: string | null;
|
| has_refresh_token?: boolean;
|
| last_refresh?: string | null;
|
| error?: string;
|
| }
|
|
|
| export interface OAuthProvider {
|
| id: string;
|
| name: string;
|
| |
|
|
| flow: "pkce" | "device_code" | "external";
|
| cli_command: string;
|
| docs_url: string;
|
| status: OAuthProviderStatus;
|
| }
|
|
|
| export interface OAuthProvidersResponse {
|
| providers: OAuthProvider[];
|
| }
|
|
|
|
|
| export type OAuthStartResponse =
|
| | {
|
| session_id: string;
|
| flow: "pkce";
|
| auth_url: string;
|
| expires_in: number;
|
| }
|
| | {
|
| session_id: string;
|
| flow: "device_code";
|
| user_code: string;
|
| verification_url: string;
|
| expires_in: number;
|
| poll_interval: number;
|
| };
|
|
|
| export interface OAuthSubmitResponse {
|
| ok: boolean;
|
| status: "approved" | "error";
|
| message?: string;
|
| }
|
|
|
| export interface OAuthPollResponse {
|
| session_id: string;
|
| status: "pending" | "approved" | "denied" | "expired" | "error";
|
| error_message?: string | null;
|
| expires_at?: number | null;
|
| }
|
|
|
|
|
|
|
| export interface DashboardThemeSummary {
|
| description: string;
|
| label: string;
|
| name: string;
|
| |
|
|
| definition?: DashboardTheme;
|
| }
|
|
|
| export interface DashboardThemesResponse {
|
| active: string;
|
| themes: DashboardThemeSummary[];
|
| }
|
|
|
|
|
|
|
| export interface PluginManifestResponse {
|
| name: string;
|
| label: string;
|
| description: string;
|
| icon: string;
|
| version: string;
|
| tab: {
|
| path: string;
|
| position?: string;
|
| override?: string;
|
| hidden?: boolean;
|
| };
|
| slots?: string[];
|
| entry: string;
|
| css?: string | null;
|
| has_api: boolean;
|
| source: string;
|
| }
|
|
|
| export interface HubAgentPluginRow {
|
| name: string;
|
| version: string;
|
| description: string;
|
| source: string;
|
| runtime_status: "disabled" | "enabled" | "inactive";
|
| has_dashboard_manifest: boolean;
|
| dashboard_manifest: PluginManifestResponse | null;
|
| path: string;
|
| can_remove: boolean;
|
| can_update_git: boolean;
|
| auth_required: boolean;
|
| auth_command: string;
|
| user_hidden: boolean;
|
| }
|
|
|
| export interface PluginsHubProviders {
|
| memory_provider: string;
|
| memory_options: Array<{ name: string; description: string }>;
|
| context_engine: string;
|
| context_options: Array<{ name: string; description: string }>;
|
| }
|
|
|
| export interface PluginsHubResponse {
|
| plugins: HubAgentPluginRow[];
|
| orphan_dashboard_plugins: PluginManifestResponse[];
|
| providers: PluginsHubProviders;
|
| }
|
|
|
| export interface AgentPluginInstallRequest {
|
| identifier: string;
|
| force?: boolean;
|
| enable?: boolean;
|
| }
|
|
|
| export interface AgentPluginInstallResponse {
|
| ok: boolean;
|
| plugin_name?: string;
|
| warnings?: string[];
|
| missing_env?: string[];
|
| after_install_path?: string | null;
|
| enabled?: boolean;
|
| error?: string;
|
| }
|
|
|
| export interface AgentPluginUpdateResponse {
|
| ok: boolean;
|
| name?: string;
|
| output?: string;
|
| unchanged?: boolean;
|
| error?: string;
|
| }
|
|
|
| export interface PluginProvidersPutRequest {
|
| memory_provider?: string;
|
| context_engine?: string;
|
| }
|
|
|