feat: return project-relative workspace mapping in query responses

This commit is contained in:
lingyuzeng
2026-03-07 23:41:27 +08:00
parent 41329cc532
commit 1b3e04176c
4 changed files with 25 additions and 3 deletions

View File

@@ -95,6 +95,16 @@ flowchart LR
- QMD cache: `/var/lib/qmd/cache`qmd 容器)/ `/data/qmd-cache`gateway 调 CLI - QMD cache: `/var/lib/qmd/cache`qmd 容器)/ `/data/qmd-cache`gateway 调 CLI
- QMD config: `/var/lib/qmd/config`qmd 容器)/ `/data/qmd-config`gateway 调 CLI - QMD config: `/var/lib/qmd/config`qmd 容器)/ `/data/qmd-config`gateway 调 CLI
### 查询返回路径映射(项目相对路径)
为方便你直接在项目目录定位,`/query``/sync` 返回的 `resolved_workspace` 使用项目相对路径,而不是容器绝对路径。
- `main` -> `data/workspaces/main`
- `memory/2026-03` -> `data/workspaces/memory-2026-03`
- `task/TASK-001` -> `data/workspaces/task-TASK-001`
内部容器路径仍是 `/data/workspaces/...`,网关会在响应时转换为相对路径表示。
## 5. 分支与 profile 规则 ## 5. 分支与 profile 规则
优先级:`branch > memory_profile > main` 优先级:`branch > memory_profile > main`
@@ -194,7 +204,7 @@ curl -fsS -X POST http://127.0.0.1:8787/query \
- `ok` - `ok`
- `branch` - `branch`
- `resolved_workspace` - `resolved_workspace`(项目相对路径,例如 `data/workspaces/main`
- `commit_hash` - `commit_hash`
- `synced_at` - `synced_at`
- `query_type` - `query_type`

View File

@@ -28,6 +28,8 @@ class Settings(BaseSettings):
xdg_cache_home: Path = Path("/var/lib/qmd/cache") xdg_cache_home: Path = Path("/var/lib/qmd/cache")
xdg_config_home: Path = Path("/var/lib/qmd/config") xdg_config_home: Path = Path("/var/lib/qmd/config")
container_data_root: Path = Path("/data")
project_data_relative_root: str = "data"
@model_validator(mode="after") @model_validator(mode="after")
def _normalize_paths(self) -> "Settings": def _normalize_paths(self) -> "Settings":

View File

@@ -57,7 +57,7 @@ class QueryService:
return QueryResponse( return QueryResponse(
ok=True, ok=True,
branch=sync_meta.branch, branch=sync_meta.branch,
resolved_workspace=str(sync_meta.workspace_path), resolved_workspace=sync_meta.workspace_relative_path,
commit_hash=sync_meta.commit_hash, commit_hash=sync_meta.commit_hash,
synced_at=sync_meta.synced_at, synced_at=sync_meta.synced_at,
query_type=request.query_type, query_type=request.query_type,
@@ -90,7 +90,7 @@ class QueryService:
return SyncResponse( return SyncResponse(
ok=True, ok=True,
branch=sync_meta.branch, branch=sync_meta.branch,
resolved_workspace=str(sync_meta.workspace_path), resolved_workspace=sync_meta.workspace_relative_path,
commit_hash=sync_meta.commit_hash, commit_hash=sync_meta.commit_hash,
synced_at=sync_meta.synced_at, synced_at=sync_meta.synced_at,
qmd_collection=sync_meta.qmd_collection, qmd_collection=sync_meta.qmd_collection,

View File

@@ -18,6 +18,7 @@ class SyncMetadata:
branch: str branch: str
workspace_name: str workspace_name: str
workspace_path: Path workspace_path: Path
workspace_relative_path: str
qmd_collection: str qmd_collection: str
qmd_index: str qmd_index: str
commit_hash: str commit_hash: str
@@ -118,6 +119,7 @@ class SyncService:
branch=resolved.branch, branch=resolved.branch,
workspace_name=resolved.workspace_name, workspace_name=resolved.workspace_name,
workspace_path=resolved.workspace_path, workspace_path=resolved.workspace_path,
workspace_relative_path=self._to_project_relative_path(resolved.workspace_path),
qmd_collection=resolved.qmd_collection, qmd_collection=resolved.qmd_collection,
qmd_index=resolved.qmd_index, qmd_index=resolved.qmd_index,
commit_hash=git_sync.commit_hash, commit_hash=git_sync.commit_hash,
@@ -147,6 +149,7 @@ class SyncService:
"branch": metadata.branch, "branch": metadata.branch,
"workspace": metadata.workspace_name, "workspace": metadata.workspace_name,
"workspace_path": str(metadata.workspace_path), "workspace_path": str(metadata.workspace_path),
"workspace_relative_path": metadata.workspace_relative_path,
"qmd_collection": metadata.qmd_collection, "qmd_collection": metadata.qmd_collection,
"qmd_index": metadata.qmd_index, "qmd_index": metadata.qmd_index,
"commit_hash": metadata.commit_hash, "commit_hash": metadata.commit_hash,
@@ -159,3 +162,10 @@ class SyncService:
"synced_at": metadata.synced_at.isoformat(), "synced_at": metadata.synced_at.isoformat(),
} }
path.write_text(json.dumps(payload, ensure_ascii=True, indent=2), encoding="utf-8") path.write_text(json.dumps(payload, ensure_ascii=True, indent=2), encoding="utf-8")
def _to_project_relative_path(self, path: Path) -> str:
try:
rel = path.relative_to(self.settings.container_data_root)
return str(Path(self.settings.project_data_relative_root) / rel)
except ValueError:
return str(path)