openwiki-server 0.1.0__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 (53) hide show
  1. openwiki_server-0.1.0/.gitignore +17 -0
  2. openwiki_server-0.1.0/LICENSE +21 -0
  3. openwiki_server-0.1.0/PKG-INFO +269 -0
  4. openwiki_server-0.1.0/README.md +225 -0
  5. openwiki_server-0.1.0/openwiki_engine/__init__.py +3 -0
  6. openwiki_server-0.1.0/openwiki_engine/adapters/__init__.py +1 -0
  7. openwiki_server-0.1.0/openwiki_engine/adapters/openwiki.py +342 -0
  8. openwiki_server-0.1.0/openwiki_engine/application/__init__.py +1 -0
  9. openwiki_server-0.1.0/openwiki_engine/application/service.py +481 -0
  10. openwiki_server-0.1.0/openwiki_engine/config.py +80 -0
  11. openwiki_server-0.1.0/openwiki_engine/domain/__init__.py +18 -0
  12. openwiki_server-0.1.0/openwiki_engine/domain/ids.py +30 -0
  13. openwiki_server-0.1.0/openwiki_engine/domain/merge.py +43 -0
  14. openwiki_server-0.1.0/openwiki_engine/domain/models.py +117 -0
  15. openwiki_server-0.1.0/openwiki_engine/domain/wiki_config.py +68 -0
  16. openwiki_server-0.1.0/openwiki_engine/errors.py +50 -0
  17. openwiki_server-0.1.0/openwiki_engine/interfaces/__init__.py +1 -0
  18. openwiki_server-0.1.0/openwiki_engine/interfaces/celery_app.py +116 -0
  19. openwiki_server-0.1.0/openwiki_engine/interfaces/cli.py +309 -0
  20. openwiki_server-0.1.0/openwiki_engine/interfaces/grpc_server.py +253 -0
  21. openwiki_server-0.1.0/openwiki_engine/interfaces/http_app.py +203 -0
  22. openwiki_server-0.1.0/openwiki_engine/interfaces/mcp_server.py +147 -0
  23. openwiki_server-0.1.0/openwiki_engine/persistence/__init__.py +1 -0
  24. openwiki_server-0.1.0/openwiki_engine/persistence/sqlite_store.py +459 -0
  25. openwiki_server-0.1.0/openwiki_engine/protocol.py +31 -0
  26. openwiki_server-0.1.0/openwiki_engine/runtime.py +45 -0
  27. openwiki_server-0.1.0/proto/wiki/v1/wiki.proto +35 -0
  28. openwiki_server-0.1.0/pyproject.toml +75 -0
  29. openwiki_server-0.1.0/sdk/python/README.md +140 -0
  30. openwiki_server-0.1.0/sdk/python/examples/async_quickstart.py +33 -0
  31. openwiki_server-0.1.0/sdk/python/examples/quickstart.py +70 -0
  32. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/__init__.py +83 -0
  33. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/_bootstrap.py +71 -0
  34. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/_version.py +1 -0
  35. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/async_client.py +287 -0
  36. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/client.py +306 -0
  37. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/envelope.py +39 -0
  38. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/errors.py +80 -0
  39. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/headers.py +42 -0
  40. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/models/__init__.py +3 -0
  41. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/models/wiki.py +506 -0
  42. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/trace.py +20 -0
  43. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/transport.py +207 -0
  44. openwiki_server-0.1.0/sdk/python/openwiki_server_sdk/transport_async.py +147 -0
  45. openwiki_server-0.1.0/sdk/python/pyproject.toml +21 -0
  46. openwiki_server-0.1.0/sdk/python/tests/conftest.py +6 -0
  47. openwiki_server-0.1.0/sdk/python/tests/test_async.py +90 -0
  48. openwiki_server-0.1.0/sdk/python/tests/test_bootstrap.py +47 -0
  49. openwiki_server-0.1.0/sdk/python/tests/test_client.py +196 -0
  50. openwiki_server-0.1.0/sdk/python/tests/test_envelope.py +33 -0
  51. openwiki_server-0.1.0/sdk/python/tests/test_errors.py +30 -0
  52. openwiki_server-0.1.0/sdk/python/tests/test_models.py +68 -0
  53. openwiki_server-0.1.0/sdk/python/tests/test_trace.py +19 -0
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ node_modules/
5
+ data/
6
+ .pytest_cache/
7
+ *.egg-info/
8
+
9
+ # docker compose 环境变量(本地模板 docker/.env.example)
10
+ .env
11
+
12
+ # PyPI 发布
13
+ dist/
14
+ build/
15
+ .eggs/
16
+ config/pypi.env
17
+ !config/pypi.env.example
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shark8848 <admin@sharky-ai.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,269 @@
1
+ Metadata-Version: 2.5
2
+ Name: openwiki-server
3
+ Version: 0.1.0
4
+ Summary: Lightweight SDK + Server for OpenWiki — wiki engine as standalone service with HTTP/gRPC/Celery/MCP/CLI interfaces and application integration SDK.
5
+ Author-email: shark8848 <admin@sharky-ai.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: knowledge-base,llm,openwiki,rag,sdk,server,wiki
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: httpx<1.0,>=0.27
20
+ Provides-Extra: all
21
+ Requires-Dist: celery>=5.3; extra == 'all'
22
+ Requires-Dist: fastapi>=0.115; extra == 'all'
23
+ Requires-Dist: grpcio>=1.81; extra == 'all'
24
+ Requires-Dist: protobuf>=5.29; extra == 'all'
25
+ Requires-Dist: pydantic>=2.0; extra == 'all'
26
+ Requires-Dist: redis>=5.0; extra == 'all'
27
+ Requires-Dist: typer>=0.12; extra == 'all'
28
+ Requires-Dist: uvicorn[standard]>=0.30; extra == 'all'
29
+ Provides-Extra: dev
30
+ Requires-Dist: httpx<1.0,>=0.27; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Requires-Dist: ruff>=0.1; extra == 'dev'
34
+ Provides-Extra: server
35
+ Requires-Dist: celery>=5.3; extra == 'server'
36
+ Requires-Dist: fastapi>=0.115; extra == 'server'
37
+ Requires-Dist: grpcio>=1.81; extra == 'server'
38
+ Requires-Dist: protobuf>=5.29; extra == 'server'
39
+ Requires-Dist: pydantic>=2.0; extra == 'server'
40
+ Requires-Dist: redis>=5.0; extra == 'server'
41
+ Requires-Dist: typer>=0.12; extra == 'server'
42
+ Requires-Dist: uvicorn[standard]>=0.30; extra == 'server'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # OpenWiki Server
46
+
47
+ 把 LangChain **OpenWiki**(`langchain-ai/openwiki`,Markdown wiki 内核)封装为独立对外服务的 Wiki 引擎,
48
+ 供 `/home/open-ikc` 的 Wiki 库能力消费;对外提供 **HTTP / gRPC / Celery / MCP / CLI** 五类接口。
49
+
50
+ <p align="center">
51
+ <a href="https://pypi.org/project/openwiki-server/"><img src="https://img.shields.io/pypi/v/openwiki-server" alt="PyPI" /></a>
52
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT" /></a>
53
+ <img src="https://img.shields.io/badge/Python-3.10%2B-blue" alt="Python 3.10+" />
54
+ </p>
55
+
56
+ - 设计方案:`docs/解决方案.md`
57
+ - gRPC 权威契约:`proto/wiki/v1/wiki.proto`
58
+ - 配置样例:`config/engine.example.yaml`(全部可用环境变量覆盖)
59
+ - 命令行测试与调用指南:`docs/命令行测试与调用指南.md`(五类接口全部命令,已用仓库真实文档实测)
60
+ - 独立承载服务与 SDK 集成设计:`docs/独立承载服务与SDK集成设计.md`(应用侧快速集成)
61
+
62
+ ## 安装(PyPI)
63
+
64
+ ```bash
65
+ pip install openwiki-server # SDK(httpx,应用侧集成)
66
+ pip install openwiki-server[server] # + 独立承载服务(HTTP/gRPC/Celery/MCP/CLI)
67
+ pip install openwiki-server[all] # 全部依赖
68
+ ```
69
+
70
+ PyPI 包同时包含引擎(`openwiki_engine`)与应用集成 SDK(`openwiki_server_sdk`),
71
+ 与 `ikc-log-center` 的发布形态一致。SDK 快速开始见
72
+ [`sdk/python/README.md`](sdk/python/README.md)。
73
+
74
+ 发布到 PyPI:
75
+
76
+ ```bash
77
+ cp config/pypi.env.example config/pypi.env # 填入 OPENWIKI_PYPI_TOKEN
78
+ ./scripts/publish-pypi.sh # 构建 + 上传
79
+ ./scripts/publish-pypi.sh --test # 上传到 TestPyPI
80
+ ```
81
+
82
+ ## 内核说明
83
+
84
+ - OpenWiki 为 Node CLI(`npm i openwiki`,项目内 `node_modules/.bin/openwiki`),引擎以子进程方式调用,
85
+ `HOME` 指向 wiki 实例目录实现多租户隔离(`~/.openwiki` 配置与 `~/.openwiki/wiki` 产物均落在实例目录内)。
86
+ - **守卫式降级**:openwiki 未安装 / LLM 调用失败 / 无网络时,`build_from_doc` 自动切规则切页
87
+ (`granularity=heading/section/page` + `extractFields` 行抽取),全链路离线可用。
88
+ - 稳定 ID 与 open-ikc 完全兼容:`wikiId = wiki_ + sha1(kbId)[:12]`,
89
+ `pageId = wiki_ + sha1(kbId:stableKey)[:12]`,`stableKey = normalize_title(title)`。
90
+
91
+ ## 快速开始
92
+
93
+ ```bash
94
+ # 依赖(复用已有 venv;本机可用 semantica-graph-server/.venv)
95
+ pip install -e . --no-build-isolation
96
+
97
+ # 启动 HTTP 服务(默认 18011)
98
+ openwiki-server serve http
99
+
100
+ # CLI 走通全链路(离线规则模式)
101
+ export OPENWIKI_SERVER_DATA_DIR=/tmp/ow-demo OPENWIKI_SERVER_OPENWIKI=0
102
+ openwiki-server create --kb-id kb_demo --name 演示Wiki \
103
+ --config '{"granularity":"heading","extractFields":["负责人"]}'
104
+ openwiki-server build wiki_fb42912a4348 --doc-id doc1 --title 产品手册 \
105
+ --markdown '# 产品手册\n\n## 安装\n\n安装说明。负责人:张三'
106
+ openwiki-server tree wiki_fb42912a4348
107
+ openwiki-server search wiki_fb42912a4348 --q 安装
108
+ openwiki-server stat wiki_fb42912a4348
109
+ openwiki-server export wiki_fb42912a4348
110
+ ```
111
+
112
+ ## Docker 部署(单镜像,含 HAProxy)
113
+
114
+ 参考 `/home/open-ikc` 的单镜像代理拓扑:**Python 引擎 + Node openwiki 内核 + HAProxy 代理层构建到同一镜像**,
115
+ 引擎进程(uvicorn 18011 / gRPC 50052)只监听容器回环,对外唯一入口为 HAProxy
116
+ (HTTP `:8080` 反代 uvicorn、gRPC `:50052` TCP 透传、stats `:8404`)。
117
+
118
+ ```
119
+ 宿主机 client
120
+ │ http://127.0.0.1:18011 grpc://127.0.0.1:50052 http://127.0.0.1:8404(stats)
121
+
122
+ ┌────────────────────────────────────────────────┐
123
+ │ 容器 openwiki-server │
124
+ │ HAProxy(:8080 HTTP / :50052 gRPC / :8404 stats)│
125
+ │ │ 反向代理 / TCP 透传 │
126
+ │ ▼ │
127
+ │ uvicorn(127.0.0.1:18011) + gRPC(127.0.0.1:50052)│
128
+ └────────────────────────────────────────────────┘
129
+ ```
130
+
131
+ ```bash
132
+ # 构建镜像(openwiki-server:<package.json version>,含 openwiki 内核与 HAProxy)
133
+ bash scripts/build_docker.sh
134
+ # 启动(默认入口 http://127.0.0.1:18011;stats http://127.0.0.1:8404)
135
+ docker compose up -d
136
+ # 启用 Celery worker(broker/backend 用外部 redis,默认 redis://host.docker.internal:6379/0)
137
+ docker compose --profile worker up -d
138
+ # 冒烟验证(7 项断言,--force-build 可强制重建)
139
+ bash scripts/docker_smoke.sh
140
+ ```
141
+
142
+ - 镜像内 HAProxy 配置模板 `/etc/haproxy/haproxy.cfg.tmpl` 由入口脚本 envsubst 渲染
143
+ `HAPROXY_STATS_USER / HAPROXY_STATS_PASSWORD`(默认 `admin/change-me`,生产必改)。
144
+ - 数据卷 `app_data` 挂载 `/app/data`(SQLite 与 wiki 产物持久化);worker 与 app 共用同一数据卷。
145
+ - 环境变量模板:`cp docker/.env.example .env`(生产密码、端口、LLM 内核配置)。
146
+ - Celery 使用**外部 redis**(compose 不再内置 redis 服务);默认指向宿主机
147
+ `host.docker.internal:6379`,远程实例在 `.env` 用 `OPENWIKI_SERVER_CELERY_BROKER` /
148
+ `OPENWIKI_SERVER_CELERY_BACKEND` 覆盖;本机 redis 若需密码写成
149
+ `redis://:<密码>@host.docker.internal:6379/0`(未启用 worker 时 app 不主动连接)。
150
+ - `OPENWIKI_SERVER_OPENWIKI=0` 可强制离线规则切页(镜像内已含 Node 22 + openwiki 内核,
151
+ 默认启用、LLM 失败自动降级)。
152
+ - 异步加工:build/merge 等请求带 `async=1` 时登记为 job 并经 Celery 投递(broker 不可达时
153
+ 保持 `pending`,可调 `POST /api/v1/wiki/jobs/{job_id}/run` 手动执行;轮询
154
+ `GET /api/v1/wiki/jobs/{job_id}` 查看结果)。
155
+
156
+ ## 五类接口
157
+
158
+ | 协议面 | 入口 | 说明 |
159
+ | --- | --- | --- |
160
+ | HTTP | `openwiki-server serve http` | FastAPI,`/api/v1/wiki/*`,envelope 对齐 open-ikc |
161
+ | gRPC | `openwiki-server serve grpc` | `wiki.v1.WikiService`,动态 descriptor 实现 |
162
+ | Celery | `openwiki-server serve worker` | 任务 `openwiki_server.build / merge / deprecate_doc / export / update / ingest` |
163
+ | MCP | `openwiki-server serve mcp` | stdio JSON-RPC,`initialize / tools/list / tools/call` |
164
+ | CLI | `openwiki-server ...` | typer,退出码 0/1/6 约定同 open-ikc `ikc` |
165
+
166
+ ## SDK(应用侧快速集成)
167
+
168
+ openwiki-server 可作**独立承载服务**(本地进程或 Docker 单镜像栈),应用侧用
169
+ `openwiki-server-sdk`(参考 open-ikc `open-ikc-sdk` 定义)快速接入全部 wiki 能力:
170
+
171
+ ```bash
172
+ pip install sdk/python
173
+ ```
174
+
175
+ ```python
176
+ from openwiki_server_sdk import OpenWikiServerClient
177
+
178
+ with OpenWikiServerClient(base_url="http://127.0.0.1:18011") as client:
179
+ wiki = client.wikis.create(kbId="kb_demo", name="产品知识库",
180
+ wikiConfig={"granularity": "heading"})
181
+ result = client.wikis.build(
182
+ wiki.wikiId, docId="doc_1", title="产品手册",
183
+ markdown=open("docs/进展.md", encoding="utf-8").read())
184
+ print(result.mode, result.total)
185
+ hits = client.wikis.search(wiki.wikiId, q="HAProxy")
186
+ job = client.wikis.build(wiki.wikiId, docId="doc_2", title="异步", async_=True)
187
+ print(client.jobs.run(job.jobId).status)
188
+ ```
189
+
190
+ - 领域方法:`client.wikis.create/list/get/delete/tree/page/search/stat/export/
191
+ build/merge/deprecate_doc/update/ingest` 与 `client.jobs.run/get/list`;
192
+ 同步 `OpenWikiServerClient` / 异步 `AsyncOpenWikiServerClient` 共享同一套模型。
193
+ - 环境变量引导:`OPENWIKI_SERVER_BASE_URL`(默认 `http://127.0.0.1:18011`)/
194
+ `OPENWIKI_SERVER_TOKEN` / `OPENWIKI_SERVER_USER_ID` / `OPENWIKI_SERVER_TENANT_ID` /
195
+ `OPENWIKI_SERVER_ROLES`,经 `client_from_env()` 构造。
196
+ - 自测与冒烟:`cd sdk/python && PYTHONPATH=. python -m pytest tests -q`(36 例 MockTransport);
197
+ 真实联调 `python sdk/python/examples/quickstart.py`。
198
+ - 完整设计(包结构 / 异常层级 / 请求链路 / API 对照表 / 独立承载部署):见
199
+ `docs/独立承载服务与SDK集成设计.md`;SDK 使用说明见 `sdk/python/README.md`。
200
+
201
+ ## 环境变量
202
+
203
+ `OPENWIKI_SERVER_DATA_DIR` / `_DB_PATH` / `_HTTP_HOST` / `_HTTP_PORT`(18011)/
204
+ `_GRPC_HOST` / `_GRPC_PORT`(50052)/ `_CELERY_BROKER` / `_CELERY_BACKEND` /
205
+ `_OPENWIKI_BIN` / `_OPENWIKI`(0 关闭内核)/ `_PROVIDER` / `_MODEL_ID` /
206
+ `_UPDATE_TIMEOUT` / `_LOG_LEVEL`;Docker 额外使用 `HAPROXY_STATS_USER` /
207
+ `HAPROXY_STATS_PASSWORD`(HAProxy stats 登录)与 `OPENWIKI_HTTP_PORT` /
208
+ `OPENWIKI_GRPC_PORT` / `HAPROXY_STATS_PORT`(宿主端口映射)
209
+
210
+ ## 测试
211
+
212
+ ### 单元 / 冒烟(pytest)
213
+
214
+ ```bash
215
+ PYTHONPATH=. python -m pytest tests -q
216
+ ```
217
+
218
+ > 沙箱/CI 若禁止绑定 socket,gRPC 真链路测试自动 skip(进程内 handler 语义仍覆盖)。
219
+
220
+ ### 命令行测试与调用(五类接口)
221
+
222
+ 详细手册见 `docs/命令行测试与调用指南.md`:HTTP(curl) / CLI / gRPC / MCP / Celery(jobs) 全部命令,
223
+ 已用仓库真实文档(`docs/进展.md`、`docs/解决方案.md`、`README.md`)实测通过。
224
+
225
+ 一键全链路演练(探针 → CRUD → 真实文档 build → tree/page/search/stat/export →
226
+ merge/deprecate → 异步 job → CLI 等价命令,全部断言通过后打印 `ALL PASS`):
227
+
228
+ ```bash
229
+ bash scripts/wiki_api_drill.sh
230
+ ```
231
+
232
+ 常用命令速查(离线规则模式 `OPENWIKI_SERVER_OPENWIKI=0`,服务默认 `127.0.0.1:18011`):
233
+
234
+ ```bash
235
+ BASE=http://127.0.0.1:18011
236
+
237
+ # 起服务
238
+ export OPENWIKI_SERVER_DATA_DIR=/tmp/ow-live OPENWIKI_SERVER_OPENWIKI=0
239
+ openwiki-server serve http
240
+
241
+ # 创建 wiki(WID 取返回 data.wikiId)
242
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis" -H 'Content-Type: application/json' \
243
+ -d '{"kbId":"kb_live_demo","name":"演示","wikiConfig":{"granularity":"heading"}}'
244
+
245
+ # 用真实文档建页(docs/进展.md,heading 粒度切 11 页)
246
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis/$WID/build" -H 'Content-Type: application/json' \
247
+ -d "$(python -c "import json;print(json.dumps({'docId':'d1','title':'任务进展记录','tags':['运维'],'markdown':open('docs/进展.md',encoding='utf-8').read()}))")"
248
+
249
+ # 查询 / 检索 / 导出
250
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/tree?page=1&pageSize=20"
251
+ curl -sS --get "$BASE/api/v1/wiki/wikis/$WID/search" --data-urlencode "q=检索"
252
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/stat"
253
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/export?format=json"
254
+
255
+ # 异步任务:async=1 提交(JOB_ID 取返回 data.jobId)→ 手动执行 → 查询
256
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis/$WID/build" -H 'Content-Type: application/json' \
257
+ -d '{"async":"1","docId":"d_async","title":"异步示例","markdown":"# 异步示例"}'
258
+ curl -sS -X POST "$BASE/api/v1/wiki/jobs/$JOB_ID/run"
259
+ curl -sS "$BASE/api/v1/wiki/jobs/$JOB_ID"
260
+
261
+ # gRPC / MCP
262
+ python - <<'PY'
263
+ from openwiki_engine.interfaces.grpc_server import grpc_client
264
+ client = grpc_client("127.0.0.1", 50052)
265
+ print(client("Stat", {"wikiId": "wiki_<id>"}))
266
+ PY
267
+ printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize"}' \
268
+ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | openwiki-server serve mcp
269
+ ```
@@ -0,0 +1,225 @@
1
+ # OpenWiki Server
2
+
3
+ 把 LangChain **OpenWiki**(`langchain-ai/openwiki`,Markdown wiki 内核)封装为独立对外服务的 Wiki 引擎,
4
+ 供 `/home/open-ikc` 的 Wiki 库能力消费;对外提供 **HTTP / gRPC / Celery / MCP / CLI** 五类接口。
5
+
6
+ <p align="center">
7
+ <a href="https://pypi.org/project/openwiki-server/"><img src="https://img.shields.io/pypi/v/openwiki-server" alt="PyPI" /></a>
8
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="MIT" /></a>
9
+ <img src="https://img.shields.io/badge/Python-3.10%2B-blue" alt="Python 3.10+" />
10
+ </p>
11
+
12
+ - 设计方案:`docs/解决方案.md`
13
+ - gRPC 权威契约:`proto/wiki/v1/wiki.proto`
14
+ - 配置样例:`config/engine.example.yaml`(全部可用环境变量覆盖)
15
+ - 命令行测试与调用指南:`docs/命令行测试与调用指南.md`(五类接口全部命令,已用仓库真实文档实测)
16
+ - 独立承载服务与 SDK 集成设计:`docs/独立承载服务与SDK集成设计.md`(应用侧快速集成)
17
+
18
+ ## 安装(PyPI)
19
+
20
+ ```bash
21
+ pip install openwiki-server # SDK(httpx,应用侧集成)
22
+ pip install openwiki-server[server] # + 独立承载服务(HTTP/gRPC/Celery/MCP/CLI)
23
+ pip install openwiki-server[all] # 全部依赖
24
+ ```
25
+
26
+ PyPI 包同时包含引擎(`openwiki_engine`)与应用集成 SDK(`openwiki_server_sdk`),
27
+ 与 `ikc-log-center` 的发布形态一致。SDK 快速开始见
28
+ [`sdk/python/README.md`](sdk/python/README.md)。
29
+
30
+ 发布到 PyPI:
31
+
32
+ ```bash
33
+ cp config/pypi.env.example config/pypi.env # 填入 OPENWIKI_PYPI_TOKEN
34
+ ./scripts/publish-pypi.sh # 构建 + 上传
35
+ ./scripts/publish-pypi.sh --test # 上传到 TestPyPI
36
+ ```
37
+
38
+ ## 内核说明
39
+
40
+ - OpenWiki 为 Node CLI(`npm i openwiki`,项目内 `node_modules/.bin/openwiki`),引擎以子进程方式调用,
41
+ `HOME` 指向 wiki 实例目录实现多租户隔离(`~/.openwiki` 配置与 `~/.openwiki/wiki` 产物均落在实例目录内)。
42
+ - **守卫式降级**:openwiki 未安装 / LLM 调用失败 / 无网络时,`build_from_doc` 自动切规则切页
43
+ (`granularity=heading/section/page` + `extractFields` 行抽取),全链路离线可用。
44
+ - 稳定 ID 与 open-ikc 完全兼容:`wikiId = wiki_ + sha1(kbId)[:12]`,
45
+ `pageId = wiki_ + sha1(kbId:stableKey)[:12]`,`stableKey = normalize_title(title)`。
46
+
47
+ ## 快速开始
48
+
49
+ ```bash
50
+ # 依赖(复用已有 venv;本机可用 semantica-graph-server/.venv)
51
+ pip install -e . --no-build-isolation
52
+
53
+ # 启动 HTTP 服务(默认 18011)
54
+ openwiki-server serve http
55
+
56
+ # CLI 走通全链路(离线规则模式)
57
+ export OPENWIKI_SERVER_DATA_DIR=/tmp/ow-demo OPENWIKI_SERVER_OPENWIKI=0
58
+ openwiki-server create --kb-id kb_demo --name 演示Wiki \
59
+ --config '{"granularity":"heading","extractFields":["负责人"]}'
60
+ openwiki-server build wiki_fb42912a4348 --doc-id doc1 --title 产品手册 \
61
+ --markdown '# 产品手册\n\n## 安装\n\n安装说明。负责人:张三'
62
+ openwiki-server tree wiki_fb42912a4348
63
+ openwiki-server search wiki_fb42912a4348 --q 安装
64
+ openwiki-server stat wiki_fb42912a4348
65
+ openwiki-server export wiki_fb42912a4348
66
+ ```
67
+
68
+ ## Docker 部署(单镜像,含 HAProxy)
69
+
70
+ 参考 `/home/open-ikc` 的单镜像代理拓扑:**Python 引擎 + Node openwiki 内核 + HAProxy 代理层构建到同一镜像**,
71
+ 引擎进程(uvicorn 18011 / gRPC 50052)只监听容器回环,对外唯一入口为 HAProxy
72
+ (HTTP `:8080` 反代 uvicorn、gRPC `:50052` TCP 透传、stats `:8404`)。
73
+
74
+ ```
75
+ 宿主机 client
76
+ │ http://127.0.0.1:18011 grpc://127.0.0.1:50052 http://127.0.0.1:8404(stats)
77
+
78
+ ┌────────────────────────────────────────────────┐
79
+ │ 容器 openwiki-server │
80
+ │ HAProxy(:8080 HTTP / :50052 gRPC / :8404 stats)│
81
+ │ │ 反向代理 / TCP 透传 │
82
+ │ ▼ │
83
+ │ uvicorn(127.0.0.1:18011) + gRPC(127.0.0.1:50052)│
84
+ └────────────────────────────────────────────────┘
85
+ ```
86
+
87
+ ```bash
88
+ # 构建镜像(openwiki-server:<package.json version>,含 openwiki 内核与 HAProxy)
89
+ bash scripts/build_docker.sh
90
+ # 启动(默认入口 http://127.0.0.1:18011;stats http://127.0.0.1:8404)
91
+ docker compose up -d
92
+ # 启用 Celery worker(broker/backend 用外部 redis,默认 redis://host.docker.internal:6379/0)
93
+ docker compose --profile worker up -d
94
+ # 冒烟验证(7 项断言,--force-build 可强制重建)
95
+ bash scripts/docker_smoke.sh
96
+ ```
97
+
98
+ - 镜像内 HAProxy 配置模板 `/etc/haproxy/haproxy.cfg.tmpl` 由入口脚本 envsubst 渲染
99
+ `HAPROXY_STATS_USER / HAPROXY_STATS_PASSWORD`(默认 `admin/change-me`,生产必改)。
100
+ - 数据卷 `app_data` 挂载 `/app/data`(SQLite 与 wiki 产物持久化);worker 与 app 共用同一数据卷。
101
+ - 环境变量模板:`cp docker/.env.example .env`(生产密码、端口、LLM 内核配置)。
102
+ - Celery 使用**外部 redis**(compose 不再内置 redis 服务);默认指向宿主机
103
+ `host.docker.internal:6379`,远程实例在 `.env` 用 `OPENWIKI_SERVER_CELERY_BROKER` /
104
+ `OPENWIKI_SERVER_CELERY_BACKEND` 覆盖;本机 redis 若需密码写成
105
+ `redis://:<密码>@host.docker.internal:6379/0`(未启用 worker 时 app 不主动连接)。
106
+ - `OPENWIKI_SERVER_OPENWIKI=0` 可强制离线规则切页(镜像内已含 Node 22 + openwiki 内核,
107
+ 默认启用、LLM 失败自动降级)。
108
+ - 异步加工:build/merge 等请求带 `async=1` 时登记为 job 并经 Celery 投递(broker 不可达时
109
+ 保持 `pending`,可调 `POST /api/v1/wiki/jobs/{job_id}/run` 手动执行;轮询
110
+ `GET /api/v1/wiki/jobs/{job_id}` 查看结果)。
111
+
112
+ ## 五类接口
113
+
114
+ | 协议面 | 入口 | 说明 |
115
+ | --- | --- | --- |
116
+ | HTTP | `openwiki-server serve http` | FastAPI,`/api/v1/wiki/*`,envelope 对齐 open-ikc |
117
+ | gRPC | `openwiki-server serve grpc` | `wiki.v1.WikiService`,动态 descriptor 实现 |
118
+ | Celery | `openwiki-server serve worker` | 任务 `openwiki_server.build / merge / deprecate_doc / export / update / ingest` |
119
+ | MCP | `openwiki-server serve mcp` | stdio JSON-RPC,`initialize / tools/list / tools/call` |
120
+ | CLI | `openwiki-server ...` | typer,退出码 0/1/6 约定同 open-ikc `ikc` |
121
+
122
+ ## SDK(应用侧快速集成)
123
+
124
+ openwiki-server 可作**独立承载服务**(本地进程或 Docker 单镜像栈),应用侧用
125
+ `openwiki-server-sdk`(参考 open-ikc `open-ikc-sdk` 定义)快速接入全部 wiki 能力:
126
+
127
+ ```bash
128
+ pip install sdk/python
129
+ ```
130
+
131
+ ```python
132
+ from openwiki_server_sdk import OpenWikiServerClient
133
+
134
+ with OpenWikiServerClient(base_url="http://127.0.0.1:18011") as client:
135
+ wiki = client.wikis.create(kbId="kb_demo", name="产品知识库",
136
+ wikiConfig={"granularity": "heading"})
137
+ result = client.wikis.build(
138
+ wiki.wikiId, docId="doc_1", title="产品手册",
139
+ markdown=open("docs/进展.md", encoding="utf-8").read())
140
+ print(result.mode, result.total)
141
+ hits = client.wikis.search(wiki.wikiId, q="HAProxy")
142
+ job = client.wikis.build(wiki.wikiId, docId="doc_2", title="异步", async_=True)
143
+ print(client.jobs.run(job.jobId).status)
144
+ ```
145
+
146
+ - 领域方法:`client.wikis.create/list/get/delete/tree/page/search/stat/export/
147
+ build/merge/deprecate_doc/update/ingest` 与 `client.jobs.run/get/list`;
148
+ 同步 `OpenWikiServerClient` / 异步 `AsyncOpenWikiServerClient` 共享同一套模型。
149
+ - 环境变量引导:`OPENWIKI_SERVER_BASE_URL`(默认 `http://127.0.0.1:18011`)/
150
+ `OPENWIKI_SERVER_TOKEN` / `OPENWIKI_SERVER_USER_ID` / `OPENWIKI_SERVER_TENANT_ID` /
151
+ `OPENWIKI_SERVER_ROLES`,经 `client_from_env()` 构造。
152
+ - 自测与冒烟:`cd sdk/python && PYTHONPATH=. python -m pytest tests -q`(36 例 MockTransport);
153
+ 真实联调 `python sdk/python/examples/quickstart.py`。
154
+ - 完整设计(包结构 / 异常层级 / 请求链路 / API 对照表 / 独立承载部署):见
155
+ `docs/独立承载服务与SDK集成设计.md`;SDK 使用说明见 `sdk/python/README.md`。
156
+
157
+ ## 环境变量
158
+
159
+ `OPENWIKI_SERVER_DATA_DIR` / `_DB_PATH` / `_HTTP_HOST` / `_HTTP_PORT`(18011)/
160
+ `_GRPC_HOST` / `_GRPC_PORT`(50052)/ `_CELERY_BROKER` / `_CELERY_BACKEND` /
161
+ `_OPENWIKI_BIN` / `_OPENWIKI`(0 关闭内核)/ `_PROVIDER` / `_MODEL_ID` /
162
+ `_UPDATE_TIMEOUT` / `_LOG_LEVEL`;Docker 额外使用 `HAPROXY_STATS_USER` /
163
+ `HAPROXY_STATS_PASSWORD`(HAProxy stats 登录)与 `OPENWIKI_HTTP_PORT` /
164
+ `OPENWIKI_GRPC_PORT` / `HAPROXY_STATS_PORT`(宿主端口映射)
165
+
166
+ ## 测试
167
+
168
+ ### 单元 / 冒烟(pytest)
169
+
170
+ ```bash
171
+ PYTHONPATH=. python -m pytest tests -q
172
+ ```
173
+
174
+ > 沙箱/CI 若禁止绑定 socket,gRPC 真链路测试自动 skip(进程内 handler 语义仍覆盖)。
175
+
176
+ ### 命令行测试与调用(五类接口)
177
+
178
+ 详细手册见 `docs/命令行测试与调用指南.md`:HTTP(curl) / CLI / gRPC / MCP / Celery(jobs) 全部命令,
179
+ 已用仓库真实文档(`docs/进展.md`、`docs/解决方案.md`、`README.md`)实测通过。
180
+
181
+ 一键全链路演练(探针 → CRUD → 真实文档 build → tree/page/search/stat/export →
182
+ merge/deprecate → 异步 job → CLI 等价命令,全部断言通过后打印 `ALL PASS`):
183
+
184
+ ```bash
185
+ bash scripts/wiki_api_drill.sh
186
+ ```
187
+
188
+ 常用命令速查(离线规则模式 `OPENWIKI_SERVER_OPENWIKI=0`,服务默认 `127.0.0.1:18011`):
189
+
190
+ ```bash
191
+ BASE=http://127.0.0.1:18011
192
+
193
+ # 起服务
194
+ export OPENWIKI_SERVER_DATA_DIR=/tmp/ow-live OPENWIKI_SERVER_OPENWIKI=0
195
+ openwiki-server serve http
196
+
197
+ # 创建 wiki(WID 取返回 data.wikiId)
198
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis" -H 'Content-Type: application/json' \
199
+ -d '{"kbId":"kb_live_demo","name":"演示","wikiConfig":{"granularity":"heading"}}'
200
+
201
+ # 用真实文档建页(docs/进展.md,heading 粒度切 11 页)
202
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis/$WID/build" -H 'Content-Type: application/json' \
203
+ -d "$(python -c "import json;print(json.dumps({'docId':'d1','title':'任务进展记录','tags':['运维'],'markdown':open('docs/进展.md',encoding='utf-8').read()}))")"
204
+
205
+ # 查询 / 检索 / 导出
206
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/tree?page=1&pageSize=20"
207
+ curl -sS --get "$BASE/api/v1/wiki/wikis/$WID/search" --data-urlencode "q=检索"
208
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/stat"
209
+ curl -sS "$BASE/api/v1/wiki/wikis/$WID/export?format=json"
210
+
211
+ # 异步任务:async=1 提交(JOB_ID 取返回 data.jobId)→ 手动执行 → 查询
212
+ curl -sS -X POST "$BASE/api/v1/wiki/wikis/$WID/build" -H 'Content-Type: application/json' \
213
+ -d '{"async":"1","docId":"d_async","title":"异步示例","markdown":"# 异步示例"}'
214
+ curl -sS -X POST "$BASE/api/v1/wiki/jobs/$JOB_ID/run"
215
+ curl -sS "$BASE/api/v1/wiki/jobs/$JOB_ID"
216
+
217
+ # gRPC / MCP
218
+ python - <<'PY'
219
+ from openwiki_engine.interfaces.grpc_server import grpc_client
220
+ client = grpc_client("127.0.0.1", 50052)
221
+ print(client("Stat", {"wikiId": "wiki_<id>"}))
222
+ PY
223
+ printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize"}' \
224
+ '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | openwiki-server serve mcp
225
+ ```
@@ -0,0 +1,3 @@
1
+ """OpenWiki-backed wiki engine: HTTP/gRPC/Celery/MCP/CLI 五面接口。"""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """适配层:OpenWiki CLI 子进程适配 + OKF 解析 + 规则切页(守卫式导入)。"""