openwiki-server 0.3.2__tar.gz → 0.3.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/PKG-INFO +1 -1
  2. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/__init__.py +1 -1
  3. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/adapters/openwiki.py +17 -0
  4. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/config.py +7 -2
  5. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/http_app.py +19 -4
  6. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/persistence/sqlite_store.py +1 -1
  7. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/pyproject.toml +1 -1
  8. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/.gitignore +0 -0
  9. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/LICENSE +0 -0
  10. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/README.md +0 -0
  11. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/adapters/__init__.py +0 -0
  12. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/application/__init__.py +0 -0
  13. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/application/service.py +0 -0
  14. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/domain/__init__.py +0 -0
  15. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/domain/ids.py +0 -0
  16. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/domain/merge.py +0 -0
  17. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/domain/models.py +0 -0
  18. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/domain/wiki_config.py +0 -0
  19. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/errors.py +0 -0
  20. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/__init__.py +0 -0
  21. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/celery_app.py +0 -0
  22. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/cli.py +0 -0
  23. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/grpc_server.py +0 -0
  24. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/interfaces/mcp_server.py +0 -0
  25. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/logging_setup.py +0 -0
  26. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/persistence/__init__.py +0 -0
  27. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/protocol.py +0 -0
  28. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/openwiki_engine/runtime.py +0 -0
  29. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/proto/wiki/v1/wiki.proto +0 -0
  30. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/sdk/python/README.md +0 -0
  31. {openwiki_server-0.3.2 → openwiki_server-0.3.4}/sdk/python/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: openwiki-server
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Lightweight SDK + Server for OpenWiki — wiki engine as standalone service with HTTP/gRPC/Celery/MCP/CLI interfaces and application integration SDK.
5
5
  Author-email: shark8848 <admin@sharky-ai.com>
6
6
  License: MIT
@@ -1,3 +1,3 @@
1
1
  """OpenWiki-backed wiki engine: HTTP/gRPC/Celery/MCP/CLI 五面接口。"""
2
2
 
3
- __version__ = "0.3.2"
3
+ __version__ = "0.3.4"
@@ -16,6 +16,7 @@ import os
16
16
  import re
17
17
  import shutil
18
18
  import subprocess
19
+ from datetime import date, datetime
19
20
  from pathlib import Path
20
21
  from typing import Any
21
22
 
@@ -30,6 +31,19 @@ MD_LINK_RE = re.compile(r"\[([^\]]+)\]\(([^)]+\.md)\)")
30
31
  FIELD_RE = re.compile(r"^\s*([\u4e00-\u9fa5\w]+)[::]\s*(.+?)\s*$")
31
32
 
32
33
 
34
+ def _json_safe(value: Any) -> Any:
35
+ """YAML front matter 的日期/时间归一化为 ISO 字符串,避免响应序列化失败。"""
36
+ if isinstance(value, datetime):
37
+ return value.isoformat()
38
+ if isinstance(value, date):
39
+ return value.isoformat()
40
+ if isinstance(value, list):
41
+ return [_json_safe(item) for item in value]
42
+ if isinstance(value, dict):
43
+ return {key: _json_safe(item) for key, item in value.items()}
44
+ return value
45
+
46
+
33
47
  def openwiki_bin(settings: Settings | None = None) -> str:
34
48
  settings = settings or Settings()
35
49
  return settings.openwiki_bin_resolved()
@@ -55,6 +69,7 @@ def run_update(
55
69
  settings: Settings | None = None,
56
70
  ) -> dict[str, Any]:
57
71
  """运行 `openwiki personal --update <message>`(非交互,stdin 关闭自动退出)。"""
72
+ wiki_root = os.path.abspath(wiki_root)
58
73
  binary = openwiki_bin(settings)
59
74
  cmd = [binary, "personal", "--update"]
60
75
  if message:
@@ -106,6 +121,7 @@ def run_ingest(
106
121
  timeout: int = 600,
107
122
  ) -> dict[str, Any]:
108
123
  """运行 `openwiki ingest <connector>`。"""
124
+ wiki_root = os.path.abspath(wiki_root)
109
125
  binary = openwiki_bin(settings)
110
126
  cmd = [binary, "ingest", connector]
111
127
  env = dict(os.environ)
@@ -217,6 +233,7 @@ def parse_okf_pages(wiki_dir: str, *, kb_id: str = "") -> list[dict[str, Any]]:
217
233
  for key, value in front.items()
218
234
  if str(key) not in ("title", "type", "generated", "tags", "sources", "status", "stale_after", "stableKey")
219
235
  }
236
+ fields = {key: _json_safe(value) for key, value in fields.items()}
220
237
  status = str(front.get("status") or "active").strip().lower()
221
238
  if status not in ("active", "deprecated"):
222
239
  status = "active"
@@ -98,13 +98,18 @@ class Settings:
98
98
  def resolved_db_path(self) -> str:
99
99
  if self.db_path:
100
100
  return self.db_path
101
- data_dir = Path(self.data_dir)
101
+ data_dir = Path(self.resolved_data_dir)
102
102
  data_dir.mkdir(parents=True, exist_ok=True)
103
103
  return str(data_dir / "engine.db")
104
104
 
105
+ @property
106
+ def resolved_data_dir(self) -> str:
107
+ """数据目录绝对路径(openwiki 子进程 HOME/cwd 必须为绝对路径)。"""
108
+ return str(Path(self.data_dir).expanduser().resolve())
109
+
105
110
  def wiki_root(self, wiki_id: str) -> str:
106
111
  """wiki 实例根目录:{data_dir}/wikis/{wiki_id}/(含 .openwiki/wiki 与 sources/)。"""
107
- root = Path(self.data_dir) / "wikis" / wiki_id
112
+ root = Path(self.resolved_data_dir) / "wikis" / wiki_id
108
113
  root.mkdir(parents=True, exist_ok=True)
109
114
  (root / ".openwiki" / "wiki").mkdir(parents=True, exist_ok=True)
110
115
  (root / "sources").mkdir(parents=True, exist_ok=True)
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
6
+ from datetime import date, datetime
5
7
  from typing import Any
6
8
 
7
9
  from fastapi import FastAPI, Query, Request
@@ -14,13 +16,26 @@ from ..protocol import TRACE_ID_HEADER, error, new_trace_id, ok
14
16
  from ..runtime import get_service
15
17
 
16
18
 
19
+ def _json_default(value: Any) -> str:
20
+ if isinstance(value, (datetime, date)):
21
+ return value.isoformat()
22
+ return str(value)
23
+
24
+
25
+ class _JsonResponse(JSONResponse):
26
+ """响应序列化兜底:datetime/date 等非标准类型转字符串,避免业务数据 500。"""
27
+
28
+ def render(self, content: Any) -> bytes:
29
+ return json.dumps(content, ensure_ascii=False, default=_json_default).encode("utf-8")
30
+
31
+
17
32
  def _trace(request: Request) -> str:
18
33
  return request.headers.get(TRACE_ID_HEADER) or new_trace_id()
19
34
 
20
35
 
21
36
  def _handle(trace_id: str, fn) -> JSONResponse:
22
37
  try:
23
- return JSONResponse(ok(trace_id, fn()))
38
+ return _JsonResponse(ok(trace_id, fn()))
24
39
  except OpenWikiError as exc:
25
40
  status = (
26
41
  400
@@ -31,16 +46,16 @@ def _handle(trace_id: str, fn) -> JSONResponse:
31
46
  if exc.code == "200409"
32
47
  else 500
33
48
  )
34
- return JSONResponse(error(trace_id, exc), status_code=status)
49
+ return _JsonResponse(error(trace_id, exc), status_code=status)
35
50
  except Exception as exc: # pragma: no cover
36
- return JSONResponse(error(trace_id, exc), status_code=500)
51
+ return _JsonResponse(error(trace_id, exc), status_code=500)
37
52
 
38
53
 
39
54
  def create_app(service: Any | None = None) -> FastAPI:
40
55
  settings = Settings()
41
56
  configure_logging(level=settings.log_level, log_center=settings.log_center)
42
57
  svc = service or get_service()
43
- app = FastAPI(title="OpenWiki Server", version="0.3.2")
58
+ app = FastAPI(title="OpenWiki Server", version="0.3.4")
44
59
 
45
60
  @app.get("/health")
46
61
  def health() -> dict[str, Any]:
@@ -88,7 +88,7 @@ class SqliteWikiStore:
88
88
  # ---------- wiki 文件根目录 ----------
89
89
 
90
90
  def wiki_root(self, wiki_id: str) -> str:
91
- root = Path(self.data_dir) / "wikis" / wiki_id
91
+ root = Path(self.data_dir).expanduser().resolve() / "wikis" / wiki_id
92
92
  root.mkdir(parents=True, exist_ok=True)
93
93
  (root / ".openwiki" / "wiki").mkdir(parents=True, exist_ok=True)
94
94
  (root / "sources").mkdir(parents=True, exist_ok=True)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openwiki-server"
7
- version = "0.3.2"
7
+ version = "0.3.4"
8
8
  description = "Lightweight SDK + Server for OpenWiki — wiki engine as standalone service with HTTP/gRPC/Celery/MCP/CLI interfaces and application integration SDK."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes