feat: project verified PNCC runtime into HoloLake
This commit is contained in:
parent
1b55f3407a
commit
0c80296593
33 changed files with 1265 additions and 24 deletions
|
|
@ -0,0 +1,211 @@
|
|||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { isTauri, mockInvoke } from '../mock-tauri'
|
||||
|
||||
export interface PersonaRuntimeAttribution {
|
||||
humanResponsibilitySubject: string
|
||||
personaCognitiveAuthor: string
|
||||
executionRuntime: string
|
||||
developmentId: string
|
||||
authorizationScope: string
|
||||
sourceLanguageAnchor: string
|
||||
}
|
||||
|
||||
export interface PersonaRuntimeSessionReceipt {
|
||||
sessionId: string
|
||||
state: string
|
||||
gitHead: string
|
||||
nodeId: string
|
||||
modelInstanceId: string
|
||||
activeOrgan: string | null
|
||||
eventCount: number
|
||||
firstEventAt: string
|
||||
lastEventAt: string
|
||||
lastEvent: string
|
||||
eventChainHead: string
|
||||
attribution: PersonaRuntimeAttribution
|
||||
}
|
||||
|
||||
export interface PersonaRuntimeQueryReceipt {
|
||||
schema: 'hololake.pncc-runtime-query/v1'
|
||||
personaId: string
|
||||
repositoryPath: string
|
||||
observedGitHead: string
|
||||
repositoryClean: boolean
|
||||
matchingSessionCount: number
|
||||
returnedSessionCount: number
|
||||
sessions: PersonaRuntimeSessionReceipt[]
|
||||
}
|
||||
|
||||
export interface PersonaRuntimeSessionProjection extends PersonaRuntimeSessionReceipt {
|
||||
repositoryPath: string
|
||||
observedGitHead: string
|
||||
repositoryClean: boolean
|
||||
}
|
||||
|
||||
export interface PersonaRuntimeProjectionError {
|
||||
code: string
|
||||
repositoryPath: string
|
||||
}
|
||||
|
||||
export interface PersonaRuntimeProjection {
|
||||
errors: PersonaRuntimeProjectionError[]
|
||||
inspectedRepositoryCount: number
|
||||
phase: 'unavailable' | 'verified' | 'error'
|
||||
sessions: PersonaRuntimeSessionProjection[]
|
||||
}
|
||||
|
||||
interface LoadPersonaRuntimeProjectionInput {
|
||||
personaId: string
|
||||
repositoryPaths: readonly string[]
|
||||
query?: (personaId: string, repositoryPath: string) => Promise<unknown>
|
||||
}
|
||||
|
||||
function errorCode(error: unknown): string {
|
||||
if (typeof error === 'string') return error
|
||||
if (error instanceof Error) return error.message
|
||||
return 'PERSONA_RUNTIME_QUERY_FAILED'
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
|
||||
function requiredString(record: Record<string, unknown>, key: string): string {
|
||||
const value = Reflect.get(record, key)
|
||||
if (typeof value !== 'string' || value.length === 0) throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
return value
|
||||
}
|
||||
|
||||
function requiredNumber(record: Record<string, unknown>, key: string): number {
|
||||
const value = Reflect.get(record, key)
|
||||
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
|
||||
throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
function parseAttribution(value: unknown): PersonaRuntimeAttribution {
|
||||
if (!isRecord(value)) throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
return {
|
||||
humanResponsibilitySubject: requiredString(value, 'humanResponsibilitySubject'),
|
||||
personaCognitiveAuthor: requiredString(value, 'personaCognitiveAuthor'),
|
||||
executionRuntime: requiredString(value, 'executionRuntime'),
|
||||
developmentId: requiredString(value, 'developmentId'),
|
||||
authorizationScope: requiredString(value, 'authorizationScope'),
|
||||
sourceLanguageAnchor: requiredString(value, 'sourceLanguageAnchor'),
|
||||
}
|
||||
}
|
||||
|
||||
function parseSession(value: unknown): PersonaRuntimeSessionReceipt {
|
||||
if (!isRecord(value)) throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
const activeOrgan = Reflect.get(value, 'activeOrgan')
|
||||
if (activeOrgan !== null && typeof activeOrgan !== 'string') {
|
||||
throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
}
|
||||
return {
|
||||
sessionId: requiredString(value, 'sessionId'),
|
||||
state: requiredString(value, 'state'),
|
||||
gitHead: requiredString(value, 'gitHead'),
|
||||
nodeId: requiredString(value, 'nodeId'),
|
||||
modelInstanceId: requiredString(value, 'modelInstanceId'),
|
||||
activeOrgan,
|
||||
eventCount: requiredNumber(value, 'eventCount'),
|
||||
firstEventAt: requiredString(value, 'firstEventAt'),
|
||||
lastEventAt: requiredString(value, 'lastEventAt'),
|
||||
lastEvent: requiredString(value, 'lastEvent'),
|
||||
eventChainHead: requiredString(value, 'eventChainHead'),
|
||||
attribution: parseAttribution(Reflect.get(value, 'attribution')),
|
||||
}
|
||||
}
|
||||
|
||||
function parseReceipt(
|
||||
value: unknown,
|
||||
expectedPersonaId: string,
|
||||
expectedRepositoryPath: string,
|
||||
): PersonaRuntimeQueryReceipt {
|
||||
if (!isRecord(value)) throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
const schema = requiredString(value, 'schema')
|
||||
const personaId = requiredString(value, 'personaId')
|
||||
const repositoryPath = requiredString(value, 'repositoryPath')
|
||||
const observedGitHead = requiredString(value, 'observedGitHead')
|
||||
const repositoryClean = Reflect.get(value, 'repositoryClean')
|
||||
const sessionsValue = Reflect.get(value, 'sessions')
|
||||
if (
|
||||
schema !== 'hololake.pncc-runtime-query/v1'
|
||||
|| personaId !== expectedPersonaId
|
||||
|| repositoryPath !== expectedRepositoryPath
|
||||
|| typeof repositoryClean !== 'boolean'
|
||||
|| !Array.isArray(sessionsValue)
|
||||
) {
|
||||
throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
}
|
||||
const matchingSessionCount = requiredNumber(value, 'matchingSessionCount')
|
||||
const returnedSessionCount = requiredNumber(value, 'returnedSessionCount')
|
||||
const sessions = sessionsValue.map(parseSession)
|
||||
if (returnedSessionCount !== sessions.length || matchingSessionCount < returnedSessionCount) {
|
||||
throw new Error('PERSONA_RUNTIME_RECEIPT_INVALID')
|
||||
}
|
||||
return {
|
||||
schema,
|
||||
personaId,
|
||||
repositoryPath,
|
||||
observedGitHead,
|
||||
repositoryClean,
|
||||
matchingSessionCount,
|
||||
returnedSessionCount,
|
||||
sessions,
|
||||
}
|
||||
}
|
||||
|
||||
async function queryNativeRuntime(personaId: string, repositoryPath: string): Promise<unknown> {
|
||||
const args = {
|
||||
input: {
|
||||
expectedPersonaId: personaId,
|
||||
expectedRepositoryPath: repositoryPath,
|
||||
limit: 25,
|
||||
},
|
||||
}
|
||||
return isTauri()
|
||||
? invoke<unknown>('query_persona_code_channel_runtime', args)
|
||||
: mockInvoke<unknown>('query_persona_code_channel_runtime', args)
|
||||
}
|
||||
|
||||
export async function loadPersonaRuntimeProjection({
|
||||
personaId,
|
||||
repositoryPaths,
|
||||
query = queryNativeRuntime,
|
||||
}: LoadPersonaRuntimeProjectionInput): Promise<PersonaRuntimeProjection> {
|
||||
const uniqueRepositoryPaths = [...new Set(repositoryPaths.map((path) => path.trim()).filter(Boolean))]
|
||||
if (uniqueRepositoryPaths.length === 0) {
|
||||
return { errors: [], inspectedRepositoryCount: 0, phase: 'unavailable', sessions: [] }
|
||||
}
|
||||
|
||||
const results = await Promise.all(uniqueRepositoryPaths.map(async (repositoryPath) => {
|
||||
try {
|
||||
const receipt = parseReceipt(await query(personaId, repositoryPath), personaId, repositoryPath)
|
||||
return { receipt, repositoryPath, error: null }
|
||||
} catch (error) {
|
||||
return { receipt: null, repositoryPath, error: errorCode(error) }
|
||||
}
|
||||
}))
|
||||
const verified = results.flatMap((result) => result.receipt ? [result.receipt] : [])
|
||||
const errors = results.flatMap((result) => result.error
|
||||
? [{ code: result.error, repositoryPath: result.repositoryPath }]
|
||||
: [])
|
||||
const sessions = verified.flatMap((receipt) => receipt.sessions.map((session) => ({
|
||||
...session,
|
||||
repositoryPath: receipt.repositoryPath,
|
||||
observedGitHead: receipt.observedGitHead,
|
||||
repositoryClean: receipt.repositoryClean,
|
||||
}))).sort((left, right) => (
|
||||
right.lastEventAt.localeCompare(left.lastEventAt)
|
||||
|| right.sessionId.localeCompare(left.sessionId)
|
||||
))
|
||||
|
||||
return {
|
||||
errors,
|
||||
inspectedRepositoryCount: verified.length,
|
||||
phase: verified.length > 0 ? 'verified' : 'error',
|
||||
sessions,
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue