feat(community): 通过已验证的 Host 下载暂存桌面包
This commit is contained in:
@@ -143,7 +143,7 @@ function toggleSource() {
|
||||
<dl><dt>作者 / 来源</dt><dd>{{ detail.author_id }} / {{ detail.namespace }}</dd><dt>许可证</dt><dd>{{ detail.license }}</dd><dt>大小 / 摘要</dt><dd>{{ detail.size }} 字节<br />{{ detail.sha256 }}</dd><dt>兼容平台</dt><dd>{{ detail.platforms.join(', ') }} / {{ detail.architectures.join(', ') }}</dd><dt>权限</dt><dd>{{ detail.permissions.join(', ') || '无' }}</dd><dt>依赖</dt><dd>{{ JSON.stringify(detail.dependencies) }}</dd></dl>
|
||||
<pre>{{ detail.changelog }}</pre>
|
||||
<p>安装不会自动启用包或其依赖。人设、模板、MCP 与模型方案仅保存为可检查的候选。</p>
|
||||
<button class="btn btn-primary" :disabled="busy || detail.withdrawn || offline" @click="install">校验并安装</button>
|
||||
<button class="btn btn-primary" :disabled="busy || detail.withdrawn || offline" @click="install">{{ isDesktop() ? '校验并暂存' : '校验并安装' }}</button>
|
||||
</template>
|
||||
</AppDialog>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { afterEach, expect, it, vi } from 'vitest'
|
||||
const native = vi.hoisted(() => ({ invoke: vi.fn() }))
|
||||
vi.mock('@tauri-apps/api/core', () => ({ invoke: native.invoke }))
|
||||
vi.mock('./platform/desktop', () => ({ isDesktop: () => true }))
|
||||
import { installRelease } from './communityService'
|
||||
import vector from './fixtures/community-python-vector.json'
|
||||
import type { CommunityRelease, CommunitySource } from '@/contracts/community'
|
||||
afterEach(() => { vi.unstubAllGlobals(); native.invoke.mockReset() })
|
||||
it('desktop stages through Host without renderer download or legacy installation', async () => {
|
||||
const fetch = vi.fn(); vi.stubGlobal('fetch', fetch)
|
||||
native.invoke.mockResolvedValue({ state: 'staged' })
|
||||
const source: CommunitySource = { id: 'fixture', url: 'https://catalog.example/', keys: [], enabled: true }
|
||||
const release = vector.release as CommunityRelease
|
||||
expect(await installRelease(source, release)).toContain('尚未安装或启用')
|
||||
expect(fetch).not.toHaveBeenCalled()
|
||||
const [command, args] = native.invoke.mock.calls[0]!
|
||||
expect(command).toBe('extension_stage')
|
||||
expect(args.request.release.signature).toBe(release.signature)
|
||||
expect(args.request.release).not.toHaveProperty('withdrawn')
|
||||
expect(args.request.release).not.toHaveProperty('download_path')
|
||||
expect(args.request.release).not.toHaveProperty('release_id')
|
||||
expect(vector.release).toHaveProperty('release_id')
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
/** 只请求用户配置来源;公钥固定、签名及摘要检查先于任何安装 API。 */
|
||||
import type { CommunityCatalog, CommunityRelease, CommunitySource, CommunityKey } from '@/contracts/community'
|
||||
import { valid, gt, lt } from 'semver'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { isDesktop } from './platform/desktop'
|
||||
import appPackage from '../../package.json'
|
||||
import { decodeThemePackage, inspectThemePackage, installTheme } from './themePackageService'
|
||||
import { installSkill } from './skillService'
|
||||
@@ -89,6 +91,14 @@ export async function verifyRelease(release: CommunityRelease, pinned: Community
|
||||
}
|
||||
|
||||
export async function installRelease(source: CommunitySource, selected: CommunityRelease, signal?: AbortSignal): Promise<string> {
|
||||
if (isDesktop()) {
|
||||
signal?.throwIfAborted()
|
||||
if (!source.enabled || selected.withdrawn) throw new Error('来源已停用或发行已撤回')
|
||||
const release = { ...selected } as Partial<CommunityRelease>
|
||||
delete release.release_id; delete release.withdrawn; delete release.download_path
|
||||
await invoke('extension_stage', { request: { operation_id: crypto.randomUUID(), source: source.url, release } })
|
||||
return '已校验并暂存到桌面安装库,尚未安装或启用'
|
||||
}
|
||||
const catalog = await fetchCatalog(source, '', selected.type, signal)
|
||||
const release = catalog.items.find(item => item.release_id === selected.release_id)
|
||||
if (!release || release.sha256 !== selected.sha256 || release.withdrawn) throw new Error('发行已变更或撤回,请刷新目录')
|
||||
|
||||
Reference in New Issue
Block a user