diff --git a/packages/tui/src/component/dialog-skill.tsx b/packages/tui/src/component/dialog-skill.tsx index fa675f7a7..e962a6e7c 100644 --- a/packages/tui/src/component/dialog-skill.tsx +++ b/packages/tui/src/component/dialog-skill.tsx @@ -1,7 +1,10 @@ +import { TextAttributes } from "@opentui/core" import { DialogSelect, type DialogSelectOption } from "../ui/dialog-select" -import { createResource, createMemo } from "solid-js" +import { createResource, createMemo, createSignal } from "solid-js" import { useDialog } from "../ui/dialog" import { useSDK } from "../context/sdk" +import { useTheme } from "../context/theme" +import { errorMessage } from "../util/error" export type DialogSkillProps = { onSelect: (skill: string) => void @@ -10,14 +13,27 @@ export type DialogSkillProps = { export function DialogSkill(props: DialogSkillProps) { const dialog = useDialog() const sdk = useSDK() + const { theme } = useTheme() dialog.setSize("large") - const [skills] = createResource(async () => { - const result = await sdk.client.app.skills() - return result.data ?? [] - }) + const [loadError, setLoadError] = createSignal() + + const [skills] = createResource(() => + sdk.client.app + .skills({}, { throwOnError: true }) + .then((result) => result.data ?? []) + // Catch so the rejected resource never reaches the memo below: reading + // skills() in an errored state re-throws and tears down the dialog. + .catch((error) => { + setLoadError(error) + return undefined + }), + ) + + const showError = createMemo(() => Boolean(loadError())) const options = createMemo[]>(() => { + if (showError()) return [] const list = skills() ?? [] const maxWidth = Math.max(0, ...list.map((s) => s.name.length)) return list.map((skill) => ({ @@ -32,5 +48,23 @@ export function DialogSkill(props: DialogSkillProps) { })) }) - return + return ( + + + Could not load skills + + {errorMessage(loadError())} + + ) : undefined + } + /> + ) }