mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-08 21:09:23 +08:00
chore: Fix all TypeScript errors in ui.
This commit is contained in:
@@ -10,7 +10,7 @@ import { loadSessions } from "./controllers/sessions";
|
||||
import { normalizeBasePath } from "./navigation";
|
||||
import { generateUUID } from "./uuid";
|
||||
|
||||
type ChatHost = {
|
||||
export type ChatHost = {
|
||||
connected: boolean;
|
||||
chatMessage: string;
|
||||
chatAttachments: ChatAttachment[];
|
||||
|
||||
@@ -4,9 +4,10 @@ import type { AppViewState } from "./app-view-state";
|
||||
import type { ThemeMode } from "./theme";
|
||||
import type { ThemeTransitionContext } from "./theme-transition";
|
||||
import type { SessionsListResult } from "./types";
|
||||
import { OpenClawApp } from "./app";
|
||||
import { refreshChat } from "./app-chat";
|
||||
import { syncUrlWithSessionKey } from "./app-settings";
|
||||
import { loadChatHistory } from "./controllers/chat";
|
||||
import { ChatState, loadChatHistory } from "./controllers/chat";
|
||||
import { icons } from "./icons";
|
||||
import { iconForTab, pathForTab, titleForTab, type Tab } from "./navigation";
|
||||
|
||||
@@ -94,18 +95,18 @@ export function renderChatControls(state: AppViewState) {
|
||||
state.sessionKey = next;
|
||||
state.chatMessage = "";
|
||||
state.chatStream = null;
|
||||
state.chatStreamStartedAt = null;
|
||||
(state as unknown as OpenClawApp).chatStreamStartedAt = null;
|
||||
state.chatRunId = null;
|
||||
state.resetToolStream();
|
||||
state.resetChatScroll();
|
||||
(state as unknown as OpenClawApp).resetToolStream();
|
||||
(state as unknown as OpenClawApp).resetChatScroll();
|
||||
state.applySettings({
|
||||
...state.settings,
|
||||
sessionKey: next,
|
||||
lastActiveSessionKey: next,
|
||||
});
|
||||
void state.loadAssistantIdentity();
|
||||
syncUrlWithSessionKey(state, next, true);
|
||||
void loadChatHistory(state);
|
||||
syncUrlWithSessionKey(next, true);
|
||||
void loadChatHistory(state as unknown as ChatState);
|
||||
}}
|
||||
>
|
||||
${repeat(
|
||||
@@ -122,7 +123,7 @@ export function renderChatControls(state: AppViewState) {
|
||||
class="btn btn--sm btn--icon"
|
||||
?disabled=${state.chatLoading || !state.connected}
|
||||
@click=${() => {
|
||||
state.resetToolStream();
|
||||
(state as unknown as OpenClawApp).resetToolStream();
|
||||
void refreshChat(state as unknown as Parameters<typeof refreshChat>[0]);
|
||||
}}
|
||||
title="Refresh chat data"
|
||||
@@ -228,7 +229,7 @@ function resolveSessionOptions(
|
||||
seen.add(mainSessionKey);
|
||||
options.push({
|
||||
key: mainSessionKey,
|
||||
displayName: resolveSessionDisplayName(mainSessionKey, resolvedMain),
|
||||
displayName: resolveSessionDisplayName(mainSessionKey, resolvedMain || undefined),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { html, nothing } from "lit";
|
||||
import type { AppViewState } from "./app-view-state";
|
||||
import { parseAgentSessionKey } from "../../../src/routing/session-key.js";
|
||||
import { refreshChatAvatar } from "./app-chat";
|
||||
import { OpenClawApp } from "./app";
|
||||
import { ChatHost, refreshChatAvatar } from "./app-chat";
|
||||
import { renderChatControls, renderTab, renderThemeToggle } from "./app-render.helpers";
|
||||
import { loadAgentFileContent, loadAgentFiles, saveAgentFile } from "./controllers/agent-files";
|
||||
import { loadAgentIdentities, loadAgentIdentity } from "./controllers/agent-identity";
|
||||
import { loadAgentSkills } from "./controllers/agent-skills";
|
||||
import { loadAgents } from "./controllers/agents";
|
||||
import { loadChannels } from "./controllers/channels";
|
||||
import { loadChatHistory } from "./controllers/chat";
|
||||
import { ChatState, loadChatHistory } from "./controllers/chat";
|
||||
import {
|
||||
applyConfig,
|
||||
ConfigState,
|
||||
loadConfig,
|
||||
runUpdate,
|
||||
saveConfig,
|
||||
@@ -38,7 +40,7 @@ import {
|
||||
saveExecApprovals,
|
||||
updateExecApprovalsFormValue,
|
||||
} from "./controllers/exec-approvals";
|
||||
import { loadLogs } from "./controllers/logs";
|
||||
import { loadLogs, LogsState } from "./controllers/logs";
|
||||
import { loadNodes } from "./controllers/nodes";
|
||||
import { loadPresence } from "./controllers/presence";
|
||||
import { deleteSession, loadSessions, patchSession } from "./controllers/sessions";
|
||||
@@ -51,6 +53,7 @@ import {
|
||||
} from "./controllers/skills";
|
||||
import { icons } from "./icons";
|
||||
import { TAB_GROUPS, subtitleForTab, titleForTab } from "./navigation";
|
||||
import { ConfigUiHints } from "./types";
|
||||
import { renderAgents } from "./views/agents";
|
||||
import { renderChannels } from "./views/channels";
|
||||
import { renderChat } from "./views/chat";
|
||||
@@ -213,7 +216,7 @@ export function renderApp(state: AppViewState) {
|
||||
onSessionKeyChange: (next) => {
|
||||
state.sessionKey = next;
|
||||
state.chatMessage = "";
|
||||
state.resetToolStream();
|
||||
(state as unknown as OpenClawApp).resetToolStream();
|
||||
state.applySettings({
|
||||
...state.settings,
|
||||
sessionKey: next,
|
||||
@@ -242,7 +245,7 @@ export function renderApp(state: AppViewState) {
|
||||
configSchema: state.configSchema,
|
||||
configSchemaLoading: state.configSchemaLoading,
|
||||
configForm: state.configForm,
|
||||
configUiHints: state.configUiHints,
|
||||
configUiHints: state.configUiHints as ConfigUiHints,
|
||||
configSaving: state.configSaving,
|
||||
configFormDirty: state.configFormDirty,
|
||||
nostrProfileFormState: state.nostrProfileFormState,
|
||||
@@ -251,7 +254,8 @@ export function renderApp(state: AppViewState) {
|
||||
onWhatsAppStart: (force) => state.handleWhatsAppStart(force),
|
||||
onWhatsAppWait: () => state.handleWhatsAppWait(),
|
||||
onWhatsAppLogout: () => state.handleWhatsAppLogout(),
|
||||
onConfigPatch: (path, value) => updateConfigFormValue(state, path, value),
|
||||
onConfigPatch: (path, value) =>
|
||||
updateConfigFormValue(state as unknown as ConfigState, path, value),
|
||||
onConfigSave: () => state.handleChannelConfigSave(),
|
||||
onConfigReload: () => state.handleChannelConfigReload(),
|
||||
onNostrProfileEdit: (accountId, profile) =>
|
||||
@@ -460,12 +464,19 @@ export function renderApp(state: AppViewState) {
|
||||
}
|
||||
const basePath = ["agents", "list", index, "tools"];
|
||||
if (profile) {
|
||||
updateConfigFormValue(state, [...basePath, "profile"], profile);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
[...basePath, "profile"],
|
||||
profile,
|
||||
);
|
||||
} else {
|
||||
removeConfigFormValue(state, [...basePath, "profile"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [
|
||||
...basePath,
|
||||
"profile",
|
||||
]);
|
||||
}
|
||||
if (clearAllow) {
|
||||
removeConfigFormValue(state, [...basePath, "allow"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [...basePath, "allow"]);
|
||||
}
|
||||
},
|
||||
onToolsOverridesChange: (agentId, alsoAllow, deny) => {
|
||||
@@ -488,18 +499,29 @@ export function renderApp(state: AppViewState) {
|
||||
}
|
||||
const basePath = ["agents", "list", index, "tools"];
|
||||
if (alsoAllow.length > 0) {
|
||||
updateConfigFormValue(state, [...basePath, "alsoAllow"], alsoAllow);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
[...basePath, "alsoAllow"],
|
||||
alsoAllow,
|
||||
);
|
||||
} else {
|
||||
removeConfigFormValue(state, [...basePath, "alsoAllow"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [
|
||||
...basePath,
|
||||
"alsoAllow",
|
||||
]);
|
||||
}
|
||||
if (deny.length > 0) {
|
||||
updateConfigFormValue(state, [...basePath, "deny"], deny);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
[...basePath, "deny"],
|
||||
deny,
|
||||
);
|
||||
} else {
|
||||
removeConfigFormValue(state, [...basePath, "deny"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [...basePath, "deny"]);
|
||||
}
|
||||
},
|
||||
onConfigReload: () => loadConfig(state),
|
||||
onConfigSave: () => saveConfig(state),
|
||||
onConfigReload: () => loadConfig(state as unknown as ConfigState),
|
||||
onConfigSave: () => saveConfig(state as unknown as ConfigState),
|
||||
onChannelsRefresh: () => loadChannels(state, false),
|
||||
onCronRefresh: () => state.loadCron(),
|
||||
onSkillsFilterChange: (next) => (state.skillsFilter = next),
|
||||
@@ -544,7 +566,11 @@ export function renderApp(state: AppViewState) {
|
||||
} else {
|
||||
next.delete(normalizedSkill);
|
||||
}
|
||||
updateConfigFormValue(state, ["agents", "list", index, "skills"], [...next]);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
["agents", "list", index, "skills"],
|
||||
[...next],
|
||||
);
|
||||
},
|
||||
onAgentSkillsClear: (agentId) => {
|
||||
if (!configValue) {
|
||||
@@ -564,7 +590,12 @@ export function renderApp(state: AppViewState) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
removeConfigFormValue(state, ["agents", "list", index, "skills"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [
|
||||
"agents",
|
||||
"list",
|
||||
index,
|
||||
"skills",
|
||||
]);
|
||||
},
|
||||
onAgentSkillsDisableAll: (agentId) => {
|
||||
if (!configValue) {
|
||||
@@ -584,7 +615,11 @@ export function renderApp(state: AppViewState) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
updateConfigFormValue(state, ["agents", "list", index, "skills"], []);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
["agents", "list", index, "skills"],
|
||||
[],
|
||||
);
|
||||
},
|
||||
onModelChange: (agentId, modelId) => {
|
||||
if (!configValue) {
|
||||
@@ -606,7 +641,7 @@ export function renderApp(state: AppViewState) {
|
||||
}
|
||||
const basePath = ["agents", "list", index, "model"];
|
||||
if (!modelId) {
|
||||
removeConfigFormValue(state, basePath);
|
||||
removeConfigFormValue(state as unknown as ConfigState, basePath);
|
||||
return;
|
||||
}
|
||||
const entry = list[index] as { model?: unknown };
|
||||
@@ -617,9 +652,9 @@ export function renderApp(state: AppViewState) {
|
||||
primary: modelId,
|
||||
...(Array.isArray(fallbacks) ? { fallbacks } : {}),
|
||||
};
|
||||
updateConfigFormValue(state, basePath, next);
|
||||
updateConfigFormValue(state as unknown as ConfigState, basePath, next);
|
||||
} else {
|
||||
updateConfigFormValue(state, basePath, modelId);
|
||||
updateConfigFormValue(state as unknown as ConfigState, basePath, modelId);
|
||||
}
|
||||
},
|
||||
onModelFallbacksChange: (agentId, fallbacks) => {
|
||||
@@ -660,16 +695,16 @@ export function renderApp(state: AppViewState) {
|
||||
const primary = resolvePrimary();
|
||||
if (normalized.length === 0) {
|
||||
if (primary) {
|
||||
updateConfigFormValue(state, basePath, primary);
|
||||
updateConfigFormValue(state as unknown as ConfigState, basePath, primary);
|
||||
} else {
|
||||
removeConfigFormValue(state, basePath);
|
||||
removeConfigFormValue(state as unknown as ConfigState, basePath);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const next = primary
|
||||
? { primary, fallbacks: normalized }
|
||||
: { fallbacks: normalized };
|
||||
updateConfigFormValue(state, basePath, next);
|
||||
updateConfigFormValue(state as unknown as ConfigState, basePath, next);
|
||||
},
|
||||
})
|
||||
: nothing
|
||||
@@ -726,7 +761,7 @@ export function renderApp(state: AppViewState) {
|
||||
onDeviceRotate: (deviceId, role, scopes) =>
|
||||
rotateDeviceToken(state, { deviceId, role, scopes }),
|
||||
onDeviceRevoke: (deviceId, role) => revokeDeviceToken(state, { deviceId, role }),
|
||||
onLoadConfig: () => loadConfig(state),
|
||||
onLoadConfig: () => loadConfig(state as unknown as ConfigState),
|
||||
onLoadExecApprovals: () => {
|
||||
const target =
|
||||
state.execApprovalsTarget === "node" && state.execApprovalsTargetNodeId
|
||||
@@ -736,20 +771,28 @@ export function renderApp(state: AppViewState) {
|
||||
},
|
||||
onBindDefault: (nodeId) => {
|
||||
if (nodeId) {
|
||||
updateConfigFormValue(state, ["tools", "exec", "node"], nodeId);
|
||||
updateConfigFormValue(
|
||||
state as unknown as ConfigState,
|
||||
["tools", "exec", "node"],
|
||||
nodeId,
|
||||
);
|
||||
} else {
|
||||
removeConfigFormValue(state, ["tools", "exec", "node"]);
|
||||
removeConfigFormValue(state as unknown as ConfigState, [
|
||||
"tools",
|
||||
"exec",
|
||||
"node",
|
||||
]);
|
||||
}
|
||||
},
|
||||
onBindAgent: (agentIndex, nodeId) => {
|
||||
const basePath = ["agents", "list", agentIndex, "tools", "exec", "node"];
|
||||
if (nodeId) {
|
||||
updateConfigFormValue(state, basePath, nodeId);
|
||||
updateConfigFormValue(state as unknown as ConfigState, basePath, nodeId);
|
||||
} else {
|
||||
removeConfigFormValue(state, basePath);
|
||||
removeConfigFormValue(state as unknown as ConfigState, basePath);
|
||||
}
|
||||
},
|
||||
onSaveBindings: () => saveConfig(state),
|
||||
onSaveBindings: () => saveConfig(state as unknown as ConfigState),
|
||||
onExecApprovalsTargetChange: (kind, nodeId) => {
|
||||
state.execApprovalsTarget = kind;
|
||||
state.execApprovalsTargetNodeId = nodeId;
|
||||
@@ -784,30 +827,29 @@ export function renderApp(state: AppViewState) {
|
||||
state.chatMessage = "";
|
||||
state.chatAttachments = [];
|
||||
state.chatStream = null;
|
||||
state.chatStreamStartedAt = null;
|
||||
state.chatRunId = null;
|
||||
(state as unknown as OpenClawApp).chatStreamStartedAt = null;
|
||||
state.chatQueue = [];
|
||||
state.resetToolStream();
|
||||
state.resetChatScroll();
|
||||
(state as unknown as OpenClawApp).resetToolStream();
|
||||
(state as unknown as OpenClawApp).resetChatScroll();
|
||||
state.applySettings({
|
||||
...state.settings,
|
||||
sessionKey: next,
|
||||
lastActiveSessionKey: next,
|
||||
});
|
||||
void state.loadAssistantIdentity();
|
||||
void loadChatHistory(state);
|
||||
void refreshChatAvatar(state);
|
||||
void loadChatHistory(state as unknown as ChatState);
|
||||
void refreshChatAvatar(state as unknown as ChatHost);
|
||||
},
|
||||
thinkingLevel: state.chatThinkingLevel,
|
||||
showThinking,
|
||||
loading: state.chatLoading,
|
||||
sending: state.chatSending,
|
||||
compactionStatus: state.compactionStatus,
|
||||
assistantAvatarUrl: chatAvatarUrl,
|
||||
messages: state.chatMessages,
|
||||
toolMessages: state.chatToolMessages,
|
||||
stream: state.chatStream,
|
||||
streamStartedAt: state.chatStreamStartedAt,
|
||||
streamStartedAt: null,
|
||||
draft: state.chatMessage,
|
||||
queue: state.chatQueue,
|
||||
connected: state.connected,
|
||||
@@ -817,8 +859,10 @@ export function renderApp(state: AppViewState) {
|
||||
sessions: state.sessionsResult,
|
||||
focusMode: chatFocus,
|
||||
onRefresh: () => {
|
||||
state.resetToolStream();
|
||||
return Promise.all([loadChatHistory(state), refreshChatAvatar(state)]);
|
||||
return Promise.all([
|
||||
loadChatHistory(state as unknown as ChatState),
|
||||
refreshChatAvatar(state as unknown as ChatHost),
|
||||
]);
|
||||
},
|
||||
onToggleFocusMode: () => {
|
||||
if (state.onboarding) {
|
||||
@@ -829,25 +873,28 @@ export function renderApp(state: AppViewState) {
|
||||
chatFocusMode: !state.settings.chatFocusMode,
|
||||
});
|
||||
},
|
||||
onChatScroll: (event) => state.handleChatScroll(event),
|
||||
onChatScroll: (event) => (state as unknown as OpenClawApp).handleChatScroll(event),
|
||||
onDraftChange: (next) => (state.chatMessage = next),
|
||||
attachments: state.chatAttachments,
|
||||
onAttachmentsChange: (next) => (state.chatAttachments = next),
|
||||
onSend: () => state.handleSendChat(),
|
||||
onSend: () => (state as unknown as OpenClawApp).handleSendChat(),
|
||||
canAbort: Boolean(state.chatRunId),
|
||||
onAbort: () => void state.handleAbortChat(),
|
||||
onQueueRemove: (id) => state.removeQueuedMessage(id),
|
||||
onNewSession: () => state.handleSendChat("/new", { restoreDraft: true }),
|
||||
onAbort: () => void (state as unknown as OpenClawApp).handleAbortChat(),
|
||||
onQueueRemove: (id) => (state as unknown as OpenClawApp).removeQueuedMessage(id),
|
||||
onNewSession: () =>
|
||||
(state as unknown as OpenClawApp).handleSendChat("/new", { restoreDraft: true }),
|
||||
showNewMessages: state.chatNewMessagesBelow,
|
||||
onScrollToBottom: () => state.scrollToBottom(),
|
||||
// Sidebar props for tool output viewing
|
||||
sidebarOpen: state.sidebarOpen,
|
||||
sidebarContent: state.sidebarContent,
|
||||
sidebarError: state.sidebarError,
|
||||
splitRatio: state.splitRatio,
|
||||
onOpenSidebar: (content: string) => state.handleOpenSidebar(content),
|
||||
onCloseSidebar: () => state.handleCloseSidebar(),
|
||||
onSplitRatioChange: (ratio: number) => state.handleSplitRatioChange(ratio),
|
||||
sidebarOpen: (state as unknown as OpenClawApp).sidebarOpen,
|
||||
sidebarContent: (state as unknown as OpenClawApp).sidebarContent,
|
||||
sidebarError: (state as unknown as OpenClawApp).sidebarError,
|
||||
splitRatio: (state as unknown as OpenClawApp).splitRatio,
|
||||
onOpenSidebar: (content: string) =>
|
||||
(state as unknown as OpenClawApp).handleOpenSidebar(content),
|
||||
onCloseSidebar: () => (state as unknown as OpenClawApp).handleCloseSidebar(),
|
||||
onSplitRatioChange: (ratio: number) =>
|
||||
(state as unknown as OpenClawApp).handleSplitRatioChange(ratio),
|
||||
assistantName: state.assistantName,
|
||||
assistantAvatar: state.assistantAvatar,
|
||||
})
|
||||
@@ -868,28 +915,31 @@ export function renderApp(state: AppViewState) {
|
||||
connected: state.connected,
|
||||
schema: state.configSchema,
|
||||
schemaLoading: state.configSchemaLoading,
|
||||
uiHints: state.configUiHints,
|
||||
uiHints: state.configUiHints as ConfigUiHints,
|
||||
formMode: state.configFormMode,
|
||||
formValue: state.configForm,
|
||||
originalValue: state.configFormOriginal,
|
||||
searchQuery: state.configSearchQuery,
|
||||
activeSection: state.configActiveSection,
|
||||
activeSubsection: state.configActiveSubsection,
|
||||
searchQuery: (state as unknown as OpenClawApp).configSearchQuery,
|
||||
activeSection: (state as unknown as OpenClawApp).configActiveSection,
|
||||
activeSubsection: (state as unknown as OpenClawApp).configActiveSubsection,
|
||||
onRawChange: (next) => {
|
||||
state.configRaw = next;
|
||||
},
|
||||
onFormModeChange: (mode) => (state.configFormMode = mode),
|
||||
onFormPatch: (path, value) => updateConfigFormValue(state, path, value),
|
||||
onSearchChange: (query) => (state.configSearchQuery = query),
|
||||
onFormPatch: (path, value) =>
|
||||
updateConfigFormValue(state as unknown as OpenClawApp, path, value),
|
||||
onSearchChange: (query) =>
|
||||
((state as unknown as OpenClawApp).configSearchQuery = query),
|
||||
onSectionChange: (section) => {
|
||||
state.configActiveSection = section;
|
||||
state.configActiveSubsection = null;
|
||||
(state as unknown as OpenClawApp).configActiveSection = section;
|
||||
(state as unknown as OpenClawApp).configActiveSubsection = null;
|
||||
},
|
||||
onSubsectionChange: (section) => (state.configActiveSubsection = section),
|
||||
onReload: () => loadConfig(state),
|
||||
onSave: () => saveConfig(state),
|
||||
onApply: () => applyConfig(state),
|
||||
onUpdate: () => runUpdate(state),
|
||||
onSubsectionChange: (section) =>
|
||||
((state as unknown as OpenClawApp).configActiveSubsection = section),
|
||||
onReload: () => loadConfig(state as unknown as OpenClawApp),
|
||||
onSave: () => saveConfig(state as unknown as OpenClawApp),
|
||||
onApply: () => applyConfig(state as unknown as OpenClawApp),
|
||||
onUpdate: () => runUpdate(state as unknown as OpenClawApp),
|
||||
})
|
||||
: nothing
|
||||
}
|
||||
@@ -931,9 +981,10 @@ export function renderApp(state: AppViewState) {
|
||||
state.logsLevelFilters = { ...state.logsLevelFilters, [level]: enabled };
|
||||
},
|
||||
onToggleAutoFollow: (next) => (state.logsAutoFollow = next),
|
||||
onRefresh: () => loadLogs(state, { reset: true }),
|
||||
onExport: (lines, label) => state.exportLogs(lines, label),
|
||||
onScroll: (event) => state.handleLogsScroll(event),
|
||||
onRefresh: () => loadLogs(state as unknown as LogsState, { reset: true }),
|
||||
onExport: (lines, label) =>
|
||||
(state as unknown as OpenClawApp).exportLogs(lines, label),
|
||||
onScroll: (event) => (state as unknown as OpenClawApp).handleLogsScroll(event),
|
||||
})
|
||||
: nothing
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ export function applySettingsFromUrl(host: SettingsHost) {
|
||||
if (passwordRaw != null) {
|
||||
const password = passwordRaw.trim();
|
||||
if (password) {
|
||||
(host as { password: string }).password = password;
|
||||
(host as unknown as { password: string }).password = password;
|
||||
}
|
||||
params.delete("password");
|
||||
shouldCleanUrl = true;
|
||||
@@ -189,23 +189,24 @@ export async function refreshActiveTab(host: SettingsHost) {
|
||||
await loadSkills(host as unknown as OpenClawApp);
|
||||
}
|
||||
if (host.tab === "agents") {
|
||||
await loadAgents(host as unknown as OpenClawApp);
|
||||
await loadConfig(host as unknown as OpenClawApp);
|
||||
const agentIds = host.agentsList?.agents?.map((entry) => entry.id) ?? [];
|
||||
const app = host as unknown as OpenClawApp;
|
||||
await loadAgents(app);
|
||||
await loadConfig(app);
|
||||
const agentIds = app.agentsList?.agents?.map((entry) => entry.id) ?? [];
|
||||
if (agentIds.length > 0) {
|
||||
void loadAgentIdentities(host as unknown as OpenClawApp, agentIds);
|
||||
void loadAgentIdentities(app, agentIds);
|
||||
}
|
||||
const agentId =
|
||||
host.agentsSelectedId ?? host.agentsList?.defaultId ?? host.agentsList?.agents?.[0]?.id;
|
||||
app.agentsSelectedId ?? app.agentsList?.defaultId ?? app.agentsList?.agents?.[0]?.id;
|
||||
if (agentId) {
|
||||
void loadAgentIdentity(host as unknown as OpenClawApp, agentId);
|
||||
if (host.agentsPanel === "skills") {
|
||||
void loadAgentSkills(host as unknown as OpenClawApp, agentId);
|
||||
void loadAgentIdentity(app, agentId);
|
||||
if (app.agentsPanel === "skills") {
|
||||
void loadAgentSkills(app, agentId);
|
||||
}
|
||||
if (host.agentsPanel === "channels") {
|
||||
void loadChannels(host as unknown as OpenClawApp, false);
|
||||
if (app.agentsPanel === "channels") {
|
||||
void loadChannels(app, false);
|
||||
}
|
||||
if (host.agentsPanel === "cron") {
|
||||
if (app.agentsPanel === "cron") {
|
||||
void loadCron(host);
|
||||
}
|
||||
}
|
||||
@@ -380,7 +381,7 @@ export function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
export function syncUrlWithSessionKey(host: SettingsHost, sessionKey: string, replace: boolean) {
|
||||
export function syncUrlWithSessionKey(sessionKey: string, replace: boolean) {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPaylo
|
||||
sessionKey,
|
||||
name,
|
||||
args,
|
||||
output,
|
||||
output: output || undefined,
|
||||
startedAt: typeof payload.ts === "number" ? payload.ts : now,
|
||||
updatedAt: now,
|
||||
message: {},
|
||||
@@ -270,7 +270,7 @@ export function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPaylo
|
||||
entry.args = args;
|
||||
}
|
||||
if (output !== undefined) {
|
||||
entry.output = output;
|
||||
entry.output = output || undefined;
|
||||
}
|
||||
entry.updatedAt = now;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ describe("config form renderer", () => {
|
||||
container,
|
||||
);
|
||||
|
||||
const tokenInput = container.querySelector("input[type='password']");
|
||||
const tokenInput: HTMLInputElement | null = container.querySelector("input[type='password']");
|
||||
expect(tokenInput).not.toBeNull();
|
||||
if (!tokenInput) {
|
||||
return;
|
||||
@@ -67,7 +67,7 @@ describe("config form renderer", () => {
|
||||
tokenButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
||||
expect(onPatch).toHaveBeenCalledWith(["mode"], "token");
|
||||
|
||||
const checkbox = container.querySelector("input[type='checkbox']");
|
||||
const checkbox: HTMLInputElement | null = container.querySelector("input[type='checkbox']");
|
||||
expect(checkbox).not.toBeNull();
|
||||
if (!checkbox) {
|
||||
return;
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function loadAgents(state: AgentsState) {
|
||||
state.agentsLoading = true;
|
||||
state.agentsError = null;
|
||||
try {
|
||||
const res = await state.client.request("agents.list", {});
|
||||
const res = await state.client.request<AgentsListResult>("agents.list", {});
|
||||
if (res) {
|
||||
state.agentsList = res;
|
||||
const selected = state.agentsSelectedId;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ChannelsState } from "./channels.types";
|
||||
import { ChannelsStatusSnapshot } from "../types";
|
||||
|
||||
export type { ChannelsState };
|
||||
|
||||
@@ -12,7 +13,7 @@ export async function loadChannels(state: ChannelsState, probe: boolean) {
|
||||
state.channelsLoading = true;
|
||||
state.channelsError = null;
|
||||
try {
|
||||
const res = await state.client.request("channels.status", {
|
||||
const res = await state.client.request<ChannelsStatusSnapshot | null>("channels.status", {
|
||||
probe,
|
||||
timeoutMs: 8000,
|
||||
});
|
||||
@@ -31,10 +32,13 @@ export async function startWhatsAppLogin(state: ChannelsState, force: boolean) {
|
||||
}
|
||||
state.whatsappBusy = true;
|
||||
try {
|
||||
const res = await state.client.request("web.login.start", {
|
||||
force,
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
const res = await state.client.request<{ message?: string; qrDataUrl?: string }>(
|
||||
"web.login.start",
|
||||
{
|
||||
force,
|
||||
timeoutMs: 30000,
|
||||
},
|
||||
);
|
||||
state.whatsappLoginMessage = res.message ?? null;
|
||||
state.whatsappLoginQrDataUrl = res.qrDataUrl ?? null;
|
||||
state.whatsappLoginConnected = null;
|
||||
@@ -53,9 +57,12 @@ export async function waitWhatsAppLogin(state: ChannelsState) {
|
||||
}
|
||||
state.whatsappBusy = true;
|
||||
try {
|
||||
const res = await state.client.request("web.login.wait", {
|
||||
timeoutMs: 120000,
|
||||
});
|
||||
const res = await state.client.request<{ message?: string; connected?: boolean }>(
|
||||
"web.login.wait",
|
||||
{
|
||||
timeoutMs: 120000,
|
||||
},
|
||||
);
|
||||
state.whatsappLoginMessage = res.message ?? null;
|
||||
state.whatsappLoginConnected = res.connected ?? null;
|
||||
if (res.connected) {
|
||||
|
||||
@@ -3,18 +3,19 @@ import { handleChatEvent, type ChatEventPayload, type ChatState } from "./chat";
|
||||
|
||||
function createState(overrides: Partial<ChatState> = {}): ChatState {
|
||||
return {
|
||||
client: null,
|
||||
connected: true,
|
||||
sessionKey: "main",
|
||||
chatAttachments: [],
|
||||
chatLoading: false,
|
||||
chatMessages: [],
|
||||
chatThinkingLevel: null,
|
||||
chatSending: false,
|
||||
chatMessage: "",
|
||||
chatMessages: [],
|
||||
chatRunId: null,
|
||||
chatSending: false,
|
||||
chatStream: null,
|
||||
chatStreamStartedAt: null,
|
||||
chatThinkingLevel: null,
|
||||
client: null,
|
||||
connected: true,
|
||||
lastError: null,
|
||||
sessionKey: "main",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,10 +34,13 @@ export async function loadChatHistory(state: ChatState) {
|
||||
state.chatLoading = true;
|
||||
state.lastError = null;
|
||||
try {
|
||||
const res = await state.client.request("chat.history", {
|
||||
sessionKey: state.sessionKey,
|
||||
limit: 200,
|
||||
});
|
||||
const res = await state.client.request<{ messages?: Array<unknown>; thinkingLevel?: string }>(
|
||||
"chat.history",
|
||||
{
|
||||
sessionKey: state.sessionKey,
|
||||
limit: 200,
|
||||
},
|
||||
);
|
||||
state.chatMessages = Array.isArray(res.messages) ? res.messages : [];
|
||||
state.chatThinkingLevel = res.thinkingLevel ?? null;
|
||||
} catch (err) {
|
||||
|
||||
@@ -9,27 +9,30 @@ import {
|
||||
|
||||
function createState(): ConfigState {
|
||||
return {
|
||||
client: null,
|
||||
connected: false,
|
||||
applySessionKey: "main",
|
||||
client: null,
|
||||
configActiveSection: null,
|
||||
configActiveSubsection: null,
|
||||
configApplying: false,
|
||||
configForm: null,
|
||||
configFormDirty: false,
|
||||
configFormMode: "form",
|
||||
configFormOriginal: null,
|
||||
configIssues: [],
|
||||
configLoading: false,
|
||||
configRaw: "",
|
||||
configRawOriginal: "",
|
||||
configValid: null,
|
||||
configIssues: [],
|
||||
configSaving: false,
|
||||
configApplying: false,
|
||||
updateRunning: false,
|
||||
configSnapshot: null,
|
||||
configSchema: null,
|
||||
configSchemaVersion: null,
|
||||
configSchemaLoading: false,
|
||||
configSchemaVersion: null,
|
||||
configSearchQuery: "",
|
||||
configSnapshot: null,
|
||||
configUiHints: {},
|
||||
configForm: null,
|
||||
configFormOriginal: null,
|
||||
configFormDirty: false,
|
||||
configFormMode: "form",
|
||||
configValid: null,
|
||||
connected: false,
|
||||
lastError: null,
|
||||
updateRunning: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export async function loadConfig(state: ConfigState) {
|
||||
state.configLoading = true;
|
||||
state.lastError = null;
|
||||
try {
|
||||
const res = await state.client.request("config.get", {});
|
||||
const res = await state.client.request<ConfigSnapshot>("config.get", {});
|
||||
applyConfigSnapshot(state, res);
|
||||
} catch (err) {
|
||||
state.lastError = String(err);
|
||||
@@ -59,7 +59,7 @@ export async function loadConfigSchema(state: ConfigState) {
|
||||
}
|
||||
state.configSchemaLoading = true;
|
||||
try {
|
||||
const res = await state.client.request("config.schema", {});
|
||||
const res = await state.client.request<ConfigSchemaResponse>("config.schema", {});
|
||||
applyConfigSchema(state, res);
|
||||
} catch (err) {
|
||||
state.lastError = String(err);
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function loadCronStatus(state: CronState) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await state.client.request("cron.status", {});
|
||||
const res = await state.client.request<CronStatus>("cron.status", {});
|
||||
state.cronStatus = res;
|
||||
} catch (err) {
|
||||
state.cronError = String(err);
|
||||
@@ -38,7 +38,7 @@ export async function loadCronJobs(state: CronState) {
|
||||
state.cronLoading = true;
|
||||
state.cronError = null;
|
||||
try {
|
||||
const res = await state.client.request("cron.list", {
|
||||
const res = await state.client.request<{ jobs?: Array<CronJob> }>("cron.list", {
|
||||
includeDisabled: true,
|
||||
});
|
||||
state.cronJobs = Array.isArray(res.jobs) ? res.jobs : [];
|
||||
@@ -211,7 +211,7 @@ export async function loadCronRuns(state: CronState, jobId: string) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await state.client.request("cron.runs", {
|
||||
const res = await state.client.request<{ entries?: Array<CronRunLogEntry> }>("cron.runs", {
|
||||
id: jobId,
|
||||
limit: 50,
|
||||
});
|
||||
|
||||
@@ -57,7 +57,10 @@ export async function loadDevices(state: DevicesState, opts?: { quiet?: boolean
|
||||
state.devicesError = null;
|
||||
}
|
||||
try {
|
||||
const res = await state.client.request("device.pair.list", {});
|
||||
const res = await state.client.request<{
|
||||
pending?: Array<PendingDevice>;
|
||||
paired?: Array<PendingDevice>;
|
||||
}>("device.pair.list", {});
|
||||
state.devicesList = {
|
||||
pending: Array.isArray(res?.pending) ? res.pending : [],
|
||||
paired: Array.isArray(res?.paired) ? res.paired : [],
|
||||
@@ -107,7 +110,12 @@ export async function rotateDeviceToken(
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await state.client.request("device.token.rotate", params);
|
||||
const res = await state.client.request<{
|
||||
token: string;
|
||||
role?: string;
|
||||
deviceId?: string;
|
||||
scopes?: Array<string>;
|
||||
}>("device.token.rotate", params);
|
||||
if (res?.token) {
|
||||
const identity = await loadOrCreateDeviceIdentity();
|
||||
const role = res.role ?? params.role;
|
||||
|
||||
@@ -94,7 +94,7 @@ export async function loadExecApprovals(
|
||||
state.lastError = "Select a node before loading exec approvals.";
|
||||
return;
|
||||
}
|
||||
const res = await state.client.request(rpc.method, rpc.params);
|
||||
const res = await state.client.request<ExecApprovalsSnapshot>(rpc.method, rpc.params);
|
||||
applyExecApprovalsSnapshot(state, res);
|
||||
} catch (err) {
|
||||
state.lastError = String(err);
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function loadNodes(state: NodesState, opts?: { quiet?: boolean }) {
|
||||
state.lastError = null;
|
||||
}
|
||||
try {
|
||||
const res = await state.client.request("node.list", {});
|
||||
const res = await state.client.request<{ nodes?: Record<string, unknown> }>("node.list", {});
|
||||
state.nodes = Array.isArray(res.nodes) ? res.nodes : [];
|
||||
} catch (err) {
|
||||
if (!opts?.quiet) {
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function loadSessions(
|
||||
if (limit > 0) {
|
||||
params.limit = limit;
|
||||
}
|
||||
const res = await state.client.request("sessions.list", params);
|
||||
const res = await state.client.request<SessionsListResult | undefined>("sessions.list", params);
|
||||
if (res) {
|
||||
state.sessionsResult = res;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export async function loadSkills(state: SkillsState, options?: LoadSkillsOptions
|
||||
state.skillsLoading = true;
|
||||
state.skillsError = null;
|
||||
try {
|
||||
const res = await state.client.request("skills.status", {});
|
||||
const res = await state.client.request<SkillStatusReport | undefined>("skills.status", {});
|
||||
if (res) {
|
||||
state.skillsReport = res;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export async function installSkill(
|
||||
state.skillsBusyKey = skillKey;
|
||||
state.skillsError = null;
|
||||
try {
|
||||
const result = await state.client.request("skills.install", {
|
||||
const result = await state.client.request<{ message?: string }>("skills.install", {
|
||||
name,
|
||||
installId,
|
||||
timeoutMs: 120000,
|
||||
|
||||
@@ -42,7 +42,7 @@ function bytesToHex(bytes: Uint8Array): string {
|
||||
}
|
||||
|
||||
async function fingerprintPublicKey(publicKey: Uint8Array): Promise<string> {
|
||||
const hash = await crypto.subtle.digest("SHA-256", publicKey);
|
||||
const hash = await crypto.subtle.digest("SHA-256", publicKey.slice().buffer);
|
||||
return bytesToHex(new Uint8Array(hash));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { truncateText } from "./format";
|
||||
marked.setOptions({
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
mangle: false,
|
||||
});
|
||||
|
||||
const allowedTags = [
|
||||
|
||||
@@ -116,7 +116,7 @@ describe("control UI routing", () => {
|
||||
const app = mountApp("/chat");
|
||||
await app.updateComplete;
|
||||
|
||||
const initialContainer = app.querySelector(".chat-thread");
|
||||
const initialContainer: HTMLElement | null = app.querySelector(".chat-thread");
|
||||
expect(initialContainer).not.toBeNull();
|
||||
if (!initialContainer) {
|
||||
return;
|
||||
|
||||
@@ -302,18 +302,20 @@ export type ConfigSchemaResponse = {
|
||||
};
|
||||
|
||||
export type PresenceEntry = {
|
||||
instanceId?: string | null;
|
||||
host?: string | null;
|
||||
ip?: string | null;
|
||||
version?: string | null;
|
||||
platform?: string | null;
|
||||
deviceFamily?: string | null;
|
||||
modelIdentifier?: string | null;
|
||||
mode?: string | null;
|
||||
host?: string | null;
|
||||
instanceId?: string | null;
|
||||
ip?: string | null;
|
||||
lastInputSeconds?: number | null;
|
||||
mode?: string | null;
|
||||
modelIdentifier?: string | null;
|
||||
platform?: string | null;
|
||||
reason?: string | null;
|
||||
roles?: Array<string | null> | null;
|
||||
scopes?: Array<string | null> | null;
|
||||
text?: string | null;
|
||||
ts?: number | null;
|
||||
version?: string | null;
|
||||
};
|
||||
|
||||
export type GatewaySessionsDefaults = {
|
||||
|
||||
@@ -124,7 +124,7 @@ function renderChannel(key: ChannelKey, props: ChannelsProps, data: ChannelsChan
|
||||
case "googlechat":
|
||||
return renderGoogleChatCard({
|
||||
props,
|
||||
googlechat: data.googlechat,
|
||||
googleChat: data.googlechat,
|
||||
accountCountLabel,
|
||||
});
|
||||
case "slack":
|
||||
|
||||
@@ -194,7 +194,7 @@ describe("config view", () => {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
input.value = "gateway";
|
||||
(input as HTMLInputElement).value = "gateway";
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
expect(onSearchChange).toHaveBeenCalledWith("gateway");
|
||||
});
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["vite/client"],
|
||||
|
||||
Reference in New Issue
Block a user