fix: sửa copilot không gửi AI provider 2
This commit is contained in:
@@ -3,249 +3,49 @@
|
||||
|
||||
const AIGateway = (function() {
|
||||
const DEFAULT_TOOLS = [{
|
||||
name: 'create_track',
|
||||
description: 'Tạo một track âm thanh mới trong dự án',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string', description: 'Tên cho track mới (VD: Beat, Vocal, Guitar)' },
|
||||
type: { type: 'string', enum: ['audio', 'midi'], description: 'Loại track' }
|
||||
},
|
||||
required: ['name']
|
||||
}
|
||||
name: 'set_selection', description: 'Chọn vùng timeline', parameters: { type: 'object', properties: { start_bar: { type: 'number' }, end_bar: { type: 'number' }, start_time: { type: 'number' }, end_time: { type: 'number' }, length_bars: { type: 'number' } } }
|
||||
}, {
|
||||
name: 'delete_track',
|
||||
description: 'Xóa một track khỏi dự án',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần xóa. Nếu không có thì xóa track đang chọn.' }
|
||||
}
|
||||
}
|
||||
name: 'cut_audio', description: 'Cắt audio, snap zero-crossing, tạo track mới', parameters: { type: 'object', properties: { track_id: { type: 'string' }, start_time: { type: 'number' }, end_time: { type: 'number' }, start_bar: { type: 'number' }, end_bar: { type: 'number' }, length_bars: { type: 'number' }, snap_silence: { type: 'boolean' }, new_track_name: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'add_clip',
|
||||
description: 'Thêm một clip âm thanh rỗng vào track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track đích' },
|
||||
start_time: { type: 'number', description: 'Vị trí bắt đầu (giây)' },
|
||||
duration_seconds: { type: 'number', description: 'Độ dài clip (giây)' },
|
||||
start_bar: { type: 'number', description: 'Vị trí bắt đầu (bar). Bar 0 = bar đầu tiên. Dùng thay cho start_time.' },
|
||||
length_bars: { type: 'number', description: 'Độ dài (bar). Dùng thay cho duration_seconds.' },
|
||||
name: { type: 'string', description: 'Tên clip' }
|
||||
}
|
||||
}
|
||||
name: 'create_track', description: 'Tạo track mới', parameters: { type: 'object', properties: { name: { type: 'string' }, type: { type: 'string', enum: ['audio', 'midi'] } }, required: ['name'] }
|
||||
}, {
|
||||
name: 'remove_clip',
|
||||
description: 'Xóa một clip khỏi track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track' },
|
||||
clip_id: { type: 'string', description: 'ID của clip cần xóa' }
|
||||
},
|
||||
required: ['clip_id']
|
||||
}
|
||||
name: 'delete_track', description: 'Xóa track', parameters: { type: 'object', properties: { track_id: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'set_track_volume',
|
||||
description: 'Điều chỉnh âm lượng của track (dB)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track' },
|
||||
volume_db: { type: 'number', description: 'Âm lượng tính bằng dB (VD: -6, 0, +3)' }
|
||||
},
|
||||
required: ['volume_db']
|
||||
}
|
||||
name: 'rename_track', description: 'Đổi tên track', parameters: { type: 'object', properties: { track_id: { type: 'string' }, name: { type: 'string' } }, required: ['track_id', 'name'] }
|
||||
}, {
|
||||
name: 'set_track_pan',
|
||||
description: 'Điều chỉnh cân bằng trái/phải (pan) của track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track' },
|
||||
pan: { type: 'integer', description: 'Pan value: -100 (trái), 0 (trung tâm), 100 (phải)' }
|
||||
},
|
||||
required: ['pan']
|
||||
}
|
||||
name: 'add_clip', description: 'Thêm clip rỗng vào track', parameters: { type: 'object', properties: { track_id: { type: 'string' }, start_time: { type: 'number' }, duration_seconds: { type: 'number' }, start_bar: { type: 'number' }, length_bars: { type: 'number' }, name: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'toggle_mute',
|
||||
description: 'Bật/tắt mute (tắt tiếng) của track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần mute/unmute' }
|
||||
}
|
||||
}
|
||||
name: 'remove_clip', description: 'Xóa clip khỏi track', parameters: { type: 'object', properties: { track_id: { type: 'string' }, clip_id: { type: 'string' } }, required: ['clip_id'] }
|
||||
}, {
|
||||
name: 'toggle_solo',
|
||||
description: 'Bật/tắt solo (chỉ nghe track này) của track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần solo/unsolo' }
|
||||
}
|
||||
}
|
||||
name: 'set_track_volume', description: 'Chỉnh âm lượng dB', parameters: { type: 'object', properties: { track_id: { type: 'string' }, volume_db: { type: 'number' } }, required: ['volume_db'] }
|
||||
}, {
|
||||
name: 'rename_track',
|
||||
description: 'Đổi tên của một track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần đổi tên' },
|
||||
name: { type: 'string', description: 'Tên mới cho track' }
|
||||
},
|
||||
required: ['track_id', 'name']
|
||||
}
|
||||
name: 'set_track_pan', description: 'Chỉnh pan trái/phải', parameters: { type: 'object', properties: { track_id: { type: 'string' }, pan: { type: 'integer' } }, required: ['pan'] }
|
||||
}, {
|
||||
name: 'set_bpm',
|
||||
description: 'Thay đổi tempo (BPM) của dự án',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bpm: { type: 'number', description: 'Tempo mới tính bằng BPM (VD: 120, 128, 140)' }
|
||||
},
|
||||
required: ['bpm']
|
||||
}
|
||||
name: 'toggle_mute', description: 'Mute/unmute track', parameters: { type: 'object', properties: { track_id: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'set_playhead',
|
||||
description: 'Di chuyển playhead (con trỏ phát) đến vị trí chỉ định',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
time: { type: 'number', description: 'Vị trí thời gian tính bằng giây' },
|
||||
bar: { type: 'number', description: 'Vị trí bar (0 = bar đầu tiên). Dùng thay cho time.' }
|
||||
}
|
||||
}
|
||||
name: 'toggle_solo', description: 'Solo/unsolo track', parameters: { type: 'object', properties: { track_id: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'add_marker',
|
||||
description: 'Thêm một marker (đánh dấu) vào track tại vị trí chỉ định',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track' },
|
||||
time: { type: 'number', description: 'Vị trí thời gian (giây). Mặc định là vị trí playhead hiện tại.' },
|
||||
label: { type: 'string', description: 'Nhãn cho marker' }
|
||||
}
|
||||
}
|
||||
name: 'set_bpm', description: 'Thay đổi BPM', parameters: { type: 'object', properties: { bpm: { type: 'number' } }, required: ['bpm'] }
|
||||
}, {
|
||||
name: 'process_audio_dsp',
|
||||
description: 'Xử lý hiệu ứng âm thanh DSP cho track (chuẩn hóa, đảo phase, gain, pitch shift)',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track âm thanh' },
|
||||
action: { type: 'string', enum: ['normalize', 'invert_phase', 'gain', 'pitch_shift'], description: 'Loại xử lý DSP' },
|
||||
params: { type: 'object', description: 'Tham số bổ sung: gain_db cho gain, semitones cho pitch_shift' }
|
||||
},
|
||||
required: ['track_id', 'action']
|
||||
}
|
||||
name: 'set_playhead', description: 'Di chuyển playhead', parameters: { type: 'object', properties: { time: { type: 'number' }, bar: { type: 'number' } } }
|
||||
}, {
|
||||
name: 'create_midi_item',
|
||||
description: 'Thêm một MIDI item/clip vào track',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track đích' },
|
||||
start_bar: { type: 'number', description: 'Vị trí bắt đầu (tính bằng bar)' },
|
||||
length_bars: { type: 'number', description: 'Độ dài item (tính bằng bar)' }
|
||||
},
|
||||
required: ['track_id', 'start_bar', 'length_bars']
|
||||
}
|
||||
name: 'add_marker', description: 'Thêm marker', parameters: { type: 'object', properties: { track_id: { type: 'string' }, time: { type: 'number' }, label: { type: 'string' } } }
|
||||
}, {
|
||||
name: 'set_selection',
|
||||
description: 'Chọn một vùng trên timeline (selection range). Dùng để xác định khoảng thời gian trước khi gọi các lệnh khác.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
start_bar: { type: 'number', description: 'Bar bắt đầu (0 = bar đầu tiên của project)' },
|
||||
end_bar: { type: 'number', description: 'Bar kết thúc' },
|
||||
start_time: { type: 'number', description: 'Thời gian bắt đầu (giây). Dùng thay cho start_bar.' },
|
||||
end_time: { type: 'number', description: 'Thời gian kết thúc (giây). Dùng thay cho end_bar.' },
|
||||
length_bars: { type: 'number', description: 'Độ dài vùng chọn (bar). Dùng cùng start_bar thay cho end_bar.' }
|
||||
}
|
||||
}
|
||||
name: 'process_audio_dsp', description: 'Xử lý DSP: normalize/invert/gain/pitch', parameters: { type: 'object', properties: { track_id: { type: 'string' }, action: { type: 'string', enum: ['normalize', 'invert_phase', 'gain', 'pitch_shift'] }, params: { type: 'object' } }, required: ['track_id', 'action'] }
|
||||
}, {
|
||||
name: 'select_item',
|
||||
description: 'Chọn một item/clip/sample cụ thể trên track. Nếu không có track_id và item_name thì chọn toàn bộ timeline.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track. Nếu không có thì dùng track đang chọn.' },
|
||||
item_name: { type: 'string', description: 'Tên của clip/sample cần chọn. VD: "Cut_Cartoon Capers Loop.mp3". Nếu không có thì chọn toàn bộ track.' },
|
||||
select_all: { type: 'boolean', description: 'Chọn toàn bộ timeline (bỏ qua track_id và item_name)' }
|
||||
}
|
||||
}
|
||||
name: 'create_midi_item', description: 'Tạo MIDI item trên track', parameters: { type: 'object', properties: { track_id: { type: 'string' }, start_bar: { type: 'number' }, length_bars: { type: 'number' } }, required: ['track_id', 'start_bar', 'length_bars'] }
|
||||
}, {
|
||||
name: 'cut_audio',
|
||||
description: 'Cắt một đoạn audio từ track nguồn. Tự động tạo selection, snap zero-crossing, và tạo track mới chứa đoạn cắt. Lệnh DUY NHẤT cho thao tác cắt - không cần gọi set_selection trước.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track nguồn' },
|
||||
start_time: { type: 'number', description: 'Vị trí bắt đầu cắt (giây). Mặc định: dùng playhead hiện tại.' },
|
||||
end_time: { type: 'number', description: 'Vị trí kết thúc cắt (giây). Mặc định: dùng selection hiện tại.' },
|
||||
start_bar: { type: 'number', description: 'Bar bắt đầu cắt (0 = bar đầu). Dùng thay cho start_time.' },
|
||||
end_bar: { type: 'number', description: 'Bar kết thúc cắt. VD: end_bar=12 cắt đến bar 12. Dùng thay cho end_time.' },
|
||||
length_bars: { type: 'number', description: 'Độ dài cắt (bar). Dùng cùng start_bar thay cho end_bar.' },
|
||||
snap_silence: { type: 'boolean', description: 'Tự động snap vào điểm zero-crossing gần nhất ở hai đầu (mặc định: true)' },
|
||||
new_track_name: { type: 'string', description: 'Tên cho track mới. Mặc định: "Cut_<tên_track_gốc>"' }
|
||||
}
|
||||
}
|
||||
name: 'modify_midi_notes', description: 'Sửa note MIDI trong item', parameters: { type: 'object', properties: { item_id: { type: 'string' }, notes: { type: 'array', items: { type: 'object', properties: { pitch: { type: 'string' }, start_time: { type: 'number' }, duration: { type: 'number' }, velocity: { type: 'integer', minimum: 0, maximum: 127 } }, required: ['pitch', 'start_time', 'duration'] } } }, required: ['item_id', 'notes'] }
|
||||
}, {
|
||||
name: 'scan_track',
|
||||
description: 'Quét và phân tích track âm thanh: phát hiện BPM (tempo) và tự động cập nhật tempo hệ thống, sample rate, số kênh (mono/stereo), duration',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần quét' },
|
||||
set_tempo: { type: 'boolean', description: 'Tự động cập nhật tempo hệ thống (mặc định: true)' }
|
||||
}
|
||||
}
|
||||
name: 'select_item', description: 'Chọn clip/item theo tên', parameters: { type: 'object', properties: { track_id: { type: 'string' }, item_name: { type: 'string' }, select_all: { type: 'boolean' } } }
|
||||
}, {
|
||||
name: 'modify_midi_notes',
|
||||
description: 'Thêm, chỉnh sửa hoặc xóa các note MIDI trong item',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
item_id: { type: 'string', description: 'ID của MIDI item' },
|
||||
notes: {
|
||||
type: 'array',
|
||||
description: 'Danh sách các note MIDI',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
pitch: { type: 'string', description: 'VD: C4, D#3, F5' },
|
||||
start_time: { type: 'number', description: 'Thời điểm bắt đầu (bar hoặc giây)' },
|
||||
duration: { type: 'number', description: 'Độ dài note' },
|
||||
velocity: { type: 'integer', minimum: 0, maximum: 127, description: 'Độ mạnh 0-127' }
|
||||
},
|
||||
required: ['pitch', 'start_time', 'duration']
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['item_id', 'notes']
|
||||
}
|
||||
name: 'scan_track', description: 'Phân tích track: BPM, SR, kênh', parameters: { type: 'object', properties: { track_id: { type: 'string' }, set_tempo: { type: 'boolean' } } }
|
||||
}, {
|
||||
name: 'export_audio',
|
||||
description: 'Xuất (export/render) âm thanh ra file WAV/MP3/OGG và tải về. Lệnh DUY NHẤT cho thao tác xuất file - không cần gọi lệnh khác.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
track_id: { type: 'string', description: 'ID của track cần xuất. Nếu không có thì dùng track đang chọn.' },
|
||||
format: { type: 'string', enum: ['wav', 'mp3', 'ogg'], description: 'Định dạng file xuất' },
|
||||
sample_rate: { type: 'string', enum: ['22500', '44100'], description: 'Sample rate (Hz). Chỉ dùng cho WAV.' },
|
||||
bit_depth: { type: 'string', enum: ['8', '16', '24'], description: 'Bit depth. Chỉ dùng cho WAV.' },
|
||||
quality: { type: 'string', enum: ['44khz', 'lossless'], description: 'Chất lượng. Dùng cho MP3/OGG.' },
|
||||
channels: { type: 'string', enum: ['mono', 'stereo'], description: 'Số kênh (mono/stereo)' },
|
||||
start_time: { type: 'number', description: 'Vị trí bắt đầu xuất (giây).' },
|
||||
end_time: { type: 'number', description: 'Vị trí kết thúc xuất (giây).' },
|
||||
start_bar: { type: 'number', description: 'Bar bắt đầu (0 = bar đầu). Dùng thay cho start_time.' },
|
||||
length_bars: { type: 'number', description: 'Độ dài (bar). Dùng cùng start_bar thay cho end_time.' }
|
||||
},
|
||||
required: ['format']
|
||||
}
|
||||
name: 'fade_in', description: 'Fade-in clip (0.5s đến max)', parameters: { type: 'object', properties: { track_id: { type: 'string' }, duration_seconds: { type: 'number' } } }
|
||||
}, {
|
||||
name: 'export_audio', description: 'Xuất file WAV/MP3/OGG và tải về', parameters: { type: 'object', properties: { track_id: { type: 'string' }, format: { type: 'string', enum: ['wav', 'mp3', 'ogg'] }, sample_rate: { type: 'string', enum: ['22500', '44100'] }, bit_depth: { type: 'string', enum: ['8', '16', '24'] }, quality: { type: 'string', enum: ['44khz', 'lossless'] }, channels: { type: 'string', enum: ['mono', 'stereo'] }, start_time: { type: 'number' }, end_time: { type: 'number' }, start_bar: { type: 'number' }, length_bars: { type: 'number' } }, required: ['format'] }
|
||||
}, {
|
||||
name: 'fade_out', description: 'Fade-out clip (0.5s đến max)', parameters: { type: 'object', properties: { track_id: { type: 'string' }, duration_seconds: { type: 'number' } } }
|
||||
}];
|
||||
|
||||
function parseOrigin(urlStr) {
|
||||
@@ -343,7 +143,7 @@ const AIGateway = (function() {
|
||||
const contextStr = JSON.stringify(context, null, 2);
|
||||
const toolNames = DEFAULT_TOOLS.map(t => ` - ${t.name}: ${t.description}`).join('\n');
|
||||
return [
|
||||
{ role: 'system', content: `Bạn là trợ lý AI cho DAW. Dùng function calls để thực hiện yêu cầu. Các function có sẵn:\n${toolNames}\n\nHƯỚNG DẪN:\n- Để xuất file: gọi export_audio với format, sample_rate, bit_depth, channels, start_time, end_time.\n- Để chọn vùng: gọi set_selection với start_time/end_time hoặc start_bar/end_bar.\n- Bar 0 = bar đầu tiên.\n- Có thể gọi NHIỀU function cùng lúc, không cần chờ kết quả function trước.` },
|
||||
{ role: 'system', content: `Bạn là trợ lý DAW. Dùng function calls. Bar 0 = bar đầu. Có thể gọi nhiều function cùng lúc.` },
|
||||
{ role: 'user', content: `Ngữ cảnh DAW hiện tại:\n${contextStr}\n\nYêu cầu người dùng: ${prompt}` }
|
||||
];
|
||||
}
|
||||
@@ -391,6 +191,11 @@ const AIGateway = (function() {
|
||||
toolChoice: 'auto'
|
||||
});
|
||||
|
||||
if (completion && completion.error) {
|
||||
const errMsg = completion.error.message || completion.error.code || JSON.stringify(completion.error);
|
||||
throw new Error(`AI Provider error: ${errMsg}`);
|
||||
}
|
||||
|
||||
const functionCalls = extractFunctionCalls(completion);
|
||||
const textResponse = completion.choices && completion.choices[0] && completion.choices[0].message && completion.choices[0].message.content
|
||||
? completion.choices[0].message.content
|
||||
|
||||
@@ -59,6 +59,8 @@ const DAWCommandDispatcher = (function() {
|
||||
register('PROCESS_AUDIO_DSP', (args) => api.processAudioDsp(args));
|
||||
register('RENAME_TRACK', (args) => api.renameTrack(args));
|
||||
register('SCAN_TRACK', (args) => api.scanTrack(args));
|
||||
register('FADE_IN', (args) => api.fadeIn(args));
|
||||
register('FADE_OUT', (args) => api.fadeOut(args));
|
||||
register('CUT_AUDIO', (args) => api.cutAudio(args));
|
||||
register('SET_SELECTION', (args) => api.setSelection(args));
|
||||
register('EXPORT_AUDIO', (args) => api.exportAudio(args));
|
||||
|
||||
Reference in New Issue
Block a user