Fix AI proxy origin in Tauri, SF2 program_select, VSTi GUI reopen + sample rate bridge

- aiGateway.js: use window.API_BASE_URL (engine port) instead of window.location.origin (tauri://localhost asset protocol returned index.html -> JSON parse error); check content-type before parsing response
- NativeInstrumentEngine.cpp: fluid_synth_program_select for SF2 instrument + program change
- Vst3Instrument.cpp: activate all audio/event buses, channel=0 forced, GUI resize/reopen, kEvent using fix
- main.cpp: VST GUI reopen via WM_DESTROY, OleInitialize, steady_clock loop
- lib.rs: BridgeSampleRate state, restart_bridge_with_sample_rate command, borrow fix
- app.jsx/nativeBridgeService.js: isMidiTrack widening, bridge masterbus connect, held MIDI notes, sample-rate restart, openNativeGUI channel
This commit is contained in:
2026-08-13 11:26:39 +07:00
parent 49549aba2e
commit d168328004
8 changed files with 218 additions and 59 deletions
+16 -2
View File
@@ -294,7 +294,7 @@ ${rules.join('\n')}` },
async function callLLM({ provider, model, apiKey, baseUrl, messages, tools, toolChoice }) {
const base = baseUrl.replace(/\/$/, '');
const url = `${base}/chat/completions`;
const origin = window.location.origin;
const origin = (window.API_BASE_URL || window.location.origin).replace(/\/+$/, '');
const urlOrigin = parseOrigin(url);
const appOrigin = parseOrigin(origin);
const sameOrigin = urlOrigin === appOrigin;
@@ -341,7 +341,21 @@ ${rules.join('\n')}` },
throw new Error(detail);
}
return await response.json();
const ct = (response.headers.get('content-type') || '').toLowerCase();
if (!ct.includes('application/json') && !ct.includes('text/json')) {
const raw = (await response.text()).slice(0, 300);
throw new Error(`Phản hồi không phải JSON (HTTP ${response.status}, ${ct || 'no content-type'}).
Có thể proxy trỏ sai địa chỉ hoặc server trả trang HTML.
Raw: ${raw}`);
}
try {
return await response.json();
} catch (e) {
const raw = (await response.text()).slice(0, 300);
throw new Error(`JSON parse lỗi từ server AI (HTTP ${response.status}): ${e.message}
Raw: ${raw}`);
}
}
function extractFunctionCalls(completion) {
@@ -135,10 +135,13 @@
/**
* 3. OPEN FLOATING CHILD WINDOW NATIVE GUI
*/
openNativeGUI: async function (pluginId) {
openNativeGUI: async function (pluginId, channel) {
if (!this._tauri()) return false;
try {
await window.__TAURI__.core.invoke('open_vst_gui', { pluginId: pluginId });
await window.__TAURI__.core.invoke('open_vst_gui', {
pluginId: pluginId,
channel: channel === undefined ? 0 : channel
});
return true;
} catch (e) {
console.warn('[BridgeService] open_vst_gui:', e);