* feat: add custom endpoint fields to new profile form
* fix: skip config write tests when PyYAML not installed
The 4 unit tests for _write_endpoint_to_config imported yaml directly
without handling ImportError. Added pytest.importorskip('yaml') at
module level so the entire test class skips cleanly in environments
without PyYAML. Removed redundant per-method yaml imports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: wire frontend for custom endpoint fields in new profile form
- Add Base URL and API key inputs to the profile create form (index.html)
- Wire panels.js submitProfileCreate() to send base_url and api_key
- Clear new fields on form toggle/cancel
- Add client-side URL format validation (must start with http:// or https://)
- Add server-side URL format validation in routes.py (400 for invalid scheme)
- Add test_api_route_rejects_invalid_base_url() covering the new validation
- Base URL input has placeholder 'http://localhost:11434' per review suggestion
---------
Co-authored-by: Nathan Esquenazi <nesquena@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -841,6 +841,8 @@ function toggleProfileForm() {
|
||||
if (form.style.display !== 'none') {
|
||||
$('profileFormName').value = '';
|
||||
$('profileFormClone').checked = false;
|
||||
if ($('profileFormBaseUrl')) $('profileFormBaseUrl').value = '';
|
||||
if ($('profileFormApiKey')) $('profileFormApiKey').value = '';
|
||||
const errEl = $('profileFormError');
|
||||
if (errEl) errEl.style.display = 'none';
|
||||
$('profileFormName').focus();
|
||||
@@ -854,7 +856,15 @@ async function submitProfileCreate() {
|
||||
if (!name) { errEl.textContent = 'Name is required'; errEl.style.display = ''; return; }
|
||||
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(name)) { errEl.textContent = 'Lowercase letters, numbers, hyphens, underscores only'; errEl.style.display = ''; return; }
|
||||
try {
|
||||
await api('/api/profile/create', { method: 'POST', body: JSON.stringify({ name, clone_config: cloneConfig }) });
|
||||
const baseUrl = (($('profileFormBaseUrl') && $('profileFormBaseUrl').value) || '').trim();
|
||||
const apiKey = (($('profileFormApiKey') && $('profileFormApiKey').value) || '').trim();
|
||||
if (baseUrl && !/^https?:\/\//.test(baseUrl)) {
|
||||
errEl.textContent = 'Base URL must start with http:// or https://'; errEl.style.display = ''; return;
|
||||
}
|
||||
const payload = { name, clone_config: cloneConfig };
|
||||
if (baseUrl) payload.base_url = baseUrl;
|
||||
if (apiKey) payload.api_key = apiKey;
|
||||
await api('/api/profile/create', { method: 'POST', body: JSON.stringify(payload) });
|
||||
toggleProfileForm();
|
||||
await loadProfilesPanel();
|
||||
showToast('Profile created: ' + name);
|
||||
|
||||
Reference in New Issue
Block a user