7519309a27
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { LANGUAGE_VERSION } from './LanguageScene';
|
|
import { validateJevDecision, type AgentVersion, type JevDecision, type Skill } from './protocol';
|
|
|
|
export const QUALITY_POINTS = { poor: 0, partial: 25, good: 75, excellent: 100 } as const;
|
|
const REASONS = {
|
|
unsafe: '检测到不安全因素',
|
|
insufficient_evidence: '当前阶段证据不足',
|
|
tracking_error: '动作跟踪或对齐异常',
|
|
verified_progress: '模型报告已有进展,但仍拒绝继续',
|
|
} as const;
|
|
function stopReason(decision: JevDecision): string {
|
|
const reason = decision.reason;
|
|
if (reason && reason !== 'none') return REASONS[reason];
|
|
return decision.noul === 'uncertain'
|
|
? '模型无法确认下一技能安全,未提供具体原因'
|
|
: '模型拒绝继续,未提供具体原因';
|
|
}
|
|
/** Supervisory advice can veto but cannot grant physical authority. */
|
|
export class TaskSupervisor {
|
|
last?: JevDecision;
|
|
get qualityScore(): number | undefined {
|
|
const score = this.last?.score;
|
|
return score && score !== 'unavailable' ? QUALITY_POINTS[score] : undefined;
|
|
}
|
|
inspect(
|
|
value: unknown,
|
|
candidates: readonly (Skill | 'stop')[],
|
|
version: AgentVersion,
|
|
secure: boolean,
|
|
): JevDecision {
|
|
const decision = validateJevDecision(value, candidates, version);
|
|
this.last = decision;
|
|
if (version === LANGUAGE_VERSION && decision.noul !== 'allow')
|
|
throw new Error(`Noul 拦截(${decision.noul}):${stopReason(decision)}`);
|
|
if (decision.choice === 'stop' || decision.recovery === 'stop')
|
|
throw new Error(`Jev 请求安全停止:${stopReason(decision)}`);
|
|
if (decision.grasp === 'secure' && !secure) throw new Error('Jev 抓持判断与本地物理证据矛盾');
|
|
if (
|
|
['carry', 'stop-base'].includes(decision.choice) &&
|
|
(decision.grasp !== 'secure' || !secure)
|
|
)
|
|
throw new Error('搬运前未取得一致抓持证据');
|
|
return decision;
|
|
}
|
|
}
|