Fix daily note path to match vault structure
Update from journal/YYYY/YYYY-MM-DD.md to 50 - Journal/YYYY/MM/YYYY-MM-DD.md to match the actual Obsidian vault folder layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,7 @@ You have access to Ryan's Obsidian vault through the Obsidian integration. When
|
|||||||
Always use these tools when users ask about notes, research, ideas, tasks, or when you want to save information for future reference.
|
Always use these tools when users ask about notes, research, ideas, tasks, or when you want to save information for future reference.
|
||||||
|
|
||||||
DAILY JOURNAL (Task Tracking):
|
DAILY JOURNAL (Task Tracking):
|
||||||
You have access to Ryan's daily journal notes. Each note lives at journal/YYYY/YYYY-MM-DD.md and has two sections: tasks and log.
|
You have access to Ryan's daily journal notes. Each note lives at 50 - Journal/YYYY/MM/YYYY-MM-DD.md and has two sections: tasks and log.
|
||||||
- Use journal_get_today to read today's full daily note (tasks + log)
|
- Use journal_get_today to read today's full daily note (tasks + log)
|
||||||
- Use journal_get_tasks to list tasks (done/pending) for today or a specific date
|
- Use journal_get_tasks to list tasks (done/pending) for today or a specific date
|
||||||
- Use journal_add_task to add a new task to today's (or a given date's) note
|
- Use journal_add_task to add a new task to today's (or a given date's) note
|
||||||
|
|||||||
@@ -93,13 +93,15 @@ class TestGetDailyNotePath:
|
|||||||
def test_formats_path_correctly(self, service):
|
def test_formats_path_correctly(self, service):
|
||||||
date = datetime(2026, 3, 15)
|
date = datetime(2026, 3, 15)
|
||||||
path = service.get_daily_note_path(date)
|
path = service.get_daily_note_path(date)
|
||||||
assert path == "journal/2026/2026-03-15.md"
|
assert path == "50 - Journal/2026/03/2026-03-15.md"
|
||||||
|
|
||||||
def test_defaults_to_today(self, service):
|
def test_defaults_to_today(self, service):
|
||||||
path = service.get_daily_note_path()
|
path = service.get_daily_note_path()
|
||||||
today = datetime.now()
|
today = datetime.now()
|
||||||
assert today.strftime("%Y-%m-%d") in path
|
assert today.strftime("%Y-%m-%d") in path
|
||||||
assert path.startswith(f"journal/{today.strftime('%Y')}/")
|
assert path.startswith(
|
||||||
|
f"50 - Journal/{today.strftime('%Y')}/{today.strftime('%m')}/"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestWalkVault:
|
class TestWalkVault:
|
||||||
|
|||||||
+49
-13
@@ -61,7 +61,9 @@ class ObsidianService:
|
|||||||
|
|
||||||
return md_files
|
return md_files
|
||||||
|
|
||||||
def parse_markdown(self, content: str, filepath: Optional[Path] = None) -> dict[str, Any]:
|
def parse_markdown(
|
||||||
|
self, content: str, filepath: Optional[Path] = None
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Parse Obsidian markdown to extract metadata and clean content.
|
"""Parse Obsidian markdown to extract metadata and clean content.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -85,7 +87,7 @@ class ObsidianService:
|
|||||||
|
|
||||||
if match:
|
if match:
|
||||||
frontmatter = match.group(1)
|
frontmatter = match.group(1)
|
||||||
body_content = content[match.end():].strip()
|
body_content = content[match.end() :].strip()
|
||||||
try:
|
try:
|
||||||
metadata = yaml.safe_load(frontmatter) or {}
|
metadata = yaml.safe_load(frontmatter) or {}
|
||||||
except yaml.YAMLError:
|
except yaml.YAMLError:
|
||||||
@@ -187,7 +189,9 @@ class ObsidianService:
|
|||||||
default_frontmatter.setdefault("tags", []).extend(tags)
|
default_frontmatter.setdefault("tags", []).extend(tags)
|
||||||
|
|
||||||
# Write note
|
# Write note
|
||||||
frontmatter_yaml = yaml.dump(default_frontmatter, allow_unicode=True, default_flow_style=False)
|
frontmatter_yaml = yaml.dump(
|
||||||
|
default_frontmatter, allow_unicode=True, default_flow_style=False
|
||||||
|
)
|
||||||
full_content = f"---\n{frontmatter_yaml}---\n\n{content}"
|
full_content = f"---\n{frontmatter_yaml}---\n\n{content}"
|
||||||
|
|
||||||
with open(note_path, "w", encoding="utf-8") as f:
|
with open(note_path, "w", encoding="utf-8") as f:
|
||||||
@@ -247,7 +251,7 @@ class ObsidianService:
|
|||||||
"""
|
"""
|
||||||
if date is None:
|
if date is None:
|
||||||
date = datetime.now()
|
date = datetime.now()
|
||||||
return f"journal/{date.strftime('%Y')}/{date.strftime('%Y-%m-%d')}.md"
|
return f"50 - Journal/{date.strftime('%Y')}/{date.strftime('%m')}/{date.strftime('%Y-%m-%d')}.md"
|
||||||
|
|
||||||
def get_daily_note(self, date: Optional[datetime] = None) -> dict[str, Any]:
|
def get_daily_note(self, date: Optional[datetime] = None) -> dict[str, Any]:
|
||||||
"""Read a daily note from the vault.
|
"""Read a daily note from the vault.
|
||||||
@@ -264,12 +268,22 @@ class ObsidianService:
|
|||||||
note_path = Path(self.vault_path) / relative_path
|
note_path = Path(self.vault_path) / relative_path
|
||||||
|
|
||||||
if not note_path.exists():
|
if not note_path.exists():
|
||||||
return {"found": False, "path": relative_path, "content": None, "date": date.strftime("%Y-%m-%d")}
|
return {
|
||||||
|
"found": False,
|
||||||
|
"path": relative_path,
|
||||||
|
"content": None,
|
||||||
|
"date": date.strftime("%Y-%m-%d"),
|
||||||
|
}
|
||||||
|
|
||||||
with open(note_path, "r", encoding="utf-8") as f:
|
with open(note_path, "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
|
||||||
return {"found": True, "path": relative_path, "content": content, "date": date.strftime("%Y-%m-%d")}
|
return {
|
||||||
|
"found": True,
|
||||||
|
"path": relative_path,
|
||||||
|
"content": content,
|
||||||
|
"date": date.strftime("%Y-%m-%d"),
|
||||||
|
}
|
||||||
|
|
||||||
def get_daily_tasks(self, date: Optional[datetime] = None) -> dict[str, Any]:
|
def get_daily_tasks(self, date: Optional[datetime] = None) -> dict[str, Any]:
|
||||||
"""Extract tasks from a daily note's tasks section.
|
"""Extract tasks from a daily note's tasks section.
|
||||||
@@ -284,7 +298,12 @@ class ObsidianService:
|
|||||||
date = datetime.now()
|
date = datetime.now()
|
||||||
note = self.get_daily_note(date)
|
note = self.get_daily_note(date)
|
||||||
if not note["found"]:
|
if not note["found"]:
|
||||||
return {"found": False, "tasks": [], "date": note["date"], "path": note["path"]}
|
return {
|
||||||
|
"found": False,
|
||||||
|
"tasks": [],
|
||||||
|
"date": note["date"],
|
||||||
|
"path": note["path"],
|
||||||
|
}
|
||||||
|
|
||||||
tasks = []
|
tasks = []
|
||||||
in_tasks = False
|
in_tasks = False
|
||||||
@@ -302,9 +321,16 @@ class ObsidianService:
|
|||||||
elif todo_match:
|
elif todo_match:
|
||||||
tasks.append({"text": todo_match.group(1), "done": False})
|
tasks.append({"text": todo_match.group(1), "done": False})
|
||||||
|
|
||||||
return {"found": True, "tasks": tasks, "date": note["date"], "path": note["path"]}
|
return {
|
||||||
|
"found": True,
|
||||||
|
"tasks": tasks,
|
||||||
|
"date": note["date"],
|
||||||
|
"path": note["path"],
|
||||||
|
}
|
||||||
|
|
||||||
def add_task_to_daily_note(self, task_text: str, date: Optional[datetime] = None) -> dict[str, Any]:
|
def add_task_to_daily_note(
|
||||||
|
self, task_text: str, date: Optional[datetime] = None
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Add a task checkbox to a daily note, creating the note if needed.
|
"""Add a task checkbox to a daily note, creating the note if needed.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -336,7 +362,9 @@ class ObsidianService:
|
|||||||
log_match = re.search(r"\n(### log)", content, re.IGNORECASE)
|
log_match = re.search(r"\n(### log)", content, re.IGNORECASE)
|
||||||
if log_match:
|
if log_match:
|
||||||
insert_pos = log_match.start()
|
insert_pos = log_match.start()
|
||||||
content = content[:insert_pos] + f"\n- [ ] {task_text}" + content[insert_pos:]
|
content = (
|
||||||
|
content[:insert_pos] + f"\n- [ ] {task_text}" + content[insert_pos:]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
content = content.rstrip() + f"\n- [ ] {task_text}\n"
|
content = content.rstrip() + f"\n- [ ] {task_text}\n"
|
||||||
|
|
||||||
@@ -345,7 +373,9 @@ class ObsidianService:
|
|||||||
|
|
||||||
return {"success": True, "created_note": False, "path": relative_path}
|
return {"success": True, "created_note": False, "path": relative_path}
|
||||||
|
|
||||||
def complete_task_in_daily_note(self, task_text: str, date: Optional[datetime] = None) -> dict[str, Any]:
|
def complete_task_in_daily_note(
|
||||||
|
self, task_text: str, date: Optional[datetime] = None
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Mark a task as complete in a daily note by matching task text.
|
"""Mark a task as complete in a daily note by matching task text.
|
||||||
|
|
||||||
Searches for a task matching the given text (exact or partial) and
|
Searches for a task matching the given text (exact or partial) and
|
||||||
@@ -374,9 +404,15 @@ class ObsidianService:
|
|||||||
if exact in content:
|
if exact in content:
|
||||||
content = content.replace(exact, f"- [x] {task_text}", 1)
|
content = content.replace(exact, f"- [x] {task_text}", 1)
|
||||||
else:
|
else:
|
||||||
match = re.search(r"- \[ \] .*" + re.escape(task_text) + r".*", content, re.IGNORECASE)
|
match = re.search(
|
||||||
|
r"- \[ \] .*" + re.escape(task_text) + r".*", content, re.IGNORECASE
|
||||||
|
)
|
||||||
if not match:
|
if not match:
|
||||||
return {"success": False, "error": f"Task '{task_text}' not found", "path": relative_path}
|
return {
|
||||||
|
"success": False,
|
||||||
|
"error": f"Task '{task_text}' not found",
|
||||||
|
"path": relative_path,
|
||||||
|
}
|
||||||
completed = match.group(0).replace("- [ ]", "- [x]", 1)
|
completed = match.group(0).replace("- [ ]", "- [x]", 1)
|
||||||
content = content.replace(match.group(0), completed, 1)
|
content = content.replace(match.group(0), completed, 1)
|
||||||
task_text = match.group(0).replace("- [ ] ", "")
|
task_text = match.group(0).replace("- [ ] ", "")
|
||||||
|
|||||||
Reference in New Issue
Block a user