jishushell 0.4.30 → 0.5.22
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.
- package/Dockerfile.hermes-slim +2 -5
- package/apps/anythingllm-container.yaml +287 -0
- package/apps/browserless-chromium-container.yaml +18 -6
- package/apps/filebrowser-container.yaml +164 -0
- package/apps/ollama-binary.yaml +44 -0
- package/apps/ollama-with-hollama-binary.yaml +45 -1
- package/apps/openclaw-binary.yaml +8 -0
- package/apps/openclaw-container.yaml +9 -1
- package/apps/openclaw-with-searxng-container.yaml +4 -0
- package/apps/searxng-container.yaml +5 -4
- package/apps/weknora-container.yaml +471 -0
- package/dist/cli/doctor.js +144 -16
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/panel.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.js +99 -1
- package/dist/config.js.map +1 -1
- package/dist/install.js +4 -4
- package/dist/install.js.map +1 -1
- package/dist/routes/auth.js +2 -2
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/backup.js +64 -11
- package/dist/routes/backup.js.map +1 -1
- package/dist/routes/external-mounts.d.ts +17 -0
- package/dist/routes/external-mounts.js +73 -0
- package/dist/routes/external-mounts.js.map +1 -0
- package/dist/routes/file-mounts.d.ts +13 -0
- package/dist/routes/file-mounts.js +90 -0
- package/dist/routes/file-mounts.js.map +1 -0
- package/dist/routes/files-organize.d.ts +28 -0
- package/dist/routes/files-organize.js +167 -0
- package/dist/routes/files-organize.js.map +1 -0
- package/dist/routes/files.d.ts +31 -0
- package/dist/routes/files.js +321 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/instances.js +87 -12
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/internal.d.ts +2 -0
- package/dist/routes/internal.js +59 -0
- package/dist/routes/internal.js.map +1 -0
- package/dist/routes/llm.js +29 -0
- package/dist/routes/llm.js.map +1 -1
- package/dist/routes/setup.js +9 -9
- package/dist/routes/setup.js.map +1 -1
- package/dist/routes/system.js +1 -1
- package/dist/routes/system.js.map +1 -1
- package/dist/routes/webdav.d.ts +17 -0
- package/dist/routes/webdav.js +114 -0
- package/dist/routes/webdav.js.map +1 -0
- package/dist/server.js +358 -6
- package/dist/server.js.map +1 -1
- package/dist/services/agent-apps/catalog.d.ts +3 -0
- package/dist/services/agent-apps/catalog.js +40 -13
- package/dist/services/agent-apps/catalog.js.map +1 -1
- package/dist/services/agent-apps/installers/shell-script.d.ts +1 -1
- package/dist/services/agent-apps/installers/shell-script.js +19 -2
- package/dist/services/agent-apps/installers/shell-script.js.map +1 -1
- package/dist/services/agent-apps/types.d.ts +3 -0
- package/dist/services/app/app-compiler.d.ts +1 -1
- package/dist/services/app/app-compiler.js +5 -5
- package/dist/services/app/app-compiler.js.map +1 -1
- package/dist/services/app/app-manager.d.ts +9 -0
- package/dist/services/app/app-manager.js +248 -43
- package/dist/services/app/app-manager.js.map +1 -1
- package/dist/services/app/custom-manager.js.map +1 -1
- package/dist/services/app/hermes-agent-manager.js +1 -0
- package/dist/services/app/hermes-agent-manager.js.map +1 -1
- package/dist/services/app/ollama-manager.js +1 -1
- package/dist/services/app/ollama-manager.js.map +1 -1
- package/dist/services/app/openclaw-manager.js +37 -5
- package/dist/services/app/openclaw-manager.js.map +1 -1
- package/dist/services/app/platform-transform.d.ts +32 -0
- package/dist/services/app/platform-transform.js +65 -0
- package/dist/services/app/platform-transform.js.map +1 -0
- package/dist/services/app-passwords.d.ts +61 -0
- package/dist/services/app-passwords.js +173 -0
- package/dist/services/app-passwords.js.map +1 -0
- package/dist/services/backup-manager.d.ts +11 -0
- package/dist/services/backup-manager.js +220 -8
- package/dist/services/backup-manager.js.map +1 -1
- package/dist/services/capability-endpoint-validator.js +26 -7
- package/dist/services/capability-endpoint-validator.js.map +1 -1
- package/dist/services/connection-apply.d.ts +2 -0
- package/dist/services/connection-apply.js +55 -1
- package/dist/services/connection-apply.js.map +1 -1
- package/dist/services/connection-resolver.js +1 -1
- package/dist/services/connection-resolver.js.map +1 -1
- package/dist/services/connection-transactor.d.ts +2 -0
- package/dist/services/connection-transactor.js +12 -2
- package/dist/services/connection-transactor.js.map +1 -1
- package/dist/services/external-mounts.d.ts +40 -0
- package/dist/services/external-mounts.js +187 -0
- package/dist/services/external-mounts.js.map +1 -0
- package/dist/services/files-manager.d.ts +252 -0
- package/dist/services/files-manager.js +1075 -0
- package/dist/services/files-manager.js.map +1 -0
- package/dist/services/files-mounts.d.ts +42 -0
- package/dist/services/files-mounts.js +207 -0
- package/dist/services/files-mounts.js.map +1 -0
- package/dist/services/instance-manager.js +90 -32
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/llm-proxy/index.d.ts +28 -0
- package/dist/services/llm-proxy/index.js +76 -3
- package/dist/services/llm-proxy/index.js.map +1 -1
- package/dist/services/llm-proxy/ssrf.js +6 -2
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/llm-proxy/validate-key.d.ts +41 -0
- package/dist/services/llm-proxy/validate-key.js +672 -0
- package/dist/services/llm-proxy/validate-key.js.map +1 -0
- package/dist/services/macos-launchd.d.ts +89 -0
- package/dist/services/macos-launchd.js +273 -0
- package/dist/services/macos-launchd.js.map +1 -0
- package/dist/services/nomad-manager.d.ts +11 -0
- package/dist/services/nomad-manager.js +343 -98
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/organize/applier.d.ts +46 -0
- package/dist/services/organize/applier.js +218 -0
- package/dist/services/organize/applier.js.map +1 -0
- package/dist/services/organize/rules.d.ts +57 -0
- package/dist/services/organize/rules.js +286 -0
- package/dist/services/organize/rules.js.map +1 -0
- package/dist/services/organize/scanner.d.ts +50 -0
- package/dist/services/organize/scanner.js +366 -0
- package/dist/services/organize/scanner.js.map +1 -0
- package/dist/services/organize/store.d.ts +14 -0
- package/dist/services/organize/store.js +82 -0
- package/dist/services/organize/store.js.map +1 -0
- package/dist/services/panel-manager.js +40 -11
- package/dist/services/panel-manager.js.map +1 -1
- package/dist/services/process-manager.js +3 -2
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/runtime/adapters/custom.js +56 -0
- package/dist/services/runtime/adapters/custom.js.map +1 -1
- package/dist/services/runtime/adapters/hermes.d.ts +4 -3
- package/dist/services/runtime/adapters/hermes.js +166 -64
- package/dist/services/runtime/adapters/hermes.js.map +1 -1
- package/dist/services/runtime/adapters/openclaw-routes.d.ts +8 -2
- package/dist/services/runtime/adapters/openclaw-routes.js +68 -0
- package/dist/services/runtime/adapters/openclaw-routes.js.map +1 -1
- package/dist/services/runtime/adapters/openclaw.d.ts +118 -0
- package/dist/services/runtime/adapters/openclaw.js +1459 -49
- package/dist/services/runtime/adapters/openclaw.js.map +1 -1
- package/dist/services/runtime/instance.d.ts +1 -1
- package/dist/services/runtime/instance.js +1 -1
- package/dist/services/runtime/instance.js.map +1 -1
- package/dist/services/runtime/mcp-shims/anythingllm-shim.d.ts +46 -0
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js +281 -0
- package/dist/services/runtime/mcp-shims/anythingllm-shim.js.map +1 -0
- package/dist/services/runtime/mcp-shims/drive-shim.d.ts +54 -0
- package/dist/services/runtime/mcp-shims/drive-shim.js +489 -0
- package/dist/services/runtime/mcp-shims/drive-shim.js.map +1 -0
- package/dist/services/runtime/types.d.ts +31 -0
- package/dist/services/setup-manager.js +190 -68
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/suggestions.js.map +1 -1
- package/dist/services/update-manager.js +32 -14
- package/dist/services/update-manager.js.map +1 -1
- package/dist/services/webdav/server.d.ts +24 -0
- package/dist/services/webdav/server.js +420 -0
- package/dist/services/webdav/server.js.map +1 -0
- package/dist/services/webdav/xml-builder.d.ts +73 -0
- package/dist/services/webdav/xml-builder.js +156 -0
- package/dist/services/webdav/xml-builder.js.map +1 -0
- package/dist/services/workspace-builder.d.ts +29 -0
- package/dist/services/workspace-builder.js +188 -0
- package/dist/services/workspace-builder.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/utils/path-locks.d.ts +30 -0
- package/dist/utils/path-locks.js +63 -0
- package/dist/utils/path-locks.js.map +1 -0
- package/dist/utils/path-safety.d.ts +41 -0
- package/dist/utils/path-safety.js +119 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/dist/utils/safe-write.d.ts +24 -0
- package/dist/utils/safe-write.js +82 -0
- package/dist/utils/safe-write.js.map +1 -0
- package/install/jishu-install.sh +247 -35
- package/install/jishu-uninstall.sh +45 -5
- package/package.json +20 -2
- package/public/assets/ApiKeyField-CvyAOcJS.js +1 -0
- package/public/assets/Dashboard-AuJESBlJ.js +1 -0
- package/public/assets/{HermesChatPanel-_GHoklgo.js → HermesChatPanel-CByPREwb.js} +1 -1
- package/public/assets/HermesConfigForm-DRda8FKX.js +4 -0
- package/public/assets/InitPassword-ka4wNpM5.js +1 -0
- package/public/assets/InstanceDetail-Cg1nS8HX.js +92 -0
- package/public/assets/Login-aPajuQzf.js +1 -0
- package/public/assets/NewInstance-Dd1ebNIx.js +1 -0
- package/public/assets/ProviderRecommendations-DFmADQ7V.js +1 -0
- package/public/assets/Settings-BYQnbLYL.js +1 -0
- package/public/assets/Setup-D05lwDOV.js +1 -0
- package/public/assets/WeixinLoginPanel-D89kdhP4.js +9 -0
- package/public/assets/index-HSXCsceK.css +1 -0
- package/public/assets/index-bnBu0nlQ.js +19 -0
- package/public/assets/registry-C_qeFTkZ.js +2 -0
- package/public/assets/usePolling-Bn93fe7M.js +1 -0
- package/public/assets/{vendor-i18n-ucpM0OR0.js → vendor-i18n-flxcMVeP.js} +2 -2
- package/public/assets/{vendor-react-Bk1hRGiY.js → vendor-react-ZC5T_huj.js} +7 -7
- package/public/index.html +4 -4
- package/scripts/check-app-spec.mjs +18 -4
- package/scripts/check-colima-launchd.mjs +230 -0
- package/scripts/check-new-file-tests.mjs +230 -0
- package/scripts/check-quarantine-expiry.mjs +105 -0
- package/scripts/perf/README.md +49 -0
- package/scripts/perf/auth.js +99 -0
- package/scripts/perf/config.js +63 -0
- package/scripts/perf/instances.js +143 -0
- package/scripts/perf/proxy.js +96 -0
- package/scripts/smoke/files-w1.sh +142 -0
- package/scripts/smoke-backend.mjs +122 -0
- package/scripts/smoke-post-publish.mjs +346 -0
- package/public/assets/Dashboard-rkWp-CXd.js +0 -1
- package/public/assets/HermesConfigForm-anDnwUp_.js +0 -4
- package/public/assets/InitPassword-ZU9_-hDr.js +0 -1
- package/public/assets/InstanceDetail-CN0FH1aw.js +0 -92
- package/public/assets/Login-BItXqYAJ.js +0 -1
- package/public/assets/NewInstance-BousE6kY.js +0 -1
- package/public/assets/ProviderRecommendations-DFYj7Fb6.js +0 -1
- package/public/assets/Settings-Bttc6QmM.js +0 -1
- package/public/assets/Setup-Bsxx1zgj.js +0 -1
- package/public/assets/WeixinLoginPanel-DPZpAKgO.js +0 -9
- package/public/assets/index-8xZy1z5k.css +0 -1
- package/public/assets/index-Dw3HhUYE.js +0 -19
- package/public/assets/input-paste-CrNVAyOy.js +0 -1
- package/public/assets/providers-DtNXh9JD.js +0 -1
- package/public/assets/registry-5s2UB6is.js +0 -2
- package/public/assets/usePolling-Do5Erqm_.js +0 -1
|
@@ -64,6 +64,14 @@ requires:
|
|
|
64
64
|
inject_as: "MCP_SERVERS"
|
|
65
65
|
required: false
|
|
66
66
|
cardinality: "many"
|
|
67
|
+
- capability: "files"
|
|
68
|
+
inject_as: "FILES_BROWSER_URL"
|
|
69
|
+
required: false
|
|
70
|
+
cardinality: "one"
|
|
71
|
+
- capability: "knowledge"
|
|
72
|
+
inject_as: "KNOWLEDGE_BASE_URL"
|
|
73
|
+
required: false
|
|
74
|
+
cardinality: "one"
|
|
67
75
|
|
|
68
76
|
lifecycle:
|
|
69
77
|
install:
|
|
@@ -69,4 +69,12 @@ requires:
|
|
|
69
69
|
- capability: "mcp"
|
|
70
70
|
inject_as: "MCP_SERVERS"
|
|
71
71
|
required: false
|
|
72
|
-
cardinality: "many"
|
|
72
|
+
cardinality: "many"
|
|
73
|
+
- capability: "files"
|
|
74
|
+
inject_as: "FILES_BROWSER_URL"
|
|
75
|
+
required: false
|
|
76
|
+
cardinality: "one"
|
|
77
|
+
- capability: "knowledge"
|
|
78
|
+
inject_as: "KNOWLEDGE_BASE_URL"
|
|
79
|
+
required: false
|
|
80
|
+
cardinality: "one"
|
|
@@ -20,7 +20,8 @@ tasks:
|
|
|
20
20
|
memory: "512Mi"
|
|
21
21
|
ports:
|
|
22
22
|
- name: http
|
|
23
|
-
port:
|
|
23
|
+
port: 18080
|
|
24
|
+
container_port: 8080
|
|
24
25
|
visibility: external
|
|
25
26
|
volumes:
|
|
26
27
|
- source: "~/.jishushell/apps/${app_id}/settings/settings.yml"
|
|
@@ -41,17 +42,17 @@ tasks:
|
|
|
41
42
|
provides:
|
|
42
43
|
- capability: "web-ui"
|
|
43
44
|
task: "searxng"
|
|
44
|
-
port:
|
|
45
|
+
port: 18080
|
|
45
46
|
protocol: "http"
|
|
46
47
|
description: "SearXNG Web UI(legacy capability,请改用 web-searxng)"
|
|
47
48
|
- capability: "web-searxng"
|
|
48
49
|
task: "searxng"
|
|
49
|
-
port:
|
|
50
|
+
port: 18080
|
|
50
51
|
protocol: "http"
|
|
51
52
|
description: "SearXNG Web UI"
|
|
52
53
|
- capability: "search-searxng"
|
|
53
54
|
task: "searxng"
|
|
54
|
-
port:
|
|
55
|
+
port: 18080
|
|
55
56
|
path: "/search"
|
|
56
57
|
protocol: "http"
|
|
57
58
|
description: "SearXNG 搜索 API,支持 JSON 格式 (/search?q=xxx&format=json)"
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
id: weknora-container
|
|
2
|
+
name: WeKnora
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
jishushell:
|
|
5
|
+
min_version: "0.5.15"
|
|
6
|
+
description: "Tencent 开源 RAG 知识库:文档解析 + 向量检索 + 对话式问答(5 容器单 Nomad TaskGroup)"
|
|
7
|
+
singleInstance: true
|
|
8
|
+
|
|
9
|
+
# 拓扑(每个 task 独立 docker netns,跨 task 经 host.docker.internal:<host-port>):
|
|
10
|
+
# 注:原始设计想用 Nomad group bridge mode 让 task 共享 netns 走 127.0.0.1,
|
|
11
|
+
# 但需要 /opt/cni/bin/ 下的 containernetworking 插件(Pi 默认没装)。退而用
|
|
12
|
+
# host 端口发布 + host.docker.internal 路由(panel `extra_hosts:host-gateway`
|
|
13
|
+
# 已 mapping 到 172.17.0.1 = docker0 bridge gateway)。
|
|
14
|
+
# 关键:5 个发布端口都设 `host_network: docker_bridge` 让 panel/Nomad 把
|
|
15
|
+
# docker-proxy 绑到 docker0 IP(172.17.0.1),peer 容器走 host.docker.internal
|
|
16
|
+
# 即 172.17.0.1 时打得通。要求 nomad.hcl 声明 `host_network "docker_bridge"
|
|
17
|
+
# { cidr = "172.17.0.0/16" }`(panel doctor 会自动写入)。
|
|
18
|
+
#
|
|
19
|
+
# weknora-ui (nginx :80) ─proxy_pass─► weknora-app :8080
|
|
20
|
+
# │ │
|
|
21
|
+
# │ ├─► paradedb :5432 (PG17 + pgvector + FTS5;同时承担 vector store)
|
|
22
|
+
# │ ├─► redis :6379 (任务队列 / 流式响应缓存)
|
|
23
|
+
# │ └─► docreader:50051 (gRPC:PDF / Word / Markdown 解析)
|
|
24
|
+
# │
|
|
25
|
+
# host :18092 ◄── published (visibility: external)
|
|
26
|
+
#
|
|
27
|
+
# 关键裁剪(相对官方 docker-compose):
|
|
28
|
+
# - RETRIEVE_DRIVER=postgres:复用 paradedb 的 pgvector,**不装 Qdrant / Milvus / Weaviate**(省 1 task + ~70MB 下载)
|
|
29
|
+
# - WEKNORA_SANDBOX_MODE=disabled:不装 weknora-sandbox(省 ~80MB;阉割 agent 工具沙箱执行,RAG 主流程不受影响)
|
|
30
|
+
# - 不装 Neo4j / MinIO / Langfuse / Jaeger / SearXNG / Doris / ClickHouse / Dex(都是 profile 才启的)
|
|
31
|
+
#
|
|
32
|
+
# 镜像总下载:~2.8 GB (arm64) / ~3.0 GB (amd64);解压磁盘 ~6.5 GB
|
|
33
|
+
# 稳态内存预算:~1.5–2.0 GB(4 GB Pi 紧张,建议 8 GB Pi 5 / x86 节点)
|
|
34
|
+
|
|
35
|
+
tasks:
|
|
36
|
+
# ────────────────────────────────────────────────────────────────
|
|
37
|
+
# 1) PostgreSQL(ParadeDB:PG17 + pgvector + ParadeDB BM25 全文)
|
|
38
|
+
# role: sidecar → prestart 起来并持续运行;service tasks 在所有
|
|
39
|
+
# sidecar Running 后再启动(但 Running ≠ Ready,weknora-app 自己
|
|
40
|
+
# 要靠连接重试兜住 DB init 的 30s 窗口)。
|
|
41
|
+
# ────────────────────────────────────────────────────────────────
|
|
42
|
+
- name: paradedb
|
|
43
|
+
role: sidecar
|
|
44
|
+
runtime: container
|
|
45
|
+
image: "paradedb/paradedb:v0.22.2-pg17"
|
|
46
|
+
user: "host"
|
|
47
|
+
env:
|
|
48
|
+
POSTGRES_USER: "weknora"
|
|
49
|
+
# ⚠️ 开发默认值。生产请改:
|
|
50
|
+
# docker exec -it <container> psql -U weknora -c "ALTER USER weknora WITH PASSWORD '<new>'"
|
|
51
|
+
# 并同步更新 weknora-app 的 DB_PASSWORD。
|
|
52
|
+
POSTGRES_PASSWORD: "weknora-dev-pg-pw"
|
|
53
|
+
POSTGRES_DB: "WeKnora"
|
|
54
|
+
PGDATA: "/var/lib/postgresql/data/pgdata"
|
|
55
|
+
resources:
|
|
56
|
+
cpu: "500m"
|
|
57
|
+
memory: "384Mi"
|
|
58
|
+
ports:
|
|
59
|
+
- name: pg
|
|
60
|
+
port: 18093
|
|
61
|
+
container_port: 5432
|
|
62
|
+
visibility: external
|
|
63
|
+
host_network: docker_bridge
|
|
64
|
+
volumes:
|
|
65
|
+
- source: "~/.jishushell/apps/${app_id}/postgres"
|
|
66
|
+
target: "/var/lib/postgresql/data"
|
|
67
|
+
|
|
68
|
+
# ────────────────────────────────────────────────────────────────
|
|
69
|
+
# 2) Redis(任务队列 + Stream Manager 状态)
|
|
70
|
+
# ────────────────────────────────────────────────────────────────
|
|
71
|
+
- name: redis
|
|
72
|
+
role: sidecar
|
|
73
|
+
runtime: container
|
|
74
|
+
image: "redis:7.0-alpine"
|
|
75
|
+
user: "host"
|
|
76
|
+
args:
|
|
77
|
+
- "redis-server"
|
|
78
|
+
- "--appendonly"
|
|
79
|
+
- "yes"
|
|
80
|
+
# 无密码:仅 group 内 127.0.0.1 可达,未发布到宿主。
|
|
81
|
+
# 如需密码,加 --requirepass <pw> 并同步设 weknora-app 的 REDIS_PASSWORD。
|
|
82
|
+
resources:
|
|
83
|
+
cpu: "100m"
|
|
84
|
+
memory: "96Mi"
|
|
85
|
+
ports:
|
|
86
|
+
- name: redis
|
|
87
|
+
port: 18094
|
|
88
|
+
container_port: 6379
|
|
89
|
+
visibility: external
|
|
90
|
+
host_network: docker_bridge
|
|
91
|
+
volumes:
|
|
92
|
+
- source: "~/.jishushell/apps/${app_id}/redis"
|
|
93
|
+
target: "/data"
|
|
94
|
+
|
|
95
|
+
# ────────────────────────────────────────────────────────────────
|
|
96
|
+
# 3) docreader(最大头:1.7 GB;Python + markitdown + PDF 渲染)
|
|
97
|
+
# weknora-app `depends_on: docreader (service_healthy)` 是 core
|
|
98
|
+
# 依赖,**不能砍**。
|
|
99
|
+
# ────────────────────────────────────────────────────────────────
|
|
100
|
+
- name: docreader
|
|
101
|
+
role: sidecar
|
|
102
|
+
runtime: container
|
|
103
|
+
image: "wechatopenai/weknora-docreader:latest"
|
|
104
|
+
# Image entrypoint uses `uv` package manager which writes to /.cache/uv;
|
|
105
|
+
# forcing host uid (1000:1000) gets Permission denied on the root-owned
|
|
106
|
+
# filesystem and the container exits 2. Run as root — image is read-only
|
|
107
|
+
# in the layers that matter; runtime writes go to /tmp/docreader (bind
|
|
108
|
+
# mount, panel-user owned).
|
|
109
|
+
user: "0:0"
|
|
110
|
+
env:
|
|
111
|
+
DOCREADER_IMAGE_OUTPUT_DIR: "/tmp/docreader"
|
|
112
|
+
MAX_FILE_SIZE_MB: "50"
|
|
113
|
+
DOCREADER_MARKITDOWN_MAX_WORKERS: "1"
|
|
114
|
+
DOCREADER_PDF_RENDER_MAX_WORKERS: "1"
|
|
115
|
+
DOCREADER_PDF_RENDER_DPI: "200"
|
|
116
|
+
DOCREADER_PDF_JPEG_QUALITY: "90"
|
|
117
|
+
resources:
|
|
118
|
+
cpu: "800m"
|
|
119
|
+
memory: "768Mi"
|
|
120
|
+
ports:
|
|
121
|
+
- name: grpc
|
|
122
|
+
port: 18095
|
|
123
|
+
container_port: 50051
|
|
124
|
+
visibility: external
|
|
125
|
+
host_network: docker_bridge
|
|
126
|
+
volumes:
|
|
127
|
+
# tmp 目录与 weknora-app 共享,docreader 写 / app 读(图片提取场景)。
|
|
128
|
+
- source: "~/.jishushell/apps/${app_id}/docreader-tmp"
|
|
129
|
+
target: "/tmp/docreader"
|
|
130
|
+
|
|
131
|
+
# ────────────────────────────────────────────────────────────────
|
|
132
|
+
# 4) WeKnora 后端 app(Go)
|
|
133
|
+
# ────────────────────────────────────────────────────────────────
|
|
134
|
+
- name: app
|
|
135
|
+
role: service
|
|
136
|
+
runtime: container
|
|
137
|
+
image: "wechatopenai/weknora-app:latest"
|
|
138
|
+
# Image entrypoint chowns /app/skills/preloaded; with host uid the
|
|
139
|
+
# chown fails with "Operation not permitted" and the container crashes.
|
|
140
|
+
# Bind-mounted /data/files is panel-user owned (1000) — Go binary opens
|
|
141
|
+
# it as root without issue.
|
|
142
|
+
user: "0:0"
|
|
143
|
+
# panel default is cap_drop:ALL; weknora-app entrypoint does
|
|
144
|
+
# `chown -R appuser /app/skills/preloaded` at startup → needs CHOWN.
|
|
145
|
+
# It then `su appuser` to drop to non-root → needs SETUID/SETGID/SETPCAP.
|
|
146
|
+
cap_add: ["CHOWN", "FOWNER", "DAC_OVERRIDE", "SETUID", "SETGID", "SETPCAP"]
|
|
147
|
+
env:
|
|
148
|
+
# ── 基础运行时 ──
|
|
149
|
+
GIN_MODE: "release"
|
|
150
|
+
LOG_LEVEL: "info"
|
|
151
|
+
TZ: "Asia/Shanghai"
|
|
152
|
+
WEKNORA_LANGUAGE: "zh-CN"
|
|
153
|
+
DISABLE_REGISTRATION: "false"
|
|
154
|
+
|
|
155
|
+
# ── 数据库(host_network: docker_bridge → 绑 docker0 IP,
|
|
156
|
+
# host.docker.internal=172.17.0.1 容器内可达) ──
|
|
157
|
+
DB_DRIVER: "postgres"
|
|
158
|
+
DB_HOST: "host.docker.internal"
|
|
159
|
+
DB_PORT: "18093"
|
|
160
|
+
DB_USER: "weknora"
|
|
161
|
+
DB_PASSWORD: "weknora-dev-pg-pw"
|
|
162
|
+
DB_NAME: "WeKnora"
|
|
163
|
+
|
|
164
|
+
# ── 向量检索:走 paradedb 的 pgvector(砍 Qdrant / Milvus / Weaviate) ──
|
|
165
|
+
RETRIEVE_DRIVER: "postgres"
|
|
166
|
+
|
|
167
|
+
# ── Redis ──
|
|
168
|
+
REDIS_ADDR: "host.docker.internal:18094"
|
|
169
|
+
REDIS_DB: "0"
|
|
170
|
+
REDIS_PREFIX: "stream:"
|
|
171
|
+
STREAM_MANAGER_TYPE: "redis"
|
|
172
|
+
|
|
173
|
+
# ── docreader gRPC ──
|
|
174
|
+
DOCREADER_ADDR: "host.docker.internal:18095"
|
|
175
|
+
DOCREADER_TRANSPORT: "grpc"
|
|
176
|
+
|
|
177
|
+
# ── 文件存储:local 模式,写到 bind-mounted /data/files ──
|
|
178
|
+
STORAGE_TYPE: "local"
|
|
179
|
+
LOCAL_STORAGE_BASE_DIR: "/data/files"
|
|
180
|
+
MAX_FILE_SIZE_MB: "50"
|
|
181
|
+
|
|
182
|
+
# ── Sandbox:关。Agent 工具调用执行能力不可用,RAG 主流程不受影响。 ──
|
|
183
|
+
# 如需开启:(a) 把 weknora-sandbox 也加进 tasks[];(b) 改为
|
|
184
|
+
# WEKNORA_SANDBOX_MODE=docker;(c) 注意 sandbox 需要 docker.sock 挂载,
|
|
185
|
+
# Nomad 调度的容器内不一定有权限——可能需要额外设计。
|
|
186
|
+
WEKNORA_SANDBOX_MODE: "disabled"
|
|
187
|
+
|
|
188
|
+
# ── 安全密钥 ⚠️ 开发默认值,生产前必改 ──
|
|
189
|
+
# 推荐:openssl rand -hex 32 重新生成;同步改前端 NEXTAUTH_SECRET 之类。
|
|
190
|
+
JWT_SECRET: "weknora-dev-jwt-secret-CHANGE-ME-IN-PROD"
|
|
191
|
+
TENANT_AES_KEY: "weknora-dev-tenant-key-32bytes!!"
|
|
192
|
+
SYSTEM_AES_KEY: "weknora-dev-system-key-32bytes!!"
|
|
193
|
+
|
|
194
|
+
# ── LLM provider:留空,让用户在 WeKnora UI 里手动配。 ──
|
|
195
|
+
# 想用 panel 内嵌 LLM proxy(推荐)的话,UI 里填:
|
|
196
|
+
# base_url: http://host.docker.internal:8090/proxy/v1
|
|
197
|
+
# api_key: <从 panel /instances/:id 拿到的 sk-js-*>
|
|
198
|
+
# 这样审计 / 限流 / 上游切换都收敛在 panel 一层。
|
|
199
|
+
OLLAMA_BASE_URL: ""
|
|
200
|
+
|
|
201
|
+
# ── Tracing / Observability:全关 ──
|
|
202
|
+
LANGFUSE_ENABLED: "false"
|
|
203
|
+
OTEL_TRACES_EXPORTER: "none"
|
|
204
|
+
OTEL_METRICS_EXPORTER: "none"
|
|
205
|
+
OTEL_LOGS_EXPORTER: "none"
|
|
206
|
+
ENABLE_GRAPH_RAG: "false"
|
|
207
|
+
NEO4J_ENABLE: "false"
|
|
208
|
+
|
|
209
|
+
# ── 并发 ──
|
|
210
|
+
CONCURRENCY_POOL_SIZE: "5"
|
|
211
|
+
|
|
212
|
+
# ── SSRF 白名单:默认走 panel 反代,无需对外。 ──
|
|
213
|
+
SSRF_WHITELIST: ""
|
|
214
|
+
SSRF_WHITELIST_EXTRA: ""
|
|
215
|
+
resources:
|
|
216
|
+
cpu: "600m"
|
|
217
|
+
memory: "640Mi"
|
|
218
|
+
ports:
|
|
219
|
+
- name: http
|
|
220
|
+
# Published on docker0 so the ui task can reach backend via
|
|
221
|
+
# host.docker.internal:18096 (no shared netns on Pi w/o CNI).
|
|
222
|
+
port: 18096
|
|
223
|
+
container_port: 8080
|
|
224
|
+
visibility: external
|
|
225
|
+
host_network: docker_bridge
|
|
226
|
+
volumes:
|
|
227
|
+
# 知识库附件落盘。与 ~/.jishushell/files/ 故意分离 ——
|
|
228
|
+
# WeKnora 自己管文件元数据 / RAG 索引,避免与 panel W3 FTS5 打架。
|
|
229
|
+
- source: "~/.jishushell/apps/${app_id}/files"
|
|
230
|
+
target: "/data/files"
|
|
231
|
+
|
|
232
|
+
# ────────────────────────────────────────────────────────────────
|
|
233
|
+
# 5) WeKnora 前端 UI(nginx + Vue dist)
|
|
234
|
+
# ⚠️ 镜像不支持 BASE_URL 子路径 → 不走 panel /apps/weknora/* 反代,
|
|
235
|
+
# 用端口直连 18092。子路径要走需 fork 镜像(vite.config base + nginx
|
|
236
|
+
# location prefix),暂列为后续工作。
|
|
237
|
+
# ────────────────────────────────────────────────────────────────
|
|
238
|
+
- name: ui
|
|
239
|
+
role: service
|
|
240
|
+
runtime: container
|
|
241
|
+
image: "wechatopenai/weknora-ui:latest"
|
|
242
|
+
# nginx entrypoint needs to mkdir /var/cache/nginx/client_temp and
|
|
243
|
+
# rewrite /etc/nginx/conf.d/default.conf via envsubst — both require root.
|
|
244
|
+
# Host uid breaks both steps and the container crashloops.
|
|
245
|
+
user: "0:0"
|
|
246
|
+
# nginx master spawns workers as uid 101 (nginx user) and chowns the
|
|
247
|
+
# cache dir to it — needs CHOWN to do so even when master is root.
|
|
248
|
+
cap_add: ["CHOWN", "SETGID", "SETUID"]
|
|
249
|
+
env:
|
|
250
|
+
MAX_FILE_SIZE_MB: "50"
|
|
251
|
+
APP_HOST: "host.docker.internal"
|
|
252
|
+
APP_PORT: "18096"
|
|
253
|
+
APP_SCHEME: "http"
|
|
254
|
+
resources:
|
|
255
|
+
cpu: "100m"
|
|
256
|
+
memory: "48Mi"
|
|
257
|
+
ports:
|
|
258
|
+
- name: http
|
|
259
|
+
# 18092 在 panel 18xxx 范围内(filebrowser 18088 / openclaw-gw 18790)。
|
|
260
|
+
# 避开 OpenWebUI 3000、SearXNG 8080、panel 8090。
|
|
261
|
+
port: 18092
|
|
262
|
+
container_port: 80
|
|
263
|
+
visibility: external
|
|
264
|
+
volumes:
|
|
265
|
+
# 覆盖镜像内的 nginx 模板:上游模板带 `add_header X-Frame-Options
|
|
266
|
+
# SAMEORIGIN`,panel 实例详情页 iframe (origin=panel:8090) 嵌
|
|
267
|
+
# WeKnora UI (origin=panel:18092) 会被浏览器拒绝。我们这份完全
|
|
268
|
+
# 照搬上游 location 块,只去掉 X-Frame-Options/CSP 限制,保留
|
|
269
|
+
# ${APP_HOST}/${APP_PORT}/${APP_SCHEME}/${MAX_FILE_SIZE} 由镜像
|
|
270
|
+
# docker-entrypoint.sh envsubst。
|
|
271
|
+
- source: "~/.jishushell/apps/${app_id}/nginx/default.conf.template"
|
|
272
|
+
target: "/etc/nginx/templates/default.conf.template"
|
|
273
|
+
readonly: true
|
|
274
|
+
health:
|
|
275
|
+
http:
|
|
276
|
+
path: /
|
|
277
|
+
port: 80
|
|
278
|
+
interval: "15s"
|
|
279
|
+
timeout: "5s"
|
|
280
|
+
retries: 6
|
|
281
|
+
start_period: "60s" # 等 paradedb 初始化 + weknora-app boot + nginx 上线
|
|
282
|
+
|
|
283
|
+
provides:
|
|
284
|
+
# ⚠️ Capability 命名特意避开 `web-<slug>` 和 `<slug>-ui` 这两种 panel 顶层
|
|
285
|
+
# `/apps/<slug>/*` 反代会命中的模式(详见 src/server.ts:69 resolveAppSlugUpstream)。
|
|
286
|
+
# 原因:panel 反代**不去掉** `/apps/<slug>` 前缀(server.ts:382 注释),原样
|
|
287
|
+
# 转发给上游;而 WeKnora 前端镜像的 nginx 只 listen `/`、vite build 也没设
|
|
288
|
+
# `base`——任何 `/apps/weknora/*` 请求到了 ui 容器都会 404。
|
|
289
|
+
#
|
|
290
|
+
# 因此用 `knowledge-weknora`(业务命名、非通配前缀),让它**只**进 capability
|
|
291
|
+
# registry 供未来 agent `requires:` 注入使用,**不**触发 panel 顶层反代。
|
|
292
|
+
# 用户访问 UI 走端口直连:http://<host>:18092/。
|
|
293
|
+
- capability: "knowledge-weknora"
|
|
294
|
+
task: "ui"
|
|
295
|
+
port: 18092
|
|
296
|
+
path: "/"
|
|
297
|
+
protocol: "http"
|
|
298
|
+
visibility: "external"
|
|
299
|
+
# 强制 iframe 走 panel 反代而不是端口直连。原因:
|
|
300
|
+
# 1. 用户从 panel 8090 同源加载详情页,corp 防火墙 / VPN / 混合内容
|
|
301
|
+
# 策略可能让 8090 通但 18092 不通(典型:"refused to connect")。
|
|
302
|
+
# 2. nginx SAMEORIGIN/CSP 即便去掉了,浏览器 Private Network Access
|
|
303
|
+
# 仍可能拒绝跨网段 iframe;走 panel 反代后 iframe src 与 panel
|
|
304
|
+
# 同源,绕开所有边界检查。
|
|
305
|
+
# 3. WeKnora 前端 vite build 没设 `base`,绝对路径 `/api/...` 直接
|
|
306
|
+
# 打到 panel API → 但反代会把 base 改成 /api/instances/.../provides/
|
|
307
|
+
# /knowledge-weknora/,后续相对 fetch 正确(panel 反代有 base 重写)。
|
|
308
|
+
# Direct mode: iframe loads http://<host>:18092/ instead of the panel
|
|
309
|
+
# capability proxy. The proxy path approach kept tripping over WeKnora's
|
|
310
|
+
# axios 401 interceptor, which hard-codes `window.location.href = '/login'`
|
|
311
|
+
# and bounces the iframe to the panel root login page. Rewriting that
|
|
312
|
+
# literal at the proxy works for the assignment but the bundle has
|
|
313
|
+
# additional indirect navigations (vue-router fallback when pushState is
|
|
314
|
+
# blocked, internal pinia store actions) that aren't reachable from a
|
|
315
|
+
# text rewrite — same-origin iframe vs. direct iframe tradeoff favors
|
|
316
|
+
# direct here because the dev/internal browser already reaches 18092
|
|
317
|
+
# successfully (popout link confirmed working).
|
|
318
|
+
embedded: "direct"
|
|
319
|
+
description: "WeKnora 知识库 Web UI"
|
|
320
|
+
|
|
321
|
+
lifecycle:
|
|
322
|
+
install:
|
|
323
|
+
# 镜像按尺寸升序下载:小的先稳,大的(docreader 1.7GB)放最后,
|
|
324
|
+
# 万一失败下次重试时小的全部 skip,从大的断点续。
|
|
325
|
+
- downloadImage: "redis:7.0-alpine"
|
|
326
|
+
- downloadImage: "wechatopenai/weknora-ui:latest"
|
|
327
|
+
- downloadImage: "wechatopenai/weknora-app:latest"
|
|
328
|
+
- downloadImage: "paradedb/paradedb:v0.22.2-pg17"
|
|
329
|
+
# docreader 单独给 30 分钟总超时 + 30 分钟 idle 超时(1.7GB 内含 400MB+ 的
|
|
330
|
+
# 大 layer;Pi 带宽 ~2 MB/s 下单 layer 下载耗时可超 panel 默认 180s idle
|
|
331
|
+
# → 误判 stalled。设 30 分钟 idle 给慢网充足时间)。
|
|
332
|
+
- downloadImage: "wechatopenai/weknora-docreader:latest"
|
|
333
|
+
timeout_ms: 1800000
|
|
334
|
+
idle_timeout_ms: 1800000
|
|
335
|
+
|
|
336
|
+
- mkdir: "~/.jishushell/apps/${app_id}/postgres"
|
|
337
|
+
- mkdir: "~/.jishushell/apps/${app_id}/redis"
|
|
338
|
+
- mkdir: "~/.jishushell/apps/${app_id}/docreader-tmp"
|
|
339
|
+
- mkdir: "~/.jishushell/apps/${app_id}/files"
|
|
340
|
+
- mkdir: "~/.jishushell/apps/${app_id}/nginx"
|
|
341
|
+
# 写自定义 nginx 模板(去掉 X-Frame-Options 让 panel 实例详情页能
|
|
342
|
+
# iframe 嵌入)。单引号 heredoc 关掉 shell 展开,保留 ${APP_HOST}/
|
|
343
|
+
# ${APP_PORT}/${APP_SCHEME}/${MAX_FILE_SIZE} 由镜像 envsubst 替换。
|
|
344
|
+
- run: |
|
|
345
|
+
set -e
|
|
346
|
+
TPL="$HOME/.jishushell/apps/${app_id}/nginx/default.conf.template"
|
|
347
|
+
cat > "$TPL" <<'NGX'
|
|
348
|
+
server {
|
|
349
|
+
listen 80;
|
|
350
|
+
server_name localhost;
|
|
351
|
+
|
|
352
|
+
client_max_body_size ${MAX_FILE_SIZE};
|
|
353
|
+
|
|
354
|
+
gzip on;
|
|
355
|
+
gzip_min_length 1024;
|
|
356
|
+
gzip_comp_level 6;
|
|
357
|
+
gzip_types text/plain text/css application/json application/javascript
|
|
358
|
+
application/xml text/xml application/x-javascript;
|
|
359
|
+
|
|
360
|
+
# X-Frame-Options 故意不发:panel 实例详情页 (origin=panel:8090)
|
|
361
|
+
# 要 iframe 嵌入本服务 (origin=panel:18092),原版 SAMEORIGIN
|
|
362
|
+
# 会被浏览器拒。其余安全头照旧。
|
|
363
|
+
add_header X-Content-Type-Options nosniff always;
|
|
364
|
+
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
|
365
|
+
|
|
366
|
+
location /assets/ {
|
|
367
|
+
root /usr/share/nginx/html;
|
|
368
|
+
expires max;
|
|
369
|
+
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
location = /files {
|
|
373
|
+
proxy_pass ${APP_SCHEME}://${APP_HOST}:${APP_PORT}/files;
|
|
374
|
+
proxy_http_version 1.1;
|
|
375
|
+
proxy_set_header Host $host;
|
|
376
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
377
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
location /api/ {
|
|
381
|
+
proxy_pass ${APP_SCHEME}://${APP_HOST}:${APP_PORT}/api/;
|
|
382
|
+
proxy_http_version 1.1;
|
|
383
|
+
proxy_set_header Host $host;
|
|
384
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
385
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
386
|
+
proxy_set_header Connection "";
|
|
387
|
+
proxy_buffering off;
|
|
388
|
+
proxy_cache off;
|
|
389
|
+
proxy_read_timeout 3600s;
|
|
390
|
+
proxy_send_timeout 3600s;
|
|
391
|
+
proxy_connect_timeout 30s;
|
|
392
|
+
proxy_next_upstream error timeout http_502 http_503 http_504;
|
|
393
|
+
proxy_next_upstream_tries 3;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
location / {
|
|
397
|
+
root /usr/share/nginx/html;
|
|
398
|
+
try_files $uri $uri/ /index.html;
|
|
399
|
+
add_header Cache-Control "no-cache, must-revalidate";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
NGX
|
|
403
|
+
chmod 644 "$TPL"
|
|
404
|
+
echo "[install] wrote nginx template (no X-Frame-Options) → $TPL"
|
|
405
|
+
|
|
406
|
+
pre_start:
|
|
407
|
+
# 幂等:start/restart 都过这条路径,目录被误删可自愈。
|
|
408
|
+
- mkdir: "~/.jishushell/apps/${app_id}/postgres"
|
|
409
|
+
- mkdir: "~/.jishushell/apps/${app_id}/redis"
|
|
410
|
+
- mkdir: "~/.jishushell/apps/${app_id}/docreader-tmp"
|
|
411
|
+
- mkdir: "~/.jishushell/apps/${app_id}/files"
|
|
412
|
+
- mkdir: "~/.jishushell/apps/${app_id}/nginx"
|
|
413
|
+
- run: |
|
|
414
|
+
set -e
|
|
415
|
+
TPL="$HOME/.jishushell/apps/${app_id}/nginx/default.conf.template"
|
|
416
|
+
if [ ! -f "$TPL" ]; then
|
|
417
|
+
cat > "$TPL" <<'NGX'
|
|
418
|
+
server {
|
|
419
|
+
listen 80;
|
|
420
|
+
server_name localhost;
|
|
421
|
+
client_max_body_size ${MAX_FILE_SIZE};
|
|
422
|
+
gzip on;
|
|
423
|
+
gzip_min_length 1024;
|
|
424
|
+
gzip_comp_level 6;
|
|
425
|
+
gzip_types text/plain text/css application/json application/javascript
|
|
426
|
+
application/xml text/xml application/x-javascript;
|
|
427
|
+
add_header X-Content-Type-Options nosniff always;
|
|
428
|
+
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
|
429
|
+
location /assets/ {
|
|
430
|
+
root /usr/share/nginx/html;
|
|
431
|
+
expires max;
|
|
432
|
+
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
433
|
+
}
|
|
434
|
+
location = /files {
|
|
435
|
+
proxy_pass ${APP_SCHEME}://${APP_HOST}:${APP_PORT}/files;
|
|
436
|
+
proxy_http_version 1.1;
|
|
437
|
+
proxy_set_header Host $host;
|
|
438
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
439
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
440
|
+
}
|
|
441
|
+
location /api/ {
|
|
442
|
+
proxy_pass ${APP_SCHEME}://${APP_HOST}:${APP_PORT}/api/;
|
|
443
|
+
proxy_http_version 1.1;
|
|
444
|
+
proxy_set_header Host $host;
|
|
445
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
446
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
447
|
+
proxy_set_header Connection "";
|
|
448
|
+
proxy_buffering off;
|
|
449
|
+
proxy_cache off;
|
|
450
|
+
proxy_read_timeout 3600s;
|
|
451
|
+
proxy_send_timeout 3600s;
|
|
452
|
+
proxy_connect_timeout 30s;
|
|
453
|
+
proxy_next_upstream error timeout http_502 http_503 http_504;
|
|
454
|
+
proxy_next_upstream_tries 3;
|
|
455
|
+
}
|
|
456
|
+
location / {
|
|
457
|
+
root /usr/share/nginx/html;
|
|
458
|
+
try_files $uri $uri/ /index.html;
|
|
459
|
+
add_header Cache-Control "no-cache, must-revalidate";
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
NGX
|
|
463
|
+
chmod 644 "$TPL"
|
|
464
|
+
fi
|
|
465
|
+
|
|
466
|
+
uninstall:
|
|
467
|
+
- deleteImage: "wechatopenai/weknora-docreader:latest"
|
|
468
|
+
- deleteImage: "paradedb/paradedb:v0.22.2-pg17"
|
|
469
|
+
- deleteImage: "wechatopenai/weknora-app:latest"
|
|
470
|
+
- deleteImage: "wechatopenai/weknora-ui:latest"
|
|
471
|
+
- deleteImage: "redis:7.0-alpine"
|