jishushell 0.4.30 → 0.5.15
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/apps/anythingllm-container.yaml +287 -0
- package/apps/browserless-chromium-container.yaml +18 -6
- package/apps/filebrowser-container.yaml +163 -0
- 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/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 +3 -3
- 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 +45 -7
- 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/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 +341 -3
- package/dist/server.js.map +1 -1
- 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 +1 -0
- package/dist/services/app/app-manager.js +172 -41
- 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 +20 -3
- 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 +177 -4
- package/dist/services/backup-manager.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 +1 -23
- package/dist/services/instance-manager.js.map +1 -1
- 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/nomad-manager.d.ts +4 -0
- package/dist/services/nomad-manager.js +53 -19
- 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 +20 -1
- 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/hermes.js +1 -1
- 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 +90 -0
- package/dist/services/runtime/adapters/openclaw.js +957 -45
- 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 +93 -18
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/suggestions.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 +60 -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/package.json +16 -1
- package/public/assets/Dashboard-BdWPtroF.js +1 -0
- package/public/assets/{HermesChatPanel-_GHoklgo.js → HermesChatPanel-B_2HlVBQ.js} +1 -1
- package/public/assets/{HermesConfigForm-anDnwUp_.js → HermesConfigForm-DVlhg3WV.js} +2 -2
- package/public/assets/{InitPassword-ZU9_-hDr.js → InitPassword-D7glTExX.js} +1 -1
- package/public/assets/InstanceDetail-CxSy2cpe.js +92 -0
- package/public/assets/{Login-BItXqYAJ.js → Login-Cfr5c2sv.js} +1 -1
- package/public/assets/NewInstance-BIYDmJis.js +1 -0
- package/public/assets/{ProviderRecommendations-DFYj7Fb6.js → ProviderRecommendations-BuRnvRcI.js} +1 -1
- package/public/assets/{Settings-Bttc6QmM.js → Settings-Cc-tYBil.js} +1 -1
- package/public/assets/{Setup-Bsxx1zgj.js → Setup-lGZEk5jq.js} +1 -1
- package/public/assets/{WeixinLoginPanel-DPZpAKgO.js → WeixinLoginPanel-CoGqzxeV.js} +2 -2
- package/public/assets/index-87IJXG-w.css +1 -0
- package/public/assets/index-BZc5zH7u.js +19 -0
- package/public/assets/{registry-5s2UB6is.js → registry-BWnkJgZ1.js} +2 -2
- package/public/assets/{usePolling-Do5Erqm_.js → usePolling-CwwT9KrC.js} +1 -1
- package/public/assets/{vendor-i18n-ucpM0OR0.js → vendor-i18n-y9V7Sfuu.js} +1 -1
- package/public/assets/{vendor-react-Bk1hRGiY.js → vendor-react-BWrEVJVb.js} +6 -6
- package/public/index.html +4 -4
- package/scripts/check-app-spec.mjs +18 -4
- 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/InstanceDetail-CN0FH1aw.js +0 -92
- package/public/assets/NewInstance-BousE6kY.js +0 -1
- package/public/assets/index-8xZy1z5k.css +0 -1
- package/public/assets/index-Dw3HhUYE.js +0 -19
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
id: anythingllm-container
|
|
2
|
+
name: AnythingLLM
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
jishushell:
|
|
5
|
+
min_version: "0.5.15"
|
|
6
|
+
description: "Mintplex Labs 开源 RAG 引擎:单容器 + 内置 LanceDB 向量库 + 内置 Xenova ONNX embedder(默认零外部依赖)+ OpenAI 兼容 chat API;通过 anythingllm-shim 暴露 kb_search 工具给 OpenClaw agent"
|
|
7
|
+
singleInstance: true
|
|
8
|
+
|
|
9
|
+
# 拓扑(单容器,无 sidecar)
|
|
10
|
+
# anythingllm (port 3001) ── host :18097 ── 用户浏览器 / shim API 调
|
|
11
|
+
# └─ /app/server/storage (LanceDB + sqlite + 上传文件 + Xenova embedder ONNX 模型)
|
|
12
|
+
#
|
|
13
|
+
# 端到端调用链(agent 模式 / 路 2):
|
|
14
|
+
# Feishu 用户 → claw1 (MiniMax) → 决定调 kb_search → mcporter call kb.kb_search
|
|
15
|
+
# → anythingllm-shim → POST http://host.docker.internal:18097/api/v1/openai/chat/completions
|
|
16
|
+
# → AnythingLLM workspace 自动 RAG 检索 + 拼 prompt → AnythingLLM 上游 LLM
|
|
17
|
+
# → 答案 + citation → 回 claw1 → Feishu 用户
|
|
18
|
+
#
|
|
19
|
+
# 关键裁剪 / 配置:
|
|
20
|
+
# - SERVER_PORT 3001(AnythingLLM 默认 unified port)
|
|
21
|
+
# - STORAGE_DIR 落到 bind-mounted /app/server/storage,模型/向量/文件全持久化
|
|
22
|
+
# - DISABLE_TELEMETRY=true 不发数据回 Mintplex
|
|
23
|
+
# - 默认 embedder 内置(Xenova/all-MiniLM-L6-v2 ONNX)—— 不配 EMBEDDING_ENGINE 走 native
|
|
24
|
+
# - LLM provider 不预设;用户首启时 setup wizard 或 API 配,或者让 shim 通过 API 预填
|
|
25
|
+
#
|
|
26
|
+
# 端口选择:18097 在 panel 18xxx 段,避开 18088 filebrowser / 18092-18096 weknora 段
|
|
27
|
+
# (虽然 weknora 已卸) / 18099 fastembed-bge (已删) / 18790 openclaw gateway。
|
|
28
|
+
#
|
|
29
|
+
# host_network: docker_bridge 让 anythingllm-shim 容器(实际跑在 claw1 gateway
|
|
30
|
+
# 容器内)经 host.docker.internal:18097 调 AnythingLLM(跟之前 fastembed-bge
|
|
31
|
+
# 同套路;nomad.hcl 已经声明 docker_bridge host_network)。同时用户浏览器
|
|
32
|
+
# 走 LAN IP 10.188.5.25:18097 直接访问 UI(双地址 docker-proxy 自动处理)。
|
|
33
|
+
|
|
34
|
+
tasks:
|
|
35
|
+
- name: anythingllm
|
|
36
|
+
role: service
|
|
37
|
+
runtime: container
|
|
38
|
+
image: "mintplexlabs/anythingllm:latest"
|
|
39
|
+
# AnythingLLM 镜像 Dockerfile 用 `USER anythingllm` 设了非 root user (uid 1000),
|
|
40
|
+
# bind-mount /app/server/storage 给 panel-user (uid 1000) 拥有 → 容器侧
|
|
41
|
+
# uid 1000 (anythingllm user) 能写。"host" 解析到 1000:1000 跟镜像默认对上,
|
|
42
|
+
# 不需要 cap_add,干净。
|
|
43
|
+
user: "host"
|
|
44
|
+
env:
|
|
45
|
+
# 监听端口(unified backend + frontend)
|
|
46
|
+
SERVER_PORT: "3001"
|
|
47
|
+
# 数据持久化目录。镜像默认就是这个,显式声明便于看 spec 时一目了然。
|
|
48
|
+
STORAGE_DIR: "/app/server/storage"
|
|
49
|
+
# 关 telemetry,本地用不需要给 Mintplex 上报。
|
|
50
|
+
DISABLE_TELEMETRY: "true"
|
|
51
|
+
# 关闭强制 setup wizard 的 onboarding 锁(首启可直接调 API 创建 workspace
|
|
52
|
+
# 而不必先点完 UI 向导)。
|
|
53
|
+
DISABLE_SETUP_GUIDED_TOUR: "true"
|
|
54
|
+
TZ: "Asia/Shanghai"
|
|
55
|
+
resources:
|
|
56
|
+
# AnythingLLM 实际跑 ~400-700MB RSS:Node.js backend + Xenova ONNX embedder
|
|
57
|
+
# + LanceDB (mmap)。给 1024Mi 留 buffer。
|
|
58
|
+
cpu: "1500m"
|
|
59
|
+
memory: "1024Mi"
|
|
60
|
+
ports:
|
|
61
|
+
- name: http
|
|
62
|
+
port: 18097
|
|
63
|
+
container_port: 3001
|
|
64
|
+
visibility: external
|
|
65
|
+
# 不指定 host_network → 默认 0.0.0.0 publish:LAN(用户浏览器)和
|
|
66
|
+
# docker0 (172.17.0.1,shim 经 host.docker.internal 调) 全覆盖。
|
|
67
|
+
# 之前 docker_bridge 只绑 172.17.0.1,UI 不可达。
|
|
68
|
+
volumes:
|
|
69
|
+
# 单一数据卷涵盖 sqlite + LanceDB + workspace docs + embedder ONNX cache。
|
|
70
|
+
# 跟其它 app 数据目录保持隔离习惯。
|
|
71
|
+
- source: "~/.jishushell/apps/${app_id}/data"
|
|
72
|
+
target: "/app/server/storage"
|
|
73
|
+
health:
|
|
74
|
+
http:
|
|
75
|
+
# AnythingLLM 健康检查 endpoint —— /api/ping 在 backend 起来后即 200。
|
|
76
|
+
# 首启要 Node 启动 ~5s + 初始化 sqlite + 加载 ONNX embedder(首次解压 ~150MB
|
|
77
|
+
# ONNX 模型到 /app/server/storage/models/Xenova/ ~30s on Pi)。
|
|
78
|
+
path: /api/ping
|
|
79
|
+
port: 3001
|
|
80
|
+
interval: "15s"
|
|
81
|
+
timeout: "5s"
|
|
82
|
+
retries: 6
|
|
83
|
+
start_period: "180s"
|
|
84
|
+
|
|
85
|
+
provides:
|
|
86
|
+
# 通用 capability:让其它 agent / shim `requires: knowledge` 时
|
|
87
|
+
# panel 注入 ANYTHINGLLM_BASE_URL。命名遵循 `<category>-<name>` 约定
|
|
88
|
+
# (见 scripts/check-app-spec.mjs 的 categoryOf 分类规则)。
|
|
89
|
+
- capability: "knowledge-anythingllm"
|
|
90
|
+
task: "anythingllm"
|
|
91
|
+
port: 18097
|
|
92
|
+
path: "/api/v1"
|
|
93
|
+
protocol: "http"
|
|
94
|
+
visibility: "external"
|
|
95
|
+
description: "AnythingLLM OpenAI 兼容 chat-with-rag endpoint (/api/v1/openai/chat/completions)"
|
|
96
|
+
|
|
97
|
+
# Web UI capability:通过 panel `/apps/anythingllm/*` 反代 或者用户直接访问
|
|
98
|
+
# LAN IP:18097。AnythingLLM 默认 SPA 不绑 sub-path → 走端口直连(同 weknora 套路)。
|
|
99
|
+
- capability: "anythingllm-ui"
|
|
100
|
+
task: "anythingllm"
|
|
101
|
+
port: 18097
|
|
102
|
+
path: "/"
|
|
103
|
+
protocol: "http"
|
|
104
|
+
visibility: "external"
|
|
105
|
+
description: "AnythingLLM Web UI"
|
|
106
|
+
|
|
107
|
+
lifecycle:
|
|
108
|
+
install:
|
|
109
|
+
# ~1 GB 压缩镜像,~2GB 解压。给 30 min idle timeout 兜 Pi 慢网(同 weknora-app 同等级)。
|
|
110
|
+
# idle_timeout_ms 字段最近修过,现在真透传到 docker pull 的 stall 检测。
|
|
111
|
+
- downloadImage: "mintplexlabs/anythingllm:latest"
|
|
112
|
+
timeout_ms: 1800000
|
|
113
|
+
idle_timeout_ms: 1800000
|
|
114
|
+
- mkdir: "~/.jishushell/apps/${app_id}/data"
|
|
115
|
+
|
|
116
|
+
pre_start:
|
|
117
|
+
# 幂等:start/restart 都过这条路径,目录被误删可自愈。
|
|
118
|
+
- mkdir: "~/.jishushell/apps/${app_id}/data"
|
|
119
|
+
|
|
120
|
+
post_start:
|
|
121
|
+
# 首启自动布线,幂等可重跑:
|
|
122
|
+
# 1) 等 /api/ping 200(首启要解压 ~150MB Xenova ONNX,Pi 上 ~60-120s)
|
|
123
|
+
# 2) 从 panel 拿默认 LLM provider 凭据(GET /api/internal/default-provider)
|
|
124
|
+
# panel 端 default_provider 没设 → ready:false → 跳过 LLM 自配,
|
|
125
|
+
# 留给用户在 UI 里手动选
|
|
126
|
+
# 3) ready:true 时把 generic-openai provider 灌进去(无视用户上游真协议;
|
|
127
|
+
# panel proxy 反正只暴露 OpenAI 兼容口子)
|
|
128
|
+
# 4) 生成 AnythingLLM dev API key(POST /api/system/generate-api-key,
|
|
129
|
+
# 单用户模式无 auth),落 credentials.json
|
|
130
|
+
# 5) 建默认 workspace "default"(已存在则忽略,AnythingLLM 自身的 unique 约束)
|
|
131
|
+
#
|
|
132
|
+
# 关键设计:整个脚本必须幂等。每次 start/restart 都重跑,但:
|
|
133
|
+
# - update-env 重复 POST = 同样的环境值再写一遍,OK
|
|
134
|
+
# - generate-api-key 重复调 = 多生成几把 key(不丢失旧的,但旧的也能用,
|
|
135
|
+
# credentials.json 只保留最新一把,shim 端拿这把就行)
|
|
136
|
+
# - workspace/new 重复调 = AnythingLLM 返回 409 / 重复,被 || true 吞掉
|
|
137
|
+
#
|
|
138
|
+
# 失败处理:任何一步失败都 set -e 兜,post_start 整体失败 → app 状态停留
|
|
139
|
+
# 在 "installed" 但 currentTaskStatus=error,用户在 UI 上看得到,重启再跑。
|
|
140
|
+
# 全部 JSON 解析 / 文件写入走 `node -e` —— node 是 panel 装机后**唯一**
|
|
141
|
+
# 必定存在的运行时(jishushell 本身跑在 node 上)。jq 在 Pi/Debian 默认不装;
|
|
142
|
+
# python3 在 Alpine slim / 极简 Linux 上不一定有。用 node 才能保证第三方
|
|
143
|
+
# 用户初装即可用。
|
|
144
|
+
- run: |
|
|
145
|
+
set -e
|
|
146
|
+
BASE_URL="http://${JISHUSHELL_LAN_HOST:-127.0.0.1}:18097"
|
|
147
|
+
CRED_DIR="$HOME/.jishushell/apps/anythingllm-container"
|
|
148
|
+
CRED_FILE="$CRED_DIR/credentials.json"
|
|
149
|
+
mkdir -p "$CRED_DIR"
|
|
150
|
+
|
|
151
|
+
# jget <dot.path> — read JSON from stdin, print field at path, empty on miss
|
|
152
|
+
jget() {
|
|
153
|
+
node -e 'let s="";process.stdin.on("data",c=>s+=c).on("end",()=>{try{let v=JSON.parse(s);for(const k of process.argv[1].split("."))v=v?.[k];process.stdout.write(v==null?"":String(v));}catch{process.stdout.write("")}})' "$1"
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
echo "[post_start] waiting for AnythingLLM /api/ping ..."
|
|
157
|
+
for i in $(seq 1 60); do
|
|
158
|
+
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "$BASE_URL/api/ping" || echo 000)
|
|
159
|
+
if [ "$code" = "200" ]; then
|
|
160
|
+
echo "[post_start] /api/ping is 200 (after ${i}x2s)"
|
|
161
|
+
break
|
|
162
|
+
fi
|
|
163
|
+
sleep 2
|
|
164
|
+
done
|
|
165
|
+
# final check; if still down, post_start fails fast
|
|
166
|
+
curl -sf --max-time 5 "$BASE_URL/api/ping" >/dev/null
|
|
167
|
+
|
|
168
|
+
echo "[post_start] fetching panel default provider ..."
|
|
169
|
+
DP_JSON=$(curl -sf --max-time 8 \
|
|
170
|
+
-H "X-Jishushell-Internal-Token: $JISHUSHELL_INTERNAL_TOKEN" \
|
|
171
|
+
"$JISHUSHELL_PANEL_URL/api/internal/default-provider" || echo '{"ready":false,"reason":"panel_unreachable"}')
|
|
172
|
+
READY=$(printf '%s' "$DP_JSON" | jget ready)
|
|
173
|
+
|
|
174
|
+
if [ "$READY" = "true" ]; then
|
|
175
|
+
MODEL=$(printf '%s' "$DP_JSON" | jget modelId)
|
|
176
|
+
# W1 直连上游:用户上游 baseUrl + decrypted apiKey 直接给 AnythingLLM。
|
|
177
|
+
# 牺牲了 panel proxy 的 rate-limit / circuit-break / usage logging —
|
|
178
|
+
# W2 加 app-scoped proxy key 后切回经 proxy。
|
|
179
|
+
BASE=$(printf '%s' "$DP_JSON" | jget baseUrl)
|
|
180
|
+
KEY=$(printf '%s' "$DP_JSON" | jget apiKey)
|
|
181
|
+
echo "[post_start] configuring LLM provider: $MODEL @ $BASE"
|
|
182
|
+
# Build update-env body in node so apiKey / baseUrl / modelId can contain
|
|
183
|
+
# `"`, `\`, newlines, or any other JSON-significant chars without breaking
|
|
184
|
+
# the shell-interpolated payload (review finding F5).
|
|
185
|
+
UPDATE_BODY=$(BASE="$BASE" KEY="$KEY" MODEL="$MODEL" node -e '
|
|
186
|
+
process.stdout.write(JSON.stringify({
|
|
187
|
+
LLMProvider: "generic-openai",
|
|
188
|
+
GenericOpenAiBasePath: process.env.BASE,
|
|
189
|
+
GenericOpenAiKey: process.env.KEY,
|
|
190
|
+
GenericOpenAiModelPref: process.env.MODEL,
|
|
191
|
+
GenericOpenAiMaxTokens: "4096",
|
|
192
|
+
}));
|
|
193
|
+
')
|
|
194
|
+
# Tolerate 401/403 — AnythingLLM ships single-user no-auth by default,
|
|
195
|
+
# but a user can opt-in to password protection via UI. validatedRequest
|
|
196
|
+
# then mandates a JWT we don't have, and there's no admin-bootstrap
|
|
197
|
+
# endpoint we can call here. Log the actionable next step and continue
|
|
198
|
+
# so the script stays idempotent (review finding F1).
|
|
199
|
+
UPDATE_HTTP=$(curl -s -o /tmp/anyllm-upd.txt -w '%{http_code}' --max-time 10 \
|
|
200
|
+
-X POST "$BASE_URL/api/system/update-env" \
|
|
201
|
+
-H "Content-Type: application/json" \
|
|
202
|
+
--data "$UPDATE_BODY" || echo 000)
|
|
203
|
+
case "$UPDATE_HTTP" in
|
|
204
|
+
2*) echo "[post_start] LLM provider configured" ;;
|
|
205
|
+
401|403)
|
|
206
|
+
echo "[post_start] WARN: AnythingLLM /api/system/update-env returned HTTP $UPDATE_HTTP — looks like a password is set; configure LLM in the UI then restart"
|
|
207
|
+
;;
|
|
208
|
+
*)
|
|
209
|
+
echo "[post_start] WARN: update-env HTTP $UPDATE_HTTP — leaving LLM unconfigured"
|
|
210
|
+
[ -s /tmp/anyllm-upd.txt ] && head -c 400 /tmp/anyllm-upd.txt
|
|
211
|
+
;;
|
|
212
|
+
esac
|
|
213
|
+
else
|
|
214
|
+
REASON=$(printf '%s' "$DP_JSON" | jget reason)
|
|
215
|
+
echo "[post_start] skip LLM auto-config (reason=${REASON:-unknown}); user will pick in UI"
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
# 复用已存在的 dev API key(generate-api-key 增量、不可撤销,
|
|
219
|
+
# 每次重启重生只会堆 key;credentials.json 保稳定)。
|
|
220
|
+
if [ -f "$CRED_FILE" ]; then
|
|
221
|
+
KEY_JSON=$(CRED_FILE="$CRED_FILE" node -e 'try{const j=JSON.parse(require("fs").readFileSync(process.env.CRED_FILE,"utf-8"));process.stdout.write(String(j.apiKey||""))}catch{process.stdout.write("")}')
|
|
222
|
+
else
|
|
223
|
+
KEY_JSON=""
|
|
224
|
+
fi
|
|
225
|
+
if [ -n "$KEY_JSON" ]; then
|
|
226
|
+
echo "[post_start] reusing existing dev API key from $CRED_FILE"
|
|
227
|
+
else
|
|
228
|
+
echo "[post_start] generating new dev API key ..."
|
|
229
|
+
# Same 401 tolerance as update-env: if the user enabled password
|
|
230
|
+
# protection, generate-api-key needs a JWT. Surface the next step
|
|
231
|
+
# and exit cleanly so OpenClaw adapters fall back to "knowledge
|
|
232
|
+
# unconfigured" instead of leaving post_start in a permanent error.
|
|
233
|
+
GEN_HTTP=$(curl -s -o /tmp/anyllm-gen.json -w '%{http_code}' --max-time 8 \
|
|
234
|
+
-X POST "$BASE_URL/api/system/generate-api-key" || echo 000)
|
|
235
|
+
case "$GEN_HTTP" in
|
|
236
|
+
2*)
|
|
237
|
+
KEY_JSON=$(jget apiKey.secret < /tmp/anyllm-gen.json)
|
|
238
|
+
if [ -z "$KEY_JSON" ]; then
|
|
239
|
+
echo "[post_start] WARN: generate-api-key returned 2xx but apiKey.secret missing — skipping kb wiring"
|
|
240
|
+
head -c 400 /tmp/anyllm-gen.json; echo
|
|
241
|
+
fi
|
|
242
|
+
;;
|
|
243
|
+
401|403)
|
|
244
|
+
echo "[post_start] WARN: generate-api-key HTTP $GEN_HTTP — AnythingLLM is password-protected. Generate a dev API key in the UI (Settings → API Keys) and write it to $CRED_FILE, then restart. Skipping kb wiring for this start."
|
|
245
|
+
;;
|
|
246
|
+
*)
|
|
247
|
+
echo "[post_start] WARN: generate-api-key HTTP $GEN_HTTP — skipping kb wiring"
|
|
248
|
+
[ -s /tmp/anyllm-gen.json ] && head -c 400 /tmp/anyllm-gen.json
|
|
249
|
+
;;
|
|
250
|
+
esac
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
if [ -z "$KEY_JSON" ]; then
|
|
254
|
+
echo "[post_start] no API key available; skipping workspace seed + credentials write (post_start still considered success)"
|
|
255
|
+
echo "[post_start] DONE"
|
|
256
|
+
exit 0
|
|
257
|
+
fi
|
|
258
|
+
|
|
259
|
+
echo "[post_start] ensuring default workspace ..."
|
|
260
|
+
WS_HTTP=$(curl -s -o /tmp/anyllm-ws.json -w '%{http_code}' --max-time 10 \
|
|
261
|
+
-X POST "$BASE_URL/api/v1/workspace/new" \
|
|
262
|
+
-H "Authorization: Bearer $KEY_JSON" \
|
|
263
|
+
-H "Content-Type: application/json" \
|
|
264
|
+
-d '{"name":"default"}')
|
|
265
|
+
echo "[post_start] workspace POST → HTTP $WS_HTTP"
|
|
266
|
+
case "$WS_HTTP" in
|
|
267
|
+
2*) : ;;
|
|
268
|
+
4*) echo " (likely already exists; ignoring)" ;;
|
|
269
|
+
*) echo "[post_start] FAIL: workspace creation HTTP $WS_HTTP"; cat /tmp/anyllm-ws.json; exit 1 ;;
|
|
270
|
+
esac
|
|
271
|
+
|
|
272
|
+
# 写 credentials.json — 用 node 避免 shell quote 注入风险。
|
|
273
|
+
APIKEY="$KEY_JSON" BASEURL="$BASE_URL" CREDFILE="$CRED_FILE" node -e '
|
|
274
|
+
const fs = require("fs");
|
|
275
|
+
fs.writeFileSync(process.env.CREDFILE, JSON.stringify({
|
|
276
|
+
apiKey: process.env.APIKEY,
|
|
277
|
+
workspace: "default",
|
|
278
|
+
baseUrl: process.env.BASEURL,
|
|
279
|
+
}, null, 2));
|
|
280
|
+
fs.chmodSync(process.env.CREDFILE, 0o600);
|
|
281
|
+
'
|
|
282
|
+
echo "[post_start] credentials.json written → $CRED_FILE"
|
|
283
|
+
echo "[post_start] DONE"
|
|
284
|
+
timeout_ms: 300000
|
|
285
|
+
|
|
286
|
+
uninstall:
|
|
287
|
+
- deleteImage: "mintplexlabs/anythingllm:latest"
|
|
@@ -10,6 +10,11 @@ tasks:
|
|
|
10
10
|
- name: browserless
|
|
11
11
|
role: service
|
|
12
12
|
runtime: container
|
|
13
|
+
# rebrowser 镜像在 Chromium 源码层面 patch 了 CDP Runtime.Enable 泄露问题,
|
|
14
|
+
# 是目前对抗自动化检测最彻底的方案(适用于小红书/淘宝等强风控场景)。
|
|
15
|
+
# 如遇 ghcr.io/browserless/chromium 仍被风控,可切换为:
|
|
16
|
+
# image: "ghcr.io/browserless/chromium:rebrowser"
|
|
17
|
+
# (rebrowser 分支由 browserless 官方维护,与 latest 保持同步)
|
|
13
18
|
image: "ghcr.io/browserless/chromium:latest"
|
|
14
19
|
env:
|
|
15
20
|
HOST: "0.0.0.0"
|
|
@@ -18,13 +23,19 @@ tasks:
|
|
|
18
23
|
CONCURRENT: "5"
|
|
19
24
|
QUEUED: "10"
|
|
20
25
|
TIMEOUT: "120000"
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
# 反风控配置
|
|
27
|
+
# STEALTH=true: 启用 puppeteer-extra-plugin-stealth,注入多项 evasion 补丁:
|
|
28
|
+
# 修复 navigator.plugins/languages、WebGL vendor、canvas 指纹、chrome 对象等
|
|
29
|
+
STEALTH: "true"
|
|
30
|
+
# UA 不指定版本号,由 Chromium 自行上报实际版本,避免版本不一致被检测
|
|
31
|
+
DEFAULT_USER_AGENT: ""
|
|
32
|
+
FUNCTION_ENABLE_INCOGNITO: "false"
|
|
24
33
|
NAVIGATION_TIMEOUT: "30000"
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
# --disable-blink-features=AutomationControlled: 隐藏 navigator.webdriver
|
|
35
|
+
# headed 模式(不加 --headless):小红书/百度会检测 headless 特征,
|
|
36
|
+
# browserless 容器内置 Xvfb,直接使用 headed 模式即可
|
|
37
|
+
DEFAULT_LAUNCH_ARGS: "--disable-blink-features=AutomationControlled --disable-infobars --window-size=1920,1080 --start-maximized --no-first-run --no-default-browser-check"
|
|
38
|
+
DEFAULT_HEADLESS: "false"
|
|
28
39
|
# 持久化用户数据(cookies/localStorage/session),登录后会话保持
|
|
29
40
|
DATA_DIR: "/tmp/browserless-data"
|
|
30
41
|
volumes:
|
|
@@ -53,6 +64,7 @@ provides:
|
|
|
53
64
|
protocol: "http"
|
|
54
65
|
description: "Browserless Debug Viewer,可在实例页中嵌入浏览器画面"
|
|
55
66
|
- capability: "browserless-api"
|
|
67
|
+
task: "browserless"
|
|
56
68
|
port: 3000
|
|
57
69
|
path: "/"
|
|
58
70
|
protocol: "http"
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
id: filebrowser-container
|
|
2
|
+
name: File Browser
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
jishushell:
|
|
5
|
+
min_version: "0.5.15"
|
|
6
|
+
description: "通过浏览器管理本地文件的 Web UI"
|
|
7
|
+
singleInstance: true
|
|
8
|
+
|
|
9
|
+
tasks:
|
|
10
|
+
- name: filebrowser
|
|
11
|
+
role: service
|
|
12
|
+
runtime: container
|
|
13
|
+
image: "filebrowser/filebrowser:latest"
|
|
14
|
+
# Run as the panel user's uid:gid so files written via Filebrowser are
|
|
15
|
+
# owned by the same user that owns ~/.jishushell/files and the drive_*
|
|
16
|
+
# HTTP path. Mirrors openwebui's "user: host". Avoids the PUID/PGID
|
|
17
|
+
# entrypoint dance from the :s6 variant — uid/gid is set once at job
|
|
18
|
+
# build time.
|
|
19
|
+
user: "host"
|
|
20
|
+
args:
|
|
21
|
+
# Filebrowser CLI flag precedence is Flags > Env > Config file > DB.
|
|
22
|
+
# The image's init.sh seeds /config/settings.json from baked-in
|
|
23
|
+
# defaults (baseURL=""), which would otherwise mask the DB value —
|
|
24
|
+
# so we re-assert baseURL/root/etc here at runtime. auth.method is
|
|
25
|
+
# not exposed as a runtime flag and lives in the DB only (seeded
|
|
26
|
+
# during lifecycle/install below).
|
|
27
|
+
- "--root=/srv"
|
|
28
|
+
- "--database=/database/filebrowser.db"
|
|
29
|
+
- "--address=0.0.0.0"
|
|
30
|
+
- "--port=8080"
|
|
31
|
+
- "--baseURL=/apps/filebrowser"
|
|
32
|
+
resources:
|
|
33
|
+
cpu: "200m"
|
|
34
|
+
memory: "128Mi"
|
|
35
|
+
ports:
|
|
36
|
+
- name: http
|
|
37
|
+
# Host port 18088 is in the panel-managed 18xxx range (OpenClaw
|
|
38
|
+
# gateway uses 18790). Picked outside common defaults so it
|
|
39
|
+
# never collides with SearXNG (8080), OpenWebUI (3000), or the
|
|
40
|
+
# panel itself (8090). Container internal port stays at 8080
|
|
41
|
+
# — Filebrowser's natural default and what `--port=8080` in
|
|
42
|
+
# args wires it to.
|
|
43
|
+
port: 18088
|
|
44
|
+
container_port: 8080
|
|
45
|
+
visibility: external
|
|
46
|
+
volumes:
|
|
47
|
+
# The user's file tree — POSIX source of truth, shared with the panel
|
|
48
|
+
# drive_* substrate (src/services/files-manager.ts) and the drive-shim
|
|
49
|
+
# MCP path. Both sides operate on the same inodes.
|
|
50
|
+
- source: "~/.jishushell/files"
|
|
51
|
+
target: "/srv"
|
|
52
|
+
# SQLite settings DB + the auto-seeded admin user record.
|
|
53
|
+
- source: "~/.jishushell/apps/${app_id}/database"
|
|
54
|
+
target: "/database"
|
|
55
|
+
# Filebrowser image's init.sh writes /config/settings.json from defaults
|
|
56
|
+
# on first run; bind-mounting an app-owned dir lets us persist any
|
|
57
|
+
# branding tweaks without baking them into the image.
|
|
58
|
+
- source: "~/.jishushell/apps/${app_id}/config"
|
|
59
|
+
target: "/config"
|
|
60
|
+
health:
|
|
61
|
+
http:
|
|
62
|
+
# `--baseURL=/apps/filebrowser` is set in the DB by lifecycle/install
|
|
63
|
+
# below; the SPA serves from that prefix. Root / redirects 302 →
|
|
64
|
+
# /apps/filebrowser/ which answers HEAD with 200.
|
|
65
|
+
path: /apps/filebrowser/
|
|
66
|
+
port: 8080
|
|
67
|
+
interval: "15s"
|
|
68
|
+
timeout: "5s"
|
|
69
|
+
retries: 6
|
|
70
|
+
start_period: "20s"
|
|
71
|
+
|
|
72
|
+
provides:
|
|
73
|
+
# Canonical capability used by the panel's reverse-proxy resolver to mount
|
|
74
|
+
# Filebrowser at /apps/filebrowser/*. No `auth:` block — Filebrowser
|
|
75
|
+
# itself runs in noauth mode and authentication is enforced one layer
|
|
76
|
+
# higher, in src/server.ts middleware, via the panel JWT cookie.
|
|
77
|
+
- capability: "filebrowser-ui"
|
|
78
|
+
task: "filebrowser"
|
|
79
|
+
port: 18088
|
|
80
|
+
path: "/"
|
|
81
|
+
protocol: "http"
|
|
82
|
+
visibility: "external"
|
|
83
|
+
description: "Filebrowser Web UI;panel 反代到 /apps/filebrowser/*"
|
|
84
|
+
# Web-* convention (matches web-openwebui / web-searxng) so adapters that
|
|
85
|
+
# iterate "web-*" capabilities pick it up for dashboard tiles.
|
|
86
|
+
- capability: "web-filebrowser"
|
|
87
|
+
task: "filebrowser"
|
|
88
|
+
port: 18088
|
|
89
|
+
path: "/"
|
|
90
|
+
protocol: "http"
|
|
91
|
+
visibility: "external"
|
|
92
|
+
description: "Filebrowser Web UI(web-* convention 别名)"
|
|
93
|
+
# files-* convention: satisfies `requires: files` on consumer specs (OpenClaw
|
|
94
|
+
# etc.). The `files` category is UI-only — binding injects FILES_BROWSER_URL
|
|
95
|
+
# into the agent env so it can surface /apps/filebrowser/ to users in chat.
|
|
96
|
+
# Does NOT gate any API calls; Filebrowser itself runs noauth and is guarded
|
|
97
|
+
# by the panel JWT reverse-proxy layer.
|
|
98
|
+
- capability: "files-filebrowser"
|
|
99
|
+
task: "filebrowser"
|
|
100
|
+
port: 18088
|
|
101
|
+
path: "/apps/filebrowser"
|
|
102
|
+
protocol: "http"
|
|
103
|
+
visibility: "external"
|
|
104
|
+
description: "Filebrowser 文件管理 UI;满足 agent requires:files 绑定"
|
|
105
|
+
|
|
106
|
+
lifecycle:
|
|
107
|
+
install:
|
|
108
|
+
- downloadImage: "filebrowser/filebrowser:latest"
|
|
109
|
+
- mkdir: "~/.jishushell/apps/${app_id}/database"
|
|
110
|
+
- mkdir: "~/.jishushell/apps/${app_id}/config"
|
|
111
|
+
# Seed the SQLite DB with three things Filebrowser needs in noauth mode:
|
|
112
|
+
# 1. `config init --auth.method=noauth` — creates DB with noauth scheme
|
|
113
|
+
# 2. `config set --baseURL=/apps/filebrowser` — bakes the sub-path so the
|
|
114
|
+
# Vue SPA hash router resolves assets under the panel reverse proxy
|
|
115
|
+
# 3. `users add admin <random-pw> --perm.admin` — Filebrowser's noauth
|
|
116
|
+
# mode still requires a user record; POST /api/login mints a token
|
|
117
|
+
# for this user without checking the password. The password is
|
|
118
|
+
# throwaway (placeholder for the ≥12-char rule) and never used at
|
|
119
|
+
# runtime since the panel JWT layer guards the reverse proxy.
|
|
120
|
+
# Idempotent: skipped when DB already exists. Mirrors searxng's heredoc
|
|
121
|
+
# settings.yml generation pattern.
|
|
122
|
+
- run: |
|
|
123
|
+
DB_DIR="$HOME/.jishushell/apps/${app_id}/database"
|
|
124
|
+
CONFIG_DIR="$HOME/.jishushell/apps/${app_id}/config"
|
|
125
|
+
DB_FILE="$DB_DIR/filebrowser.db"
|
|
126
|
+
if [ ! -f "$DB_FILE" ]; then
|
|
127
|
+
docker run --rm \
|
|
128
|
+
--user "$(id -u):$(id -g)" \
|
|
129
|
+
-v "$DB_DIR:/database" \
|
|
130
|
+
-v "$CONFIG_DIR:/config" \
|
|
131
|
+
filebrowser/filebrowser:latest \
|
|
132
|
+
config init \
|
|
133
|
+
--database=/database/filebrowser.db \
|
|
134
|
+
--auth.method=noauth >/dev/null
|
|
135
|
+
docker run --rm \
|
|
136
|
+
--user "$(id -u):$(id -g)" \
|
|
137
|
+
-v "$DB_DIR:/database" \
|
|
138
|
+
-v "$CONFIG_DIR:/config" \
|
|
139
|
+
filebrowser/filebrowser:latest \
|
|
140
|
+
config set \
|
|
141
|
+
--database=/database/filebrowser.db \
|
|
142
|
+
--auth.method=noauth \
|
|
143
|
+
--baseURL=/apps/filebrowser \
|
|
144
|
+
--address=0.0.0.0 \
|
|
145
|
+
--port=8080 >/dev/null
|
|
146
|
+
# Password is throwaway: noauth mode never checks it, but Filebrowser
|
|
147
|
+
# enforces a 12-char minimum at create time. Generate a 32-char random
|
|
148
|
+
# to satisfy the rule without leaving a guessable trail.
|
|
149
|
+
PLACEHOLDER_PW="$(head -c 48 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 32)"
|
|
150
|
+
docker run --rm \
|
|
151
|
+
--user "$(id -u):$(id -g)" \
|
|
152
|
+
-v "$DB_DIR:/database" \
|
|
153
|
+
-v "$CONFIG_DIR:/config" \
|
|
154
|
+
filebrowser/filebrowser:latest \
|
|
155
|
+
users add admin "$PLACEHOLDER_PW" \
|
|
156
|
+
--database=/database/filebrowser.db \
|
|
157
|
+
--perm.admin >/dev/null
|
|
158
|
+
fi
|
|
159
|
+
pre_start:
|
|
160
|
+
- mkdir: "~/.jishushell/apps/${app_id}/database"
|
|
161
|
+
- mkdir: "~/.jishushell/apps/${app_id}/config"
|
|
162
|
+
uninstall:
|
|
163
|
+
- deleteImage: "filebrowser/filebrowser:latest"
|
|
@@ -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)"
|