fix(phase2): restore agent streams and persist extension installations

This commit is contained in:
2026-09-06 02:21:27 +08:00
parent 9497519e8b
commit 7001794a22
35 changed files with 870 additions and 39 deletions
@@ -123,9 +123,11 @@ function close() { disarm(); viewer.value?.close(); svgHtml.value = ''; opener?.
.diagram-controls button:hover { border-color: var(--color-accent-primary); }
.diagram-controls button:focus-visible { outline: 2px solid var(--color-accent-primary); }
.diagram-viewer { width: min(1200px, 94vw); max-width: 94vw; height: 85vh; padding: 16px; color: var(--color-text-primary); background: var(--color-background-primary); border: 1px solid var(--color-border-default); border-radius: var(--radius-md); }
.diagram-viewer::backdrop { background: #0008; }
.diagram-viewer header { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.diagram-viewer-scroll { height: calc(100% - 64px); overflow: auto; }
.diagram-viewer[open] { display: flex; flex-direction: column; gap: var(--space-md); overflow: hidden; }
.diagram-viewer::backdrop { background: var(--color-background-overlay); }
.diagram-viewer header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-sm); flex-shrink: 0; }
.diagram-viewer header .diagram-controls { flex-wrap: wrap; }
.diagram-viewer-scroll { flex: 1; min-height: 0; overflow: auto; }
.diagram-viewer-image { margin: auto; transition: width 180ms ease-out; }
.diagram-viewer-image svg { width: 100% !important; max-width: none !important; height: auto !important; }
</style>
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import apiClient from '@/services/apiClient'
import { t } from '@/i18n'
const props = defineProps<{ kind: 'skill' | 'plugin' }>()
const errors = ref<{ kind: string; id: string; message: string }[]>([])
const failure = ref('')
onMounted(async () => {
try { errors.value = (await apiClient.get<{ items: typeof errors.value }>('/api/extensions/restore-errors')).items.filter(item => item.kind === props.kind) }
catch { failure.value = t('无法读取扩展恢复状态。', 'Unable to read extension recovery status.') }
})
</script>
<template>
<div v-if="errors.length || failure" class="notice-banner" role="status">
<p v-if="failure">{{ failure }}</p>
<p v-for="item in errors" :key="item.id">{{ item.id }}{{ t('启动恢复未完成请检查包文件并重新安装原授权不会自动用于变更后的包', 'Startup recovery failed. Check and reinstall the package; previous grants are not applied to changed packages.') }}</p>
</div>
</template>