Add CalDAV calendar integration, LLM-suggested tags, and settings refinements

- CalDAV integration: per-user calendar config, create/list/search events
  via caldav library, LLM tools for calendar operations from chat
- LLM-suggested tags: new tag_suggestions service prompts LLM with existing
  tags and note content to suggest 3-5 relevant tags; exposed via API
  endpoints (suggest-tags, append-tag); integrated into editor views
  (suggest button + clickable pills) and chat tool calls (pills in
  ToolCallCard with one-click apply)
- Settings/model UI refinements, generation task improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 22:40:20 -05:00
parent 8996b45e50
commit d7bc3f3222
22 changed files with 1158 additions and 837 deletions
+1 -34
View File
@@ -1,13 +1,12 @@
import { ref, computed } from "vue";
import { defineStore } from "pinia";
import { apiGet, apiPut, apiPost, apiStreamPost } from "@/api/client";
import { apiGet, apiPut } from "@/api/client";
import { useToastStore } from "@/stores/toast";
import type { AppSettings } from "@/types/settings";
export const useSettingsStore = defineStore("settings", () => {
const settings = ref<AppSettings>({});
const loading = ref(false);
const installedModels = ref<string[]>([]);
const assistantName = computed(
() => settings.value.assistant_name || "Fable"
@@ -40,44 +39,12 @@ export const useSettingsStore = defineStore("settings", () => {
}
}
async function fetchInstalledModels() {
try {
const data = await apiGet<{ models: { name: string }[] }>("/api/chat/models");
installedModels.value = data.models.map((m) => m.name);
} catch {
installedModels.value = [];
}
}
async function pullModel(
model: string,
onProgress?: (data: Record<string, unknown>) => void,
) {
await apiStreamPost("/api/chat/models/pull", { model }, (data) => {
if (onProgress) onProgress(data);
});
}
async function deleteModel(model: string) {
try {
await apiPost("/api/chat/models/delete", { model });
await fetchInstalledModels();
} catch (e) {
useToastStore().show("Failed to delete model", "error");
throw e;
}
}
return {
settings,
loading,
installedModels,
assistantName,
defaultModel,
fetchSettings,
updateSettings,
fetchInstalledModels,
pullModel,
deleteModel,
};
});