Check live FIR enable state before each analysis
Deploy B9 / deploy (push) Successful in 3m36s

This commit is contained in:
fucheng
2026-11-05 14:33:36 +08:00
parent 4b3b86f256
commit d20d2bb11e
4 changed files with 59 additions and 5 deletions
+16
View File
@@ -40,6 +40,22 @@ export function validatePair(pair: FirPair) {
encodeFir(pair.left);
encodeFir(pair.right);
}
export async function requireFirEnabled(
api: Pick<LuxsinAPI, "getDeviceState">
): Promise<void> {
// Always query the device: a React state snapshot may predate the FIR toggle.
const state = await api.getDeviceState();
if (state.fir_enable !== 1) {
throw new Error("FIR 未启用或无法确认开关状态,请先前往 Effect → FIR 手动启用,再重新分析。 / FIR is disabled or its status is unknown. Please manually enable it at Effect → FIR before analyzing.");
}
}
export async function readEnabledCurrentFir(
api: Pick<LuxsinAPI, "getDeviceState" | "getFirChannel">
): Promise<FirPair> {
await requireFirEnabled(api);
return readCurrentFir(api);
}
export async function readCurrentFir(
api: Pick<LuxsinAPI, "getFirChannel">
): Promise<FirPair> {
+1 -1
View File
@@ -383,7 +383,7 @@ export class LuxsinAPI {
async getDeviceState(): Promise<DeviceState> {
try {
const response = await fetch(`${this.baseUrl}/dev/info.cgi?action=syncData`);
const response = await fetch(`${this.baseUrl}/dev/info.cgi?action=syncData`, { cache: "no-store" });
const text = await response.text();
const decoded = decodeCustomBase64(text.trim());
const state = JSON.parse(decoded) as DeviceState;
+9 -4
View File
@@ -1,6 +1,6 @@
import AiFirCard from '@/components/AiFirCard';
import {aiFirText} from '@/lib/aiFirLocale';
import {readCurrentFir, firMetrics, renderFir, type FirPair, type FirProposal, type FirAdjustment} from '@/lib/aiFir';
import {readEnabledCurrentFir, requireFirEnabled, firMetrics, renderFir, type FirPair, type FirProposal, type FirAdjustment} from '@/lib/aiFir';
/* ============================================================
AI PAGE — Luxsin X9 AI Assistant
- 首次进入: 中央 Logo + 建议气泡,引导用户如何提问
@@ -260,11 +260,13 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
try {
if(block.name==='get_current_fir') {
firSnapshot.current=null;
const pair=await readCurrentFir(api);
setFirProposal(null);
const pair=await readEnabledCurrentFir(api);
if(firDeviceRef.current!==device) throw new Error('Device changed');
const id=makeId();firSnapshot.current={id,pair};
return {ok:true,content:{snapshot_id:id,...firMetrics(pair)}};
}
await requireFirEnabled(api);
const a=block.input as FirAdjustment;
const snapshot=firSnapshot.current;
if(!snapshot || a.snapshot_id!==snapshot.id) throw new Error('Read current FIR in this turn before proposing an adjustment');
@@ -273,7 +275,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
setFirCardVisible(true);
setFirProposal({id:makeId(),device,before:snapshot.pair,after,adjustment:a,created:new Date().toISOString()});
return {ok:true,content:{status:'awaiting_user_confirmation',before:firMetrics(snapshot.pair),after:firMetrics(after),message:'FIR arrays staged only. Device unchanged. User must confirm upload in the AI FIR card; backup precedes upload, then A/B is available.'}};
}catch(error){return {ok:false,message:error instanceof Error?error.message:'FIR failed'};}
}catch(error){firSnapshot.current=null;setFirProposal(null);return {ok:false,message:error instanceof Error?error.message:'FIR failed'};}
};
const [chatId, setChatId] = useState<string | null>(null);
@@ -534,7 +536,10 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
// 组装新版 /sse/question 请求体
const buildAndStream = async () => {
let devicePeq: any;
let latestDeviceState;
try {
latestDeviceState = await api.getDeviceState();
if (firDeviceRef.current !== mac) throw new Error("Device changed");
const peqState = await api.getPeqState();
devicePeq = {
peqSelect: peqState.peqSelect ?? deviceState.peqSelect ?? 0,
@@ -566,7 +571,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
const controller = streamQuestion(
{
question: trimmed,
device_setting: { ...deviceState },
device_setting: { ...latestDeviceState },
device_peq: devicePeq,
chat_id: currentChatId,
},