Merge pull request #3 from KGAudioLab/fix/2025-08-12-misc
Fix/2025 08 12 misc
This commit is contained in:
@@ -8,6 +8,12 @@ K.G.Studio is a lightweight, modern DAW that runs entirely in the browser with *
|
|||||||
|
|
||||||
**K.G.Studio Musician Assistant** is an AI assistance agent for harmony, arrangement, and note editing — but not full auto‑composition.
|
**K.G.Studio Musician Assistant** is an AI assistance agent for harmony, arrangement, and note editing — but not full auto‑composition.
|
||||||
|
|
||||||
|
## Project Status
|
||||||
|
|
||||||
|
**K.G.Studio is an experimental project in early development.** We're exploring the possibilities of integrating AI agents and LLMs into music production workflows — essentially building a "Cursor or Claude Code for DAW" experience.
|
||||||
|
|
||||||
|
This project investigates how AI-human collaboration can enhance creative music-making, from intelligent harmony suggestions to automated editing tasks. As an experimental platform, expect frequent changes, evolving features, and occasional instability as we push the boundaries of what's possible in AI-assisted music production.
|
||||||
|
|
||||||
### Highlights
|
### Highlights
|
||||||
- **K.G.Studio Musician Assistant**: Chat with the LLM‑powered K.G.Studio Musician Assistant AI Agent; it can automatically execute tools to make music edits.
|
- **K.G.Studio Musician Assistant**: Chat with the LLM‑powered K.G.Studio Musician Assistant AI Agent; it can automatically execute tools to make music edits.
|
||||||
- **Multiple LLM providers**: OpenAI, Claude (via OpenRouter), Gemini (via OpenRouter), or OpenAI‑compatible (e.g., Ollama, OpenRouter).
|
- **Multiple LLM providers**: OpenAI, Claude (via OpenRouter), Gemini (via OpenRouter), or OpenAI‑compatible (e.g., Ollama, OpenRouter).
|
||||||
@@ -144,13 +150,48 @@ K.G.Studio does not provide or host any of the models listed above, nor is it af
|
|||||||
## Upcoming Features
|
## Upcoming Features
|
||||||
|
|
||||||
- [ ] More instruments
|
- [ ] More instruments
|
||||||
|
- [ ] Automated testing (unit tests, integration tests, etc.)
|
||||||
- [ ] Support track control automations (e.g. sustain, volume, pan, etc.)
|
- [ ] Support track control automations (e.g. sustain, volume, pan, etc.)
|
||||||
- [ ] Support MIDI control events (e.g. CC, pitch bend, etc.)
|
- [ ] Support MIDI control events (e.g. CC, pitch bend, etc.)
|
||||||
- [ ] Support WAV audio tracks
|
- [ ] Support WAV audio tracks
|
||||||
|
- [ ] Filters and effects
|
||||||
- [ ] MCP Support
|
- [ ] MCP Support
|
||||||
- [ ] Add support for OpenAI's open source models (`gpt-oss-20b` and `gpt-oss-120b`)
|
- [ ] Add support for OpenAI's open source models (`gpt-oss-20b` and `gpt-oss-120b`)
|
||||||
- [ ] Automatically compact conversations when the context window runs low on space
|
- [ ] Automatically compact conversations when the context window runs low on space
|
||||||
|
|
||||||
|
## Help Needed
|
||||||
|
|
||||||
|
We're looking for contributors to help make K.G.Studio even better! Whether you're a developer, musician, or designer, your expertise can make a real difference.
|
||||||
|
|
||||||
|
### How You Can Help
|
||||||
|
|
||||||
|
**🎵 Musicians & Music Producers**
|
||||||
|
- Test the DAW with real-world music production workflows
|
||||||
|
- Provide feedback on instrument quality and realism
|
||||||
|
- Suggest missing features that are essential for music creation
|
||||||
|
- Help improve the AI assistant's musical understanding
|
||||||
|
|
||||||
|
**💻 Developers**
|
||||||
|
- Implement new features from our roadmap
|
||||||
|
- Fix bugs and improve performance
|
||||||
|
- Enhance the Web Audio integration
|
||||||
|
- Work on AI assistant capabilities
|
||||||
|
|
||||||
|
**🎨 UI/UX Designers**
|
||||||
|
- Improve the user interface and workflow
|
||||||
|
- Design better visual feedback for music editing
|
||||||
|
- Create more intuitive interactions
|
||||||
|
|
||||||
|
### Get Involved
|
||||||
|
|
||||||
|
Interested in contributing? We'd love to hear from you!
|
||||||
|
|
||||||
|
- **Email us**: [kgstudio@duck.com](mailto:kgstudio@duck.com)
|
||||||
|
- **Check our Issues**: Browse open issues labeled with `help wanted` or `good first issue`
|
||||||
|
- **Join Discussions**: Share ideas and feedback in GitHub Discussions
|
||||||
|
|
||||||
|
No contribution is too small — from reporting bugs to suggesting new features, every bit of help moves the project forward!
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0, with additional terms (see `LICENSE`):
|
Licensed under the Apache License, Version 2.0, with additional terms (see `LICENSE`):
|
||||||
|
|||||||
+1
-1
@@ -1591,7 +1591,7 @@ textarea {
|
|||||||
|
|
||||||
.settings-input, .settings-select, .settings-textarea {
|
.settings-input, .settings-select, .settings-textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 300px;
|
/* max-width: 300px; */
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
background-color: #3a3a3a;
|
background-color: #3a3a3a;
|
||||||
border: 1px solid #555;
|
border: 1px solid #555;
|
||||||
|
|||||||
+93
-1
@@ -29,7 +29,8 @@ export class KGDebugger {
|
|||||||
'createTestRegion()',
|
'createTestRegion()',
|
||||||
'testExtractXMLFromString(input)',
|
'testExtractXMLFromString(input)',
|
||||||
'testXMLToolExecution(input)',
|
'testXMLToolExecution(input)',
|
||||||
'testAttemptCompletion(comment)'
|
'testAttemptCompletion(comment)',
|
||||||
|
'inputChatBox(content, interval?)'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,6 +403,7 @@ export class KGDebugger {
|
|||||||
console.log(" testExtractXMLFromString(input) - Test XML extraction from string");
|
console.log(" testExtractXMLFromString(input) - Test XML extraction from string");
|
||||||
console.log(" testXMLToolExecution(input) - Test complete XML tool execution pipeline");
|
console.log(" testXMLToolExecution(input) - Test complete XML tool execution pipeline");
|
||||||
console.log(" testAttemptCompletion(comment) - Test AttemptCompletionTool with agent state");
|
console.log(" testAttemptCompletion(comment) - Test AttemptCompletionTool with agent state");
|
||||||
|
console.log(" inputChatBox(content, interval?) - Type into ChatBox textarea and submit with Enter");
|
||||||
console.log(" help() - Show this help");
|
console.log(" help() - Show this help");
|
||||||
console.log("");
|
console.log("");
|
||||||
console.log("💡 Usage tips:");
|
console.log("💡 Usage tips:");
|
||||||
@@ -412,4 +414,94 @@ export class KGDebugger {
|
|||||||
console.log(" - For full tool execution, try: await testXMLToolExecution('Create notes: <add_notes><note><pitch>C4</pitch><start_beat>0</start_beat><length>1</length></note></add_notes>');");
|
console.log(" - For full tool execution, try: await testXMLToolExecution('Create notes: <add_notes><note><pitch>C4</pitch><start_beat>0</start_beat><length>1</length></note></add_notes>');");
|
||||||
console.log(" - For completion testing, try: await testAttemptCompletion('Successfully created a C major chord');");
|
console.log(" - For completion testing, try: await testAttemptCompletion('Successfully created a C major chord');");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type content into ChatBox textarea character-by-character and submit with Enter.
|
||||||
|
* Honors auto-resize (by dispatching 'input' events) and ChatBox's Enter-to-send behavior.
|
||||||
|
* @param content - The text to type into the chat input
|
||||||
|
* @param interval - Delay in ms between characters (default 30ms)
|
||||||
|
*/
|
||||||
|
public async inputChatBox(content: string, interval: number = 30): Promise<void> {
|
||||||
|
try {
|
||||||
|
const textarea = document.querySelector('textarea.chatbox-input') as HTMLTextAreaElement | null;
|
||||||
|
if (!textarea) {
|
||||||
|
console.error('❌ ChatBox textarea not found. Ensure ChatBox is mounted and visible.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus to trigger ChatBox focus handlers and ensure caret/attribute setup
|
||||||
|
textarea.focus();
|
||||||
|
|
||||||
|
// Use native value setter to keep React's value tracker in sync
|
||||||
|
const valueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;
|
||||||
|
const setValue = (val: string) => {
|
||||||
|
if (valueSetter) {
|
||||||
|
valueSetter.call(textarea, val);
|
||||||
|
} else {
|
||||||
|
textarea.value = val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to dispatch an InputEvent so React's onChange fires
|
||||||
|
const dispatchInput = (data?: string) => {
|
||||||
|
const ev = typeof InputEvent !== 'undefined'
|
||||||
|
? new InputEvent('input', { bubbles: true, data, inputType: 'insertText' })
|
||||||
|
: new Event('input', { bubbles: true });
|
||||||
|
textarea.dispatchEvent(ev);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start from empty content to simulate a fresh user input
|
||||||
|
setValue('');
|
||||||
|
dispatchInput('');
|
||||||
|
|
||||||
|
// Helper: sleep
|
||||||
|
const sleep = (ms: number) => new Promise<void>(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
let typed = '';
|
||||||
|
for (let i = 0; i < content.length; i++) {
|
||||||
|
typed += content[i];
|
||||||
|
|
||||||
|
// Update the controlled textarea and dispatch input so React onChange fires
|
||||||
|
setValue(typed);
|
||||||
|
dispatchInput(content[i]);
|
||||||
|
|
||||||
|
// Place caret at end for realism
|
||||||
|
try {
|
||||||
|
textarea.selectionStart = textarea.selectionEnd = typed.length;
|
||||||
|
} catch {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interval > 0) {
|
||||||
|
await sleep(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give React a brief moment to commit the last setState and run auto-resize effect
|
||||||
|
await sleep(Math.max(30, interval));
|
||||||
|
|
||||||
|
// Simulate pressing Enter to submit (ChatBox listens on keydown)
|
||||||
|
const enterEvent = new KeyboardEvent('keydown', {
|
||||||
|
key: 'Enter',
|
||||||
|
code: 'Enter',
|
||||||
|
keyCode: 13,
|
||||||
|
which: 13,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true
|
||||||
|
} as KeyboardEventInit & { keyCode: number; which: number });
|
||||||
|
textarea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
|
// Optional: follow-up keyup to mirror real typing (some UIs inspect it)
|
||||||
|
const keyupEvent = new KeyboardEvent('keyup', {
|
||||||
|
key: 'Enter',
|
||||||
|
code: 'Enter',
|
||||||
|
keyCode: 13,
|
||||||
|
which: 13,
|
||||||
|
bubbles: true,
|
||||||
|
} as KeyboardEventInit & { keyCode: number; which: number });
|
||||||
|
textarea.dispatchEvent(keyupEvent);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error in inputChatBox:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user