Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,16 @@ var configSetCmd = &cobra.Command{
Available keys:
- data-dir: Data directory for storing notes database
- ollama-endpoint: Ollama API endpoint
- embedding-model: Embedding model name
- vector-dimensions: Number of vector dimensions
- enable-vector: Enable/disable vector search (true/false)
- debug: Enable/disable debug logging (true/false)
- summarization-model: Model to use for summarization
- enable-summarization: Enable/disable summarization features (true/false)
- editor: Default editor to use for editing notes (e.g., "vim", "code --wait")
- enable-auto-tagging: Enable/disable AI auto-tagging features (true/false)
- auto-tag-model: Model to use for auto-tagging (leave empty to use summarization model)
- max-auto-tags: Maximum number of tags to auto-generate per note (1-20)
- github-owner: GitHub repository owner for updates (default: streed)
- github-repo: GitHub repository name for updates (default: ml-notes)`,
- github-repo: GitHub repository name for updates (default: ml-notes)
- lilrag-url: Lil-Rag service endpoint for enhanced semantic search`,
Args: cobra.ExactArgs(2),
RunE: runConfigSet,
}
Expand Down Expand Up @@ -168,6 +169,8 @@ func runConfigSet(cmd *cobra.Command, args []string) error {
cfg.GitHubOwner = value
case "github-repo":
cfg.GitHubRepo = value
case "lilrag-url":
cfg.LilRagURL = value
default:
return fmt.Errorf("%w: %s", interrors.ErrUnknownConfigKey, key)
}
Expand Down
16 changes: 16 additions & 0 deletions internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,12 @@ type UpdateSettingsRequest struct {
EnableSummarization *bool `json:"enable_summarization,omitempty"`
Editor string `json:"editor,omitempty"`
EnableAutoTagging *bool `json:"enable_auto_tagging,omitempty"`
AutoTagModel string `json:"auto_tag_model,omitempty"`
MaxAutoTags *int `json:"max_auto_tags,omitempty"`
GitHubOwner string `json:"github_owner,omitempty"`
GitHubRepo string `json:"github_repo,omitempty"`
LilRagURL string `json:"lilrag_url,omitempty"`
WebUITheme string `json:"webui_theme,omitempty"`
}

func NewAPIServer(cfg *config.Config, db *sql.DB, repo *models.NoteRepository, vectorSearch search.SearchProvider, assetProvider AssetProvider) *APIServer {
Expand Down Expand Up @@ -1411,9 +1414,11 @@ func (s *APIServer) handleGetSettings(w http.ResponseWriter, r *http.Request) {
"enable_summarization": s.cfg.EnableSummarization,
"editor": s.cfg.Editor,
"enable_auto_tagging": s.cfg.EnableAutoTagging,
"auto_tag_model": s.cfg.AutoTagModel,
"max_auto_tags": s.cfg.MaxAutoTags,
"github_owner": s.cfg.GitHubOwner,
"github_repo": s.cfg.GitHubRepo,
"lilrag_url": s.cfg.LilRagURL,
"webui_theme": s.cfg.WebUITheme,
}

Expand Down Expand Up @@ -1448,6 +1453,9 @@ func (s *APIServer) handleUpdateSettings(w http.ResponseWriter, r *http.Request)
if req.EnableAutoTagging != nil {
newCfg.EnableAutoTagging = *req.EnableAutoTagging
}
if req.AutoTagModel != "" {
newCfg.AutoTagModel = req.AutoTagModel
}
Comment on lines +1456 to +1458
Copy link

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto tag model field should allow empty strings to be set (to clear the value), but this condition prevents empty strings from being processed. Consider checking if the field exists in the request rather than if it's non-empty.

Copilot uses AI. Check for mistakes.
if req.MaxAutoTags != nil {
if *req.MaxAutoTags < 1 || *req.MaxAutoTags > 20 {
s.writeError(w, http.StatusBadRequest, fmt.Errorf("max auto tags must be between 1 and 20"))
Expand All @@ -1461,6 +1469,12 @@ func (s *APIServer) handleUpdateSettings(w http.ResponseWriter, r *http.Request)
if req.GitHubRepo != "" {
newCfg.GitHubRepo = req.GitHubRepo
}
if req.LilRagURL != "" {
newCfg.LilRagURL = req.LilRagURL
}
Comment on lines +1472 to +1474
Copy link

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the auto tag model, this condition prevents clearing the LilRag URL by setting it to an empty string. The field should be updateable to empty values.

Suggested change
if req.LilRagURL != "" {
newCfg.LilRagURL = req.LilRagURL
}
newCfg.LilRagURL = req.LilRagURL

Copilot uses AI. Check for mistakes.
if req.WebUITheme != "" {
newCfg.WebUITheme = req.WebUITheme
}
Comment on lines +1475 to +1477
Copy link

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition prevents clearing the WebUI theme setting. Consider allowing empty strings to reset to default theme behavior.

Suggested change
if req.WebUITheme != "" {
newCfg.WebUITheme = req.WebUITheme
}
newCfg.WebUITheme = req.WebUITheme

Copilot uses AI. Check for mistakes.

// Save the updated configuration
if err := config.Save(&newCfg); err != nil {
Expand All @@ -1483,9 +1497,11 @@ func (s *APIServer) handleUpdateSettings(w http.ResponseWriter, r *http.Request)
"enable_summarization": s.cfg.EnableSummarization,
"editor": s.cfg.Editor,
"enable_auto_tagging": s.cfg.EnableAutoTagging,
"auto_tag_model": s.cfg.AutoTagModel,
"max_auto_tags": s.cfg.MaxAutoTags,
"github_owner": s.cfg.GitHubOwner,
"github_repo": s.cfg.GitHubRepo,
"lilrag_url": s.cfg.LilRagURL,
"webui_theme": s.cfg.WebUITheme,
},
}
Expand Down
71 changes: 37 additions & 34 deletions web/templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,6 @@ <h2 class="settings-title">⚙️ Configuration Settings</h2>
<!-- Alert messages will be shown as floating notifications -->

<form id="settings-form" class="settings-form">
<!-- Vector Search Settings -->
<section class="settings-section">
<h3 class="section-title">🔍 Vector Search & Embeddings</h3>
<div class="form-group">
<label for="enable-vector-search" class="form-label">
<input type="checkbox" id="enable-vector-search" name="enable_vector_search" {{if .Config.EnableVectorSearch}}checked{{end}}>
Enable Vector Search
</label>
<p class="form-help">Enable semantic search using vector embeddings for better note discovery</p>
</div>
<div class="form-group">
<label for="embedding-model" class="form-label">Embedding Model</label>
<input type="text" id="embedding-model" name="embedding_model" class="form-input"
value="{{.Config.EmbeddingModel}}" placeholder="e.g., nomic-embed-text">
<p class="form-help">The model to use for generating text embeddings</p>
</div>
<div class="form-group">
<label for="vector-dimensions" class="form-label">Vector Dimensions</label>
<input type="number" id="vector-dimensions" name="vector_dimensions" class="form-input"
value="{{.Config.VectorDimensions}}" min="1" max="4096" placeholder="384">
<p class="form-help">Number of dimensions for vector embeddings (must match your model)</p>
</div>
</section>

<!-- Ollama Settings -->
<section class="settings-section">
<h3 class="section-title">🦙 Ollama Integration</h3>
Expand All @@ -80,6 +56,17 @@ <h3 class="section-title">🦙 Ollama Integration</h3>
</div>
</section>

<!-- Lil-Rag Settings -->
<section class="settings-section">
<h3 class="section-title">🔍 Lil-Rag Integration</h3>
<div class="form-group">
<label for="lilrag-url" class="form-label">Lil-Rag Service URL</label>
<input type="url" id="lilrag-url" name="lilrag_url" class="form-input"
value="{{.Config.LilRagURL}}" placeholder="http://localhost:12121">
<p class="form-help">URL of your Lil-Rag service for enhanced semantic search with project isolation</p>
</div>
</section>

<!-- Summarization Settings -->
<section class="settings-section">
<h3 class="section-title">📊 Summarization & Analysis</h3>
Expand Down Expand Up @@ -108,6 +95,12 @@ <h3 class="section-title">🏷️ Auto-tagging</h3>
</label>
<p class="form-help">Automatically suggest and apply tags to notes using AI</p>
</div>
<div class="form-group">
<label for="auto-tag-model" class="form-label">Auto-tag Model</label>
<input type="text" id="auto-tag-model" name="auto_tag_model" class="form-input"
value="{{.Config.AutoTagModel}}" placeholder="Leave empty to use summarization model">
<p class="form-help">The model to use for auto-tagging (leave empty to use summarization model)</p>
</div>
<div class="form-group">
<label for="max-auto-tags" class="form-label">Maximum Auto Tags</label>
<input type="number" id="max-auto-tags" name="max_auto_tags" class="form-input"
Expand All @@ -127,6 +120,19 @@ <h3 class="section-title">✏️ Editor Configuration</h3>
</div>
</section>

<!-- Web UI Settings -->
<section class="settings-section">
<h3 class="section-title">🎨 Web UI Configuration</h3>
<div class="form-group">
<label for="webui-theme" class="form-label">Default Theme</label>
<select id="webui-theme" name="webui_theme" class="form-input">
<option value="light" {{if eq .Config.WebUITheme "light"}}selected{{end}}>Light</option>
<option value="dark" {{if eq .Config.WebUITheme "dark"}}selected{{end}}>Dark</option>
</select>
<p class="form-help">Default theme for the web interface</p>
</div>
</section>

<!-- Update Settings -->
<section class="settings-section">
<h3 class="section-title">🔄 Update Configuration</h3>
Expand Down Expand Up @@ -224,15 +230,15 @@ <h3 class="section-title">🔧 System Configuration</h3>
for (const [key, value] of formData.entries()) {
if (key.startsWith('enable_') || key === 'debug') {
settings[key] = true; // Checkboxes are only included if checked
} else if (key === 'vector_dimensions' || key === 'max_auto_tags') {
} else if (key === 'max_auto_tags') {
settings[key] = parseInt(value, 10);
} else if (value.trim() !== '') {
settings[key] = value.trim();
}
}

// Handle unchecked checkboxes explicitly
const checkboxes = ['enable_vector_search', 'enable_summarization', 'enable_auto_tagging', 'debug'];
const checkboxes = ['enable_summarization', 'enable_auto_tagging', 'debug'];
checkboxes.forEach(checkbox => {
if (!(checkbox in settings)) {
settings[checkbox] = false;
Expand All @@ -253,10 +259,6 @@ <h3 class="section-title">🔧 System Configuration</h3>
if (result.success) {
this.showNotification('✅ Settings saved successfully!', 'success');

if (result.data.reindex_needed) {
this.showNotification('⚠️ Vector configuration changed. Run "ml-notes reindex" to update embeddings.', 'warning');
}

// Update form with returned values
this.updateFormWithSettings(result.data.settings);
} else {
Expand All @@ -276,17 +278,18 @@ <h3 class="section-title">🔧 System Configuration</h3>
try {
// Reset to default values by sending minimal configuration
const defaultSettings = {
enable_vector_search: true,
enable_summarization: true,
enable_auto_tagging: true,
debug: false,
ollama_endpoint: 'http://localhost:11434',
embedding_model: 'nomic-embed-text',
vector_dimensions: 384,
lilrag_url: 'http://localhost:12121',
summarization_model: 'llama3.2:latest',
auto_tag_model: '',
max_auto_tags: 5,
editor: '',
github_owner: 'streed',
github_repo: 'ml-notes'
github_repo: 'ml-notes',
webui_theme: 'dark'
};

const response = await fetch('/api/v1/settings', {
Expand Down
Loading