fix(file_io): auto appending suffix for all related steps

This commit is contained in:
imrewce 2026-08-06 18:00:55 +08:00
parent c5d92a24ab
commit 31c30b8a90
3 changed files with 28 additions and 19 deletions

View file

@ -13,7 +13,7 @@ from pathlib import Path
import frontmatter
import yaml
from ._path import resolve_path
from ._path import gate_md, resolve_path
from ..base_step import BaseStep
from ...components import R
@ -35,13 +35,14 @@ class FrontmatterReadStep(BaseStep):
self.context.response.metadata.update({"path": path, "exists": False, "error": err or "invalid path"})
self.logger.info(f"[{self.name}] path={path} error={err!r}")
return
target, is_md = gate_md(target)
if not target.is_file():
self.context.response.success = False
self.context.response.answer = f"Error: {path} not found"
self.context.response.metadata.update({"path": path, "exists": False})
self.logger.info(f"[{self.name}] path={path} exists=False")
return
if target.suffix != ".md":
if not is_md:
self.context.response.success = False
self.context.response.answer = "Error: not markdown"
self.context.response.metadata.update({"path": path, "error": "not markdown"})

View file

@ -17,7 +17,7 @@ from pathlib import Path
import frontmatter
from ._file_io import get_path_lock
from ._path import _check_path_permission, resolve_path
from ._path import _check_path_permission, gate_md, resolve_path
from ..base_step import BaseStep
from ...components import R
@ -43,22 +43,24 @@ class FrontmatterUpdateStep(BaseStep):
target, err = resolve_path(workspace_dir, path)
if err or target is None:
payload: dict = {"path": path, "error": err or "invalid path"}
elif not _check_path_permission(workspace_dir, target, self.context.get("_allowed_paths")):
payload = {"path": path, "error": "no permission to update this file"}
else:
lock = await get_path_lock(target)
async with lock:
if not target.is_file():
payload = {"path": path, "error": "not found"}
elif target.suffix != ".md":
payload = {"path": path, "error": "not markdown"}
elif not metadata:
payload = {"path": path, "error": "no fields to update"}
else:
post = frontmatter.loads(target.read_text(encoding="utf-8"))
post.metadata.update(metadata)
target.write_text(frontmatter.dumps(post), encoding="utf-8")
payload = {"path": path, "updated": metadata}
target, is_md = gate_md(target)
if not _check_path_permission(workspace_dir, target, self.context.get("_allowed_paths")):
payload = {"path": path, "error": "no permission to update this file"}
else:
lock = await get_path_lock(target)
async with lock:
if not target.is_file():
payload = {"path": path, "error": "not found"}
elif not is_md:
payload = {"path": path, "error": "not markdown"}
elif not metadata:
payload = {"path": path, "error": "no fields to update"}
else:
post = frontmatter.loads(target.read_text(encoding="utf-8"))
post.metadata.update(metadata)
target.write_text(frontmatter.dumps(post), encoding="utf-8")
payload = {"path": path, "updated": metadata}
if "error" in payload:
self.context.response.success = False

View file

@ -24,7 +24,7 @@ from pathlib import Path
import frontmatter
from ._path import resolve_path
from ._path import gate_md, resolve_path
from ..base_step import BaseStep
from ...components import R
@ -46,6 +46,12 @@ class StatStep(BaseStep):
self.context.response.metadata.update({"path": path, "exists": False, "error": err or "invalid path"})
self.logger.info(f"[{self.name}] path={path} error={err!r}")
return
# Auto-append .md for suffix-less paths (consistent with edit).
# If the .md path doesn't exist but the original does (e.g., a directory), use original.
original_target = target
target, _is_md = gate_md(target)
if not target.exists() and original_target != target and original_target.exists():
target = original_target
if not target.exists():
self.context.response.success = False
self.context.response.answer = f"stat: {path} not found"