-
-
-
+ const runUninstall = async () => {
+ if (!marketMeta) return
+ setUninstalling(true)
+ try {
+ await marketApi.uninstall(marketMeta.id)
+ useUIStore.getState().addToast({
+ type: 'success',
+ message: t('market.uninstall.success', { name: skillMeta.displayName || skillMeta.name }),
+ })
+ setConfirmUninstall(false)
+ clearSelection()
+ void fetchSkills()
+ // Keep the market list in sync when it has this skill loaded.
+ const market = useMarketStore.getState()
+ const detailCache = new Map(market.detailCache)
+ detailCache.delete(marketMeta.id)
+ useMarketStore.setState({
+ detailCache,
+ items: market.items.map((item) =>
+ item.id === marketMeta.id
+ ? { ...item, installState: 'installable', installedInfo: undefined, notInstallableReason: undefined }
+ : item,
+ ),
+ })
+ } catch (err) {
+ useUIStore.getState().addToast({
+ type: 'error',
+ message: err instanceof Error ? err.message : String(err),
+ })
+ } finally {
+ setUninstalling(false)
+ }
+ }
-
-
-
-
- {t('settings.skills.entryEyebrow')}
-
-
-
- {meta.displayName || meta.name}
-
- {t(`settings.skills.source.${meta.source}`)}
- {meta.version && v{meta.version}}
- {meta.userInvocable && {t('settings.skills.slashCommand')}}
-
-
- {meta.description}
-
-
- {t('settings.skills.tokenEstimate', { count: String(Math.ceil(meta.contentLength / 4)) })}
-
- {files.length} {t('settings.skills.files')}
-
- {currentFile?.isEntry ? t('settings.skills.entryFile') : currentFile?.path}
-
-
-
-
-
-
-
- file.isEntry) ? 'SKILL.md' : '—'}
- icon="article"
- />
-
-
-
-
- {metaEntries.length > 0 && (
-
-
-
- tune
-
-
- {t('settings.skills.metaTitle')}
-
-
-
- {metaEntries.map(([key, value]) => (
-
-
- {formatMetaKey(key)}
-
-
- {formatMetaValue(value)}
-
-
- ))}
-
-
+ const actions = marketMeta ? (
+
+ ) : undefined
-
-
-
-
-
-
-
-
- {currentFile?.path}
-
- {currentFile?.isEntry && {t('settings.skills.entryFile')}}
-
-
- {t('settings.skills.readingMode', {
- mode:
- currentFile?.language === 'markdown'
- ? t('settings.skills.docMode')
- : t('settings.skills.codeMode'),
- })}
-
-
-
-
- {currentFile?.language}
-
-
-
-
-
-
- {files.map((file) => {
- const active = file.path === normalizedSelection
- return (
-
- )
- })}
-
-
-
-
- {currentFile && (
-
- {currentFile.language === 'markdown' ? (
-
- ) : (
-
- )}
-
- )}
-
-
-
-
- )
-}
-
-function TreeView({
- nodes,
- selectedPath,
- onSelect,
- depth,
-}: {
- nodes: FileTreeNode[]
- selectedPath: string
- onSelect: (path: string) => void
- depth: number
-}) {
return (
<>
- {nodes.map((node) => (
-