feat: project native persona authorization status
This commit is contained in:
parent
584f38b478
commit
8f18c3fba3
38 changed files with 268 additions and 40 deletions
|
|
@ -43,6 +43,13 @@ describe('PersonaLanguageShellPanel', () => {
|
|||
repositoryPaths={['/persona']}
|
||||
providers={[provider]}
|
||||
planGoal={planGoal}
|
||||
loadAuthorizationStatus={async () => ({
|
||||
phase: 'system_direct',
|
||||
reason: 'NO_TRUSTED_SIGNER',
|
||||
sourceCommit: 'a'.repeat(40),
|
||||
signerCount: 0,
|
||||
authorizationEnabled: false,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
|
|
@ -56,10 +63,12 @@ describe('PersonaLanguageShellPanel', () => {
|
|||
repositoryPaths: ['/persona'],
|
||||
providers: [provider],
|
||||
developmentId: 'DEV-20260811-010',
|
||||
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.15',
|
||||
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.16',
|
||||
}))
|
||||
expect(await screen.findByText('我还不能执行:需要当前证据。')).toBeInTheDocument()
|
||||
expect(screen.getByText('核验当前事实后规划下一步')).toBeInTheDocument()
|
||||
expect(screen.getByText('系统直连 · 当前没有可信授权签名方')).toBeInTheDocument()
|
||||
expect(screen.getByText('a'.repeat(40))).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows the repository gate and never calls a later lifecycle itself', async () => {
|
||||
|
|
@ -76,6 +85,13 @@ describe('PersonaLanguageShellPanel', () => {
|
|||
repositoryPaths={['/ordinary']}
|
||||
providers={[provider]}
|
||||
planGoal={planGoal}
|
||||
loadAuthorizationStatus={async () => ({
|
||||
phase: 'unavailable',
|
||||
reason: 'REGISTRY_UNAVAILABLE',
|
||||
sourceCommit: null,
|
||||
signerCount: 0,
|
||||
authorizationEnabled: false,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
|
|
@ -84,5 +100,6 @@ describe('PersonaLanguageShellPanel', () => {
|
|||
|
||||
expect(await screen.findByText('这只说明当前挂载范围没有匹配的完整证据,不能据此判定人格不存在。')).toBeInTheDocument()
|
||||
expect(screen.queryByLabelText('reality boundary confirmation')).not.toBeInTheDocument()
|
||||
expect(screen.getByText('授权状态不可核验 · 保持系统直连')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import { useMemo, useRef, useState } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import type { AiModelProvider } from '../lib/aiTargets'
|
||||
import { DEFAULT_LANGUAGE_WORLD_UI_PLUGIN } from '../lib/defaultLanguageWorldUiPlugin'
|
||||
import { translate, type AppLocale } from '../lib/i18n'
|
||||
import {
|
||||
loadPersonaControlAuthorizationStatus,
|
||||
type PersonaControlAuthorizationStatus,
|
||||
} from '../lib/personaControlAuthorization'
|
||||
import {
|
||||
planPersonaLanguageShellGoal,
|
||||
type PersonaLanguageShellPlan,
|
||||
|
|
@ -13,10 +17,11 @@ import {
|
|||
type LanguageShellViewState,
|
||||
} from './HotPluggableLanguageShell'
|
||||
|
||||
const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.15'
|
||||
const CURRENT_ARCHITECTURE_ANCHOR = 'HLP-CURRENT-ARCH-001@2026-08-12.16'
|
||||
const DEVELOPMENT_ID = 'DEV-20260811-010'
|
||||
|
||||
type Planner = typeof planPersonaLanguageShellGoal
|
||||
type AuthorizationStatusLoader = () => Promise<PersonaControlAuthorizationStatus>
|
||||
|
||||
type PersonaLanguageShellPanelProps = {
|
||||
locale: AppLocale
|
||||
|
|
@ -24,6 +29,7 @@ type PersonaLanguageShellPanelProps = {
|
|||
repositoryPaths: readonly string[]
|
||||
providers: readonly AiModelProvider[]
|
||||
planGoal?: Planner
|
||||
loadAuthorizationStatus?: AuthorizationStatusLoader
|
||||
}
|
||||
|
||||
function requestId(): string {
|
||||
|
|
@ -78,6 +84,7 @@ export function PersonaLanguageShellPanel({
|
|||
repositoryPaths,
|
||||
providers,
|
||||
planGoal = planPersonaLanguageShellGoal,
|
||||
loadAuthorizationStatus = loadPersonaControlAuthorizationStatus,
|
||||
}: PersonaLanguageShellPanelProps) {
|
||||
const plugin = useMemo(() => localizedPlugin(locale), [locale])
|
||||
const requestSequence = useRef(0)
|
||||
|
|
@ -87,6 +94,15 @@ export function PersonaLanguageShellPanel({
|
|||
receipt: null,
|
||||
evidence: null,
|
||||
})
|
||||
const [authorizationStatus, setAuthorizationStatus] = useState<PersonaControlAuthorizationStatus | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
let current = true
|
||||
void loadAuthorizationStatus().then((status) => {
|
||||
if (current) setAuthorizationStatus(status)
|
||||
})
|
||||
return () => { current = false }
|
||||
}, [loadAuthorizationStatus])
|
||||
|
||||
const submitGoal = (utterance: string) => {
|
||||
if (!utterance.trim()) return
|
||||
|
|
@ -146,6 +162,18 @@ export function PersonaLanguageShellPanel({
|
|||
</div>
|
||||
<small>{translate(locale, 'hololake.personaRuntime.readOnly')}</small>
|
||||
</header>
|
||||
<div className="persona-runtime-projection__message" aria-live="polite">
|
||||
<p>
|
||||
{authorizationStatus === null
|
||||
? translate(locale, 'hololake.personaRuntime.checking')
|
||||
: authorizationStatus.phase === 'system_direct'
|
||||
? translate(locale, 'hololake.personaAuthorization.systemDirect')
|
||||
: translate(locale, 'hololake.personaAuthorization.unavailable')}
|
||||
</p>
|
||||
{authorizationStatus?.phase === 'system_direct' && (
|
||||
<code>{authorizationStatus.sourceCommit}</code>
|
||||
)}
|
||||
</div>
|
||||
<HotPluggableLanguageShell
|
||||
plugin={plugin}
|
||||
state={state}
|
||||
|
|
|
|||
Loading…
Reference in a new issue