fix: compose named cockpit modes from capabilities
This commit is contained in:
+56
-7
@@ -8310,20 +8310,69 @@ window.CognitiveAgentConsole = {
|
||||
? draft.trim()
|
||||
: String(draft?.instruction || "").trim();
|
||||
if (!instruction) throw new Error("功能模式草稿缺少可试运行的指令。");
|
||||
const { payload } = await requestNaturalLanguageControl(instruction, {
|
||||
executionMode: "dry_run",
|
||||
clientType: "assistant_mode_trial",
|
||||
provider: "local",
|
||||
previewOnly: false,
|
||||
});
|
||||
let payload;
|
||||
if (draft && typeof draft === "object" && draft.source_request_id) {
|
||||
const response = await apiRequest("/api/mode-profile-drafts/trial", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
name: draft.name,
|
||||
instruction,
|
||||
source_request_id: draft.source_request_id,
|
||||
vehicle_id: draft.vehicle_id || state.vehicleId || null,
|
||||
}),
|
||||
timeoutMs: 30 * 1000,
|
||||
retries: 0,
|
||||
});
|
||||
payload = await response.json();
|
||||
if (response.status === 401) {
|
||||
window.location.replace("/login");
|
||||
return null;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(payload.message || payload.error || `HTTP ${response.status}`);
|
||||
}
|
||||
} else {
|
||||
({ payload } = await requestNaturalLanguageControl(instruction, {
|
||||
executionMode: "dry_run",
|
||||
clientType: "assistant_mode_trial",
|
||||
provider: "local",
|
||||
previewOnly: false,
|
||||
}));
|
||||
}
|
||||
if (!payload) throw new Error("模拟试运行没有返回结果。");
|
||||
const actualOperationCount = Object.values(payload.function_configs || {})
|
||||
.reduce((total, config) => total + (config?.spec?.operations?.length || 0), 0);
|
||||
const expectedOperationCount = Number(
|
||||
typeof draft === "object" ? draft?.operation_count : 0,
|
||||
);
|
||||
const actionSignature = (action) => {
|
||||
const target = action?.target && typeof action.target === "object"
|
||||
? action.target.instance || action.target.zone || action.target.device || ""
|
||||
: action?.target || "";
|
||||
const parameters = action?.parameters && typeof action.parameters === "object"
|
||||
? Object.fromEntries(Object.entries(action.parameters).sort(([left], [right]) => left.localeCompare(right)))
|
||||
: {};
|
||||
return JSON.stringify([
|
||||
String(action?.domain || ""),
|
||||
String(action?.capability || ""),
|
||||
String(target),
|
||||
parameters,
|
||||
]);
|
||||
};
|
||||
const expectedSignatures = Array.isArray(draft?.actions)
|
||||
? draft.actions.map(actionSignature).sort()
|
||||
: [];
|
||||
const actualActions = Array.isArray(payload?.intent_ir?.spec?.actions)
|
||||
? payload.intent_ir.spec.actions
|
||||
: [];
|
||||
const actualSignatures = actualActions.map(actionSignature).sort();
|
||||
const sameActions = expectedSignatures.length === 0
|
||||
|| (expectedSignatures.length === actualSignatures.length
|
||||
&& expectedSignatures.every((signature, index) => signature === actualSignatures[index]));
|
||||
if (payload.status !== "succeeded"
|
||||
|| (expectedOperationCount > 0 && actualOperationCount < expectedOperationCount)) {
|
||||
|| (expectedOperationCount > 0 && actualOperationCount < expectedOperationCount)
|
||||
|| !sameActions) {
|
||||
throw new Error("试运行未完整覆盖草稿动作,请重新生成模式预览。");
|
||||
}
|
||||
return payload;
|
||||
|
||||
Reference in New Issue
Block a user