Files
hermes-agent/apps/desktop/src/api/toolsets.ts
T
teknium1 d3ba5b307a fix(desktop): one scoped-dial priority helper; Capabilities selector dials foreground too
Fold the salvaged per-call ternaries in api/config.ts into a single
scopedDialPriority(scope) helper on api/client.ts and apply it to the
Capabilities scope selector's cold-start reads (getSkills / getToolsets /
getMcpCatalog), which hit the same background-capped pool queue when the
selector targets a stopped profile.

Drop the salvaged main.ts source-text change-detector test; keep only the
string update the existing #90812 wiring test needs. The renderer seam test
(hermes-capability-scope) is the invariant: an explicit scope carries
priority 'foreground', the ambient path stays untagged.

Part of #111651 (salvage #111672)
2026-09-15 18:46:08 -07:00

143 lines
4.4 KiB
TypeScript

import type {
ActionResponse,
ComputerUseStatus,
TerminalBackendsResponse,
ToolsetConfig,
ToolsetInfo,
ToolsetModelsResponse
} from '@/types/hermes'
import { capabilityScoped, hermesApi, type ProfileScope, profileScoped, scopedDialPriority } from './client'
// The optional trailing `profile` on every capability fetcher below is the
// Capabilities view's profile-scope override: it lets the Skills/Tools/MCP
// panels configure ANY profile without swapping the app-wide active profile.
// Omitting it (every pre-existing caller) means `profileScoped(undefined)`
// falls back to the app-wide `_apiProfile`, so behavior is byte-identical.
export function getToolsets(profile?: ProfileScope): Promise<ToolsetInfo[]> {
return window.hermesDesktop.api<ToolsetInfo[]>({
...capabilityScoped(profile),
...scopedDialPriority(profile),
path: '/api/tools/toolsets'
})
}
export function setToolsetEnabled(
name: string,
enabled: boolean,
profile?: ProfileScope
): Promise<{ ok: boolean; name: string; enabled: boolean }> {
return window.hermesDesktop.api<{ ok: boolean; name: string; enabled: boolean }>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}`,
method: 'PUT',
body: { enabled }
})
}
export function getToolsetConfig(name: string, profile?: ProfileScope): Promise<ToolsetConfig> {
return window.hermesDesktop.api<ToolsetConfig>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}/config`
})
}
export function getToolsetModels(
name: string,
provider?: string,
profile?: ProfileScope
): Promise<ToolsetModelsResponse> {
const suffix = provider ? `?provider=${encodeURIComponent(provider)}` : ''
return window.hermesDesktop.api<ToolsetModelsResponse>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}/models${suffix}`
})
}
export function selectToolsetModel(
name: string,
model: string,
provider?: string,
profile?: ProfileScope
): Promise<{ ok: boolean; name: string; model: string }> {
return window.hermesDesktop.api<{ ok: boolean; name: string; model: string }>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}/model`,
method: 'PUT',
body: { model, provider }
})
}
export interface SelectToolsetProviderResponse {
ok: boolean
name: string
provider: string
/** Present when the selection was scoped to one web capability. */
capability?: string
/** Present (true) when a managed Nous row was selected but the Portal
* entitlement is missing — the row won't activate until the user signs
* in to Nous Portal. */
needs_nous_auth?: boolean
/** The managed feature key (e.g. "browser") when needs_nous_auth is set. */
feature?: string
}
export function selectToolsetProvider(
name: string,
provider: string,
capability?: 'search' | 'extract',
profile?: ProfileScope
): Promise<SelectToolsetProviderResponse> {
return window.hermesDesktop.api<SelectToolsetProviderResponse>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}/provider`,
method: 'PUT',
body: capability ? { provider, capability } : { provider }
})
}
export function runToolsetPostSetup(
name: string,
key: string,
profile?: ProfileScope
): Promise<ActionResponse & { key: string }> {
return window.hermesDesktop.api<ActionResponse & { key: string }>({
...capabilityScoped(profile),
path: `/api/tools/toolsets/${encodeURIComponent(name)}/post-setup`,
method: 'POST',
body: { key }
})
}
export function getTerminalBackends(): Promise<TerminalBackendsResponse> {
return hermesApi<TerminalBackendsResponse>({
...profileScoped(),
path: '/api/tools/terminal/backends'
})
}
export function selectTerminalBackend(backend: string): Promise<{ ok: boolean; backend: string }> {
return hermesApi<{ ok: boolean; backend: string }>({
...profileScoped(),
path: '/api/tools/terminal/backend',
method: 'PUT',
body: { backend }
})
}
export function getComputerUseStatus(): Promise<ComputerUseStatus> {
return hermesApi<ComputerUseStatus>({
...profileScoped(),
path: '/api/tools/computer-use/status'
})
}
export function grantComputerUsePermissions(): Promise<ActionResponse> {
return hermesApi<ActionResponse>({
...profileScoped(),
path: '/api/tools/computer-use/permissions/grant',
method: 'POST'
})
}