diff --git a/frontend/src/utils/tags.ts b/frontend/src/utils/tags.ts index 8c79cd3..2474319 100644 --- a/frontend/src/utils/tags.ts +++ b/frontend/src/utils/tags.ts @@ -1,5 +1,5 @@ const CODE_FENCE_RE = /```[\s\S]*?```|`[^`\n]+`/g; -const TAG_RE = /(?/g, ">"); diff --git a/src/fabledassistant/routes/notes.py b/src/fabledassistant/routes/notes.py index f06b384..0d5dd9e 100644 --- a/src/fabledassistant/routes/notes.py +++ b/src/fabledassistant/routes/notes.py @@ -120,7 +120,7 @@ async def suggest_tags_route(): async def append_tag_route(note_id: int): uid = get_current_user_id() data = await request.get_json() - tag = data.get("tag", "").strip() + tag = data.get("tag", "").strip().replace(" ", "-") if not tag: return jsonify({"error": "tag is required"}), 400 diff --git a/src/fabledassistant/services/llm.py b/src/fabledassistant/services/llm.py index 3a204e8..b3ae613 100644 --- a/src/fabledassistant/services/llm.py +++ b/src/fabledassistant/services/llm.py @@ -337,6 +337,7 @@ async def build_context( tool_lines.append("When the user says 'remind me' with a time before an event, use the reminder_minutes parameter.") tool_lines.append("Use search_todos to find a specific CalDAV todo by keyword when list_todos would return too many results.") tool_lines.append("For relative dates like 'Friday' or 'next week', resolve them to YYYY-MM-DD format.") + tool_lines.append("When writing #tags in note bodies, use hyphens for multi-word tags (e.g. #science-fiction, #space-travel). Never use spaces inside a tag.") tool_lines.append( "Use update_note to edit/expand an existing note OR to update a task's status/priority/due_date. " "Use create_note ONLY for genuinely new notes with a different title. " diff --git a/src/fabledassistant/services/tag_suggestions.py b/src/fabledassistant/services/tag_suggestions.py index 7cc6cff..6b428ac 100644 --- a/src/fabledassistant/services/tag_suggestions.py +++ b/src/fabledassistant/services/tag_suggestions.py @@ -33,8 +33,10 @@ async def suggest_tags(user_id: int, title: str, body: str) -> list[str]: "content": ( "You are a tag suggestion assistant. Given a note's title and body, " "suggest 3-5 relevant tags. Prefer reusing existing tags when they fit, " - "but you may suggest new ones too. Reply with ONLY a JSON array of tag " - 'strings (without # prefix). Example: ["meeting", "project/alpha", "followup"]\n\n' + "but you may suggest new ones too. " + "Tags must use hyphens for multi-word names (e.g. science-fiction, space-travel) — never spaces. " + "Reply with ONLY a JSON array of tag strings (without # prefix). " + 'Example: ["meeting", "project/alpha", "science-fiction"]\n\n' f"Existing tags: {existing_list}" ), }, @@ -64,10 +66,13 @@ def _parse_tag_list(response: str) -> list[str]: text = response.strip() # Try direct JSON parse + def _clean(tag: str) -> str: + return str(tag).strip().lstrip("#").replace(" ", "-") + try: parsed = json.loads(text) if isinstance(parsed, list): - return [str(t).strip().lstrip("#") for t in parsed if t] + return [_clean(t) for t in parsed if t] except json.JSONDecodeError: pass @@ -77,7 +82,7 @@ def _parse_tag_list(response: str) -> list[str]: try: parsed = json.loads(match.group()) if isinstance(parsed, list): - return [str(t).strip().lstrip("#") for t in parsed if t] + return [_clean(t) for t in parsed if t] except json.JSONDecodeError: pass diff --git a/src/fabledassistant/utils/tags.py b/src/fabledassistant/utils/tags.py index a436f75..b0373e4 100644 --- a/src/fabledassistant/utils/tags.py +++ b/src/fabledassistant/utils/tags.py @@ -1,7 +1,7 @@ import re _CODE_FENCE_RE = re.compile(r"```[\s\S]*?```|`[^`\n]+`") -_TAG_RE = re.compile(r"(? list[str]: