feat: integrate safer vehicle CAN reasoning
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
};
|
||||
|
||||
const dropdownControls = new Map();
|
||||
let reasoningPickerControl = null;
|
||||
|
||||
function make(tag, className, html) {
|
||||
const node = document.createElement(tag);
|
||||
@@ -47,6 +48,99 @@
|
||||
});
|
||||
}
|
||||
|
||||
function closeReasoningPicker() {
|
||||
reasoningPickerControl?.close();
|
||||
}
|
||||
|
||||
function installReasoningPicker(reasoningField, originalForm) {
|
||||
const composer = $(".command-composer", originalForm);
|
||||
if (!composer || !reasoningField) return;
|
||||
|
||||
reasoningField.classList.add("v2-reasoning-field");
|
||||
reasoningField.hidden = true;
|
||||
const trigger = make("button", "v2-reasoning-trigger", `
|
||||
<i data-lucide="sparkles"></i>
|
||||
<span>模型智能</span>
|
||||
<strong id="v2ReasoningValue">均衡</strong>
|
||||
<i class="v2-reasoning-caret" data-lucide="chevron-up"></i>`);
|
||||
trigger.id = "v2ReasoningTrigger";
|
||||
trigger.type = "button";
|
||||
trigger.setAttribute("aria-haspopup", "listbox");
|
||||
trigger.setAttribute("aria-expanded", "false");
|
||||
trigger.setAttribute("aria-controls", "reasoningField");
|
||||
trigger.setAttribute("aria-label", "选择模型智能程度,当前均衡");
|
||||
$(".reasoning-segmented", reasoningField)?.setAttribute("role", "listbox");
|
||||
|
||||
const options = () => $$('[data-reasoning-effort]', reasoningField);
|
||||
const place = () => {
|
||||
if (reasoningField.hidden) return;
|
||||
const triggerBox = trigger.getBoundingClientRect();
|
||||
const width = Math.min(320, Math.max(250, window.innerWidth - 24));
|
||||
const left = Math.min(
|
||||
Math.max(12, triggerBox.left),
|
||||
Math.max(12, window.innerWidth - width - 12),
|
||||
);
|
||||
reasoningField.style.width = `${width}px`;
|
||||
reasoningField.style.left = `${left}px`;
|
||||
const height = reasoningField.offsetHeight;
|
||||
const above = triggerBox.top - height - 8;
|
||||
const top = above >= 12
|
||||
? above
|
||||
: Math.min(triggerBox.bottom + 8, window.innerHeight - height - 12);
|
||||
reasoningField.style.top = `${Math.max(12, top)}px`;
|
||||
};
|
||||
const sync = () => {
|
||||
const selected = options().find((button) => button.classList.contains("active"));
|
||||
const label = selected?.querySelector("strong")?.textContent?.trim() || "均衡";
|
||||
const unavailable = options().length > 0 && options().every((button) => button.disabled);
|
||||
$("#v2ReasoningValue", trigger).textContent = label;
|
||||
trigger.classList.toggle("unavailable", unavailable);
|
||||
trigger.setAttribute("aria-disabled", String(unavailable));
|
||||
trigger.setAttribute("aria-label", `选择模型智能程度,当前${label}`);
|
||||
options().forEach((button) => {
|
||||
button.setAttribute("role", "option");
|
||||
button.setAttribute("aria-selected", String(button === selected));
|
||||
});
|
||||
};
|
||||
const close = () => {
|
||||
reasoningField.hidden = true;
|
||||
trigger.classList.remove("open");
|
||||
trigger.setAttribute("aria-expanded", "false");
|
||||
};
|
||||
const open = () => {
|
||||
closeCustomDropdowns();
|
||||
reasoningField.hidden = false;
|
||||
trigger.classList.add("open");
|
||||
trigger.setAttribute("aria-expanded", "true");
|
||||
place();
|
||||
};
|
||||
reasoningPickerControl = { close, open, place, sync, trigger };
|
||||
composer.append(trigger);
|
||||
document.body.append(reasoningField);
|
||||
|
||||
trigger.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
if (reasoningField.hidden) open();
|
||||
else close();
|
||||
});
|
||||
reasoningField.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
if (!event.target.closest("[data-reasoning-effort]")) return;
|
||||
requestAnimationFrame(() => {
|
||||
sync();
|
||||
close();
|
||||
trigger.focus({ preventScroll: true });
|
||||
});
|
||||
});
|
||||
new MutationObserver(sync).observe(reasoningField, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class", "disabled"],
|
||||
subtree: true,
|
||||
});
|
||||
window.addEventListener("resize", place);
|
||||
sync();
|
||||
}
|
||||
|
||||
function enhanceSelect(select) {
|
||||
if (!select || dropdownControls.has(select)) return;
|
||||
const shell = select.parentElement;
|
||||
@@ -207,6 +301,7 @@
|
||||
function buildConfigFields(configStack, originalForm) {
|
||||
const vehicleField = $(".vehicle-field", originalForm);
|
||||
const providerField = $(".field-group:has(.segmented [data-provider])", originalForm);
|
||||
const reasoningField = $("#reasoningField", originalForm);
|
||||
const executionField = $(".field-group:has(.execution-mode-options)", originalForm);
|
||||
const simulationFaultField = $("#simulationFaultField", originalForm);
|
||||
|
||||
@@ -238,6 +333,7 @@
|
||||
<p class="provider-note" id="v2ModelNote">模型由服务端安全配置</p>`);
|
||||
modelField.id = "v2ModelField";
|
||||
configStack.append(modelField);
|
||||
installReasoningPicker(reasoningField, originalForm);
|
||||
|
||||
const gestureModelField = make("div", "v2-config-field v2-config-card v2-gesture-model-field", `
|
||||
<i data-lucide="scan-line"></i>
|
||||
@@ -773,9 +869,15 @@
|
||||
"click",
|
||||
() => setSidebarCollapsed(!ui.sidebarCollapsed),
|
||||
);
|
||||
document.addEventListener("click", () => closeCustomDropdowns());
|
||||
document.addEventListener("click", () => {
|
||||
closeCustomDropdowns();
|
||||
closeReasoningPicker();
|
||||
});
|
||||
document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") closeCustomDropdowns();
|
||||
if (event.key === "Escape") {
|
||||
closeCustomDropdowns();
|
||||
closeReasoningPicker();
|
||||
}
|
||||
});
|
||||
window.addEventListener("resize", updateScrollCues);
|
||||
window.addEventListener("resize", updateModeEdgeHints);
|
||||
|
||||
Reference in New Issue
Block a user