jishushell 0.4.24 → 0.4.30
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/INSTALL-NOTICE +11 -0
- package/apps/browserless-chromium-container.yaml +78 -0
- package/apps/hermes-container.yaml +36 -2
- package/apps/ollama-binary.yaml +91 -90
- package/apps/ollama-cpu-container.yaml +8 -1
- package/apps/ollama-with-hollama-binary.yaml +91 -90
- package/apps/openclaw-binary.yaml +30 -1
- package/apps/openclaw-container.yaml +37 -2
- package/apps/openclaw-with-ollama-container.yaml +11 -2
- package/apps/openclaw-with-searxng-container.yaml +22 -2
- package/apps/openwebui-container.yaml +45 -1
- package/apps/playwright-container.yaml +7 -1
- package/apps/searxng-container.yaml +54 -4
- package/dist/cli/app.js +79 -9
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/doctor.d.ts +12 -12
- package/dist/cli/doctor.js +242 -55
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/llm.d.ts +4 -3
- package/dist/cli/llm.js +4 -3
- package/dist/cli/llm.js.map +1 -1
- package/dist/cli/panel.d.ts +6 -5
- package/dist/cli/panel.js +10 -9
- package/dist/cli/panel.js.map +1 -1
- package/dist/control.d.ts +7 -6
- package/dist/control.js +7 -6
- package/dist/control.js.map +1 -1
- package/dist/routes/agent-apps.d.ts +1 -1
- package/dist/routes/agent-apps.js +1 -1
- package/dist/routes/apps.js +44 -11
- package/dist/routes/apps.js.map +1 -1
- package/dist/routes/auth.js +3 -0
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/instances.js +787 -16
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/llm.js +24 -35
- package/dist/routes/llm.js.map +1 -1
- package/dist/routes/setup.js +1 -1
- package/dist/routes/setup.js.map +1 -1
- package/dist/server.d.ts +9 -0
- package/dist/server.js +410 -17
- package/dist/server.js.map +1 -1
- package/dist/services/agent-apps/catalog.js +4 -3
- package/dist/services/agent-apps/catalog.js.map +1 -1
- package/dist/services/agent-apps/index.d.ts +1 -1
- package/dist/services/agent-apps/index.js +1 -1
- package/dist/services/agent-apps/installers/adapter.d.ts +1 -1
- package/dist/services/agent-apps/installers/adapter.js +1 -1
- package/dist/services/agent-apps/installers/shell-script.d.ts +1 -1
- package/dist/services/agent-apps/installers/shell-script.js +3 -3
- package/dist/services/agent-apps/installers/shell-script.js.map +1 -1
- package/dist/services/agent-apps/types.d.ts +2 -2
- package/dist/services/agent-apps/types.js +1 -1
- package/dist/services/app/app-manager.d.ts +24 -1
- package/dist/services/app/app-manager.js +664 -116
- package/dist/services/app/app-manager.js.map +1 -1
- package/dist/services/app/hermes-agent-manager.js +6 -4
- package/dist/services/app/hermes-agent-manager.js.map +1 -1
- package/dist/services/app/provide-resolver.d.ts +29 -0
- package/dist/services/app/provide-resolver.js +112 -0
- package/dist/services/app/provide-resolver.js.map +1 -0
- package/dist/services/capability-endpoint-validator.d.ts +41 -0
- package/dist/services/capability-endpoint-validator.js +104 -0
- package/dist/services/capability-endpoint-validator.js.map +1 -0
- package/dist/services/capability-health.d.ts +16 -0
- package/dist/services/capability-health.js +121 -0
- package/dist/services/capability-health.js.map +1 -0
- package/dist/services/capability-registry.d.ts +106 -0
- package/dist/services/capability-registry.js +313 -0
- package/dist/services/capability-registry.js.map +1 -0
- package/dist/services/connection-apply.d.ts +89 -0
- package/dist/services/connection-apply.js +421 -0
- package/dist/services/connection-apply.js.map +1 -0
- package/dist/services/connection-resolver.d.ts +65 -0
- package/dist/services/connection-resolver.js +281 -0
- package/dist/services/connection-resolver.js.map +1 -0
- package/dist/services/connection-transactor.d.ts +37 -0
- package/dist/services/connection-transactor.js +341 -0
- package/dist/services/connection-transactor.js.map +1 -0
- package/dist/services/instance-manager.d.ts +13 -0
- package/dist/services/instance-manager.js +137 -23
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/llm-proxy/index.d.ts +16 -2
- package/dist/services/llm-proxy/index.js +48 -44
- package/dist/services/llm-proxy/index.js.map +1 -1
- package/dist/services/llm-proxy/probe.d.ts +6 -0
- package/dist/services/llm-proxy/probe.js +85 -0
- package/dist/services/llm-proxy/probe.js.map +1 -0
- package/dist/services/llm-proxy/ssrf.d.ts +1 -0
- package/dist/services/llm-proxy/ssrf.js +18 -7
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/nomad-manager.js +375 -16
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/process-manager.js +1 -1
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/runtime/adapters/hermes.d.ts +30 -1
- package/dist/services/runtime/adapters/hermes.js +218 -5
- package/dist/services/runtime/adapters/hermes.js.map +1 -1
- package/dist/services/runtime/adapters/openclaw-mcporter.d.ts +45 -0
- package/dist/services/runtime/adapters/openclaw-mcporter.js +108 -0
- package/dist/services/runtime/adapters/openclaw-mcporter.js.map +1 -0
- package/dist/services/runtime/adapters/openclaw.d.ts +87 -0
- package/dist/services/runtime/adapters/openclaw.js +250 -2
- package/dist/services/runtime/adapters/openclaw.js.map +1 -1
- package/dist/services/runtime/mcp-shims/firewall.d.ts +26 -0
- package/dist/services/runtime/mcp-shims/firewall.js +129 -0
- package/dist/services/runtime/mcp-shims/firewall.js.map +1 -0
- package/dist/services/runtime/mcp-shims/searxng-shim.d.ts +27 -0
- package/dist/services/runtime/mcp-shims/searxng-shim.js +125 -0
- package/dist/services/runtime/mcp-shims/searxng-shim.js.map +1 -0
- package/dist/services/runtime/mcp-shims/write-mcp-entry.d.ts +83 -0
- package/dist/services/runtime/mcp-shims/write-mcp-entry.js +127 -0
- package/dist/services/runtime/mcp-shims/write-mcp-entry.js.map +1 -0
- package/dist/services/runtime/migrations.d.ts +8 -0
- package/dist/services/runtime/migrations.js +100 -0
- package/dist/services/runtime/migrations.js.map +1 -1
- package/dist/services/runtime/types.d.ts +15 -0
- package/dist/services/setup-manager.js +6 -6
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/suggestions.d.ts +27 -0
- package/dist/services/suggestions.js +133 -0
- package/dist/services/suggestions.js.map +1 -0
- package/dist/services/task-registry.js +4 -2
- package/dist/services/task-registry.js.map +1 -1
- package/dist/services/telemetry/device-fingerprint.d.ts +1 -1
- package/dist/services/telemetry/device-fingerprint.js +1 -1
- package/dist/services/types-shim.d.ts +16 -0
- package/dist/services/types-shim.js +2 -0
- package/dist/services/types-shim.js.map +1 -0
- package/dist/types.d.ts +171 -1
- package/dist/utils/instance-lock.d.ts +22 -0
- package/dist/utils/instance-lock.js +48 -0
- package/dist/utils/instance-lock.js.map +1 -0
- package/dist/utils/safe-json.js +55 -22
- package/dist/utils/safe-json.js.map +1 -1
- package/install/jishu-install.sh +323 -27
- package/install/jishu-uninstall.sh +353 -20
- package/package.json +3 -1
- package/public/assets/Dashboard-rkWp-CXd.js +1 -0
- package/public/assets/{HermesChatPanel-mFSureyc.js → HermesChatPanel-_GHoklgo.js} +1 -1
- package/public/assets/HermesConfigForm-anDnwUp_.js +4 -0
- package/public/assets/{InitPassword-CVA8wQA6.js → InitPassword-ZU9_-hDr.js} +1 -1
- package/public/assets/InstanceDetail-CN0FH1aw.js +92 -0
- package/public/assets/{Login-BWsZH2mu.js → Login-BItXqYAJ.js} +1 -1
- package/public/assets/NewInstance-BousE6kY.js +1 -0
- package/public/assets/ProviderRecommendations-DFYj7Fb6.js +1 -0
- package/public/assets/Settings-Bttc6QmM.js +1 -0
- package/public/assets/Setup-Bsxx1zgj.js +1 -0
- package/public/assets/{WeixinLoginPanel-CnjR8xMu.js → WeixinLoginPanel-DPZpAKgO.js} +2 -2
- package/public/assets/index-8xZy1z5k.css +1 -0
- package/public/assets/index-Dw3HhUYE.js +19 -0
- package/public/assets/providers-DtNXh9JD.js +1 -0
- package/public/assets/registry-5s2UB6is.js +2 -0
- package/public/index.html +2 -2
- package/scripts/check-app-spec.mjs +443 -0
- package/scripts/check-i18n.mjs +154 -0
- package/scripts/run.sh +4 -4
- package/public/assets/Dashboard-B-JoOjBQ.js +0 -1
- package/public/assets/HermesConfigForm-DvR05LK1.js +0 -4
- package/public/assets/InstanceDetail-DcZW2QGO.js +0 -91
- package/public/assets/NewInstance-BCIrAd86.js +0 -1
- package/public/assets/Settings-xkDcduFz.js +0 -1
- package/public/assets/Setup-Cfuwj4gV.js +0 -1
- package/public/assets/index-CPhVFEsx.css +0 -1
- package/public/assets/index-DQsM6Joa.js +0 -19
- package/public/assets/providers-V-vwrExZ.js +0 -1
- package/public/assets/registry-B4UFJdpA.js +0 -2
|
@@ -2,7 +2,7 @@ id: openclaw-binary
|
|
|
2
2
|
name: OpenClaw Binary
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
agentType: openclaw
|
|
7
7
|
description: "将 OpenClaw 安装到应用目录内的 npm prefix,并以 process runtime 运行网关"
|
|
8
8
|
singleInstance: false
|
|
@@ -33,8 +33,37 @@ tasks:
|
|
|
33
33
|
|
|
34
34
|
provides:
|
|
35
35
|
- capability: "openclaw-dashboard"
|
|
36
|
+
task: "gateway"
|
|
36
37
|
port: 18789
|
|
38
|
+
protocol: "http"
|
|
37
39
|
description: "OpenClaw Dashboard"
|
|
40
|
+
- capability: "llm-agent"
|
|
41
|
+
task: "gateway"
|
|
42
|
+
port: 18789
|
|
43
|
+
protocol: "http"
|
|
44
|
+
path: "/v1"
|
|
45
|
+
description: "OpenAI-compatible agent endpoint backed by OpenClaw"
|
|
46
|
+
auth:
|
|
47
|
+
kind: "bearer"
|
|
48
|
+
tokenSource: "instance.config.gateway.auth.token"
|
|
49
|
+
|
|
50
|
+
requires:
|
|
51
|
+
- capability: "llm"
|
|
52
|
+
inject_as: "LLM_ENDPOINT"
|
|
53
|
+
required: false
|
|
54
|
+
cardinality: "one"
|
|
55
|
+
- capability: "search"
|
|
56
|
+
inject_as: "SEARCH_API_BASE_URL"
|
|
57
|
+
required: false
|
|
58
|
+
cardinality: "one"
|
|
59
|
+
- capability: "browser"
|
|
60
|
+
inject_as: "BROWSER_CDP_URL"
|
|
61
|
+
required: false
|
|
62
|
+
cardinality: "one"
|
|
63
|
+
- capability: "mcp"
|
|
64
|
+
inject_as: "MCP_SERVERS"
|
|
65
|
+
required: false
|
|
66
|
+
cardinality: "many"
|
|
38
67
|
|
|
39
68
|
lifecycle:
|
|
40
69
|
install:
|
|
@@ -2,7 +2,7 @@ id: openclaw-container
|
|
|
2
2
|
name: OpenClaw Container
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
agentType: openclaw
|
|
7
7
|
description: "基于 openclaw-runtime 容器运行的 OpenClaw 网关"
|
|
8
8
|
singleInstance: false
|
|
@@ -33,5 +33,40 @@ tasks:
|
|
|
33
33
|
|
|
34
34
|
provides:
|
|
35
35
|
- capability: "openclaw-dashboard"
|
|
36
|
+
task: "gateway"
|
|
36
37
|
port: 18789
|
|
37
|
-
|
|
38
|
+
protocol: "http"
|
|
39
|
+
description: "OpenClaw Dashboard"
|
|
40
|
+
# OpenClaw exposes OpenAI-compatible chat/completions when its config has
|
|
41
|
+
# `gateway.http.endpoints.chatCompletions.enabled = true`. The runtime
|
|
42
|
+
# adapter's startInstance hook patches openclaw.json on every start to
|
|
43
|
+
# ensure that flag is on, so any consumer binding this provider gets a
|
|
44
|
+
# working /v1/chat/completions endpoint regardless of when the instance
|
|
45
|
+
# was originally created. Auth uses the gateway token from openclaw.json.
|
|
46
|
+
- capability: "llm-agent"
|
|
47
|
+
task: "gateway"
|
|
48
|
+
port: 18789
|
|
49
|
+
protocol: "http"
|
|
50
|
+
path: "/v1"
|
|
51
|
+
description: "OpenAI-compatible agent endpoint backed by OpenClaw"
|
|
52
|
+
auth:
|
|
53
|
+
kind: "bearer"
|
|
54
|
+
tokenSource: "instance.config.gateway.auth.token"
|
|
55
|
+
|
|
56
|
+
requires:
|
|
57
|
+
- capability: "llm"
|
|
58
|
+
inject_as: "LLM_ENDPOINT"
|
|
59
|
+
required: false
|
|
60
|
+
cardinality: "one"
|
|
61
|
+
- capability: "search"
|
|
62
|
+
inject_as: "SEARCH_API_BASE_URL"
|
|
63
|
+
required: false
|
|
64
|
+
cardinality: "one"
|
|
65
|
+
- capability: "browser"
|
|
66
|
+
inject_as: "BROWSER_CDP_URL"
|
|
67
|
+
required: false
|
|
68
|
+
cardinality: "one"
|
|
69
|
+
- capability: "mcp"
|
|
70
|
+
inject_as: "MCP_SERVERS"
|
|
71
|
+
required: false
|
|
72
|
+
cardinality: "many"
|
|
@@ -2,7 +2,7 @@ id: openclaw-with-ollama-container
|
|
|
2
2
|
name: OpenClaw With Ollama
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
agentType: openclaw
|
|
7
7
|
description: "通过 requires 消费 ollama-api 能力,并将解析地址注入 OpenClaw 运行环境"
|
|
8
8
|
singleInstance: false
|
|
@@ -39,4 +39,13 @@ tasks:
|
|
|
39
39
|
provides:
|
|
40
40
|
- capability: "openclaw-dashboard"
|
|
41
41
|
port: 18789
|
|
42
|
-
description: "OpenClaw Dashboard"
|
|
42
|
+
description: "OpenClaw Dashboard"
|
|
43
|
+
- capability: "llm-agent"
|
|
44
|
+
task: "gateway"
|
|
45
|
+
port: 18789
|
|
46
|
+
protocol: "http"
|
|
47
|
+
path: "/v1"
|
|
48
|
+
description: "OpenAI-compatible agent endpoint backed by OpenClaw"
|
|
49
|
+
auth:
|
|
50
|
+
kind: "bearer"
|
|
51
|
+
tokenSource: "instance.config.gateway.auth.token"
|
|
@@ -2,7 +2,7 @@ id: openclaw-with-searxng-container
|
|
|
2
2
|
name: OpenClaw With SearXNG Container
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
agentType: openclaw
|
|
7
7
|
description: "将 SearXNG 作为 sidecar 子 task 安装并运行,并注入 OpenClaw 搜索环境"
|
|
8
8
|
singleInstance: false
|
|
@@ -46,7 +46,11 @@ tasks:
|
|
|
46
46
|
args: ["gateway", "run", "--port", "18789", "--allow-unconfigured"]
|
|
47
47
|
env:
|
|
48
48
|
NODE_ENV: production
|
|
49
|
-
SEARCH_API_BASE_URL
|
|
49
|
+
# SEARCH_API_BASE_URL injected by Connection apply hook (search category, §13).
|
|
50
|
+
# Single-candidate fallback (`requires: search-searxng`) auto-binds the
|
|
51
|
+
# sidecar SearXNG below on first start, so meta-app UX stays "open the
|
|
52
|
+
# box and it works".
|
|
53
|
+
SEARCH_API_BASE_URL: "${requires.SEARCH_API_BASE_URL}"
|
|
50
54
|
resources:
|
|
51
55
|
cpu: "1000m"
|
|
52
56
|
memory: "1024Mi"
|
|
@@ -65,8 +69,24 @@ tasks:
|
|
|
65
69
|
|
|
66
70
|
provides:
|
|
67
71
|
- capability: "openclaw-dashboard"
|
|
72
|
+
task: "gateway"
|
|
68
73
|
port: 18789
|
|
74
|
+
protocol: "http"
|
|
69
75
|
description: "OpenClaw Dashboard"
|
|
76
|
+
- capability: "llm-agent"
|
|
77
|
+
task: "gateway"
|
|
78
|
+
port: 18789
|
|
79
|
+
protocol: "http"
|
|
80
|
+
path: "/v1"
|
|
81
|
+
description: "OpenAI-compatible agent endpoint backed by OpenClaw"
|
|
82
|
+
auth:
|
|
83
|
+
kind: "bearer"
|
|
84
|
+
tokenSource: "instance.config.gateway.auth.token"
|
|
85
|
+
|
|
86
|
+
requires:
|
|
87
|
+
- capability: "search-searxng"
|
|
88
|
+
inject_as: "SEARCH_API_BASE_URL"
|
|
89
|
+
required: false
|
|
70
90
|
|
|
71
91
|
lifecycle:
|
|
72
92
|
install:
|
|
@@ -2,7 +2,7 @@ id: openwebui-container
|
|
|
2
2
|
name: Open WebUI
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
description: "使用 Open WebUI 提供自托管的大模型 Web 界面,容器模式由 Nomad 管理生命周期"
|
|
7
7
|
singleInstance: false
|
|
8
8
|
|
|
@@ -11,6 +11,11 @@ tasks:
|
|
|
11
11
|
role: service
|
|
12
12
|
runtime: container
|
|
13
13
|
image: "ghcr.io/open-webui/open-webui:main"
|
|
14
|
+
# Run as the panel user's uid:gid (typically pi=1000:1000). Bind-mount
|
|
15
|
+
# source `~/.jishushell/apps/${app_id}/data` is owned by the panel user,
|
|
16
|
+
# so the container can read/write it directly — no chown, no
|
|
17
|
+
# CAP_DAC_OVERRIDE, no DB readonly errors. Mirrors hermes / openclaw.
|
|
18
|
+
user: "host"
|
|
14
19
|
env:
|
|
15
20
|
HOME: "/app/backend/data"
|
|
16
21
|
PORT: "8080"
|
|
@@ -19,6 +24,32 @@ tasks:
|
|
|
19
24
|
HF_HOME: "/app/backend/data/.cache/huggingface"
|
|
20
25
|
TRANSFORMERS_CACHE: "/app/backend/data/.cache/huggingface/transformers"
|
|
21
26
|
SENTENCE_TRANSFORMERS_HOME: "/app/backend/data/.cache/sentence-transformers"
|
|
27
|
+
# OpenWebUI's start.sh writes a generated WEBUI_SECRET_KEY to a key
|
|
28
|
+
# file. The default path is `.webui_secret_key` in the image's
|
|
29
|
+
# /app/backend WORKDIR, which is owned by root and unwritable when
|
|
30
|
+
# running as uid 1000. Redirect to the bind-mounted (and writable)
|
|
31
|
+
# data dir so the key persists across restarts and survives image
|
|
32
|
+
# upgrades.
|
|
33
|
+
WEBUI_SECRET_KEY_FILE: "/app/backend/data/.webui_secret_key"
|
|
34
|
+
# Open WebUI marks OPENAI_API_BASE_URL / OPENAI_API_KEY as PersistentConfig:
|
|
35
|
+
# without this flag, the first start writes them to the internal DB and
|
|
36
|
+
# subsequent restarts ignore env, defeating Connections "Save & Restart"
|
|
37
|
+
# rebinds. Disabling persistent config means the Admin UI's manual
|
|
38
|
+
# OpenAI config doesn't survive restarts — that's the trade-off
|
|
39
|
+
# JishuShell takes to own LLM configuration via Connections (§13.3.2.1).
|
|
40
|
+
ENABLE_PERSISTENT_CONFIG: "False"
|
|
41
|
+
# JishuShell ships Open WebUI as a chat front-end only — RAG /
|
|
42
|
+
# reranker / Whisper STT all need ML model downloads from
|
|
43
|
+
# HuggingFace at first boot (~500 MB – 1.5 GB). On slow outbound
|
|
44
|
+
# networks (Raspberry Pi behind throttled NAT) this blocks
|
|
45
|
+
# health checks for hours. Bypassing them keeps the boot path
|
|
46
|
+
# to "FastAPI up in <30s". Users who want RAG/STT can flip these
|
|
47
|
+
# back from Admin UI and accept the one-time download.
|
|
48
|
+
BYPASS_EMBEDDING_AND_RETRIEVAL: "True"
|
|
49
|
+
RAG_EMBEDDING_MODEL: ""
|
|
50
|
+
RAG_RERANKING_MODEL: ""
|
|
51
|
+
WHISPER_MODEL: ""
|
|
52
|
+
AUDIO_STT_ENGINE: ""
|
|
22
53
|
resources:
|
|
23
54
|
cpu: "1000m"
|
|
24
55
|
memory: "1024Mi"
|
|
@@ -41,10 +72,23 @@ tasks:
|
|
|
41
72
|
|
|
42
73
|
provides:
|
|
43
74
|
- capability: "openwebui-web"
|
|
75
|
+
task: "openwebui"
|
|
76
|
+
port: 3000
|
|
77
|
+
protocol: "http"
|
|
78
|
+
description: "Open WebUI Web 界面(legacy capability,请改用 web-openwebui)"
|
|
79
|
+
- capability: "web-openwebui"
|
|
80
|
+
task: "openwebui"
|
|
44
81
|
port: 3000
|
|
45
82
|
protocol: "http"
|
|
46
83
|
description: "Open WebUI Web 界面"
|
|
47
84
|
|
|
85
|
+
requires:
|
|
86
|
+
- capability: "llm"
|
|
87
|
+
inject_as: "OPENAI_API_BASE_URL"
|
|
88
|
+
apply: "openai-env"
|
|
89
|
+
cardinality: "one"
|
|
90
|
+
required: false
|
|
91
|
+
|
|
48
92
|
lifecycle:
|
|
49
93
|
install:
|
|
50
94
|
- downloadImage: "ghcr.io/open-webui/open-webui:main"
|
|
@@ -2,7 +2,7 @@ id: playwright-container
|
|
|
2
2
|
name: Playwright
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
5
|
+
min_version: "0.4.30"
|
|
6
6
|
description: "在容器中启动 Playwright UI,通过浏览器查看和管理测试运行"
|
|
7
7
|
singleInstance: false
|
|
8
8
|
|
|
@@ -52,9 +52,15 @@ tasks:
|
|
|
52
52
|
|
|
53
53
|
provides:
|
|
54
54
|
- capability: "playwright-ui"
|
|
55
|
+
task: "playwright-ui"
|
|
55
56
|
port: 14567
|
|
56
57
|
protocol: "http"
|
|
57
58
|
description: "Playwright UI Web 界面"
|
|
59
|
+
# browser-playwright (CDP endpoint) is TODO — needs a sidecar task that runs
|
|
60
|
+
# `npx playwright launch-server --browser chromium --hostname 0.0.0.0`,
|
|
61
|
+
# captures the token-bearing ws URL into a file/env, and registers it as a
|
|
62
|
+
# capability with protocol=ws. Until the sidecar lands, OpenClaw / Hermes
|
|
63
|
+
# browser slots cannot bind to this app via the Connections UI.
|
|
58
64
|
|
|
59
65
|
lifecycle:
|
|
60
66
|
install:
|
|
@@ -2,9 +2,9 @@ id: searxng-container
|
|
|
2
2
|
name: SearXNG
|
|
3
3
|
version: "1.0.0"
|
|
4
4
|
jishushell:
|
|
5
|
-
min_version: "0.4.
|
|
6
|
-
description: "
|
|
7
|
-
singleInstance:
|
|
5
|
+
min_version: "0.4.30"
|
|
6
|
+
description: "隐私优先的元搜索引擎"
|
|
7
|
+
singleInstance: true
|
|
8
8
|
|
|
9
9
|
tasks:
|
|
10
10
|
- name: searxng
|
|
@@ -40,12 +40,62 @@ tasks:
|
|
|
40
40
|
|
|
41
41
|
provides:
|
|
42
42
|
- capability: "web-ui"
|
|
43
|
+
task: "searxng"
|
|
43
44
|
port: 8080
|
|
45
|
+
protocol: "http"
|
|
46
|
+
description: "SearXNG Web UI(legacy capability,请改用 web-searxng)"
|
|
47
|
+
- capability: "web-searxng"
|
|
48
|
+
task: "searxng"
|
|
49
|
+
port: 8080
|
|
50
|
+
protocol: "http"
|
|
44
51
|
description: "SearXNG Web UI"
|
|
45
|
-
- capability: "search-
|
|
52
|
+
- capability: "search-searxng"
|
|
53
|
+
task: "searxng"
|
|
46
54
|
port: 8080
|
|
47
55
|
path: "/search"
|
|
56
|
+
protocol: "http"
|
|
48
57
|
description: "SearXNG 搜索 API,支持 JSON 格式 (/search?q=xxx&format=json)"
|
|
58
|
+
# PR 8 / docs §17 — canonical MCP surface that LLM-binding adapters
|
|
59
|
+
# (Hermes, future MCP-capable runtimes) expose via the in-tree MCP
|
|
60
|
+
# firewall. Description is deliberately minimal so MiniMax-class
|
|
61
|
+
# models don't get prompt-injected by upstream wording into adding
|
|
62
|
+
# dates / translating queries / auto-filling time_range filters.
|
|
63
|
+
# Mirrors OpenClaw's built-in searxng plugin description verbatim.
|
|
64
|
+
tool_schema:
|
|
65
|
+
name: "searxng_web_search"
|
|
66
|
+
description: "Search the web using a self-hosted SearXNG instance. Returns titles, URLs, and snippets."
|
|
67
|
+
parameters:
|
|
68
|
+
type: object
|
|
69
|
+
properties:
|
|
70
|
+
query:
|
|
71
|
+
type: string
|
|
72
|
+
description: "Search query string."
|
|
73
|
+
count:
|
|
74
|
+
type: number
|
|
75
|
+
description: "Number of results to return (1-10)."
|
|
76
|
+
minimum: 1
|
|
77
|
+
maximum: 10
|
|
78
|
+
categories:
|
|
79
|
+
type: string
|
|
80
|
+
description: "Optional comma-separated categories such as general, news, or science."
|
|
81
|
+
language:
|
|
82
|
+
type: string
|
|
83
|
+
description: "Optional language code such as en, de, or fr."
|
|
84
|
+
required:
|
|
85
|
+
- query
|
|
86
|
+
upstream:
|
|
87
|
+
command: npx
|
|
88
|
+
args:
|
|
89
|
+
- "-y"
|
|
90
|
+
- "mcp-searxng"
|
|
91
|
+
env_template:
|
|
92
|
+
# ${SEARCH_API_BASE_URL_ORIGIN} = parsed URL with /search stripped.
|
|
93
|
+
# The URL stays at the registry-resolved host:port at PUT
|
|
94
|
+
# /connections time; on host IP changes, the framework re-renders
|
|
95
|
+
# this env on next instance start (PR 9 phaseRefreshConnections),
|
|
96
|
+
# so users only need to restart the consuming agent — no re-bind.
|
|
97
|
+
SEARXNG_URL: "${SEARCH_API_BASE_URL_ORIGIN}"
|
|
98
|
+
wrap_outputs: true
|
|
49
99
|
|
|
50
100
|
lifecycle:
|
|
51
101
|
install:
|
package/dist/cli/app.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { basename, extname } from "path";
|
|
2
3
|
import { stringify } from "yaml";
|
|
3
4
|
import { parseFlag } from "./helpers.js";
|
|
4
5
|
import { loadManagedListEntries, printManagedList } from "./managed-list.js";
|
|
@@ -328,6 +329,30 @@ function parseRemoteYamlUrl(value) {
|
|
|
328
329
|
throw e;
|
|
329
330
|
}
|
|
330
331
|
}
|
|
332
|
+
const BUILTIN_INSTALL_ALIASES = {
|
|
333
|
+
ollama: "ollama-binary.yaml",
|
|
334
|
+
};
|
|
335
|
+
async function loadBuiltinInstallYaml(source) {
|
|
336
|
+
const normalizedSource = source.trim();
|
|
337
|
+
if (!normalizedSource)
|
|
338
|
+
return null;
|
|
339
|
+
const { listBuiltinAppSpecs } = await import("../services/app/app-manager.js");
|
|
340
|
+
const templates = listBuiltinAppSpecs();
|
|
341
|
+
const normalizedWithoutExt = normalizedSource.replace(/\.ya?ml$/i, "");
|
|
342
|
+
const aliasTarget = BUILTIN_INSTALL_ALIASES[normalizedWithoutExt] ?? BUILTIN_INSTALL_ALIASES[normalizedSource];
|
|
343
|
+
const template = templates.find((entry) => {
|
|
344
|
+
if (aliasTarget && entry.fileName === aliasTarget)
|
|
345
|
+
return true;
|
|
346
|
+
if (entry.fileName === normalizedSource)
|
|
347
|
+
return true;
|
|
348
|
+
if (basename(entry.fileName, extname(entry.fileName)) === normalizedWithoutExt)
|
|
349
|
+
return true;
|
|
350
|
+
if (entry.id === normalizedWithoutExt || entry.id === normalizedSource)
|
|
351
|
+
return true;
|
|
352
|
+
return false;
|
|
353
|
+
});
|
|
354
|
+
return template?.yaml ?? null;
|
|
355
|
+
}
|
|
331
356
|
async function loadInstallYaml(source) {
|
|
332
357
|
const remoteUrl = parseRemoteYamlUrl(source);
|
|
333
358
|
if (remoteUrl) {
|
|
@@ -347,6 +372,10 @@ async function loadInstallYaml(source) {
|
|
|
347
372
|
}
|
|
348
373
|
return body;
|
|
349
374
|
}
|
|
375
|
+
const builtinYaml = await loadBuiltinInstallYaml(source);
|
|
376
|
+
if (builtinYaml) {
|
|
377
|
+
return builtinYaml;
|
|
378
|
+
}
|
|
350
379
|
if (!existsSync(source)) {
|
|
351
380
|
throw new Error(`File not found: ${source}`);
|
|
352
381
|
}
|
|
@@ -377,12 +406,41 @@ async function cmdShow(id) {
|
|
|
377
406
|
}
|
|
378
407
|
console.log(JSON.stringify(instance, null, 2));
|
|
379
408
|
}
|
|
380
|
-
async function cmdInstall(
|
|
381
|
-
const
|
|
409
|
+
async function cmdInstall(args) {
|
|
410
|
+
const installSource = args[0];
|
|
411
|
+
let requestedAppId;
|
|
412
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
413
|
+
const value = args[index];
|
|
414
|
+
if (value === "--sudo-password") {
|
|
415
|
+
index += 1;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (value.startsWith("--"))
|
|
419
|
+
continue;
|
|
420
|
+
requestedAppId = value;
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
const yamlText = await loadInstallYaml(installSource);
|
|
382
424
|
const { installApp } = await import("../services/app/app-manager.js");
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
425
|
+
const sudoState = getCliSudoState(args);
|
|
426
|
+
while (true) {
|
|
427
|
+
try {
|
|
428
|
+
const installOptions = sudoState.password ? { exec: { sudoPassword: sudoState.password } } : undefined;
|
|
429
|
+
const result = installOptions
|
|
430
|
+
? await installApp(yamlText, requestedAppId, installOptions)
|
|
431
|
+
: await installApp(yamlText, requestedAppId);
|
|
432
|
+
const installModeLabel = result.manifest.install_mode === "instance-dir" ? "instance" : "app";
|
|
433
|
+
log(c.green(` ✓ Installed: ${result.manifest.id} (${result.spec.name || ""} v${result.spec.version || "?"}, ${installModeLabel})`));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
const message = err?.message || "Install failed";
|
|
438
|
+
if (isSudoPasswordError(message) && await promptForCliSudoPassword(sudoState)) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
throw err;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
386
444
|
}
|
|
387
445
|
async function cmdProvides(args) {
|
|
388
446
|
const { listProvidedCapabilities } = await import("../services/app/app-manager.js");
|
|
@@ -504,16 +562,26 @@ async function cmdUninstallAll(args = []) {
|
|
|
504
562
|
}
|
|
505
563
|
}
|
|
506
564
|
async function cmdCreateInstance(appId, instanceId, name) {
|
|
507
|
-
const { getApp, installApp,
|
|
565
|
+
const { getApp, installApp, updateInstance } = await import("../services/app/app-manager.js");
|
|
566
|
+
const { resolveConnections, resolvedToLegacyEnv } = await import("../services/connection-resolver.js");
|
|
508
567
|
const appData = getApp(appId);
|
|
509
568
|
if (!appData) {
|
|
510
569
|
log(c.red(` ✗ App "${appId}" not found.`));
|
|
511
570
|
process.exitCode = 1;
|
|
512
571
|
return;
|
|
513
572
|
}
|
|
573
|
+
// PR 3 sub-step 3e: switch CLI to resolveConnections (preCreate). Pending
|
|
574
|
+
// requires are printed so the user can see what still needs binding.
|
|
514
575
|
let resolvedEnv = {};
|
|
515
576
|
try {
|
|
516
|
-
|
|
577
|
+
const { resolved, pending } = resolveConnections(appData.spec, { connections: {} }, "preCreate");
|
|
578
|
+
resolvedEnv = resolvedToLegacyEnv(resolved);
|
|
579
|
+
if (pending.length > 0) {
|
|
580
|
+
log(c.yellow(` ⚠ ${pending.length} pending connection(s):`));
|
|
581
|
+
for (const p of pending) {
|
|
582
|
+
log(c.yellow(` - ${p.slot} (${p.capability}): ${p.reason}`));
|
|
583
|
+
}
|
|
584
|
+
}
|
|
517
585
|
}
|
|
518
586
|
catch (e) {
|
|
519
587
|
log(c.red(` ✗ ${e.message}`));
|
|
@@ -705,7 +773,7 @@ export async function run(rest) {
|
|
|
705
773
|
await cmdShow(rest[1]);
|
|
706
774
|
}
|
|
707
775
|
else if (appCmd === "install" && rest[1]) {
|
|
708
|
-
await cmdInstall(rest
|
|
776
|
+
await cmdInstall(rest.slice(1));
|
|
709
777
|
}
|
|
710
778
|
else if (appCmd === "uninstall" && rest[1] === "--all") {
|
|
711
779
|
await cmdUninstallAll(rest.slice(2));
|
|
@@ -781,7 +849,8 @@ Commands:
|
|
|
781
849
|
list [--json] 列出统一受管列表(apps 下已安装应用 + instances 下遗留实例)
|
|
782
850
|
provides [--json] 列出已安装 App 声明/注册的能力
|
|
783
851
|
show <id> 查看 App 或实例详情(JSON)
|
|
784
|
-
install <yaml-file|https-url> [app-id]
|
|
852
|
+
install <yaml-file|https-url|builtin-id> [app-id] [--sudo-password <password>]
|
|
853
|
+
从本地、HTTPS 或内置模板安装 App,可选指定安装 id
|
|
785
854
|
uninstall <app-id> [--sudo-password <password>] 卸载单个 App 或实例(停止 + 删除目录)
|
|
786
855
|
uninstall --all [--sudo-password <password>] 卸载全部 App 与实例
|
|
787
856
|
create-instance <app-id> <inst-id> [name] 从 App 创建实例(Agent 通道由 spec.agentType 决定)
|
|
@@ -798,6 +867,7 @@ Examples:
|
|
|
798
867
|
jishushell app install ./apps/ollama-with-hollama-binary.yaml
|
|
799
868
|
jishushell app install ./apps/ollama-with-hollama-binary.yaml ollama-local
|
|
800
869
|
jishushell app install https://example.com/apps/ollama-with-hollama-binary.yaml
|
|
870
|
+
jishushell app install ollama
|
|
801
871
|
jishushell app list
|
|
802
872
|
jishushell app provides
|
|
803
873
|
jishushell app copy ollama-1
|