From 31c30b8a90d7d38f6c47d374fcb8cda748c9a996 Mon Sep 17 00:00:00 2001 From: imrewce Date: Thu, 6 Aug 2026 18:00:55 +0800 Subject: [PATCH] fix(file_io): auto appending suffix for all related steps --- reme/steps/file_io/frontmatter_read.py | 5 ++-- reme/steps/file_io/frontmatter_update.py | 34 +++++++++++++----------- reme/steps/file_io/stat.py | 8 +++++- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/reme/steps/file_io/frontmatter_read.py b/reme/steps/file_io/frontmatter_read.py index 3da9f4eb..297fd574 100644 --- a/reme/steps/file_io/frontmatter_read.py +++ b/reme/steps/file_io/frontmatter_read.py @@ -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"}) diff --git a/reme/steps/file_io/frontmatter_update.py b/reme/steps/file_io/frontmatter_update.py index 3e9cf910..ce83b15d 100644 --- a/reme/steps/file_io/frontmatter_update.py +++ b/reme/steps/file_io/frontmatter_update.py @@ -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 diff --git a/reme/steps/file_io/stat.py b/reme/steps/file_io/stat.py index cb20b7b8..18dc3f4d 100644 --- a/reme/steps/file_io/stat.py +++ b/reme/steps/file_io/stat.py @@ -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"